-*.[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
--- /dev/null
+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)
--- /dev/null
+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 )
--- /dev/null
+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 )
--- /dev/null
+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 )
--- /dev/null
+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 )
--- /dev/null
+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 )
--- /dev/null
+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 )
--- /dev/null
+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 )
#define ADMIN_H
#include <string>
+#include <cstdint>
#include "admin_conf.h"
-#include "os_int.h"
class ADMIN {
public:
#include <string>
-#include "os_int.h"
+#include <cstdint>
#define ADM_LOGIN_LEN (32)
#define ADM_PASSWD_LEN (32)
#ifndef PACKETH
#define PACKETH
-#include "os_int.h"
+#include <cstdint>
#define CONN_SYN_N 0
#define CONN_SYN_ACK_N 1
*/
#include <ctime>
+#include <cstdint>
#include <string>
-#include "os_int.h"
-
//-----------------------------------------------------------------------------
struct STG_MSG_HDR
{
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.4 $
- $Date: 2008/03/25 17:41:50 $
- */
-
-
-#ifndef OS_INT_H
-#define OS_INT_H
-
-#ifdef LINUX
-#include <stdint.h>
-#endif
-
-#if defined(FREE_BSD5) || defined(DARWIN)
-#include <inttypes.h>
-#endif
-
-#ifdef FREE_BSD
-#include <sys/inttypes.h>
-#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
-
#define PLUGIN_H
#include <string>
+#include <cstdint>
#include "noncopyable.h"
-#include "os_int.h"
#include "admins.h"
#include "users.h"
#include "tariffs.h"
#define RAD_ID "00100"
-#include "os_int.h"
+#include <cstdint>
struct RAD_PACKET
{
#ifndef RAW_IP_PACKET_H
#define RAW_IP_PACKET_H
-#if defined(FREE_BSD) || defined(FREE_BSD5)
+#if defined(FREE_BSD)
#include <netinet/in_systm.h> // n_long in netinet/ip.h
#endif
#define RS_ID "RSP00"
-#include "os_int.h"
+#include <cstdint>
namespace RS
{
#define SERVICE_CONF_H
#include "resetable.h"
-#include "os_int.h"
#include <string>
+#include <cstdint>
struct SERVICE_CONF
{
#ifndef TARIFF_H
#define TARIFF_H
-#include "os_int.h"
-
#include <string>
+#include <istream>
#include <cstring>
#include <ctime>
-#include <istream>
+#include <cstdint>
struct TARIFF_DATA;
#include "message.h"
#include "tariff.h"
#include "user_traff.h"
-#include "os_int.h"
#include <vector>
#include <string>
#include <ctime>
+#include <cstdint>
class USER_PROPERTIES;
class AUTH;
#include <string>
#include <vector>
+#include <cstdint>
#include "const.h"
#include "user_ips.h"
#include "resetable.h"
-#include "os_int.h"
//-----------------------------------------------------------------------------
struct USER_CONF
#define USER_IPS_H
#include "stg/common.h"
-#include "os_int.h"
#include <cstring>
+#include <cstdint>
#include <vector>
#include <string>
#include <iostream>
#define USER_STAT_H
#include <ctime>
+#include <cstdint>
#include <map>
#include <utility>
#include <string>
-#include "os_int.h"
#include "resetable.h"
#include "user_traff.h"
//-----------------------------------------------------------------------------
#include "resetable.h"
#include "const.h"
-#include "os_int.h"
#include <iostream>
#include <vector>
+#include <cstdint>
enum TRAFF_DIRECTION {TRAFF_UPLOAD, TRAFF_DOWNLOAD};
--- /dev/null
+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 )
--- /dev/null
+set ( CPP_FILES blockio.cpp common.cpp strptime.cpp )
+
+include_directories ( include )
+
+add_library ( common STATIC ${CPP_FILES} )
+
+target_include_directories ( common PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#include "stg/blockio.h"
+
+namespace
+{
+
+void* adjust(void* base, size_t shift)
+{
+ char* ptr = static_cast<char*>(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<ssize_t>(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<ssize_t>(m_remainder))
+ m_remainder -= res;
+ else
+ m_remainder = 0;
+ return true;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.42 $
+ $Date: 2010/11/08 10:11:19 $
+ $Author: faust $
+ */
+
+// For old and dub systems
+// Like FreeBSD4
+#include <sys/types.h>
+#include <sys/time.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sys/select.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#endif
+
+#include <iconv.h>
+
+#include <algorithm>
+
+#include <cstdlib>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cassert>
+
+#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<struct sockaddr *>(&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<struct sockaddr *>(&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<char>(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<char>(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<uint16_t>((value >> 8) |
+ (value << 8));
+}
+//---------------------------------------------------------------------------
+void SwapBytes(uint32_t & value)
+{
+ value = static_cast<uint32_t>((value >> 24) |
+ ((value << 8) & 0x00FF0000L) |
+ ((value >> 8) & 0x0000FF00L) |
+ (value << 24));
+}
+//---------------------------------------------------------------------------
+void SwapBytes(uint64_t & value)
+{
+ value = static_cast<uint64_t>((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<int32_t>(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<uint32_t>(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<int>(str, *val))
+ return -1;
+return 0;
+}
+
+int ParseUnsigned(const std::string & str, unsigned * val)
+{
+if (str2x<unsigned>(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<char *>(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<const char *>(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;
+}
--- /dev/null
+#ifndef __STG_STGLIBS_BLOCK_IO_H__
+#define __STG_STGLIBS_BLOCK_IO_H__
+
+#include <vector>
+
+#include <sys/uio.h>
+
+namespace STG
+{
+
+typedef std::vector<iovec> 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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.32 $
+ $Date: 2010/11/08 10:11:19 $
+ $Author: faust $
+ */
+
+#ifndef common_h
+#define common_h
+
+//#include "stg/const.h"
+
+#include <string>
+#include <sstream>
+#include <ctime>
+#include <climits> // NAME_MAX
+#include <cstdint>
+
+#include <unistd.h> // uid_t, gid_t
+#include <sys/stat.h> // 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 <typename C, typename F>
+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 <typename T>
+inline
+T FromString(const std::string & value)
+{
+T res;
+std::istringstream stream(value);
+stream >> res;
+return res;
+}
+
+template <>
+inline
+std::string FromString<std::string>(const std::string & value)
+{
+return value;
+}
+
+template <typename C>
+inline
+C Split(const std::string & value, char delim)
+{
+ return Split<C>(value, delim, FromString<typename C::value_type>);
+}
+
+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 <typename varT>
+int str2x(const std::string & str, varT & x);
+template <typename varT>
+const std::string & x2str(varT x, std::string & s);
+template <typename varT>
+std::string x2str(varT x) { std::string s; return x2str(x, s); }
+template <typename varT>
+const std::string & unsigned2str(varT x, std::string & s);
+template <typename varT>
+std::string unsigned2str(varT x) { std::string s; return unsigned2str(x, s); }
+
+//-----------------------------------------------------------------------------
+template <typename varT>
+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 <typename varT>
+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 <typename varT>
+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
--- /dev/null
+/*
+ * $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 <time.h>
+
+#include "stg/common.h"
+
+char * stg_strptime(const char * a, const char * b, struct tm * tm)
+{
+return strptime(a, b, tm);
+}
+
--- /dev/null
+set ( CPP_FILES conffiles.cpp )
+
+add_library ( conffiles STATIC ${CPP_FILES} )
+
+target_include_directories ( conffiles PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+/*
+ * 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 <stg34@ua.fm>
+ */
+
+ /*
+ $Revision: 1.5 $
+ $Date: 2009/10/22 11:40:22 $
+ */
+
+//---------------------------------------------------------------------------
+
+// getpid
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cerrno> // E*
+#include <cstring>
+#include <sstream>
+#include <cstdlib>
+#include <cstdio>
+
+#include <fstream>
+
+#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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
+
+if (it != param_val.end())
+ {
+ char *res;
+ *val = static_cast<int>(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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
+
+if (it != param_val.end())
+ {
+ char *res;
+ *val = static_cast<unsigned int>(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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
+
+if (it != param_val.end())
+ {
+ char *res;
+ *val = static_cast<short>(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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
+
+if (it != param_val.end())
+ {
+ char *res;
+ *val = static_cast<short>(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<long long int>(val));
+param_val[param] = buf;
+changed = true;
+}
+//---------------------------------------------------------------------------
+void CONFIGFILE::WriteTime(const std::string & param, time_t val)
+{
+std::stringstream ss;
+ss<<val;
+param_val[param] = ss.str();
+changed = true;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadDouble(const std::string & param, double * val, double defaultVal) const
+{
+const std::map<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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;
+}
+//---------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@ua.fm>
+ */
+
+/*
+ $Revision: 1.5 $
+ $Date: 2009/06/22 16:00:38 $
+ */
+
+//---------------------------------------------------------------------------
+
+#ifndef ConfFilesH
+#define ConfFilesH
+
+#include <map>
+#include <string>
+#include <cstdint>
+
+//---------------------------------------------------------------------------
+
+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<std::string, std::string, StringCaseCmp_t> param_val;
+ std::string fileName;
+ mutable int error;
+ mutable bool changed;
+
+ int Flush(const std::string & path) const;
+};
+//---------------------------------------------------------------------------
+#endif
--- /dev/null
+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 )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#ifdef WIN32
+#include <process.h>
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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<<s | 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)));
+}
+
--- /dev/null
+#include "stg/bfstream.h"
+
+#include "stg/blowfish.h"
+
+#include <cstring>
+
+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<const char *>(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();
+}
--- /dev/null
+/*
+ * Author : Paul Kocher
+ * E-mail : pck@netcom.com
+ * Date : 1997
+ * Description: C implementation of the Blowfish algorithm.
+ */
+
+#include <string.h>
+
+#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;
+ }
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+#ifndef _MD5_H
+#define _MD5_H
+
+#include <time.h>
+#include <stdint.h>
+
+#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
--- /dev/null
+#ifndef __STG_STGLIBS_BF_STREAM_H__
+#define __STG_STGLIBS_BF_STREAM_H__
+
+#include <string>
+#include <cstddef> // 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
--- /dev/null
+/*
+ * 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 <cstddef> // size_t
+#include <cstdint>
+extern "C" {
+#else
+#include <stddef.h> // size_t
+#include <stdint.h>
+#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
+
--- /dev/null
+set ( CPP_FILES dotconfpp.cpp mempool.cpp )
+
+add_library ( dotconfpp STATIC ${CPP_FILES} )
+
+target_include_directories ( dotconfpp PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <krivoshey@users.sourceforge.net>
+*
+* 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 <libgen.h> // dirname
+#include <glob.h> // glob
+#include <string>
+
+#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<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){
+ delete(*i);
+ }
+ for(std::list<char*>::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){
+ free(*i);
+ }
+ for(std::list<char*>::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<char*>::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<DOTCONFDocumentNode*>::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 </%s>", 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<DOTCONFDocumentNode*>::iterator & from)
+{
+ int ret = 0;
+
+ for(std::list<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::iterator from;
+ DOTCONFDocumentNode * tagNode = NULL;
+ int vi = 0;
+ for(std::list<DOTCONFDocumentNode*>::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<char*>::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<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){
+ bool matched = false;
+ for(std::list<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::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++;
+ }
+}
+
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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 <list>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+
+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<DOTCONFDocumentNode *> nodeTree;
+ std::list<char *> requiredOptions;
+ std::list<char *> processedFiles;
+ FILE * file;
+ char * fileName;
+ std::list<char *> words;
+ int (* cmp_func)(const char *, const char *);
+
+ int checkRequiredOptions();
+ int parseLine();
+ int parseFile(DOTCONFDocumentNode * _parent = NULL);
+ int checkConfig(const std::list<DOTCONFDocumentNode *>::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
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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; i<chunksCount; i++){
+ delete chunks[i];
+ }
+ ::free(chunks);
+}
+
+int AsyncDNSMemPool::initialize()
+{
+ chunksCount = 1;
+ chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
+ if(chunks == NULL)
+ return -1;
+
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+
+ return 0;
+}
+
+void AsyncDNSMemPool::addNewChunk(size_t size)
+{
+ chunksCount++;
+ chunks = (PoolChunk**)::realloc(chunks, chunksCount*sizeof(PoolChunk*));
+ if(size <= defaultSize)
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+ else
+ chunks[chunksCount-1] = new PoolChunk(size);
+}
+
+void * AsyncDNSMemPool::alloc(size_t size)
+{
+ PoolChunk * chunk = NULL;
+ for(size_t i = 0; i<chunksCount; i++){
+ chunk = chunks[i];
+ if((chunk->size - 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; i<chunksCount; i++){
+ pu += chunks[i]->pos;
+ 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);
+}
+
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+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
+
--- /dev/null
+set ( CPP_FILES ia.cpp )
+
+add_library ( ia STATIC ${CPP_FILES} )
+
+target_include_directories ( ia PUBLIC include )
+
+target_link_libraries ( ia crypto common )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+/*
+** 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 <stg34@stargazer.dp.ua>
+* Maxim Mamontov <faust@stargazer.dp.ua>
+* Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - bugfixes.
+*/
+
+//---------------------------------------------------------------------------
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+#include <winnt.h>
+#else
+#include <fcntl.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <csignal>
+#endif
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+#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 <sys/time.h>
+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<std::string, int>::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<std::string> 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;
+}
+//---------------------------------------------------------------------------
--- /dev/null
+/*
+** 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 <stg34@stargazer.dp.ua>
+*/
+//---------------------------------------------------------------------------
+#ifndef IA_AUTH_C_H
+#define IA_AUTH_C_H
+
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+
+#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<std::string> & 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<std::string, int> 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
--- /dev/null
+set ( CPP_FILES all_in_one.cpp )
+
+add_library ( ibpp STATIC ${CPP_FILES} )
+
+target_include_directories ( ibpp PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _dpb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal DPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * DPB == Database Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int DPB::BUFFERINCR = 128;\r
+\r
+void DPB::Grow(int needed)\r
+{\r
+ if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer == 0)\r
+ {\r
+ // Initial allocation, initialize the version tag\r
+ newbuffer[0] = isc_dpb_version1;\r
+ mSize = 1;\r
+ }\r
+ else\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void DPB::Insert(char type, const char* data)\r
+{\r
+ int len = (int)strlen(data);\r
+ Grow(len + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(len);\r
+ strncpy(&mBuffer[mSize], data, len);\r
+ mSize += len;\r
+}\r
+\r
+void DPB::Insert(char type, int16_t data)\r
+{\r
+ Grow(2 + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(2);\r
+ *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&data, 2));\r
+ mSize += 2;\r
+}\r
+\r
+void DPB::Insert(char type, bool data)\r
+{\r
+ Grow(2 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = char(data ? 1 : 0);\r
+}\r
+\r
+void DPB::Insert(char type, char data)\r
+{\r
+ Grow(2 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = data;\r
+}\r
+\r
+void DPB::Reset()\r
+{\r
+ if (mAlloc != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibpp.cpp,v 1.3 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, Initialization of the library\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <limits>\r
+\r
+#ifdef IBPP_WINDOWS\r
+// New (optional) Registry Keys introduced by Firebird Server 1.5\r
+#define REG_KEY_ROOT_INSTANCES "SOFTWARE\\Firebird Project\\Firebird Server\\Instances"\r
+#define FB_DEFAULT_INSTANCE "DefaultInstance"\r
+#endif\r
+\r
+namespace ibpp_internals\r
+{\r
+ const double consts::dscales[19] = {\r
+ 1, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,\r
+ 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15,\r
+ 1E16, 1E17, 1E18 };\r
+\r
+ const int consts::Dec31_1899 = 693595;\r
+\r
+// Many compilers confuses those following min/max with macros min and max !\r
+#undef min\r
+#undef max\r
+\r
+#ifdef __DMC__ // Needs to break-down the declaration else compiler crash (!)\r
+ const std::numeric_limits<int16_t> i16_limits;\r
+ const std::numeric_limits<int32_t> i32_limits;\r
+ const int16_t consts::min16 = i16_limits.min();\r
+ const int16_t consts::max16 = i16_limits.max();\r
+ const int32_t consts::min32 = i32_limits.min();\r
+ const int32_t consts::max32 = i32_limits.max();\r
+#else\r
+ const int16_t consts::min16 = std::numeric_limits<int16_t>::min();\r
+ const int16_t consts::max16 = std::numeric_limits<int16_t>::max();\r
+ const int32_t consts::min32 = std::numeric_limits<int32_t>::min();\r
+ const int32_t consts::max32 = std::numeric_limits<int32_t>::max();\r
+#endif\r
+\r
+ GDS gds; // Global unique GDS instance\r
+\r
+#ifdef IBPP_WINDOWS\r
+ std::string AppPath; // Used by GDS::Call() below\r
+#endif\r
+\r
+#ifdef _DEBUG\r
+ std::ostream& operator<< (std::ostream& a, flush_debug_stream_type)\r
+ {\r
+ if (std::stringstream* p = dynamic_cast<std::stringstream*>(&a))\r
+ {\r
+#ifdef IBPP_WINDOWS\r
+ ::OutputDebugString(("IBPP: " + p->str() + "\n").c_str());\r
+#endif\r
+ p->str("");\r
+ }\r
+ return a;\r
+ }\r
+#endif // _DEBUG\r
+\r
+}\r
+\r
+using namespace ibpp_internals;\r
+\r
+GDS* GDS::Call()\r
+{\r
+ // Let's load the CLIENT library, if it is not already loaded.\r
+ // The load is guaranteed to be done only once per application.\r
+\r
+ if (! mReady)\r
+ {\r
+#ifdef IBPP_WINDOWS\r
+\r
+ // Let's load the FBCLIENT.DLL or GDS32.DLL, we will never release it.\r
+ // Windows will do that for us when the executable will terminate.\r
+\r
+ char fbdll[MAX_PATH];\r
+ HKEY hkey_instances;\r
+\r
+ // Try to load FBCLIENT.DLL from each of the additional optional paths\r
+ // that may have been specified through ClientLibSearchPaths().\r
+ // We also want to actually update the environment PATH so that it references\r
+ // the specific path from where we attempt the load. This is useful because\r
+ // it directs the system to attempt finding dependencies (like the C/C++\r
+ // runtime libraries) from the same location where FBCLIENT is found.\r
+\r
+ mHandle = 0;\r
+\r
+ std::string SysPath(getenv("PATH"));\r
+ std::string::size_type pos = 0;\r
+ while (pos < mSearchPaths.size())\r
+ {\r
+ std::string::size_type newpos = mSearchPaths.find(';', pos);\r
+\r
+ std::string path;\r
+ if (newpos == std::string::npos) path = mSearchPaths.substr(pos);\r
+ else path = mSearchPaths.substr(pos, newpos-pos);\r
+\r
+ if (path.size() >= 1)\r
+ {\r
+ if (path[path.size()-1] != '\\') path += '\\';\r
+\r
+ AppPath.assign("PATH=");\r
+ AppPath.append(path).append(";").append(SysPath);\r
+ putenv(AppPath.c_str());\r
+\r
+ path.append("fbclient.dll");\r
+ mHandle = LoadLibrary(path.c_str());\r
+ if (mHandle != 0 || newpos == std::string::npos) break;\r
+ }\r
+ pos = newpos + 1;\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Try to load FBCLIENT.DLL from the current application location. This\r
+ // is a usefull step for applications using the embedded version of FB\r
+ // or a local copy (for whatever reasons) of the dll.\r
+\r
+ if (! AppPath.empty())\r
+ {\r
+ // Restores the original system path\r
+ AppPath.assign("PATH=");\r
+ AppPath.append(SysPath);\r
+ putenv(AppPath.c_str());\r
+ }\r
+\r
+ int len = GetModuleFileName(NULL, fbdll, sizeof(fbdll));\r
+ if (len != 0)\r
+ {\r
+ // Get to the last '\' (this one precedes the filename part).\r
+ // There is always one after a success call to GetModuleFileName().\r
+ char* p = fbdll + len;\r
+ do {--p;} while (*p != '\\');\r
+ *p = '\0';\r
+ lstrcat(fbdll, "\\fbembed.dll");// Local copy could be named fbembed.dll\r
+ mHandle = LoadLibrary(fbdll);\r
+ if (mHandle == 0)\r
+ {\r
+ *p = '\0';\r
+ lstrcat(fbdll, "\\fbclient.dll"); // Or possibly renamed fbclient.dll\r
+ mHandle = LoadLibrary(fbdll);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Try to locate FBCLIENT.DLL through the optional FB registry key.\r
+\r
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_ROOT_INSTANCES, 0,\r
+ KEY_READ, &hkey_instances) == ERROR_SUCCESS)\r
+ {\r
+ DWORD keytype;\r
+ DWORD buflen = sizeof(fbdll);\r
+ if (RegQueryValueEx(hkey_instances, FB_DEFAULT_INSTANCE, 0,\r
+ &keytype, reinterpret_cast<UCHAR*>(fbdll),\r
+ &buflen) == ERROR_SUCCESS && keytype == REG_SZ)\r
+ {\r
+ lstrcat(fbdll, "bin\\fbclient.dll");\r
+ mHandle = LoadLibrary(fbdll);\r
+ }\r
+ RegCloseKey(hkey_instances);\r
+ }\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Let's try from the PATH and System directories\r
+ mHandle = LoadLibrary("fbclient.dll");\r
+ if (mHandle == 0)\r
+ {\r
+ // Not found. Last try : attemps loading gds32.dll from PATH and\r
+ // System directories\r
+ mHandle = LoadLibrary("gds32.dll");\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("GDS::Call()",\r
+ _("Can't find or load FBCLIENT.DLL or GDS32.DLL"));\r
+ }\r
+ }\r
+#endif\r
+\r
+ mGDSVersion = 60;\r
+\r
+ // Get the entry points that we need\r
+\r
+#ifdef IBPP_WINDOWS\r
+#define IB_ENTRYPOINT(X) \\r
+ if ((m_##X = (proto_##X*)GetProcAddress(mHandle, "isc_"#X)) == 0) \\r
+ throw LogicExceptionImpl("GDS:gds()", _("Entry-point isc_"#X" not found"))\r
+#endif\r
+#ifdef IBPP_UNIX\r
+/* TODO : perform a late-bind on unix --- not so important, well I think (OM) */\r
+#define IB_ENTRYPOINT(X) m_##X = (proto_##X*)isc_##X\r
+#endif\r
+\r
+ IB_ENTRYPOINT(create_database);\r
+ IB_ENTRYPOINT(attach_database);\r
+ IB_ENTRYPOINT(detach_database);\r
+ IB_ENTRYPOINT(drop_database);\r
+ IB_ENTRYPOINT(database_info);\r
+ IB_ENTRYPOINT(open_blob2);\r
+ IB_ENTRYPOINT(create_blob2);\r
+ IB_ENTRYPOINT(close_blob);\r
+ IB_ENTRYPOINT(cancel_blob);\r
+ IB_ENTRYPOINT(get_segment);\r
+ IB_ENTRYPOINT(put_segment);\r
+ IB_ENTRYPOINT(blob_info);\r
+ IB_ENTRYPOINT(array_lookup_bounds);\r
+ IB_ENTRYPOINT(array_get_slice);\r
+ IB_ENTRYPOINT(array_put_slice);\r
+ IB_ENTRYPOINT(vax_integer);\r
+ IB_ENTRYPOINT(sqlcode);\r
+ IB_ENTRYPOINT(sql_interprete);\r
+ IB_ENTRYPOINT(interprete);\r
+ IB_ENTRYPOINT(que_events);\r
+ IB_ENTRYPOINT(cancel_events);\r
+ IB_ENTRYPOINT(start_multiple);\r
+ IB_ENTRYPOINT(commit_transaction);\r
+ IB_ENTRYPOINT(commit_retaining);\r
+ IB_ENTRYPOINT(rollback_transaction);\r
+ IB_ENTRYPOINT(rollback_retaining);\r
+ IB_ENTRYPOINT(dsql_execute_immediate);\r
+ IB_ENTRYPOINT(dsql_allocate_statement);\r
+ IB_ENTRYPOINT(dsql_describe);\r
+ IB_ENTRYPOINT(dsql_describe_bind);\r
+ IB_ENTRYPOINT(dsql_prepare);\r
+ IB_ENTRYPOINT(dsql_execute);\r
+ IB_ENTRYPOINT(dsql_execute2);\r
+ IB_ENTRYPOINT(dsql_fetch);\r
+ IB_ENTRYPOINT(dsql_free_statement);\r
+ IB_ENTRYPOINT(dsql_set_cursor_name);\r
+ IB_ENTRYPOINT(dsql_sql_info);\r
+\r
+ IB_ENTRYPOINT(service_attach);\r
+ IB_ENTRYPOINT(service_detach);\r
+ IB_ENTRYPOINT(service_start);\r
+ IB_ENTRYPOINT(service_query);\r
+\r
+ mReady = true;\r
+ }\r
+\r
+ return this;\r
+}\r
+\r
+namespace IBPP\r
+{\r
+\r
+ bool CheckVersion(uint32_t AppVersion)\r
+ {\r
+ //(void)gds.Call(); // Just call it to trigger the initialization\r
+ return (AppVersion & 0xFFFFFF00) ==\r
+ (IBPP::Version & 0xFFFFFF00) ? true : false;\r
+ }\r
+\r
+ int GDSVersion()\r
+ {\r
+ return gds.Call()->mGDSVersion;\r
+ }\r
+\r
+#ifdef IBPP_WINDOWS\r
+ void ClientLibSearchPaths(const std::string& paths)\r
+ {\r
+ gds.mSearchPaths.assign(paths);\r
+ }\r
+#else\r
+ void ClientLibSearchPaths(const std::string&)\r
+ {\r
+ }\r
+#endif\r
+\r
+ // Factories for our Interface objects\r
+\r
+ Service ServiceFactory(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new ServiceImpl(ServerName, UserName, UserPassword);\r
+ }\r
+\r
+ Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword, const std::string& RoleName,\r
+ const std::string& CharSet, const std::string& CreateParams)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new DatabaseImpl(ServerName, DatabaseName, UserName,\r
+ UserPassword, RoleName, CharSet, CreateParams);\r
+ }\r
+\r
+ Transaction TransactionFactory(Database db, TAM am,\r
+ TIL il, TLR lr, TFF flags)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new TransactionImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ am, il, lr, flags);\r
+ }\r
+\r
+ Statement StatementFactory(Database db, Transaction tr,\r
+ const std::string& sql)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new StatementImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()),\r
+ sql);\r
+ }\r
+\r
+ Blob BlobFactory(Database db, Transaction tr)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new BlobImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()));\r
+ }\r
+\r
+ Array ArrayFactory(Database db, Transaction tr)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new ArrayImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()));\r
+ }\r
+\r
+ Events EventsFactory(Database db)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new EventsImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
+ }\r
+\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
+\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibpp.h,v 1.2 2007/05/17 08:37:05 faust Exp $\r
+// Subject : IBPP internal declarations\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+//\r
+// * 'Internal declarations' means everything used to implement ibpp. This\r
+// file and its contents is NOT needed by users of the library. All those\r
+// declarations are wrapped in a namespace : 'ibpp_internals'.\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __INTERNAL_IBPP_H__\r
+#define __INTERNAL_IBPP_H__\r
+\r
+#include "stg/ibpp.h"\r
+\r
+#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__DMC__)\r
+#define HAS_HDRSTOP\r
+#endif\r
+\r
+#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
+// Setting flags for ibase.h -- using GCC/Cygwin/MinGW on Win32\r
+#ifndef _MSC_VER\r
+#define _MSC_VER 1299\r
+#endif\r
+#ifndef _WIN32\r
+#define _WIN32 1\r
+#endif\r
+#endif\r
+\r
+#include "ibase.h" // From Firebird 1.x or InterBase 6.x installation\r
+\r
+#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
+// UNSETTING flags used above for ibase.h -- Huge conflicts with libstdc++ !\r
+#undef _MSC_VER\r
+#undef _WIN32\r
+#endif\r
+\r
+#ifdef IBPP_WINDOWS\r
+#include <windows.h>\r
+#endif\r
+\r
+//#include <limits>\r
+#include <string>\r
+#include <vector>\r
+#include <sstream>\r
+#include <cstdarg>\r
+\r
+#ifdef _DEBUG\r
+#define ASSERTION(x) {if (!(x)) {throw LogicExceptionImpl("ASSERTION", \\r
+ "'"#x"' is not verified at %s, line %d", \\r
+ __FILE__, __LINE__);}}\r
+#else\r
+#define ASSERTION(x) /* x */\r
+#endif\r
+\r
+// Fix to famous MSVC 6 variable scope bug\r
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
+#define for if(true)for\r
+#endif\r
+\r
+namespace ibpp_internals\r
+{\r
+\r
+enum flush_debug_stream_type {fds};\r
+\r
+#ifdef _DEBUG\r
+\r
+struct DebugStream : public std::stringstream\r
+{\r
+ // next two operators fix some g++ and vc++ related problems\r
+ std::ostream& operator<< (const char* p)\r
+ { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
+\r
+ std::ostream& operator<< (const std::string& p)\r
+ { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
+\r
+ DebugStream& operator=(const DebugStream&) {return *this;}\r
+ DebugStream(const DebugStream&) {}\r
+ DebugStream() {}\r
+};\r
+std::ostream& operator<< (std::ostream& a, flush_debug_stream_type);\r
+\r
+#else\r
+\r
+struct DebugStream\r
+{\r
+ template<class T> DebugStream& operator<< (const T&) { return *this; }\r
+ // for manipulators\r
+ DebugStream& operator<< (std::ostream&(*)(std::ostream&)) { return *this; }\r
+};\r
+\r
+#endif // _DEBUG\r
+\r
+class DatabaseImpl;\r
+class TransactionImpl;\r
+class StatementImpl;\r
+class BlobImpl;\r
+class ArrayImpl;\r
+class EventsImpl;\r
+\r
+// Native data types\r
+typedef enum {ivArray, ivBlob, ivDate, ivTime, ivTimestamp, ivString,\r
+ ivInt16, ivInt32, ivInt64, ivFloat, ivDouble,\r
+ ivBool, ivDBKey, ivByte} IITYPE;\r
+\r
+//\r
+// Those are the Interbase C API prototypes that we use\r
+// Taken 'asis' from IBASE.H, prefix 'isc_' replaced with 'proto_',\r
+// and 'typedef' preprended...\r
+//\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_create_database (ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_attach_database (ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_detach_database (ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_drop_database (ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_database_info (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute_immediate (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_open_blob2 (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_create_blob2 (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_close_blob (ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_cancel_blob (ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_get_segment (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_put_segment (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_blob_info (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_lookup_bounds (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_get_slice (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_put_slice (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_LONG ISC_EXPORT proto_vax_integer (char *,\r
+ short);\r
+\r
+typedef ISC_LONG ISC_EXPORT proto_sqlcode (ISC_STATUS *);\r
+\r
+typedef void ISC_EXPORT proto_sql_interprete (short,\r
+ char *,\r
+ short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_interprete (char *,\r
+ ISC_STATUS * *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_que_events (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *,\r
+ short,\r
+ char *,\r
+ isc_callback,\r
+ void *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_cancel_events (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_start_multiple (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ void *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_commit_transaction (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_commit_retaining (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_rollback_transaction (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_rollback_retaining (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+///////////\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_allocate_statement (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_describe (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_describe_bind (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute2 (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_fetch (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_free_statement (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_prepare (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_set_cursor_name (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ char *,\r
+ unsigned short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_sql_info (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef void ISC_EXPORT proto_decode_date (ISC_QUAD *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_encode_date (void *,\r
+ ISC_QUAD *);\r
+\r
+typedef int ISC_EXPORT proto_add_user (ISC_STATUS *, USER_SEC_DATA *);\r
+typedef int ISC_EXPORT proto_delete_user (ISC_STATUS *, USER_SEC_DATA *);\r
+typedef int ISC_EXPORT proto_modify_user (ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+//\r
+// Those API are only available in versions 6.x of the GDS32.DLL\r
+//\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_attach (ISC_STATUS *,\r
+ unsigned short,\r
+ char *,\r
+ isc_svc_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_detach (ISC_STATUS *,\r
+ isc_svc_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_query (ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_start (ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char*);\r
+\r
+typedef void ISC_EXPORT proto_decode_sql_date (ISC_DATE *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_decode_sql_time (ISC_TIME *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_decode_timestamp (ISC_TIMESTAMP *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_encode_sql_date (void *,\r
+ ISC_DATE *);\r
+\r
+typedef void ISC_EXPORT proto_encode_sql_time (void *,\r
+ ISC_TIME *);\r
+\r
+typedef void ISC_EXPORT proto_encode_timestamp (void *,\r
+ ISC_TIMESTAMP *);\r
+\r
+//\r
+// Internal binding structure to the GDS32 DLL\r
+//\r
+\r
+struct GDS\r
+{\r
+ // Attributes\r
+ bool mReady;\r
+ int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0)\r
+\r
+#ifdef IBPP_WINDOWS\r
+ HMODULE mHandle; // The GDS32.DLL HMODULE\r
+ std::string mSearchPaths; // Optional additional search paths\r
+#endif\r
+\r
+ GDS* Call();\r
+\r
+ // GDS32 Entry Points\r
+ proto_create_database* m_create_database;\r
+ proto_attach_database* m_attach_database;\r
+ proto_detach_database* m_detach_database;\r
+ proto_drop_database* m_drop_database;\r
+ proto_database_info* m_database_info;\r
+ proto_dsql_execute_immediate* m_dsql_execute_immediate;\r
+ proto_open_blob2* m_open_blob2;\r
+ proto_create_blob2* m_create_blob2;\r
+ proto_close_blob* m_close_blob;\r
+ proto_cancel_blob* m_cancel_blob;\r
+ proto_get_segment* m_get_segment;\r
+ proto_put_segment* m_put_segment;\r
+ proto_blob_info* m_blob_info;\r
+ proto_array_lookup_bounds* m_array_lookup_bounds;\r
+ proto_array_get_slice* m_array_get_slice;\r
+ proto_array_put_slice* m_array_put_slice;\r
+\r
+ proto_vax_integer* m_vax_integer;\r
+ proto_sqlcode* m_sqlcode;\r
+ proto_sql_interprete* m_sql_interprete;\r
+ proto_interprete* m_interprete;\r
+ proto_que_events* m_que_events;\r
+ proto_cancel_events* m_cancel_events;\r
+ proto_start_multiple* m_start_multiple;\r
+ proto_commit_transaction* m_commit_transaction;\r
+ proto_commit_retaining* m_commit_retaining;\r
+ proto_rollback_transaction* m_rollback_transaction;\r
+ proto_rollback_retaining* m_rollback_retaining;\r
+ proto_dsql_allocate_statement* m_dsql_allocate_statement;\r
+ proto_dsql_describe* m_dsql_describe;\r
+ proto_dsql_describe_bind* m_dsql_describe_bind;\r
+ proto_dsql_prepare* m_dsql_prepare;\r
+ proto_dsql_execute* m_dsql_execute;\r
+ proto_dsql_execute2* m_dsql_execute2;\r
+ proto_dsql_fetch* m_dsql_fetch;\r
+ proto_dsql_free_statement* m_dsql_free_statement;\r
+ proto_dsql_set_cursor_name* m_dsql_set_cursor_name;\r
+ proto_dsql_sql_info* m_dsql_sql_info;\r
+ //proto_decode_date* m_decode_date;\r
+ //proto_encode_date* m_encode_date;\r
+ //proto_add_user* m_add_user;\r
+ //proto_delete_user* m_delete_user;\r
+ //proto_modify_user* m_modify_user;\r
+\r
+ proto_service_attach* m_service_attach;\r
+ proto_service_detach* m_service_detach;\r
+ proto_service_start* m_service_start;\r
+ proto_service_query* m_service_query;\r
+ //proto_decode_sql_date* m_decode_sql_date;\r
+ //proto_decode_sql_time* m_decode_sql_time;\r
+ //proto_decode_timestamp* m_decode_timestamp;\r
+ //proto_encode_sql_date* m_encode_sql_date;\r
+ //proto_encode_sql_time* m_encode_sql_time;\r
+ //proto_encode_timestamp* m_encode_timestamp;\r
+\r
+ // Constructor (No need for a specific destructor)\r
+ GDS()\r
+ {\r
+ mReady = false;\r
+ mGDSVersion = 0;\r
+#ifdef IBPP_WINDOWS\r
+ mHandle = 0;\r
+#endif\r
+ }\r
+};\r
+\r
+extern GDS gds;\r
+\r
+//\r
+// Service Parameter Block (used to define a service)\r
+//\r
+\r
+class SPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated SPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size in bytes\r
+\r
+ void Grow(int needed); // Alloc or grow the mBuffer\r
+\r
+public:\r
+ void Insert(char); // Insert a single byte code\r
+ void InsertString(char, int, const char*); // Insert a string, len can be defined as 1 or 2 bytes\r
+ void InsertByte(char type, char data);\r
+ void InsertQuad(char type, int32_t data);\r
+ void Reset(); // Clears the SPB\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ SPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~SPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Database Parameter Block (used to define a database)\r
+//\r
+\r
+class DPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated DPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size in bytes\r
+\r
+ void Grow(int needed); // Allocate or grow the mBuffer, so that\r
+ // 'needed' bytes can be written (at least)\r
+\r
+public:\r
+ void Insert(char, const char*); // Insert a new char* 'cluster'\r
+ void Insert(char, int16_t); // Insert a new int16_t 'cluster'\r
+ void Insert(char, bool); // Insert a new bool 'cluster'\r
+ void Insert(char, char); // Insert a new byte 'cluster'\r
+ void Reset(); // Clears the DPB\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ DPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~DPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Transaction Parameter Block (used to define a transaction)\r
+//\r
+\r
+class TPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated TPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size\r
+\r
+ void Grow(int needed); // Alloc or re-alloc the mBuffer\r
+\r
+public:\r
+ void Insert(char); // Insert a flag item\r
+ void Insert(const std::string& data); // Insert a string (typically table name)\r
+ void Reset(); // Clears the TPB\r
+ char* Self() { return mBuffer; }\r
+ int Size() { return mSize; }\r
+\r
+ TPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~TPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Used to receive (and process) a results buffer in various API calls\r
+//\r
+\r
+class RB\r
+{\r
+ char* mBuffer;\r
+ int mSize;\r
+\r
+ char* FindToken(char token);\r
+ char* FindToken(char token, char subtoken);\r
+\r
+public:\r
+ void Reset();\r
+ int GetValue(char token);\r
+ int GetCountValue(char token);\r
+ int GetValue(char token, char subtoken);\r
+ bool GetBool(char token);\r
+ int GetString(char token, std::string& data);\r
+\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ RB();\r
+ RB(int Size);\r
+ ~RB();\r
+};\r
+\r
+//\r
+// Used to receive status info from API calls\r
+//\r
+\r
+class IBS\r
+{\r
+ mutable ISC_STATUS mVector[20];\r
+ mutable std::string mMessage;\r
+\r
+public:\r
+ ISC_STATUS* Self() { return mVector; }\r
+ bool Errors() { return (mVector[0] == 1 && mVector[1] > 0) ? true : false; }\r
+ const char* ErrorMessage() const;\r
+ int SqlCode() const;\r
+ int EngineCode() const { return (mVector[0] == 1) ? (int)mVector[1] : 0; }\r
+ void Reset();\r
+\r
+ IBS();\r
+ IBS(IBS&); // Copy Constructor\r
+ ~IBS();\r
+};\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Implementation of the "hidden" classes associated with their public\r
+// counterparts. Their private data and methods can freely change without\r
+// breaking the compatibility of the DLL. If they receive new public methods,\r
+// and those methods are reflected in the public class, then the compatibility\r
+// is broken.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+//\r
+// Hidden implementation of Exception classes.\r
+//\r
+\r
+/*\r
+ std::exception\r
+ |\r
+ IBPP::Exception\r
+ / \\r
+ / \\r
+ IBPP::LogicException ExceptionBase IBPP::SQLException\r
+ | \ / | \ /\r
+ | LogicExceptionImpl | SQLExceptionImpl\r
+ | |\r
+ IBPP::WrongType |\r
+ \ |\r
+ IBPP::WrongTypeImpl\r
+*/\r
+\r
+class ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+protected:\r
+ std::string mContext; // Exception context ("IDatabase::Drop")\r
+ std::string mWhat; // Full formatted message\r
+\r
+ void buildErrorMessage(const char* message);\r
+ void raise(const std::string& context, const char* message, va_list argptr);\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ ExceptionBase() throw();\r
+ ExceptionBase(const ExceptionBase& copied) throw();\r
+ ExceptionBase& operator=(const ExceptionBase& copied) throw();\r
+ ExceptionBase(const std::string& context, const char* message = 0, ...) throw();\r
+\r
+ virtual ~ExceptionBase() throw();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class LogicExceptionImpl : public IBPP::LogicException, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ LogicExceptionImpl() throw();\r
+ LogicExceptionImpl(const LogicExceptionImpl& copied) throw();\r
+ LogicExceptionImpl& operator=(const LogicExceptionImpl& copied) throw();\r
+ LogicExceptionImpl(const std::string& context, const char* message = 0, ...) throw();\r
+\r
+ virtual ~LogicExceptionImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class SQLExceptionImpl : public IBPP::SQLException, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mSqlCode;\r
+ int mEngineCode;\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ SQLExceptionImpl() throw();\r
+ SQLExceptionImpl(const SQLExceptionImpl& copied) throw();\r
+ SQLExceptionImpl& operator=(const SQLExceptionImpl& copied) throw();\r
+ SQLExceptionImpl(const IBS& status, const std::string& context,\r
+ const char* message = 0, ...) throw();\r
+\r
+ virtual ~SQLExceptionImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+ virtual int SqlCode() const throw();\r
+ virtual int EngineCode() const throw();\r
+};\r
+\r
+class WrongTypeImpl : public IBPP::WrongType, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ WrongTypeImpl() throw();\r
+ WrongTypeImpl(const WrongTypeImpl& copied) throw();\r
+ WrongTypeImpl& operator=(const WrongTypeImpl& copied) throw();\r
+ WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
+ const char* message = 0, ...) throw();\r
+\r
+ virtual ~WrongTypeImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class ServiceImpl : public IBPP::IService\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+ isc_svc_handle mHandle; // InterBase API Service Handle\r
+ std::string mServerName; // Nom du serveur\r
+ std::string mUserName; // Nom de l'utilisateur\r
+ std::string mUserPassword; // Mot de passe de l'utilisateur\r
+ std::string mWaitMessage; // Progress message returned by WaitMsg()\r
+\r
+ isc_svc_handle* GetHandlePtr() { return &mHandle; }\r
+ void SetServerName(const char*);\r
+ void SetUserName(const char*);\r
+ void SetUserPassword(const char*);\r
+\r
+public:\r
+ isc_svc_handle GetHandle() { return mHandle; }\r
+\r
+ ServiceImpl(const std::string& ServerName, const std::string& UserName,\r
+ const std::string& UserPassword);\r
+ ~ServiceImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Connect();\r
+ bool Connected() { return mHandle == 0 ? false : true; }\r
+ void Disconnect();\r
+\r
+ void GetVersion(std::string& version);\r
+\r
+ void AddUser(const IBPP::User&);\r
+ void GetUser(IBPP::User&);\r
+ void GetUsers(std::vector<IBPP::User>&);\r
+ void ModifyUser(const IBPP::User&);\r
+ void RemoveUser(const std::string& username);\r
+\r
+ void SetPageBuffers(const std::string& dbfile, int buffers);\r
+ void SetSweepInterval(const std::string& dbfile, int sweep);\r
+ void SetSyncWrite(const std::string& dbfile, bool);\r
+ void SetReadOnly(const std::string& dbfile, bool);\r
+ void SetReserveSpace(const std::string& dbfile, bool);\r
+\r
+ void Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout);\r
+ void Restart(const std::string& dbfile);\r
+ void Sweep(const std::string& dbfile);\r
+ void Repair(const std::string& dbfile, IBPP::RPF flags);\r
+\r
+ void StartBackup(const std::string& dbfile, const std::string& bkfile,\r
+ IBPP::BRF flags = IBPP::BRF(0));\r
+ void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize, IBPP::BRF flags = IBPP::BRF(0));\r
+\r
+ const char* WaitMsg();\r
+ void Wait();\r
+\r
+ IBPP::IService* AddRef();\r
+ void Release();\r
+};\r
+\r
+class DatabaseImpl : public IBPP::IDatabase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+ int mRefCount; // Reference counter\r
+ isc_db_handle mHandle; // InterBase API Session Handle\r
+ std::string mServerName; // Server name\r
+ std::string mDatabaseName; // Database name (path/file)\r
+ std::string mUserName; // User name\r
+ std::string mUserPassword; // User password\r
+ std::string mRoleName; // Role used for the duration of the connection\r
+ std::string mCharSet; // Character Set used for the connection\r
+ std::string mCreateParams; // Other parameters (creation only)\r
+\r
+ int mDialect; // 1 if IB5, 1 or 3 if IB6/FB1\r
+ std::vector<TransactionImpl*> mTransactions;// Table of Transaction*\r
+ std::vector<StatementImpl*> mStatements;// Table of Statement*\r
+ std::vector<BlobImpl*> mBlobs; // Table of Blob*\r
+ std::vector<ArrayImpl*> mArrays; // Table of Array*\r
+ std::vector<EventsImpl*> mEvents; // Table of Events*\r
+\r
+public:\r
+ isc_db_handle* GetHandlePtr() { return &mHandle; }\r
+ isc_db_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl(TransactionImpl*);\r
+ void AttachStatementImpl(StatementImpl*);\r
+ void DetachStatementImpl(StatementImpl*);\r
+ void AttachBlobImpl(BlobImpl*);\r
+ void DetachBlobImpl(BlobImpl*);\r
+ void AttachArrayImpl(ArrayImpl*);\r
+ void DetachArrayImpl(ArrayImpl*);\r
+ void AttachEventsImpl(EventsImpl*);\r
+ void DetachEventsImpl(EventsImpl*);\r
+\r
+ DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
+ const std::string& UserName, const std::string& UserPassword,\r
+ const std::string& RoleName, const std::string& CharSet,\r
+ const std::string& CreateParams);\r
+ ~DatabaseImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ const char* ServerName() const { return mServerName.c_str(); }\r
+ const char* DatabaseName() const { return mDatabaseName.c_str(); }\r
+ const char* Username() const { return mUserName.c_str(); }\r
+ const char* UserPassword() const { return mUserPassword.c_str(); }\r
+ const char* RoleName() const { return mRoleName.c_str(); }\r
+ const char* CharSet() const { return mCharSet.c_str(); }\r
+ const char* CreateParams() const { return mCreateParams.c_str(); }\r
+\r
+ void Info(int* ODSMajor, int* ODSMinor,\r
+ int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
+ bool* SyncWrites, bool* Reserve);\r
+ void Statistics(int* Fetches, int* Marks, int* Reads, int* Writes);\r
+ void Counts(int* Insert, int* Update, int* Delete,\r
+ int* ReadIdx, int* ReadSeq);\r
+ void Users(std::vector<std::string>& users);\r
+ int Dialect() { return mDialect; }\r
+\r
+ void Create(int dialect);\r
+ void Connect();\r
+ bool Connected() { return mHandle == 0 ? false : true; }\r
+ void Inactivate();\r
+ void Disconnect();\r
+ void Drop();\r
+\r
+ IBPP::IDatabase* AddRef();\r
+ void Release();\r
+};\r
+\r
+class TransactionImpl : public IBPP::ITransaction\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+ isc_tr_handle mHandle; // Transaction InterBase\r
+\r
+ std::vector<DatabaseImpl*> mDatabases; // Tableau de IDatabase*\r
+ std::vector<StatementImpl*> mStatements; // Tableau de IStatement*\r
+ std::vector<BlobImpl*> mBlobs; // Tableau de IBlob*\r
+ std::vector<ArrayImpl*> mArrays; // Tableau de Array*\r
+ std::vector<TPB*> mTPBs; // Tableau de TPB\r
+\r
+ void Init(); // A usage exclusif des constructeurs\r
+\r
+public:\r
+ isc_tr_handle* GetHandlePtr() { return &mHandle; }\r
+ isc_tr_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachStatementImpl(StatementImpl*);\r
+ void DetachStatementImpl(StatementImpl*);\r
+ void AttachBlobImpl(BlobImpl*);\r
+ void DetachBlobImpl(BlobImpl*);\r
+ void AttachArrayImpl(ArrayImpl*);\r
+ void DetachArrayImpl(ArrayImpl*);\r
+ void AttachDatabaseImpl(DatabaseImpl* dbi, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ void DetachDatabaseImpl(DatabaseImpl* dbi);\r
+\r
+ TransactionImpl(DatabaseImpl* db, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ ~TransactionImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void AttachDatabase(IBPP::Database db, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ void DetachDatabase(IBPP::Database db);\r
+ void AddReservation(IBPP::Database db,\r
+ const std::string& table, IBPP::TTR tr);\r
+\r
+ void Start();\r
+ bool Started() { return mHandle == 0 ? false : true; }\r
+ void Commit();\r
+ void Rollback();\r
+ void CommitRetain();\r
+ void RollbackRetain();\r
+\r
+ IBPP::ITransaction* AddRef();\r
+ void Release();\r
+};\r
+\r
+class RowImpl : public IBPP::IRow\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+\r
+ XSQLDA* mDescrArea; // XSQLDA descriptor itself\r
+ std::vector<double> mNumerics; // Temporary storage for Numerics\r
+ std::vector<float> mFloats; // Temporary storage for Floats\r
+ std::vector<int64_t> mInt64s; // Temporary storage for 64 bits\r
+ std::vector<int32_t> mInt32s; // Temporary storage for 32 bits\r
+ std::vector<int16_t> mInt16s; // Temporary storage for 16 bits\r
+ std::vector<char> mBools; // Temporary storage for Bools\r
+ std::vector<std::string> mStrings; // Temporary storage for Strings\r
+ std::vector<bool> mUpdated; // Which columns where updated (Set()) ?\r
+\r
+ int mDialect; // Related database dialect\r
+ DatabaseImpl* mDatabase; // Related Database (important for Blobs, ...)\r
+ TransactionImpl* mTransaction; // Related Transaction (same remark)\r
+\r
+ void SetValue(int, IITYPE, const void* value, int = 0);\r
+ void* GetValue(int, IITYPE, void* = 0);\r
+\r
+public:\r
+ void Free();\r
+ short AllocatedSize() { return mDescrArea->sqln; }\r
+ void Resize(int n);\r
+ void AllocVariables();\r
+ bool MissingValues(); // Returns wether one of the mMissing[] is true\r
+ XSQLDA* Self() { return mDescrArea; }\r
+\r
+ RowImpl& operator=(const RowImpl& copied);\r
+ RowImpl(const RowImpl& copied);\r
+ RowImpl(int dialect, int size, DatabaseImpl* db, TransactionImpl* tr);\r
+ ~RowImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void SetNull(int);\r
+ void Set(int, bool);\r
+ void Set(int, const char*); // c-strings\r
+ void Set(int, const void*, int); // byte buffers\r
+ void Set(int, const std::string&);\r
+ void Set(int, int16_t);\r
+ void Set(int, int32_t);\r
+ void Set(int, int64_t);\r
+ void Set(int, float);\r
+ void Set(int, double);\r
+ void Set(int, const IBPP::Timestamp&);\r
+ void Set(int, const IBPP::Date&);\r
+ void Set(int, const IBPP::Time&);\r
+ void Set(int, const IBPP::DBKey&);\r
+ void Set(int, const IBPP::Blob&);\r
+ void Set(int, const IBPP::Array&);\r
+\r
+ bool IsNull(int);\r
+ bool Get(int, bool&);\r
+ bool Get(int, char*); // c-strings, len unchecked\r
+ bool Get(int, void*, int&); // byte buffers\r
+ bool Get(int, std::string&);\r
+ bool Get(int, int16_t&);\r
+ bool Get(int, int32_t&);\r
+ bool Get(int, int64_t&);\r
+ bool Get(int, float&);\r
+ bool Get(int, double&);\r
+ bool Get(int, IBPP::Timestamp&);\r
+ bool Get(int, IBPP::Date&);\r
+ bool Get(int, IBPP::Time&);\r
+ bool Get(int, IBPP::DBKey&);\r
+ bool Get(int, IBPP::Blob&);\r
+ bool Get(int, IBPP::Array&);\r
+\r
+ bool IsNull(const std::string&);\r
+ bool Get(const std::string&, bool&);\r
+ bool Get(const std::string&, char*); // c-strings, len unchecked\r
+ bool Get(const std::string&, void*, int&); // byte buffers\r
+ bool Get(const std::string&, std::string&);\r
+ bool Get(const std::string&, int16_t&);\r
+ bool Get(const std::string&, int32_t&);\r
+ bool Get(const std::string&, int64_t&);\r
+ bool Get(const std::string&, float&);\r
+ bool Get(const std::string&, double&);\r
+ bool Get(const std::string&, IBPP::Timestamp&);\r
+ bool Get(const std::string&, IBPP::Date&);\r
+ bool Get(const std::string&, IBPP::Time&);\r
+ bool Get(const std::string&, IBPP::DBKey&);\r
+ bool Get(const std::string&, IBPP::Blob&);\r
+ bool Get(const std::string&, IBPP::Array&);\r
+\r
+ int ColumnNum(const std::string&);\r
+ const char* ColumnName(int);\r
+ const char* ColumnAlias(int);\r
+ const char* ColumnTable(int);\r
+ IBPP::SDT ColumnType(int);\r
+ int ColumnSubtype(int);\r
+ int ColumnSize(int);\r
+ int ColumnScale(int);\r
+ int Columns();\r
+\r
+ bool ColumnUpdated(int);\r
+ bool Updated();\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IRow* Clone();\r
+ IBPP::IRow* AddRef();\r
+ void Release();\r
+};\r
+\r
+class StatementImpl : public IBPP::IStatement\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class TransactionImpl;\r
+\r
+ int mRefCount; // Reference counter\r
+ isc_stmt_handle mHandle; // Statement Handle\r
+\r
+ DatabaseImpl* mDatabase; // Attached database\r
+ TransactionImpl* mTransaction; // Attached transaction\r
+ RowImpl* mInRow;\r
+ //bool* mInMissing; // Quels paramètres n'ont pas été spécifiés\r
+ RowImpl* mOutRow;\r
+ bool mResultSetAvailable; // Executed and result set is available\r
+ bool mCursorOpened; // dsql_set_cursor_name was called\r
+ IBPP::STT mType; // Type de requète\r
+ std::string mSql; // Last SQL statement prepared or executed\r
+\r
+ // Internal Methods\r
+ void CursorFree();\r
+\r
+public:\r
+ // Properties and Attributes Access Methods\r
+ isc_stmt_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ StatementImpl(DatabaseImpl*, TransactionImpl*, const std::string&);\r
+ ~StatementImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Prepare(const std::string& sql);\r
+ void Execute(const std::string& sql);\r
+ inline void Execute() { Execute(std::string()); }\r
+ void ExecuteImmediate(const std::string&);\r
+ void CursorExecute(const std::string& cursor, const std::string& sql);\r
+ inline void CursorExecute(const std::string& cursor) { CursorExecute(cursor, std::string()); }\r
+ bool Fetch();\r
+ bool Fetch(IBPP::Row&);\r
+ int AffectedRows();\r
+ void Close(); // Free resources, attachments maintained\r
+ std::string& Sql() { return mSql; }\r
+ IBPP::STT Type() { return mType; }\r
+\r
+ void SetNull(int);\r
+ void Set(int, bool);\r
+ void Set(int, const char*); // c-strings\r
+ void Set(int, const void*, int); // byte buffers\r
+ void Set(int, const std::string&);\r
+ void Set(int, int16_t);\r
+ void Set(int, int32_t);\r
+ void Set(int, int64_t);\r
+ void Set(int, float);\r
+ void Set(int, double);\r
+ void Set(int, const IBPP::Timestamp&);\r
+ void Set(int, const IBPP::Date&);\r
+ void Set(int, const IBPP::Time&);\r
+ void Set(int, const IBPP::DBKey&);\r
+ void Set(int, const IBPP::Blob&);\r
+ void Set(int, const IBPP::Array&);\r
+\r
+ bool IsNull(int);\r
+ bool Get(int, bool*);\r
+ bool Get(int, bool&);\r
+ bool Get(int, char*); // c-strings, len unchecked\r
+ bool Get(int, void*, int&); // byte buffers\r
+ bool Get(int, std::string&);\r
+ bool Get(int, int16_t*);\r
+ bool Get(int, int16_t&);\r
+ bool Get(int, int32_t*);\r
+ bool Get(int, int32_t&);\r
+ bool Get(int, int64_t*);\r
+ bool Get(int, int64_t&);\r
+ bool Get(int, float*);\r
+ bool Get(int, float&);\r
+ bool Get(int, double*);\r
+ bool Get(int, double&);\r
+ bool Get(int, IBPP::Timestamp&);\r
+ bool Get(int, IBPP::Date&);\r
+ bool Get(int, IBPP::Time&);\r
+ bool Get(int, IBPP::DBKey&);\r
+ bool Get(int, IBPP::Blob&);\r
+ bool Get(int, IBPP::Array&);\r
+\r
+ bool IsNull(const std::string&);\r
+ bool Get(const std::string&, bool*);\r
+ bool Get(const std::string&, bool&);\r
+ bool Get(const std::string&, char*); // c-strings, len unchecked\r
+ bool Get(const std::string&, void*, int&); // byte buffers\r
+ bool Get(const std::string&, std::string&);\r
+ bool Get(const std::string&, int16_t*);\r
+ bool Get(const std::string&, int16_t&);\r
+ bool Get(const std::string&, int32_t*);\r
+ bool Get(const std::string&, int32_t&);\r
+ bool Get(const std::string&, int64_t*);\r
+ bool Get(const std::string&, int64_t&);\r
+ bool Get(const std::string&, float*);\r
+ bool Get(const std::string&, float&);\r
+ bool Get(const std::string&, double*);\r
+ bool Get(const std::string&, double&);\r
+ bool Get(const std::string&, IBPP::Timestamp&);\r
+ bool Get(const std::string&, IBPP::Date&);\r
+ bool Get(const std::string&, IBPP::Time&);\r
+ bool Get(const std::string&, IBPP::DBKey&);\r
+ bool Get(const std::string&, IBPP::Blob&);\r
+ bool Get(const std::string&, IBPP::Array&);\r
+\r
+ int ColumnNum(const std::string&);\r
+ int ColumnNumAlias(const std::string&);\r
+ const char* ColumnName(int);\r
+ const char* ColumnAlias(int);\r
+ const char* ColumnTable(int);\r
+ IBPP::SDT ColumnType(int);\r
+ int ColumnSubtype(int);\r
+ int ColumnSize(int);\r
+ int ColumnScale(int);\r
+ int Columns();\r
+\r
+ IBPP::SDT ParameterType(int);\r
+ int ParameterSubtype(int);\r
+ int ParameterSize(int);\r
+ int ParameterScale(int);\r
+ int Parameters();\r
+\r
+ void Plan(std::string&);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IStatement* AddRef();\r
+ void Release();\r
+};\r
+\r
+class BlobImpl : public IBPP::IBlob\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class RowImpl;\r
+\r
+ int mRefCount;\r
+ bool mIdAssigned;\r
+ ISC_QUAD mId;\r
+ isc_blob_handle mHandle;\r
+ bool mWriteMode;\r
+ DatabaseImpl* mDatabase; // Belongs to this database\r
+ TransactionImpl* mTransaction; // Belongs to this transaction\r
+\r
+ void Init();\r
+ void SetId(ISC_QUAD*);\r
+ void GetId(ISC_QUAD*);\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ BlobImpl(const BlobImpl&);\r
+ BlobImpl(DatabaseImpl*, TransactionImpl* = 0);\r
+ ~BlobImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Create();\r
+ void Open();\r
+ void Close();\r
+ void Cancel();\r
+ int Read(void*, int size);\r
+ void Write(const void*, int size);\r
+ void Info(int* Size, int* Largest, int* Segments);\r
+\r
+ void Save(const std::string& data);\r
+ void Load(std::string& data);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IBlob* AddRef();\r
+ void Release();\r
+};\r
+\r
+class ArrayImpl : public IBPP::IArray\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class RowImpl;\r
+\r
+ int mRefCount; // Reference counter\r
+ bool mIdAssigned;\r
+ ISC_QUAD mId;\r
+ bool mDescribed;\r
+ ISC_ARRAY_DESC mDesc;\r
+ DatabaseImpl* mDatabase; // Database attachée\r
+ TransactionImpl* mTransaction; // Transaction attachée\r
+ void* mBuffer; // Buffer for native data\r
+ int mBufferSize; // Size of this buffer in bytes\r
+ int mElemCount; // Count of elements in this array\r
+ int mElemSize; // Size of an element in the buffer\r
+\r
+ void Init();\r
+ void SetId(ISC_QUAD*);\r
+ void GetId(ISC_QUAD*);\r
+ void ResetId();\r
+ void AllocArrayBuffer();\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ ArrayImpl(const ArrayImpl&);\r
+ ArrayImpl(DatabaseImpl*, TransactionImpl* = 0);\r
+ ~ArrayImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Describe(const std::string& table, const std::string& column);\r
+ void ReadTo(IBPP::ADT, void*, int);\r
+ void WriteFrom(IBPP::ADT, const void*, int);\r
+ IBPP::SDT ElementType();\r
+ int ElementSize();\r
+ int ElementScale();\r
+ int Dimensions();\r
+ void Bounds(int dim, int* low, int* high);\r
+ void SetBounds(int dim, int low, int high);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IArray* AddRef();\r
+ void Release();\r
+};\r
+\r
+//\r
+// EventBufferIterator: used in EventsImpl implementation.\r
+//\r
+\r
+template<class It>\r
+struct EventBufferIterator\r
+{\r
+ It mIt;\r
+\r
+public:\r
+ EventBufferIterator& operator++()\r
+ { mIt += 1 + static_cast<int>(*mIt) + 4; return *this; }\r
+\r
+ bool operator == (const EventBufferIterator& i) const { return i.mIt == mIt; }\r
+ bool operator != (const EventBufferIterator& i) const { return i.mIt != mIt; }\r
+\r
+#ifdef __BCPLUSPLUS__\r
+#pragma warn -8027\r
+#endif\r
+ std::string get_name() const\r
+ {\r
+ return std::string(mIt + 1, mIt + 1 + static_cast<int32_t>(*mIt));\r
+ }\r
+#ifdef __BCPLUSPLUS__\r
+#pragma warn .8027\r
+#endif\r
+\r
+ uint32_t get_count() const\r
+ {\r
+ return (*gds.Call()->m_vax_integer)\r
+ (const_cast<char*>(&*(mIt + 1 + static_cast<int>(*mIt))), 4);\r
+ }\r
+\r
+ // Those container like begin() and end() allow access to the underlying type\r
+ It begin() { return mIt; }\r
+ It end() { return mIt + 1 + static_cast<int>(*mIt) + 4; }\r
+\r
+ EventBufferIterator() {}\r
+ EventBufferIterator(It it) : mIt(it) {}\r
+};\r
+\r
+class EventsImpl : public IBPP::IEvents\r
+{\r
+ static const size_t MAXEVENTNAMELEN;\r
+ static void EventHandler(const char*, short, const char*);\r
+\r
+ typedef std::vector<IBPP::EventInterface*> ObjRefs;\r
+ ObjRefs mObjectReferences;\r
+\r
+ typedef std::vector<char> Buffer;\r
+ Buffer mEventBuffer;\r
+ Buffer mResultsBuffer;\r
+\r
+ int mRefCount; // Reference counter\r
+\r
+ DatabaseImpl* mDatabase;\r
+ ISC_LONG mId; // Firebird internal Id of these events\r
+ bool mQueued; // Has isc_que_events() been called?\r
+ bool mTrapped; // EventHandled() was called since last que_events()\r
+\r
+ void FireActions();\r
+ void Queue();\r
+ void Cancel();\r
+\r
+ EventsImpl& operator=(const EventsImpl&);\r
+ EventsImpl(const EventsImpl&);\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ \r
+ EventsImpl(DatabaseImpl* dbi);\r
+ ~EventsImpl();\r
+ \r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Add(const std::string&, IBPP::EventInterface*);\r
+ void Drop(const std::string&);\r
+ void List(std::vector<std::string>&);\r
+ void Clear(); // Drop all events\r
+ void Dispatch(); // Dispatch NON async events\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+\r
+ IBPP::IEvents* AddRef();\r
+ void Release();\r
+};\r
+\r
+void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt);\r
+void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt);\r
+\r
+void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm);\r
+void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm);\r
+\r
+void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts);\r
+void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts);\r
+\r
+struct consts // See _ibpp.cpp for initializations of these constants\r
+{\r
+ static const double dscales[19];\r
+ static const int Dec31_1899;\r
+ static const int16_t min16;\r
+ static const int16_t max16;\r
+ static const int32_t min32;\r
+ static const int32_t max32;\r
+};\r
+\r
+} // namespace ibpp_internal\r
+\r
+#endif // __INTERNAL_IBPP_H__\r
+\r
+//\r
+// Eof\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibs.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal Status class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+int IBS::SqlCode() const\r
+{\r
+ return (int)(*gds.Call()->m_sqlcode)(&mVector[0]);\r
+}\r
+\r
+const char* IBS::ErrorMessage() const\r
+{\r
+ char msg[1024];\r
+ ISC_LONG sqlcode;\r
+\r
+ if (! mMessage.empty()) return mMessage.c_str(); // If message compiled, returns it\r
+\r
+ // Compiles the message (SQL part)\r
+ std::ostringstream message;\r
+ sqlcode = (*gds.Call()->m_sqlcode)(mVector);\r
+ if (sqlcode != -999)\r
+ {\r
+ (*gds.Call()->m_sql_interprete)((short)sqlcode, msg, sizeof(msg));\r
+ message<< _("SQL Message : ")<< sqlcode<< "\n"<< msg<< "\n\n";\r
+ }\r
+\r
+ message<< _("Engine Code : ")<< EngineCode()<< "\n";\r
+\r
+ // Compiles the message (Engine part)\r
+ ISC_STATUS* error = &mVector[0];\r
+ try { (*gds.Call()->m_interprete)(msg, &error); }\r
+ catch(...) { msg[0] = '\0'; }\r
+ message<< _("Engine Message :")<< "\n"<< msg;\r
+ try\r
+ {\r
+ while ((*gds.Call()->m_interprete)(msg, &error))\r
+ message<< "\n"<< msg;\r
+ }\r
+ catch (...) { }\r
+\r
+ message<< "\n";\r
+ mMessage = message.str();\r
+ return mMessage.c_str();\r
+}\r
+\r
+void IBS::Reset()\r
+{\r
+ for (int i = 0; i < 20; i++) mVector[i] = 0;\r
+ mMessage.erase();\r
+}\r
+\r
+IBS::IBS()\r
+{\r
+ Reset();\r
+}\r
+\r
+IBS::~IBS()\r
+{\r
+}\r
+\r
+/** Copy Constructor\r
+*/\r
+\r
+IBS::IBS(IBS& copied)\r
+{\r
+ memcpy(mVector, copied.mVector, sizeof(mVector));\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _rb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal RB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * RB == Result Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+char* RB::FindToken(char token)\r
+{\r
+ char* p = mBuffer;\r
+\r
+ while (*p != isc_info_end)\r
+ {\r
+ int len;\r
+\r
+ if (*p == token) return p;\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+char* RB::FindToken(char token, char subtoken)\r
+{\r
+ char* p = mBuffer;\r
+\r
+ while (*p != isc_info_end)\r
+ {\r
+ int len;\r
+\r
+ if (*p == token)\r
+ {\r
+ // Found token, now find subtoken\r
+ int inlen = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += 3;\r
+ while (inlen > 0)\r
+ {\r
+ if (*p == subtoken) return p;\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ inlen -= (len + 3);\r
+ }\r
+ return 0;\r
+ }\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int RB::GetValue(char token)\r
+{\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetValue", _("Token not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ if (len == 0) value = 0;\r
+ else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
+\r
+ return value;\r
+}\r
+\r
+int RB::GetCountValue(char token)\r
+{\r
+ // Specifically used on tokens like isc_info_insert_count and the like\r
+ // which return detailed counts per relation. We sum up the values.\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetCountValue", _("Token not found."));\r
+\r
+ // len is the number of bytes in the following array\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += 3;\r
+ value = 0;\r
+ while (len > 0)\r
+ {\r
+ // Each array item is 6 bytes : 2 bytes for the relation_id which\r
+ // we skip, and 4 bytes for the count value which we sum up accross\r
+ // all tables.\r
+ value += (*gds.Call()->m_vax_integer)(p+2, 4);\r
+ p += 6;\r
+ len -= 6;\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int RB::GetValue(char token, char subtoken)\r
+{\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token, subtoken);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetValue", _("Token/Subtoken not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ if (len == 0) value = 0;\r
+ else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
+\r
+ return value;\r
+}\r
+\r
+bool RB::GetBool(char token)\r
+{\r
+ int value;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetBool", _("Token not found."));\r
+\r
+ value = (*gds.Call()->m_vax_integer)(p+1, 4);\r
+\r
+ return value == 0 ? false : true;\r
+}\r
+\r
+int RB::GetString(char token, std::string& data)\r
+{\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetString", _("Token not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ data = std::string(p+3, len);\r
+ return len;\r
+}\r
+\r
+void RB::Reset()\r
+{\r
+ delete [] mBuffer;\r
+ mBuffer = new char [mSize];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::RB()\r
+{\r
+ mSize = 1024;\r
+ mBuffer = new char [1024];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::RB(int Size)\r
+{\r
+ mSize = Size;\r
+ mBuffer = new char [Size];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::~RB()\r
+{\r
+ try { delete [] mBuffer; }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _spb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal SPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * SPB == Service Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int SPB::BUFFERINCR = 128;\r
+\r
+void SPB::Grow(int needed)\r
+{\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer != 0)\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void SPB::Insert(char opcode)\r
+{\r
+ Grow(1);\r
+ mBuffer[mSize++] = opcode;\r
+}\r
+\r
+void SPB::InsertString(char type, int lenwidth, const char* data)\r
+{\r
+ int16_t len = (int16_t)strlen(data);\r
+\r
+ Grow(1 + lenwidth + len);\r
+ mBuffer[mSize++] = type;\r
+ switch (lenwidth)\r
+ {\r
+ case 1 : mBuffer[mSize] = char(len); mSize++; break;\r
+ case 2 : *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&len, 2));\r
+ mSize += 2; break;\r
+ default : throw LogicExceptionImpl("IISPB::IISPB", _("Invalid length parameter"));\r
+ }\r
+ strncpy(&mBuffer[mSize], data, len);\r
+ mSize += len;\r
+}\r
+\r
+void SPB::InsertByte(char type, char data)\r
+{\r
+ Grow(1 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = data;\r
+}\r
+\r
+void SPB::InsertQuad(char type, int32_t data)\r
+{\r
+ Grow(1 + 4);\r
+ mBuffer[mSize++] = type;\r
+ *(int32_t*)&mBuffer[mSize] = int32_t((*gds.Call()->m_vax_integer)((char*)&data, 4));\r
+ mSize += 4;\r
+}\r
+\r
+void SPB::Reset()\r
+{\r
+ if (mBuffer != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+/*\r
+void SPB::Insert(char type, short data)\r
+{\r
+ Grow(1 + 3);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(2);\r
+ *(short*)&mBuffer[mSize] = data;\r
+ mSize += 2;\r
+}\r
+\r
+void SPB::Insert(char type, bool data)\r
+{\r
+ Grow(1 + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = char(data ? 1 : 0);\r
+}\r
+*/\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _tpb.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, internal TPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * TPB == Transaction Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int TPB::BUFFERINCR = 128;\r
+\r
+void TPB::Grow(int needed)\r
+{\r
+ if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer == 0)\r
+ {\r
+ // Initial allocation, initialize the version tag\r
+ newbuffer[0] = isc_tpb_version3;\r
+ mSize = 1;\r
+ }\r
+ else\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void TPB::Insert(char item)\r
+{\r
+ Grow(1);\r
+ mBuffer[mSize++] = item;\r
+}\r
+\r
+void TPB::Insert(const std::string& data)\r
+{\r
+ int len = (int)data.length();\r
+ Grow(1 + len);\r
+ mBuffer[mSize++] = (char)len;\r
+ strncpy(&mBuffer[mSize], data.c_str(), len);\r
+ mSize += len;\r
+}\r
+\r
+void TPB::Reset()\r
+{\r
+ if (mSize != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: all_in_one.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : "All In One" source code file\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+// * This file is just an "all in one" holder for all the core source files\r
+// of IBPP. When you build a project made of each individual source code\r
+// files, please DON'T include this one.\r
+// Though if you prefer, maybe for better compiler optimizations, you can\r
+// compile all of IBPP at once by just compiling this single .cpp file,\r
+// which in turn, includes all the others. Presenting such a single\r
+// compilation unit to the compiler may help it do better optimizations.\r
+// This is just provided for convenience and is in no case required.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#include "_ibpp.cpp"\r
+#include "_dpb.cpp"\r
+#include "_ibs.cpp"\r
+#include "_rb.cpp"\r
+#include "_spb.cpp"\r
+#include "_tpb.cpp"\r
+\r
+#include "array.cpp"\r
+#include "blob.cpp"\r
+#include "database.cpp"\r
+#include "date.cpp"\r
+#include "dbkey.cpp"\r
+#include "events.cpp"\r
+#include "exception.cpp"\r
+#include "row.cpp"\r
+#include "service.cpp"\r
+#include "statement.cpp"\r
+#include "time.cpp"\r
+#include "transaction.cpp"\r
+#include "user.cpp"\r
+\r
+// Eof\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: array.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Array class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <math.h>\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void ArrayImpl::Describe(const std::string& table, const std::string& column)\r
+{\r
+ //if (mIdAssigned)\r
+ // throw LogicExceptionImpl("Array::Lookup", _("Array already in use."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::Lookup", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::Lookup", _("No Transaction is attached."));\r
+\r
+ ResetId(); // Re-use this array object if was previously assigned\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_array_lookup_bounds)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), const_cast<char*>(table.c_str()),\r
+ const_cast<char*>(column.c_str()), &mDesc);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::Lookup",\r
+ _("isc_array_lookup_bounds failed."));\r
+\r
+ AllocArrayBuffer();\r
+\r
+ mDescribed = true;\r
+}\r
+\r
+void ArrayImpl::SetBounds(int dim, int low, int high)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("No Transaction is attached."));\r
+ if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("Invalid dimension."));\r
+ if (low > high ||\r
+ low < mDesc.array_desc_bounds[dim].array_bound_lower ||\r
+ low > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
+ high > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
+ high < mDesc.array_desc_bounds[dim].array_bound_lower)\r
+ throw LogicExceptionImpl("Array::SetBounds",\r
+ _("Invalid bounds. You can only narrow the bounds."));\r
+\r
+ mDesc.array_desc_bounds[dim].array_bound_lower = short(low);\r
+ mDesc.array_desc_bounds[dim].array_bound_upper = short(high);\r
+\r
+ AllocArrayBuffer();\r
+}\r
+\r
+IBPP::SDT ArrayImpl::ElementType()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementType",\r
+ _("Array description not set."));\r
+\r
+ IBPP::SDT value;\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text : value = IBPP::sdString; break;\r
+ case blr_varying : value = IBPP::sdString; break;\r
+ case blr_cstring : value = IBPP::sdString; break;\r
+ case blr_short : value = IBPP::sdSmallint; break;\r
+ case blr_long : value = IBPP::sdInteger; break;\r
+ case blr_int64 : value = IBPP::sdLargeint; break;\r
+ case blr_float : value = IBPP::sdFloat; break;\r
+ case blr_double : value = IBPP::sdDouble; break;\r
+ case blr_timestamp : value = IBPP::sdTimestamp; break;\r
+ case blr_sql_date : value = IBPP::sdDate; break;\r
+ case blr_sql_time : value = IBPP::sdTime; break;\r
+ default : throw LogicExceptionImpl("Array::ElementType",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int ArrayImpl::ElementSize()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementSize",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_length;\r
+}\r
+\r
+int ArrayImpl::ElementScale()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementScale",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_scale;\r
+}\r
+\r
+int ArrayImpl::Dimensions()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::Dimensions",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_dimensions;\r
+}\r
+\r
+void ArrayImpl::Bounds(int dim, int* low, int* high)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Array description not set."));\r
+ if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Invalid dimension."));\r
+ if (low == 0 || high == 0)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Null reference detected."));\r
+\r
+ *low = mDesc.array_desc_bounds[dim].array_bound_lower;\r
+ *high = mDesc.array_desc_bounds[dim].array_bound_upper;\r
+}\r
+\r
+/*\r
+\r
+COMMENTS\r
+\r
+1)\r
+For an array column of type CHAR(X), the internal type returned or expected is blr_text.\r
+In such case, the byte array received or submitted to get/put_slice is formatted in\r
+elements of X bytes, which correspond to what is reported in array_desc_length.\r
+The elements are not '\0' terminated but are right-padded with spaces ' '.\r
+\r
+2)\r
+For an array column of type VARCHAR(X), the internal type is blr_varying.\r
+The underlying format is rather curious and different than what is used in XSQLDA.\r
+The element size is reported in array_desc_length as X.\r
+Yet each element of the byte array is expected to be of size X+2 (just as if we were\r
+to stuff a short in the first 2 bytes to store the length (as is done with XSQLDA).\r
+No. The string of X characters maximum has to be stored in the chunks of X+2 bytes as\r
+a zero-terminated c-string. Note that the buffer is indeed one byte too large.\r
+Internally, the API probably convert in-place in these chunks the zero-terminated string\r
+to a variable-size string with a short in front and the string data non zero-terminated\r
+behind.\r
+\r
+3)\r
+With Interbase 6.0 and Firebird 1.0 (initial april 2002 release), the int64 support is\r
+broken regarding the arrays. It is not possible to work on arrays using a datatype stored\r
+in an int64, as for instance any NUMERIC(x,0) where x is equal or greater than 10. That's\r
+a bug in the engine, not in IBPP, which has been fixed in june 2002. Engines compiled from\r
+the current Firebird CVS code as of july 2002 are okay. As will be the 1.01 Firebird version.\r
+We have no idea if this is fixed or not in Interbase 6.5 though.\r
+\r
+*/\r
+\r
+void ArrayImpl::ReadTo(IBPP::ADT adtype, void* data, int datacount)\r
+{\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Array Id not read from column."));\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("No Transaction is attached."));\r
+ if (datacount != mElemCount)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
+\r
+ IBS status;\r
+ ISC_LONG lenbuf = mBufferSize;\r
+ (*gds.Call()->m_array_get_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::ReadTo", _("isc_array_get_slice failed."));\r
+ if (lenbuf != mBufferSize)\r
+ throw SQLExceptionImpl(status, "Array::ReadTo", _("Internal buffer size discrepancy."));\r
+\r
+ // Now, convert the types and copy values to the user array...\r
+ int len;\r
+ char* src = (char*)mBuffer;\r
+ char* dst = (char*)data;\r
+\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ strncpy(dst, src, mElemSize);\r
+ dst[mElemSize] = '\0';\r
+ src += mElemSize;\r
+ dst += (mElemSize + 1);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
+ *(bool*)dst = true;\r
+ else *(bool*)dst = false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_varying :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize-2) len = mElemSize-2;\r
+ strncpy(dst, src, len);\r
+ dst[len] = '\0';\r
+ src += mElemSize;\r
+ dst += (mElemSize - 2 + 1);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
+ *(bool*)dst = true;\r
+ else *(bool*)dst = false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_short :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(short*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = *(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int*)dst = (int)*(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = (int64_t)*(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(short*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(short*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_long :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(long*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = short(*(long*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(long*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(long);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = (int64_t)*(long*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(long*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(long*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_int64 :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(int64_t*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = short(*(int64_t*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(long*)dst = (long)*(int64_t*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(long);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(int64_t*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(int64_t*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(int64_t*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_float :\r
+ if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = *(float*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ break;\r
+\r
+ case blr_double :\r
+ if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ if (mDesc.array_desc_scale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(double*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = *(double*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case blr_timestamp :\r
+ if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeTimestamp(*(IBPP::Timestamp*)dst, *(ISC_TIMESTAMP*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Timestamp);\r
+ }\r
+ break;\r
+\r
+ case blr_sql_date :\r
+ if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeDate(*(IBPP::Date*)dst, *(ISC_DATE*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Date);\r
+ }\r
+ break;\r
+\r
+ case blr_sql_time :\r
+ if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeTime(*(IBPP::Time*)dst, *(ISC_TIME*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Time);\r
+ }\r
+ break;\r
+\r
+ default :\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Unknown sql type."));\r
+ }\r
+}\r
+\r
+void ArrayImpl::WriteFrom(IBPP::ADT adtype, const void* data, int datacount)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("No Transaction is attached."));\r
+ if (datacount != mElemCount)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
+\r
+ // Read user data and convert types to the mBuffer\r
+ int len;\r
+ char* src = (char*)data;\r
+ char* dst = (char*)mBuffer;\r
+\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize) len = mElemSize;\r
+ strncpy(dst, src, len);\r
+ while (len < mElemSize) dst[len++] = ' ';\r
+ src += (mElemSize + 1);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *dst = *(bool*)src ? 'T' : 'F';\r
+ len = 1;\r
+ while (len < mElemSize) dst[len++] = ' ';\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_varying :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize-2) len = mElemSize-2;\r
+ strncpy(dst, src, len);\r
+ dst[len] = '\0';\r
+ src += (mElemSize - 2 + 1);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = (short)1;\r
+ dst[2] = *(bool*)src ? 'T' : 'F';\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_short :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = short(*(bool*)src ? 1 : 0);\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = (short)*(int*)src;\r
+ src += sizeof(int);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = (short)*(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst =\r
+ (short)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst =\r
+ (short)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_long :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(bool*)src ? 1 : 0;\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(long*)src;\r
+ src += sizeof(long);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(long*)dst = (long)*(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst =\r
+ (long)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst =\r
+ (long)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_int64 :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(bool*)src ? 1 : 0;\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(long*)src;\r
+ src += sizeof(long);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst =\r
+ (int64_t)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst =\r
+ (int64_t)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Incompatible types (blr_int64 and ADT %d)."), (int)adtype);\r
+ break;\r
+\r
+ case blr_float :\r
+ if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = *(float*)src;\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_double :\r
+ if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Incompatible types."));\r
+ if (mDesc.array_desc_scale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst =\r
+ floor(*(double*)src * multiplier + 0.5) / multiplier;\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = *(double*)src;\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case blr_timestamp :\r
+ if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeTimestamp(*(ISC_TIMESTAMP*)dst, *(IBPP::Timestamp*)src);\r
+ src += sizeof(IBPP::Timestamp);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_sql_date :\r
+ if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeDate(*(ISC_DATE*)dst, *(IBPP::Date*)src); \r
+ src += sizeof(IBPP::Date);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_sql_time :\r
+ if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeTime(*(ISC_TIME*)dst, *(IBPP::Time*)src);\r
+ src += sizeof(IBPP::Time);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ default :\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Unknown sql type."));\r
+ }\r
+\r
+ IBS status;\r
+ ISC_LONG lenbuf = mBufferSize;\r
+ (*gds.Call()->m_array_put_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::WriteFrom", _("isc_array_put_slice failed."));\r
+ if (lenbuf != mBufferSize)\r
+ throw SQLExceptionImpl(status, "Array::WriteFrom", _("Internal buffer size discrepancy."));\r
+}\r
+\r
+IBPP::Database ArrayImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Array::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction ArrayImpl::TransactionPtr() const\r
+{\r
+ if (mTransaction == 0) throw LogicExceptionImpl("Array::TransactionPtr",\r
+ _("No Transaction is attached."));\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IArray* ArrayImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void ArrayImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void ArrayImpl::Init()\r
+{\r
+ ResetId();\r
+ mDescribed = false;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+ mBuffer = 0;\r
+ mBufferSize = 0;\r
+}\r
+\r
+void ArrayImpl::SetId(ISC_QUAD* quad)\r
+{\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("ArrayImpl::SetId", _("Null Id reference detected."));\r
+\r
+ memcpy(&mId, quad, sizeof(mId));\r
+ mIdAssigned = true;\r
+}\r
+\r
+void ArrayImpl::GetId(ISC_QUAD* quad)\r
+{\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("ArrayImpl::GetId", _("Null Id reference detected."));\r
+\r
+ memcpy(quad, &mId, sizeof(mId));\r
+}\r
+\r
+void ArrayImpl::ResetId()\r
+{\r
+ memset(&mId, 0, sizeof(mId));\r
+ mIdAssigned = false;\r
+}\r
+\r
+void ArrayImpl::AllocArrayBuffer()\r
+{\r
+ // Clean previous buffer if any\r
+ if (mBuffer != 0) delete [] (char*)mBuffer;\r
+ mBuffer = 0;\r
+\r
+ // Computes total number of elements in the array or slice\r
+ mElemCount = 1;\r
+ for (int i = 0; i < mDesc.array_desc_dimensions; i++)\r
+ {\r
+ mElemCount = mElemCount *\r
+ (mDesc.array_desc_bounds[i].array_bound_upper -\r
+ mDesc.array_desc_bounds[i].array_bound_lower + 1);\r
+ }\r
+\r
+ // Allocates a buffer for this count of elements\r
+ mElemSize = mDesc.array_desc_length;\r
+ if (mDesc.array_desc_dtype == blr_varying) mElemSize += 2;\r
+ else if (mDesc.array_desc_dtype == blr_cstring) mElemSize += 1;\r
+ mBufferSize = mElemSize * mElemCount;\r
+ mBuffer = (void*) new char[mBufferSize];\r
+}\r
+\r
+void ArrayImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("Array::AttachDatabase",\r
+ _("Can't attach a 0 Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachArrayImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachArrayImpl(this);\r
+}\r
+\r
+void ArrayImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0) throw LogicExceptionImpl("Array::AttachTransaction",\r
+ _("Can't attach a 0 Transaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachArrayImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachArrayImpl(this);\r
+}\r
+\r
+void ArrayImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachArrayImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void ArrayImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ mTransaction->DetachArrayImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+ArrayImpl::ArrayImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+}\r
+\r
+ArrayImpl::~ArrayImpl()\r
+{\r
+ try { if (mTransaction != 0) mTransaction->DetachArrayImpl(this); }\r
+ catch (...) {}\r
+ try { if (mDatabase != 0) mDatabase->DetachArrayImpl(this); }\r
+ catch (...) {}\r
+ try { if (mBuffer != 0) delete [] (char*)mBuffer; }\r
+ catch (...) {}\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Blob class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void BlobImpl::Open()\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached."));\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed."));\r
+ mWriteMode = false;\r
+}\r
+\r
+void BlobImpl::Create()\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Create",\r
+ _("isc_create_blob failed."));\r
+ mIdAssigned = true;\r
+ mWriteMode = true;\r
+}\r
+\r
+void BlobImpl::Close()\r
+{\r
+ if (mHandle == 0) return; // Not opened anyway\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+void BlobImpl::Cancel()\r
+{\r
+ if (mHandle == 0) return; // Not opened anyway\r
+\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read"));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed."));\r
+ mHandle = 0;\r
+ mIdAssigned = false;\r
+}\r
+\r
+int BlobImpl::Read(void* buffer, int size)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened"));\r
+ if (mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write"));\r
+ if (size < 1 || size > (64*1024-1))\r
+ throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)"));\r
+\r
+ IBS status;\r
+ unsigned short bytesread;\r
+ ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread,\r
+ (unsigned short)size, (char*)buffer);\r
+ if (result == isc_segstr_eof) return 0; // Fin du blob\r
+ if (result != isc_segment && status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed."));\r
+ return (int)bytesread;\r
+}\r
+\r
+void BlobImpl::Write(const void* buffer, int size)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened"));\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read"));\r
+ if (size < 1 || size > (64*1024-1))\r
+ throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)"));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
+ (unsigned short)size, (char*)buffer);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed."));\r
+}\r
+\r
+void BlobImpl::Info(int* Size, int* Largest, int* Segments)\r
+{\r
+ char items[] = {isc_info_blob_total_length,\r
+ isc_info_blob_max_segment,\r
+ isc_info_blob_num_segments};\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened"));\r
+\r
+ IBS status;\r
+ RB result(100);\r
+ (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ (short)result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed."));\r
+\r
+ if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length);\r
+ if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment);\r
+ if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments);\r
+}\r
+\r
+void BlobImpl::Save(const std::string& data)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save",\r
+ _("isc_create_blob failed."));\r
+ mIdAssigned = true;\r
+ mWriteMode = true;\r
+\r
+ size_t pos = 0;\r
+ size_t len = data.size();\r
+ while (len != 0)\r
+ {\r
+ size_t blklen = (len < 32*1024-1) ? len : 32*1024-1;\r
+ status.Reset();\r
+ (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
+ (unsigned short)blklen, const_cast<char*>(data.data()+pos));\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save",\r
+ _("isc_put_segment failed."));\r
+ pos += blklen;\r
+ len -= blklen;\r
+ }\r
+ \r
+ status.Reset();\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+void BlobImpl::Load(std::string& data)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached."));\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed."));\r
+ mWriteMode = false;\r
+\r
+ size_t blklen = 32*1024-1;\r
+ data.resize(blklen);\r
+\r
+ size_t size = 0;\r
+ size_t pos = 0;\r
+ for (;;)\r
+ {\r
+ status.Reset();\r
+ unsigned short bytesread;\r
+ ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle,\r
+ &bytesread, (unsigned short)blklen,\r
+ const_cast<char*>(data.data()+pos));\r
+ if (result == isc_segstr_eof) break; // End of blob\r
+ if (result != isc_segment && status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed."));\r
+\r
+ pos += bytesread;\r
+ size += bytesread;\r
+ data.resize(size + blklen);\r
+ }\r
+ data.resize(size);\r
+ \r
+ status.Reset();\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+IBPP::Database BlobImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction BlobImpl::TransactionPtr() const\r
+{\r
+ if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr",\r
+ _("No Transaction is attached."));\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IBlob* BlobImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void BlobImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void BlobImpl::Init()\r
+{\r
+ mIdAssigned = false;\r
+ mWriteMode = false;\r
+ mHandle = 0;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+}\r
+\r
+void BlobImpl::SetId(ISC_QUAD* quad)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl."));\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected."));\r
+\r
+ memcpy(&mId, quad, sizeof(mId));\r
+ mIdAssigned = true;\r
+}\r
+\r
+void BlobImpl::GetId(ISC_QUAD* quad)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl."));\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob."));\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected."));\r
+\r
+ memcpy(quad, &mId, sizeof(mId));\r
+}\r
+\r
+void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase",\r
+ _("Can't attach a NULL Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachBlobImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachBlobImpl(this);\r
+}\r
+\r
+void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction",\r
+ _("Can't attach a NULL Transaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachBlobImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachBlobImpl(this);\r
+}\r
+\r
+void BlobImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachBlobImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void BlobImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ mTransaction->DetachBlobImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+}\r
+\r
+BlobImpl::~BlobImpl()\r
+{\r
+ try\r
+ {\r
+ if (mHandle != 0)\r
+ {\r
+ if (mWriteMode) Cancel();\r
+ else Close();\r
+ }\r
+ }\r
+ catch (...) { }\r
+ \r
+ try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); }\r
+ catch (...) { }\r
+ try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: database.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Database class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <algorithm>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void DatabaseImpl::Create(int dialect)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Database::Create", _("Database is already connected."));\r
+ if (mDatabaseName.empty())\r
+ throw LogicExceptionImpl("Database::Create", _("Unspecified database name."));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Database::Create", _("Unspecified user name."));\r
+ if (dialect != 1 && dialect != 3)\r
+ throw LogicExceptionImpl("Database::Create", _("Only dialects 1 and 3 are supported."));\r
+\r
+ // Build the SQL Create Statement\r
+ std::string create;\r
+ create.assign("CREATE DATABASE '");\r
+ if (! mServerName.empty()) create.append(mServerName).append(":");\r
+ create.append(mDatabaseName).append("' ");\r
+\r
+ create.append("USER '").append(mUserName).append("' ");\r
+ if (! mUserPassword.empty())\r
+ create.append("PASSWORD '").append(mUserPassword).append("' ");\r
+\r
+ if (! mCreateParams.empty()) create.append(mCreateParams);\r
+\r
+ // Call ExecuteImmediate to create the database\r
+ isc_tr_handle tr_handle = 0;\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_execute_immediate)(status.Self(), &mHandle, &tr_handle,\r
+ 0, const_cast<char*>(create.c_str()), short(dialect), NULL);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Create", _("isc_dsql_execute_immediate failed"));\r
+\r
+ Disconnect();\r
+}\r
+\r
+void DatabaseImpl::Connect()\r
+{\r
+ if (mHandle != 0) return; // Already connected\r
+\r
+ if (mDatabaseName.empty())\r
+ throw LogicExceptionImpl("Database::Connect", _("Unspecified database name."));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Database::Connect", _("Unspecified user name."));\r
+\r
+ // Build a DPB based on the properties\r
+ DPB dpb;\r
+ dpb.Insert(isc_dpb_user_name, mUserName.c_str());\r
+ dpb.Insert(isc_dpb_password, mUserPassword.c_str());\r
+ if (! mRoleName.empty()) dpb.Insert(isc_dpb_sql_role_name, mRoleName.c_str());\r
+ if (! mCharSet.empty()) dpb.Insert(isc_dpb_lc_ctype, mCharSet.c_str());\r
+\r
+ std::string connect;\r
+ if (! mServerName.empty())\r
+ connect.assign(mServerName).append(":");\r
+ connect.append(mDatabaseName);\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_attach_database)(status.Self(), (short)connect.size(),\r
+ const_cast<char*>(connect.c_str()), &mHandle, dpb.Size(), dpb.Self());\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Database::Connect", _("isc_attach_database failed"));\r
+ }\r
+\r
+ // Now, get ODS version information and dialect.\r
+ // If ODS major is lower of equal to 9, we reject the connection.\r
+ // If ODS major is 10 or higher, this is at least an InterBase 6.x Server\r
+ // OR FireBird 1.x Server.\r
+\r
+ char items[] = {isc_info_ods_version,\r
+ isc_info_db_SQL_dialect,\r
+ isc_info_end};\r
+ RB result(100);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Database::Connect", _("isc_database_info failed"));\r
+ }\r
+\r
+ int ODS = result.GetValue(isc_info_ods_version);\r
+ if (ODS <= 9)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect",\r
+ _("Unsupported Server : wrong ODS version (%d), at least '10' required."), ODS);\r
+ }\r
+\r
+ mDialect = result.GetValue(isc_info_db_SQL_dialect);\r
+ if (mDialect != 1 && mDialect != 3)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect", _("Dialect 1 or 3 required"));\r
+ }\r
+\r
+ // Now, verify the GDS32.DLL we are using is compatible with the server\r
+ if (ODS >= 10 && gds.Call()->mGDSVersion < 60)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect", _("GDS32.DLL version 5 against IBSERVER 6"));\r
+ }\r
+}\r
+\r
+void DatabaseImpl::Inactivate()\r
+{\r
+ if (mHandle == 0) return; // Not connected anyway\r
+\r
+ IBS status;\r
+\r
+ // Rollback any started transaction...\r
+ for (unsigned i = 0; i < mTransactions.size(); i++)\r
+ {\r
+ if (mTransactions[i]->Started())\r
+ mTransactions[i]->Rollback();\r
+ }\r
+\r
+ // Cancel all pending event traps\r
+ for (unsigned i = 0; i < mEvents.size(); i++)\r
+ mEvents[i]->Clear();\r
+\r
+ // Let's detach from all Blobs\r
+ while (mBlobs.size() > 0)\r
+ mBlobs.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Arrays\r
+ while (mArrays.size() > 0)\r
+ mArrays.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Statements\r
+ while (mStatements.size() > 0)\r
+ mStatements.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Transactions\r
+ while (mTransactions.size() > 0)\r
+ mTransactions.back()->DetachDatabaseImpl(this);\r
+\r
+ // Let's detach from all Events\r
+ while (mEvents.size() > 0)\r
+ mEvents.back()->DetachDatabaseImpl();\r
+}\r
+\r
+void DatabaseImpl::Disconnect()\r
+{\r
+ if (mHandle == 0) return; // Not connected anyway\r
+\r
+ // Put the connection to rest\r
+ Inactivate();\r
+\r
+ // Detach from the server\r
+ IBS status;\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+\r
+ // Should we throw, set mHandle to 0 first, because Disconnect() may\r
+ // be called from Database destructor (keeps the object coherent).\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Disconnect", _("isc_detach_database failed"));\r
+}\r
+\r
+void DatabaseImpl::Drop()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Drop", _("Database must be connected."));\r
+\r
+ // Put the connection to a rest\r
+ Inactivate();\r
+\r
+ IBS vector;\r
+ (*gds.Call()->m_drop_database)(vector.Self(), &mHandle);\r
+ if (vector.Errors())\r
+ throw SQLExceptionImpl(vector, "Database::Drop", _("isc_drop_database failed"));\r
+\r
+ mHandle = 0;\r
+}\r
+\r
+void DatabaseImpl::Info(int* ODSMajor, int* ODSMinor,\r
+ int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
+ bool* Sync, bool* Reserve)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Info", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_ods_version,\r
+ isc_info_ods_minor_version,\r
+ isc_info_page_size,\r
+ isc_info_allocation,\r
+ isc_info_num_buffers,\r
+ isc_info_sweep_interval,\r
+ isc_info_forced_writes,\r
+ isc_info_no_reserve,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(256);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Info", _("isc_database_info failed"));\r
+\r
+ if (ODSMajor != 0) *ODSMajor = result.GetValue(isc_info_ods_version);\r
+ if (ODSMinor != 0) *ODSMinor = result.GetValue(isc_info_ods_minor_version);\r
+ if (PageSize != 0) *PageSize = result.GetValue(isc_info_page_size);\r
+ if (Pages != 0) *Pages = result.GetValue(isc_info_allocation);\r
+ if (Buffers != 0) *Buffers = result.GetValue(isc_info_num_buffers);\r
+ if (Sweep != 0) *Sweep = result.GetValue(isc_info_sweep_interval);\r
+ if (Sync != 0)\r
+ *Sync = result.GetValue(isc_info_forced_writes) == 1 ? true : false;\r
+ if (Reserve != 0)\r
+ *Reserve = result.GetValue(isc_info_no_reserve) == 1 ? false : true;\r
+}\r
+\r
+void DatabaseImpl::Statistics(int* Fetches, int* Marks, int* Reads, int* Writes)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Statistics", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_fetches,\r
+ isc_info_marks,\r
+ isc_info_reads,\r
+ isc_info_writes,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(128);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Statistics", _("isc_database_info failed"));\r
+\r
+ if (Fetches != 0) *Fetches = result.GetValue(isc_info_fetches);\r
+ if (Marks != 0) *Marks = result.GetValue(isc_info_marks);\r
+ if (Reads != 0) *Reads = result.GetValue(isc_info_reads);\r
+ if (Writes != 0) *Writes = result.GetValue(isc_info_writes);\r
+}\r
+\r
+void DatabaseImpl::Counts(int* Insert, int* Update, int* Delete, \r
+ int* ReadIdx, int* ReadSeq)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Counts", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_insert_count,\r
+ isc_info_update_count,\r
+ isc_info_delete_count,\r
+ isc_info_read_idx_count,\r
+ isc_info_read_seq_count,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(1024);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Counts", _("isc_database_info failed"));\r
+\r
+ if (Insert != 0) *Insert = result.GetCountValue(isc_info_insert_count);\r
+ if (Update != 0) *Update = result.GetCountValue(isc_info_update_count);\r
+ if (Delete != 0) *Delete = result.GetCountValue(isc_info_delete_count);\r
+ if (ReadIdx != 0) *ReadIdx = result.GetCountValue(isc_info_read_idx_count);\r
+ if (ReadSeq != 0) *ReadSeq = result.GetCountValue(isc_info_read_seq_count);\r
+}\r
+\r
+void DatabaseImpl::Users(std::vector<std::string>& users)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Users", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_user_names,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(8000);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ {\r
+ status.Reset();\r
+ throw SQLExceptionImpl(status, "Database::Users", _("isc_database_info failed"));\r
+ }\r
+\r
+ users.clear();\r
+ char* p = result.Self();\r
+ while (*p == isc_info_user_names)\r
+ {\r
+ p += 3; // Get to the length byte (there are two undocumented bytes which we skip)\r
+ int len = (int)(*p);\r
+ ++p; // Get to the first char of username\r
+ if (len != 0) users.push_back(std::string().append(p, len));\r
+ p += len; // Skip username\r
+ }\r
+ return;\r
+}\r
+\r
+IBPP::IDatabase* DatabaseImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void DatabaseImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void DatabaseImpl::AttachTransactionImpl(TransactionImpl* tr)\r
+{\r
+ if (tr == 0)\r
+ throw LogicExceptionImpl("Database::AttachTransaction",\r
+ _("Transaction object is null."));\r
+\r
+ mTransactions.push_back(tr);\r
+}\r
+\r
+void DatabaseImpl::DetachTransactionImpl(TransactionImpl* tr)\r
+{\r
+ if (tr == 0)\r
+ throw LogicExceptionImpl("Database::DetachTransaction",\r
+ _("ITransaction object is null."));\r
+\r
+ mTransactions.erase(std::find(mTransactions.begin(), mTransactions.end(), tr));\r
+}\r
+\r
+void DatabaseImpl::AttachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Database::AttachStatement",\r
+ _("Can't attach a null Statement object."));\r
+\r
+ mStatements.push_back(st);\r
+}\r
+\r
+void DatabaseImpl::DetachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Database::DetachStatement",\r
+ _("Can't detach a null Statement object."));\r
+\r
+ mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
+}\r
+\r
+void DatabaseImpl::AttachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Database::AttachBlob",\r
+ _("Can't attach a null Blob object."));\r
+\r
+ mBlobs.push_back(bb);\r
+}\r
+\r
+void DatabaseImpl::DetachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Database::DetachBlob",\r
+ _("Can't detach a null Blob object."));\r
+\r
+ mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
+}\r
+\r
+void DatabaseImpl::AttachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Database::AttachArray",\r
+ _("Can't attach a null Array object."));\r
+\r
+ mArrays.push_back(ar);\r
+}\r
+\r
+void DatabaseImpl::DetachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Database::DetachArray",\r
+ _("Can't detach a null Array object."));\r
+\r
+ mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
+}\r
+\r
+void DatabaseImpl::AttachEventsImpl(EventsImpl* ev)\r
+{\r
+ if (ev == 0)\r
+ throw LogicExceptionImpl("Database::AttachEventsImpl",\r
+ _("Can't attach a null Events object."));\r
+\r
+ mEvents.push_back(ev);\r
+}\r
+\r
+void DatabaseImpl::DetachEventsImpl(EventsImpl* ev)\r
+{\r
+ if (ev == 0)\r
+ throw LogicExceptionImpl("Database::DetachEventsImpl",\r
+ _("Can't detach a null Events object."));\r
+\r
+ mEvents.erase(std::find(mEvents.begin(), mEvents.end(), ev));\r
+}\r
+\r
+DatabaseImpl::DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
+ const std::string& UserName, const std::string& UserPassword,\r
+ const std::string& RoleName, const std::string& CharSet,\r
+ const std::string& CreateParams) :\r
+\r
+ mRefCount(0), mHandle(0),\r
+ mServerName(ServerName), mDatabaseName(DatabaseName),\r
+ mUserName(UserName), mUserPassword(UserPassword), mRoleName(RoleName),\r
+ mCharSet(CharSet), mCreateParams(CreateParams),\r
+ mDialect(3)\r
+{\r
+}\r
+\r
+DatabaseImpl::~DatabaseImpl()\r
+{\r
+ try { if (Connected()) Disconnect(); }\r
+ catch(...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: date.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Date class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
+\r
+using namespace ibpp_internals;\r
+\r
+void IBPP::Date::Today()\r
+{\r
+ time_t systime = time(0);\r
+ tm* loctime = localtime(&systime);\r
+\r
+ if (! IBPP::itod(&mDate, loctime->tm_year + 1900,\r
+ loctime->tm_mon + 1, loctime->tm_mday))\r
+ throw LogicExceptionImpl("Date::Today", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::SetDate(int dt)\r
+{\r
+ if (! IBPP::dtoi(dt, 0, 0, 0))\r
+ throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
+ mDate = dt;\r
+}\r
+\r
+void IBPP::Date::SetDate(int year, int month, int day)\r
+{\r
+ if (! IBPP::itod(&mDate, year, month, day))\r
+ throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::GetDate(int& year, int& month, int& day) const\r
+{\r
+ if (! IBPP::dtoi(mDate, &year, &month, &day))\r
+ throw LogicExceptionImpl("Date::GetDate", _("Out of range"));\r
+}\r
+\r
+int IBPP::Date::Year() const\r
+{\r
+ int year;\r
+ if (! IBPP::dtoi(mDate, &year, 0, 0))\r
+ throw LogicExceptionImpl("Date::Year", _("Out of range"));\r
+ return year;\r
+}\r
+\r
+int IBPP::Date::Month() const\r
+{\r
+ int month;\r
+ if (! IBPP::dtoi(mDate, 0, &month, 0))\r
+ throw LogicExceptionImpl("Date::Month", _("Out of range"));\r
+ return month;\r
+}\r
+\r
+int IBPP::Date::Day() const\r
+{\r
+ int day;\r
+ if (! IBPP::dtoi(mDate, 0, 0, &day))\r
+ throw LogicExceptionImpl("Date::Day", _("Out of range"));\r
+ return day;\r
+}\r
+\r
+void IBPP::Date::Add(int days)\r
+{\r
+ int newdate = mDate + days; // days can be signed\r
+ if (! IBPP::dtoi(newdate, 0, 0, 0))\r
+ throw LogicExceptionImpl("Date::Add()", _("Out of range"));\r
+ mDate = newdate;\r
+}\r
+\r
+void IBPP::Date::StartOfMonth()\r
+{\r
+ int year, month;\r
+ if (! IBPP::dtoi(mDate, &year, &month, 0))\r
+ throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
+ if (! IBPP::itod(&mDate, year, month, 1)) // First of same month\r
+ throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::EndOfMonth()\r
+{\r
+ int year, month;\r
+ if (! IBPP::dtoi(mDate, &year, &month, 0))\r
+ throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
+ if (++month > 12) { month = 1; year++; }\r
+ if (! IBPP::itod(&mDate, year, month, 1)) // First of next month\r
+ throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
+ mDate--; // Last day of original month, all weird cases accounted for\r
+}\r
+\r
+IBPP::Date::Date(int year, int month, int day)\r
+{\r
+ SetDate(year, month, day);\r
+}\r
+\r
+IBPP::Date::Date(const IBPP::Date& copied)\r
+{\r
+ mDate = copied.mDate;\r
+}\r
+\r
+IBPP::Date& IBPP::Date::operator=(const IBPP::Timestamp& assigned)\r
+{\r
+ mDate = assigned.GetDate();\r
+ return *this;\r
+}\r
+\r
+IBPP::Date& IBPP::Date::operator=(const IBPP::Date& assigned)\r
+{\r
+ mDate = assigned.mDate;\r
+ return *this;\r
+}\r
+\r
+// The following date calculations were inspired by web pages found on\r
+// Peter Baum web homepage at 'http://www.capecod.net/~pbaum/'.\r
+// His contact info is at : 'http://home.capecod.net/~pbaum/contact.htm'.\r
+// Please, understand that Peter Baum is not related to this IBPP project.\r
+// So __please__, do not contact him regarding IBPP matters.\r
+\r
+// Take a date, in its integer format as used in IBPP internals and splits\r
+// it in year (4 digits), month (1-12), day (1-31)\r
+\r
+bool IBPP::dtoi (int date, int *y, int *m, int *d)\r
+{\r
+ int RataDie, Z, H, A, B, C;\r
+ int year, month, day;\r
+\r
+ // Validity control.\r
+ if (date < IBPP::MinDate || date > IBPP::MaxDate)\r
+ return false;\r
+\r
+ // The "Rata Die" is the date specified as the number of days elapsed since\r
+ // 31 Dec of year 0. So 1 Jan 0001 is 1.\r
+\r
+ RataDie = date + ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899.\r
+\r
+ Z = RataDie + 306;\r
+ H = 100*Z - 25;\r
+ A = H/3652425;\r
+ B = A - A/4;\r
+ year = (100*B + H) / 36525;\r
+ C = B + Z - 365*year - year / 4;\r
+ month = (5*C + 456) / 153;\r
+ day = C - (153*month - 457) / 5;\r
+ if (month > 12) { year += 1; month -= 12; }\r
+\r
+ if (y != 0) *y = (int)year;\r
+ if (m != 0) *m = (int)month;\r
+ if (d != 0) *d = (int)day;\r
+\r
+ return true;\r
+}\r
+\r
+// Take a date from its components year, month, day and convert it to the\r
+// integer representation used internally in IBPP.\r
+\r
+bool IBPP::itod (int *pdate, int year, int month, int day)\r
+{\r
+ int RataDie, result;\r
+ int y, m, d;\r
+\r
+ d = day; m = month; y = year;\r
+ if (m < 3) { m += 12; y -= 1; }\r
+ RataDie = d + (153*m - 457) / 5 + 365*y + y/4 - y/100 + y/400 - 306;\r
+\r
+ result = RataDie - ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899\r
+\r
+ // Validity control\r
+ if (result < IBPP::MinDate || result > IBPP::MaxDate)\r
+ return false;\r
+\r
+ *pdate = result;\r
+ return true;\r
+}\r
+\r
+// Eof\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: dbkey.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, DBKey class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <iostream>\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// Private implementation\r
+\r
+// Public implementation\r
+\r
+void IBPP::DBKey::Clear()\r
+{\r
+ mDBKey.erase();\r
+ mString.erase();\r
+}\r
+\r
+void IBPP::DBKey::SetKey(const void* key, int size)\r
+{\r
+ if (key == 0)\r
+ throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Null DBKey reference detected."));\r
+ if (size <= 0 || ((size >> 3) << 3) != size)\r
+ throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Invalid DBKey size."));\r
+\r
+ mDBKey.assign((const char*)key, (size_t)size);\r
+ mString.erase();\r
+}\r
+\r
+void IBPP::DBKey::GetKey(void* key, int size) const\r
+{\r
+ if (mDBKey.empty())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("DBKey not assigned."));\r
+ if (key == 0)\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Null DBKey reference detected."));\r
+ if (size != (int)mDBKey.size())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Incompatible DBKey size detected."));\r
+\r
+ mDBKey.copy((char*)key, mDBKey.size());\r
+}\r
+\r
+const char* IBPP::DBKey::AsString() const\r
+{\r
+ if (mDBKey.empty())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetString", _("DBKey not assigned."));\r
+\r
+ if (mString.empty())\r
+ {\r
+ std::ostringstream hexkey;\r
+ hexkey.setf(std::ios::hex, std::ios::basefield);\r
+ hexkey.setf(std::ios::uppercase);\r
+\r
+ const uint32_t* key = reinterpret_cast<const uint32_t*>(mDBKey.data());\r
+ int n = (int)mDBKey.size() / 8;\r
+ for (int i = 0; i < n; i++)\r
+ {\r
+ if (i != 0) hexkey<< "-";\r
+ hexkey<< std::setw(4)<< key[i*2]<< ":";\r
+ hexkey<< std::setw(8)<< key[i*2+1];\r
+ }\r
+\r
+ mString = hexkey.str();\r
+ }\r
+\r
+ return mString.c_str();\r
+}\r
+\r
+IBPP::DBKey::DBKey(const DBKey& copied)\r
+{\r
+ mDBKey = copied.mDBKey;\r
+ mString = copied.mString;\r
+}\r
+\r
+IBPP::DBKey& IBPP::DBKey::operator=(const IBPP::DBKey& assigned)\r
+{\r
+ mDBKey = assigned.mDBKey;\r
+ mString = assigned.mString;\r
+ return *this;\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: events.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, internal EventsImpl class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+// SPECIAL WARNING COMMENT (by Olivier Mascia, 2000 Nov 12)\r
+// The way this source file handles events is not publicly documented, in\r
+// the ibase.h header file or in the IB 6.0 documentation. This documentation\r
+// suggests to use the API isc_event_block to construct vectors of events.\r
+// Unfortunately, this API takes a variable number of parameters to specify\r
+// the list of event names. In addition, the documentation warn on not using\r
+// more than 15 names. This is a sad limitation, partly because the maximum\r
+// number of parameters safely processed in such an API is very compiler\r
+// dependant and also because isc_event_counts() is designed to return counts\r
+// through the IB status vector which is a vector of 20 32-bits integers !\r
+// From reverse engineering of the isc_event_block() API in\r
+// source file jrd/alt.c (as available on fourceforge.net/project/InterBase as\r
+// of 2000 Nov 12), it looks like the internal format of those EPB is simple.\r
+// An EPB starts by a byte with value 1. A version identifier of some sort.\r
+// Then a small cluster is used for each event name. The cluster starts with\r
+// a byte for the length of the event name (no final '\0'). Followed by the N\r
+// characters of the name itself (no final '\0'). The cluster ends with 4 bytes\r
+// preset to 0.\r
+//\r
+// SPECIAL CREDIT (July 2004) : this is a complete re-implementation of this\r
+// class, directly based on work by Val Samko.\r
+// The whole event handling has then be completely redesigned, based on the old\r
+// EPB class to bring up the current IBPP::Events implementation.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+using namespace ibpp_internals;\r
+\r
+const size_t EventsImpl::MAXEVENTNAMELEN = 127;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void EventsImpl::Add(const std::string& eventname, IBPP::EventInterface* objref)\r
+{\r
+ if (eventname.size() == 0)\r
+ throw LogicExceptionImpl("Events::Add", _("Zero length event names not permitted"));\r
+ if (eventname.size() > MAXEVENTNAMELEN)\r
+ throw LogicExceptionImpl("Events::Add", _("Event name is too long"));\r
+ if ((mEventBuffer.size() + eventname.length() + 5) > 32766) // max signed 16 bits integer minus one\r
+ throw LogicExceptionImpl("Events::Add",\r
+ _("Can't add this event, the events list would overflow IB/FB limitation"));\r
+\r
+ Cancel();\r
+\r
+ // 1) Alloc or grow the buffers\r
+ size_t prev_buffer_size = mEventBuffer.size();\r
+ size_t needed = ((prev_buffer_size==0) ? 1 : 0) + eventname.length() + 5;\r
+ // Initial alloc will require one more byte, we need 4 more bytes for\r
+ // the count itself, and one byte for the string length prefix\r
+\r
+ mEventBuffer.resize(mEventBuffer.size() + needed);\r
+ mResultsBuffer.resize(mResultsBuffer.size() + needed);\r
+ if (prev_buffer_size == 0)\r
+ mEventBuffer[0] = mResultsBuffer[0] = 1; // First byte is a 'one'. Documentation ??\r
+\r
+ // 2) Update the buffers (append)\r
+ {\r
+ Buffer::iterator it = mEventBuffer.begin() +\r
+ ((prev_buffer_size==0) ? 1 : prev_buffer_size); // Byte after current content\r
+ *(it++) = static_cast<char>(eventname.length());\r
+ it = std::copy(eventname.begin(), eventname.end(), it);\r
+ // We initialize the counts to (uint32_t)(-1) to initialize properly, see FireActions()\r
+ *(it++) = -1; *(it++) = -1; *(it++) = -1; *it = -1;\r
+ }\r
+\r
+ // copying new event to the results buffer to keep event_buffer_ and results_buffer_ consistant,\r
+ // otherwise we might get a problem in `FireActions`\r
+ // Val Samko, val@digiways.com\r
+ std::copy(mEventBuffer.begin() + prev_buffer_size,\r
+ mEventBuffer.end(), mResultsBuffer.begin() + prev_buffer_size);\r
+\r
+ // 3) Alloc or grow the objref array and update the objref array (append)\r
+ mObjectReferences.push_back(objref);\r
+\r
+ Queue();\r
+}\r
+\r
+void EventsImpl::Drop(const std::string& eventname)\r
+{\r
+ if (eventname.size() == 0)\r
+ throw LogicExceptionImpl("EventsImpl::Drop", _("Zero length event names not permitted"));\r
+ if (eventname.size() > MAXEVENTNAMELEN)\r
+ throw LogicExceptionImpl("EventsImpl::Drop", _("Event name is too long"));\r
+\r
+ if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
+\r
+ Cancel();\r
+\r
+ // 1) Find the event in the buffers\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+ EventIterator rit(mResultsBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit, ++rit)\r
+ {\r
+ if (eventname != eit.get_name()) continue;\r
+ \r
+ // 2) Event found, remove it\r
+ mEventBuffer.erase(eit.begin(), eit.end());\r
+ mResultsBuffer.erase(rit.begin(), rit.end());\r
+ mObjectReferences.erase(oit);\r
+ break;\r
+ }\r
+\r
+ Queue();\r
+}\r
+\r
+void EventsImpl::List(std::vector<std::string>& events)\r
+{\r
+ events.clear();\r
+ \r
+ if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
+\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit)\r
+ {\r
+ events.push_back(eit.get_name());\r
+ }\r
+}\r
+\r
+void EventsImpl::Clear()\r
+{\r
+ Cancel();\r
+ \r
+ mObjectReferences.clear();\r
+ mEventBuffer.clear();\r
+ mResultsBuffer.clear();\r
+}\r
+\r
+void EventsImpl::Dispatch()\r
+{\r
+ // If no events registered, nothing to do of course.\r
+ if (mEventBuffer.size() == 0) return;\r
+\r
+ // Let's fire the events actions for all the events which triggered, if any, and requeue.\r
+ FireActions();\r
+ Queue();\r
+}\r
+\r
+IBPP::Database EventsImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Events::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::IEvents* EventsImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void EventsImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void EventsImpl::Queue()\r
+{\r
+ if (! mQueued)\r
+ {\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("EventsImpl::Queue",\r
+ _("Database is not connected"));\r
+\r
+ IBS vector;\r
+ mTrapped = false;\r
+ mQueued = true;\r
+ (*gds.Call()->m_que_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId,\r
+ short(mEventBuffer.size()), &mEventBuffer[0],\r
+ (isc_callback)EventHandler, (char*)this);\r
+\r
+ if (vector.Errors())\r
+ {\r
+ mId = 0; // Should be, but better be safe\r
+ mQueued = false;\r
+ throw SQLExceptionImpl(vector, "EventsImpl::Queue",\r
+ _("isc_que_events failed"));\r
+ }\r
+ }\r
+}\r
+\r
+void EventsImpl::Cancel()\r
+{\r
+ if (mQueued)\r
+ {\r
+ if (mDatabase->GetHandle() == 0) throw LogicExceptionImpl("EventsImpl::Cancel",\r
+ _("Database is not connected"));\r
+\r
+ IBS vector;\r
+\r
+ // A call to cancel_events will call *once* the handler routine, even\r
+ // though no events had fired. This is why we first set mEventsQueued\r
+ // to false, so that we can be sure to dismiss those unwanted callbacks\r
+ // subsequent to the execution of isc_cancel_events().\r
+ mTrapped = false;\r
+ mQueued = false;\r
+ (*gds.Call()->m_cancel_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId);\r
+\r
+ if (vector.Errors())\r
+ {\r
+ mQueued = true; // Need to restore this as cancel failed\r
+ throw SQLExceptionImpl(vector, "EventsImpl::Cancel",\r
+ _("isc_cancel_events failed"));\r
+ }\r
+\r
+ mId = 0; // Should be, but better be safe\r
+ }\r
+}\r
+\r
+void EventsImpl::FireActions()\r
+{\r
+ if (mTrapped)\r
+ {\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+ EventIterator rit(mResultsBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit, ++rit)\r
+ {\r
+ if (eit == EventIterator(mEventBuffer.end())\r
+ || rit == EventIterator(mResultsBuffer.end()))\r
+ throw LogicExceptionImpl("EventsImpl::FireActions", _("Internal buffer size error"));\r
+ uint32_t vnew = rit.get_count();\r
+ uint32_t vold = eit.get_count();\r
+ if (vnew > vold)\r
+ {\r
+ // Fire the action\r
+ try\r
+ {\r
+ (*oit)->ibppEventHandler(this, eit.get_name(), (int)(vnew - vold));\r
+ }\r
+ catch (...)\r
+ {\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ throw;\r
+ }\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ }\r
+ // This handles initialization too, where vold == (uint32_t)(-1)\r
+ // Thanks to M. Hieke for this idea and related initialization to (-1)\r
+ if (vnew != vold)\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ }\r
+ }\r
+}\r
+\r
+// This function must keep this prototype to stay compatible with\r
+// what isc_que_events() expects\r
+\r
+void EventsImpl::EventHandler(const char* object, short size, const char* tmpbuffer)\r
+{\r
+ // >>>>> This method is a STATIC member !! <<<<<\r
+ // Consider this method as a kind of "interrupt handler". It should do as\r
+ // few work as possible as quickly as possible and then return.\r
+ // Never forget: this is called by the Firebird client code, on *some*\r
+ // thread which might not be (and won't probably be) any of your application\r
+ // thread. This function is to be considered as an "interrupt-handler" of a\r
+ // hardware driver.\r
+\r
+ // There can be spurious calls to EventHandler from FB internal. We must\r
+ // dismiss those calls.\r
+ if (object == 0 || size == 0 || tmpbuffer == 0) return;\r
+ \r
+ EventsImpl* evi = (EventsImpl*)object; // Ugly, but wanted, c-style cast\r
+\r
+ if (evi->mQueued)\r
+ {\r
+ try\r
+ {\r
+ char* rb = &evi->mResultsBuffer[0];\r
+ if (evi->mEventBuffer.size() < (unsigned)size) size = (short)evi->mEventBuffer.size();\r
+ for (int i = 0; i < size; i++)\r
+ rb[i] = tmpbuffer[i];\r
+ evi->mTrapped = true;\r
+ evi->mQueued = false;\r
+ }\r
+ catch (...) { }\r
+ }\r
+}\r
+\r
+void EventsImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("EventsImpl::AttachDatabase",\r
+ _("Can't attach a null Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachEventsImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachEventsImpl(this);\r
+}\r
+\r
+void EventsImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachEventsImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+EventsImpl::EventsImpl(DatabaseImpl* database)\r
+ : mRefCount(0)\r
+{\r
+ mDatabase = 0;\r
+ mId = 0;\r
+ mQueued = mTrapped = false;\r
+ AttachDatabaseImpl(database);\r
+}\r
+\r
+EventsImpl::~EventsImpl()\r
+{\r
+ try { Clear(); }\r
+ catch (...) { }\r
+ \r
+ try { if (mDatabase != 0) mDatabase->DetachEventsImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: exception.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Initialization of the library\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// None of the exception classes methods are implemented inline, because they\r
+// are all declared throw() and Borland compilers at least, but possibly some\r
+// others emit a warning like "W8026 - functions with exception specification\r
+// are not expanded inline". Nothing we have to worry about, but we don't want\r
+// people concerned by such warnings.\r
+\r
+IBPP::Exception::~Exception() throw()\r
+{\r
+}\r
+\r
+IBPP::LogicException::~LogicException() throw()\r
+{\r
+}\r
+\r
+IBPP::SQLException::~SQLException() throw()\r
+{\r
+}\r
+\r
+IBPP::WrongType::~WrongType() throw()\r
+{\r
+}\r
+\r
+//\r
+// (((((((( ExceptionBase Implementation ))))))))\r
+//\r
+\r
+void ExceptionBase::buildErrorMessage(const char* message)\r
+{\r
+ if (! mContext.empty())\r
+ mWhat.append(_("Context: ")).append(mContext).append("\n");\r
+\r
+ if (message != 0 && *message != 0 )\r
+ mWhat.append(_("Message: ")).append(message).append("\n");\r
+ \r
+ mWhat.append("\n");\r
+}\r
+\r
+void ExceptionBase::raise(const std::string& context, const char* message, va_list argptr)\r
+{\r
+ mContext.assign(context);\r
+\r
+ if (message != 0)\r
+ {\r
+ char buffer[1024];\r
+#if defined(_MSC_VER) || defined(__DMC__)\r
+ _vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
+#else\r
+ vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
+#endif\r
+ buffer[sizeof(buffer)-1] = 0;\r
+ \r
+ buildErrorMessage(buffer);\r
+ }\r
+ else\r
+ buildErrorMessage(0);\r
+}\r
+\r
+ExceptionBase::ExceptionBase() throw()\r
+{\r
+}\r
+\r
+ExceptionBase::ExceptionBase(const ExceptionBase& copied) throw()\r
+{\r
+ mContext = copied.mContext;\r
+ mWhat = copied.mWhat;\r
+}\r
+\r
+ExceptionBase& ExceptionBase::operator=(const ExceptionBase& copied) throw()\r
+{\r
+ mContext = copied.mContext;\r
+ mWhat = copied.mWhat;\r
+ return *this;\r
+}\r
+\r
+ExceptionBase::ExceptionBase(const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::Exception ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+}\r
+\r
+ExceptionBase::~ExceptionBase() throw()\r
+{\r
+}\r
+\r
+const char* ExceptionBase::Origin() const throw()\r
+{\r
+ return mContext.c_str();\r
+}\r
+\r
+const char* ExceptionBase::ErrorMessage() const throw()\r
+{\r
+ return mWhat.c_str();\r
+}\r
+\r
+const char* ExceptionBase::what() const throw()\r
+{\r
+ return mWhat.c_str();\r
+}\r
+\r
+// (((((((( LogicExceptionImpl Implementation ))))))))\r
+\r
+// The following constructors are small and could be inlined, but for object\r
+// code compacity of the library it is much better to have them non-inlined.\r
+// The amount of code generated by compilers for a throw is well-enough.\r
+\r
+LogicExceptionImpl::LogicExceptionImpl() throw()\r
+ : ExceptionBase()\r
+{\r
+}\r
+\r
+LogicExceptionImpl::LogicExceptionImpl(const LogicExceptionImpl& copied) throw()\r
+ : IBPP::LogicException(), ExceptionBase(copied)\r
+{\r
+}\r
+\r
+LogicExceptionImpl& LogicExceptionImpl::operator=(const LogicExceptionImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ return *this;\r
+}\r
+\r
+LogicExceptionImpl::LogicExceptionImpl(const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::LogicException ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+}\r
+\r
+LogicExceptionImpl::~LogicExceptionImpl() throw ()\r
+{\r
+}\r
+\r
+const char* LogicExceptionImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* LogicExceptionImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* LogicExceptionImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+// (((((((( SQLExceptionImpl Implementation ))))))))\r
+\r
+SQLExceptionImpl::SQLExceptionImpl() throw()\r
+ : ExceptionBase(), mSqlCode(0), mEngineCode(0)\r
+{\r
+}\r
+\r
+SQLExceptionImpl::SQLExceptionImpl(const SQLExceptionImpl& copied) throw()\r
+ : IBPP::SQLException(), ExceptionBase(copied), mSqlCode(copied.mSqlCode),\r
+ mEngineCode(copied.mEngineCode)\r
+{\r
+}\r
+\r
+SQLExceptionImpl& SQLExceptionImpl::operator=(const SQLExceptionImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ mSqlCode = copied.mSqlCode;\r
+ mEngineCode = copied.mEngineCode;\r
+ return *this;\r
+}\r
+\r
+SQLExceptionImpl::SQLExceptionImpl(const IBS& status, const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::SQLException ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+ mSqlCode = status.SqlCode();\r
+ mEngineCode = status.EngineCode();\r
+ mWhat.append(status.ErrorMessage());\r
+}\r
+\r
+SQLExceptionImpl::~SQLExceptionImpl() throw ()\r
+{\r
+}\r
+\r
+const char* SQLExceptionImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* SQLExceptionImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* SQLExceptionImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+int SQLExceptionImpl::SqlCode() const throw()\r
+{\r
+ return mSqlCode;\r
+}\r
+\r
+int SQLExceptionImpl::EngineCode() const throw()\r
+{\r
+ return mEngineCode;\r
+}\r
+\r
+// (((((((( WrongTypeImpl Implementation ))))))))\r
+\r
+// The following constructors are small and could be inlined, but for object\r
+// code compacity of the library it is much better to have them non-inlined.\r
+// The amount of code generated by compilers for a throw is well-enough.\r
+\r
+WrongTypeImpl::WrongTypeImpl() throw()\r
+ : IBPP::WrongType(), ExceptionBase()\r
+{\r
+}\r
+\r
+WrongTypeImpl::WrongTypeImpl(const WrongTypeImpl& copied) throw()\r
+ : IBPP::WrongType(), ExceptionBase(copied)\r
+{\r
+}\r
+\r
+WrongTypeImpl& WrongTypeImpl::operator=(const WrongTypeImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ return *this;\r
+}\r
+\r
+WrongTypeImpl::WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::WrongType ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+\r
+ std::string info;\r
+ switch (sqlType & ~1)\r
+ {\r
+ case SQL_TEXT : info.append("CHAR"); break;\r
+ case SQL_VARYING : info.append("VARCHAR"); break;\r
+ case SQL_SHORT : info.append("SMALLINT"); break;\r
+ case SQL_LONG : info.append("INTEGER"); break;\r
+ case SQL_INT64 : info.append("BIGINT"); break;\r
+ case SQL_FLOAT : info.append("FLOAT"); break;\r
+ case SQL_DOUBLE : info.append("DOUBLE"); break;\r
+ case SQL_TIMESTAMP : info.append("TIMESTAMP"); break;\r
+ case SQL_TYPE_DATE : info.append("DATE"); break;\r
+ case SQL_TYPE_TIME : info.append("TIME"); break;\r
+ case SQL_BLOB : info.append("BLOB"); break;\r
+ case SQL_ARRAY : info.append("ARRAY"); break;\r
+ }\r
+ info.append(" ").append(_(" and ")).append(" ");\r
+ switch (varType)\r
+ {\r
+ case ivArray : info.append("Array"); break;\r
+ case ivBlob : info.append("Blob"); break;\r
+ case ivDate : info.append("Date"); break;\r
+ case ivTime : info.append("Time"); break;\r
+ case ivTimestamp : info.append("Timestamp"); break;\r
+ case ivString : info.append("std::string"); break;\r
+ case ivInt16 : info.append("int16_t"); break;\r
+ case ivInt32 : info.append("int32_t"); break;\r
+ case ivInt64 : info.append("int64_t"); break;\r
+ case ivFloat : info.append("float"); break;\r
+ case ivDouble : info.append("double"); break;\r
+ case ivBool : info.append("bool"); break;\r
+ case ivDBKey : info.append("DBKey"); break;\r
+ case ivByte : info.append("int8_t"); break;\r
+ }\r
+ mWhat.append(info).append("\n");\r
+}\r
+\r
+WrongTypeImpl::~WrongTypeImpl() throw ()\r
+{\r
+}\r
+\r
+const char* WrongTypeImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* WrongTypeImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* WrongTypeImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+/*\r
+ * MODULE: ibase.h\r
+ * DESCRIPTION: OSRI entrypoints and defines\r
+ *\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ *\r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ *\r
+ * The Original Code was created by Inprise Corporation\r
+ * and its predecessors. Portions created by Inprise Corporation are\r
+ * Copyright (C) Inprise Corporation.\r
+ *\r
+ * All Rights Reserved.\r
+ * Contributor(s): ______________________________________.\r
+ * Added TCP_NO_DELAY option for superserver on Linux\r
+ * FSG 16.03.2001\r
+ * 2001.07.28: John Bellardo: Added blr_skip\r
+ * 2001.09.18: Ann Harrison: New info codes\r
+ * 17-Oct-2001 Mike Nordell: CPU affinity\r
+ * 2001-04-16 Paul Beach: ISC_TIME_SECONDS_PRECISION_SCALE modified for HP10\r
+ * Compiler Compatibility\r
+ * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports:\r
+ * - EPSON, XENIX, MAC (MAC_AUX), Cray and OS/2\r
+ * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
+ *\r
+ * 2002.10.29 Sean Leyne - Removed support for obsolete IPX/SPX Protocol\r
+ *\r
+ */\r
+/*\r
+$Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
+ */\r
+\r
+#ifndef JRD_IBASE_H\r
+#define JRD_IBASE_H\r
+\r
+\r
+/*\r
+ *\r
+ * The contents of this file are subject to the Mozilla Public\r
+ * License Version 1.1 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy of\r
+ * the License at http://www.mozilla.org/MPL/\r
+ * Alternatively, the contents of this file may be used under the\r
+ * terms of the GNU General Public License Version 2 or later (the\r
+ * "GPL"), in which case the provisions of the GPL are applicable\r
+ * instead of those above. You may obtain a copy of the Licence at\r
+ * http://www.gnu.org/copyleft/gpl.html\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * Relevant for more details.\r
+ *\r
+ * This file was created by members of the firebird development team.\r
+ * All individual contributions remain the Copyright (C) of those\r
+ * individuals. Contributors to this file are either listed here or\r
+ * can be obtained from a CVS history command.\r
+ *\r
+ * All rights reserved.\r
+ *\r
+ * Contributor(s):\r
+ * Mike Nordel <tamlin@algonet.se>\r
+ * Mark O'Donohue <mark.odonohue@ludwig.edu.au>\r
+ *\r
+ *\r
+ * $Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
+ *\r
+ * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "OS/2" port\r
+ *\r
+ */\r
+\r
+\r
+#ifndef INCLUDE_FB_TYPES_H\r
+#define INCLUDE_FB_TYPES_H\r
+\r
+\r
+/******************************************************************/\r
+/* Define type, export and other stuff based on c/c++ and Windows */\r
+/******************************************************************/\r
+\r
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
+#ifndef __GNUC__\r
+typedef __int64 ISC_INT64;\r
+typedef unsigned __int64 ISC_UINT64;\r
+#define ISC_INT64_DEFINED\r
+#endif\r
+#define ISC_EXPORT __stdcall\r
+#define ISC_EXPORT_VARARG __cdecl\r
+#else\r
+#define ISC_EXPORT\r
+#define ISC_EXPORT_VARARG\r
+#endif\r
+\r
+/*******************************************************************/\r
+/* 64 bit Integers */\r
+/*******************************************************************/\r
+\r
+#ifdef ISC_INT64_DEFINED\r
+#undef ISC_INT64_DEFINED\r
+#else\r
+//typedef long long int ISC_INT64;\r
+//typedef unsigned long long int ISC_UINT64;\r
+typedef int64_t ISC_INT64;\r
+typedef uint64_t ISC_UINT64;\r
+#endif\r
+\r
+// Nickolay: it is easier to assume that integer is at least 32-bit.\r
+// This comes from limitation that we cannot reliably detect datatype size at\r
+// compile time in cases when we do not control compilation (public headers) \r
+// We are not going to support 16-bit platforms, right?\r
+//\r
+// Temporarly restrict new definition until ULONG clash with Windows\r
+// type is solved. Win64 port is not possible before that point.\r
+// Cannot use SIZEOF_LONG define here because we are in a public header\r
+#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
+ /* EKU: Firebird requires (S)LONG to be 32 bit */\r
+# define LONG_DEFINED\r
+ typedef int SLONG;\r
+ typedef unsigned int ULONG;\r
+#endif /* SIZEOF_LONG == 8 */\r
+\r
+\r
+\r
+/* Basic data types */\r
+\r
+\r
+#ifdef NOT_USED_OR_REPLACED\r
+typedef signed char SCHAR;\r
+#else\r
+/* TMN: TODO It seems SCHAR is used just about *everywhere* where a plain\r
+ * "char" is really intended. This currently forces us to this bad definition.\r
+ */\r
+typedef char SCHAR;\r
+#endif\r
+\r
+\r
+typedef unsigned char UCHAR;\r
+typedef short SSHORT;\r
+typedef unsigned short USHORT;\r
+\r
+\r
+#ifndef LONG_DEFINED /* 32 bit */\r
+typedef long SLONG;\r
+typedef unsigned long ULONG;\r
+#else\r
+#undef LONG_DEFINED\r
+#endif\r
+\r
+\r
+#ifndef SQUAD_DEFINED /* 64 bit */\r
+typedef struct {\r
+ SLONG high;\r
+ ULONG low;\r
+} SQUAD;\r
+#endif\r
+\r
+\r
+#ifndef DEFINED_GDS_QUAD\r
+#define DEFINED_GDS_QUAD\r
+struct GDS_QUAD_t {\r
+ SLONG gds_quad_high;\r
+ ULONG gds_quad_low;\r
+};\r
+\r
+typedef struct GDS_QUAD_t GDS_QUAD;\r
+\r
+#endif /* DEFINED_GDS_QUAD */\r
+\r
+//\r
+// TMN: some misc data types from all over the place\r
+//\r
+struct vary\r
+{\r
+ USHORT vary_length;\r
+ char vary_string[1];\r
+};\r
+// TMN: Currently we can't do this, since remote uses a different\r
+// definition of VARY than the rest of the code! :-<\r
+//typedef vary* VARY;\r
+\r
+struct lstring\r
+{\r
+ ULONG lstr_length;\r
+ ULONG lstr_allocated;\r
+ UCHAR* lstr_address;\r
+};\r
+typedef struct lstring LSTRING;\r
+\r
+\r
+typedef unsigned char BOOLEAN;\r
+typedef char TEXT; // To be expunged over time\r
+//typedef unsigned char STEXT; Signed text - not used\r
+//typedef unsigned char UTEXT; Unsigned text - not used\r
+typedef unsigned char BYTE; // Unsigned byte - common\r
+//typedef char SBYTE; Signed byte - not used\r
+typedef long ISC_STATUS;\r
+typedef long IPTR;\r
+typedef unsigned long U_IPTR;\r
+typedef void (*FPTR_VOID) ();\r
+typedef void (*FPTR_VOID_PTR) (void *);\r
+typedef int (*FPTR_INT) ();\r
+typedef int (*FPTR_INT_VOID_PTR) (void *);\r
+typedef ULONG RCRD_OFFSET;\r
+typedef USHORT FLD_LENGTH;\r
+typedef int (*lock_ast_t)(void *);\r
+\r
+typedef IPTR FB_THREAD_ID;\r
+\r
+#define ISC_STATUS_LENGTH 20\r
+typedef ISC_STATUS ISC_STATUS_ARRAY[ISC_STATUS_LENGTH];\r
+\r
+/* Number of elements in an arry */\r
+#define FB_NELEM(x) ((int)(sizeof(x) / sizeof(x[0])))\r
+#define FB_ALIGN(n,b) ((n+b-1)&~(b-1))\r
+\r
+#endif /* INCLUDE_FB_TYPES_H */\r
+\r
+#define FB_API_VER 15\r
+#define isc_version4\r
+\r
+#define ISC_TRUE 1\r
+#define ISC_FALSE 0\r
+#if !(defined __cplusplus)\r
+#define ISC__TRUE ISC_TRUE\r
+#define ISC__FALSE ISC_FALSE\r
+#endif\r
+\r
+#define ISC_FAR\r
+\r
+// It is difficult to detect 64-bit long from the redistributable header\r
+// we do not care of 16-bit platforms anymore thus we may use plain "int"\r
+// which is 32-bit on all platforms we support\r
+#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
+typedef int ISC_LONG;\r
+typedef unsigned int ISC_ULONG;\r
+#else\r
+typedef signed long ISC_LONG;\r
+typedef unsigned long ISC_ULONG;\r
+#endif\r
+\r
+typedef signed short ISC_SHORT;\r
+typedef unsigned short ISC_USHORT;\r
+\r
+typedef unsigned char ISC_UCHAR;\r
+\r
+#define DSQL_close 1\r
+#define DSQL_drop 2\r
+\r
+\r
+/********************************/\r
+/* InterBase Handle Definitions */\r
+/********************************/\r
+\r
+#ifndef JRD_Y_REF_H\r
+#define FRBRD void\r
+#endif\r
+\r
+typedef FRBRD * isc_att_handle;\r
+typedef FRBRD * isc_blob_handle;\r
+typedef FRBRD * isc_db_handle;\r
+typedef FRBRD * isc_req_handle;\r
+typedef FRBRD * isc_stmt_handle;\r
+typedef FRBRD * isc_svc_handle;\r
+typedef FRBRD * isc_tr_handle;\r
+typedef void (* isc_callback) ();\r
+typedef ISC_LONG isc_resv_handle;\r
+\r
+/*******************************************************************/\r
+/* Time & Date Support */\r
+/*******************************************************************/\r
+\r
+#ifndef ISC_TIMESTAMP_DEFINED\r
+typedef int ISC_DATE;\r
+typedef unsigned int ISC_TIME;\r
+typedef struct\r
+{\r
+ ISC_DATE timestamp_date;\r
+ ISC_TIME timestamp_time;\r
+} ISC_TIMESTAMP;\r
+#define ISC_TIMESTAMP_DEFINED\r
+#endif /* ISC_TIMESTAMP_DEFINED */\r
+\r
+#define ISC_TIME_SECONDS_PRECISION 10000L\r
+#define ISC_TIME_SECONDS_PRECISION_SCALE (-4)\r
+\r
+/*******************************************************************/\r
+/* Blob id structure */\r
+/*******************************************************************/\r
+\r
+#if !(defined __cplusplus)\r
+typedef GDS_QUAD GDS__QUAD;\r
+#endif /* !(defined __cplusplus) */\r
+\r
+typedef struct GDS_QUAD_t ISC_QUAD;\r
+\r
+#define isc_quad_high gds_quad_high\r
+#define isc_quad_low gds_quad_low\r
+\r
+typedef struct\r
+{\r
+ short array_bound_lower;\r
+ short array_bound_upper;\r
+} ISC_ARRAY_BOUND;\r
+\r
+typedef struct\r
+{\r
+ unsigned char array_desc_dtype;\r
+ char array_desc_scale;\r
+ unsigned short array_desc_length;\r
+ char array_desc_field_name[32];\r
+ char array_desc_relation_name[32];\r
+ short array_desc_dimensions;\r
+ short array_desc_flags;\r
+ ISC_ARRAY_BOUND array_desc_bounds[16];\r
+} ISC_ARRAY_DESC;\r
+\r
+typedef struct\r
+{\r
+ short blob_desc_subtype;\r
+ short blob_desc_charset;\r
+ short blob_desc_segment_size;\r
+ unsigned char blob_desc_field_name[32];\r
+ unsigned char blob_desc_relation_name[32];\r
+} ISC_BLOB_DESC;\r
+\r
+\r
+\r
+/***************************/\r
+/* Blob control structure */\r
+/***************************/\r
+\r
+typedef struct isc_blob_ctl\r
+{\r
+ ISC_STATUS (* ctl_source)(); /* Source filter */\r
+ struct isc_blob_ctl * ctl_source_handle; /* Argument to pass to source filter */\r
+ short ctl_to_sub_type; /* Target type */\r
+ short ctl_from_sub_type; /* Source type */\r
+ unsigned short ctl_buffer_length; /* Length of buffer */\r
+ unsigned short ctl_segment_length; /* Length of current segment */\r
+ unsigned short ctl_bpb_length; /* Length of blob parameter block */\r
+ char * ctl_bpb; /* Address of blob parameter block */\r
+ unsigned char * ctl_buffer; /* Address of segment buffer */\r
+ ISC_LONG ctl_max_segment; /* Length of longest segment */\r
+ ISC_LONG ctl_number_segments; /* Total number of segments */\r
+ ISC_LONG ctl_total_length; /* Total length of blob */\r
+ ISC_STATUS * ctl_status; /* Address of status vector */\r
+ long ctl_data[8]; /* Application specific data */\r
+} * ISC_BLOB_CTL;\r
+\r
+/***************************/\r
+/* Blob stream definitions */\r
+/***************************/\r
+\r
+typedef struct bstream\r
+{\r
+ isc_blob_handle bstr_blob; /* Blob handle */\r
+ char * bstr_buffer; /* Address of buffer */\r
+ char * bstr_ptr; /* Next character */\r
+ short bstr_length; /* Length of buffer */\r
+ short bstr_cnt; /* Characters in buffer */\r
+ char bstr_mode; /* (mode) ? OUTPUT : INPUT */\r
+} BSTREAM;\r
+\r
+/* Three ugly macros, one even using octal radix... sigh... */\r
+#define getb(p) (--(p)->bstr_cnt >= 0 ? *(p)->bstr_ptr++ & 0377: BLOB_get (p))\r
+#define putb(x,p) (((x) == '\n' || (!(--(p)->bstr_cnt))) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
+#define putbx(x,p) ((!(--(p)->bstr_cnt)) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
+\r
+\r
+/********************************************************************/\r
+/* CVC: Public blob interface definition held in val.h. */\r
+/* For some unknown reason, it was only documented in langRef */\r
+/* and being the structure passed by the engine to UDFs it never */\r
+/* made its way into this public definitions file. */\r
+/* Being its original name "blob", I renamed it blobcallback here. */\r
+/* I did the full definition with the proper parameters instead of */\r
+/* the weak C declaration with any number and type of parameters. */\r
+/* Since the first parameter -BLB- is unknown outside the engine, */\r
+/* it's more accurate to use void* than int* as the blob pointer */\r
+/********************************************************************/\r
+\r
+#if !defined(JRD_VAL_H) && !defined(REQUESTER)\r
+/* Blob passing structure */\r
+\r
+enum lseek_mode {blb_seek_relative = 1, blb_seek_from_tail = 2};\r
+\r
+typedef struct blobcallback {\r
+ short ( *blob_get_segment)\r
+ (void * hnd, unsigned char* buffer, ISC_USHORT buf_size, ISC_USHORT* result_len);\r
+ void *blob_handle;\r
+ ISC_LONG blob_number_segments;\r
+ ISC_LONG blob_max_segment;\r
+ ISC_LONG blob_total_length;\r
+ void ( *blob_put_segment)\r
+ (void * hnd, unsigned char* buffer, ISC_USHORT buf_size);\r
+ ISC_LONG ( *blob_lseek)\r
+ (void * hnd, ISC_USHORT mode, ISC_LONG offset);\r
+} *BLOBCALLBACK;\r
+#endif /* !defined(JRD_VAL_H) && !defined(REQUESTER) */\r
+\r
+\r
+\r
+/********************************************************************/\r
+/* CVC: Public descriptor interface held in dsc.h. */\r
+/* We need it documented to be able to recognize NULL in UDFs. */\r
+/* Being its original name "dsc", I renamed it paramdsc here. */\r
+/* Notice that I adjust to the original definition: contrary to */\r
+/* other cases, the typedef is the same struct not the pointer. */\r
+/* I included the enumeration of dsc_dtype possible values. */\r
+/* Ultimately, dsc.h should be part of the public interface. */\r
+/********************************************************************/\r
+\r
+#if !defined(JRD_DSC_H)\r
+/* This is the famous internal descriptor that UDFs can use, too. */\r
+typedef struct paramdsc {\r
+ unsigned char dsc_dtype;\r
+ signed char dsc_scale;\r
+ ISC_USHORT dsc_length;\r
+ short dsc_sub_type;\r
+ ISC_USHORT dsc_flags;\r
+ unsigned char *dsc_address;\r
+} PARAMDSC;\r
+\r
+#if !defined(JRD_VAL_H)\r
+/* This is a helper struct to work with varchars. */\r
+typedef struct paramvary {\r
+ ISC_USHORT vary_length;\r
+ unsigned char vary_string [1];\r
+} PARAMVARY;\r
+#endif /* !defined(JRD_VAL_H) */\r
+\r
+/* values for dsc_flags */\r
+/* Note: DSC_null is only reliably set for local variables\r
+ (blr_variable) */\r
+#define DSC_null 1\r
+#define DSC_no_subtype 2 /* dsc has no sub type specified */\r
+#define DSC_nullable 4 /* not stored. instead, is derived\r
+ from metadata primarily to flag\r
+ SQLDA (in DSQL) */\r
+\r
+/* Overload text typing information into the dsc_sub_type field.\r
+ See intl.h for definitions of text types */ \r
+\r
+#ifndef dsc_ttype\r
+#define dsc_ttype dsc_sub_type\r
+#endif\r
+\r
+\r
+/* Note that dtype_null actually means that we do not yet know the\r
+ dtype for this descriptor. A nice cleanup item would be to globally\r
+ change it to dtype_unknown. --chrisj 1999-02-17 */\r
+\r
+#define dtype_null 0\r
+#define dtype_text 1\r
+#define dtype_cstring 2\r
+#define dtype_varying 3\r
+\r
+#define dtype_packed 6\r
+#define dtype_byte 7\r
+#define dtype_short 8\r
+#define dtype_long 9\r
+#define dtype_quad 10\r
+#define dtype_real 11\r
+#define dtype_double 12\r
+#define dtype_d_float 13\r
+#define dtype_sql_date 14\r
+#define dtype_sql_time 15\r
+#define dtype_timestamp 16\r
+#define dtype_blob 17\r
+#define dtype_array 18\r
+#define dtype_int64 19\r
+#define DTYPE_TYPE_MAX 20\r
+#endif /* !defined(JRD_DSC_H) */\r
+\r
+\r
+/***************************/\r
+/* Dynamic SQL definitions */\r
+/***************************/\r
+\r
+/******************************/\r
+/* Declare the extended SQLDA */\r
+/******************************/\r
+\r
+#ifndef FB_SQLDA\r
+\r
+typedef struct\r
+{\r
+ short sqltype; /* datatype of field */\r
+ short sqlscale; /* scale factor */\r
+ short sqlsubtype; /* datatype subtype - BLOBs & Text types only */\r
+ short sqllen; /* length of data area */\r
+ char * sqldata; /* address of data */\r
+ short * sqlind; /* address of indicator variable */\r
+ short sqlname_length; /* length of sqlname field */\r
+ char sqlname[32]; /* name of field, name length + space for NULL */\r
+ short relname_length; /* length of relation name */\r
+ char relname[32]; /* field's relation name + space for NULL */\r
+ short ownname_length; /* length of owner name */\r
+ char ownname[32]; /* relation's owner name + space for NULL */\r
+ short aliasname_length; /* length of alias name */\r
+ char aliasname[32]; /* relation's alias name + space for NULL */\r
+} XSQLVAR;\r
+\r
+typedef struct\r
+{\r
+ short version; /* version of this XSQLDA */\r
+ char sqldaid[8]; /* XSQLDA name field */\r
+ ISC_LONG sqldabc; /* length in bytes of SQLDA */\r
+ short sqln; /* number of fields allocated */\r
+ short sqld; /* actual number of fields */\r
+ XSQLVAR sqlvar[1]; /* first field address */\r
+} XSQLDA;\r
+\r
+#define XSQLDA_LENGTH(n) (sizeof (XSQLDA) + ((n)-1) * sizeof (XSQLVAR))\r
+\r
+#define SQLDA_VERSION1 1\r
+\r
+#define SQL_DIALECT_V5 1 /* meaning is same as DIALECT_xsqlda */\r
+#define SQL_DIALECT_V6_TRANSITION 2 /* flagging anything that is delimited\r
+ by double quotes as an error and\r
+ flagging keyword DATE as an error */\r
+#define SQL_DIALECT_V6 3 /* supports SQL delimited identifier,\r
+ SQLDATE/DATE, TIME, TIMESTAMP,\r
+ CURRENT_DATE, CURRENT_TIME,\r
+ CURRENT_TIMESTAMP, and 64-bit exact\r
+ numeric type */\r
+#define SQL_DIALECT_CURRENT SQL_DIALECT_V6 /* latest IB DIALECT */\r
+\r
+\r
+#define FB_SQLDA\r
+#endif\r
+\r
+/***************************/\r
+/* OSRI database functions */\r
+/***************************/\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ISC_STATUS ISC_EXPORT isc_attach_database(ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_gen_sdl(ISC_STATUS *,\r
+ ISC_ARRAY_DESC *,\r
+ short *,\r
+ char *,\r
+ short *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_get_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_lookup_bounds(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_lookup_desc(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_set_desc(ISC_STATUS *,\r
+ char *,\r
+ char *,\r
+ short *,\r
+ short *,\r
+ short *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_put_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+void ISC_EXPORT isc_blob_default_desc(ISC_BLOB_DESC *,\r
+ unsigned char *,\r
+ unsigned char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_gen_bpb(ISC_STATUS *,\r
+ ISC_BLOB_DESC *,\r
+ ISC_BLOB_DESC *,\r
+ unsigned short,\r
+ unsigned char *,\r
+ unsigned short *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_info(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_lookup_desc(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned char *,\r
+ unsigned char *,\r
+ ISC_BLOB_DESC *,\r
+ unsigned char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_set_desc(ISC_STATUS *,\r
+ unsigned char *,\r
+ unsigned char *,\r
+ short,\r
+ short,\r
+ short,\r
+ ISC_BLOB_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_cancel_blob(ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_cancel_events(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_close_blob(ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_commit_retaining(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_commit_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_blob(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_blob2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_database(ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_database_info(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+void ISC_EXPORT isc_decode_date(ISC_QUAD *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_sql_date(ISC_DATE *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_sql_time(ISC_TIME *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_timestamp(ISC_TIMESTAMP *,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_detach_database(ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_drop_database(ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_allocate_statement(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_alloc_statement2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_describe(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_describe_bind(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_exec_immed2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_fetch(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_finish(isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_free_statement(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_insert(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_prepare(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_set_cursor_name(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ char *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_sql_info(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ short,\r
+ const char *,\r
+ short,\r
+ char *);\r
+\r
+void ISC_EXPORT isc_encode_date(void *,\r
+ ISC_QUAD *);\r
+\r
+void ISC_EXPORT isc_encode_sql_date(void *,\r
+ ISC_DATE *);\r
+\r
+void ISC_EXPORT isc_encode_sql_time(void *,\r
+ ISC_TIME *);\r
+\r
+void ISC_EXPORT isc_encode_timestamp(void *,\r
+ ISC_TIMESTAMP *);\r
+\r
+ISC_LONG ISC_EXPORT_VARARG isc_event_block(char * *,\r
+ char * *,\r
+ unsigned short, ...);\r
+\r
+void ISC_EXPORT isc_event_counts(ISC_ULONG *,\r
+ short,\r
+ char *,\r
+ char *);\r
+\r
+/* 17 May 2001 - isc_expand_dpb is DEPRECATED */\r
+void ISC_EXPORT_VARARG isc_expand_dpb(char * *,\r
+ short *, ...);\r
+\r
+int ISC_EXPORT isc_modify_dpb(char * *,\r
+ short *,\r
+ unsigned short,\r
+ char *,\r
+ short);\r
+\r
+ISC_LONG ISC_EXPORT isc_free(char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_get_segment(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_get_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *,\r
+ short,\r
+ ISC_LONG *,\r
+ ISC_LONG,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_interprete(char *,\r
+ ISC_STATUS * *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open_blob(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open_blob2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ ISC_USHORT,\r
+ ISC_UCHAR *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare_transaction2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ ISC_USHORT,\r
+ ISC_UCHAR *);\r
+\r
+void ISC_EXPORT isc_print_sqlerror(ISC_SHORT,\r
+ ISC_STATUS *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_print_status(ISC_STATUS *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_put_segment(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_put_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *,\r
+ short,\r
+ ISC_LONG *,\r
+ ISC_LONG,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_que_events(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *,\r
+ short,\r
+ char *,\r
+ isc_callback,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_rollback_retaining(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_rollback_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_multiple(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT_VARARG isc_start_transaction(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short, ...);\r
+\r
+ISC_LONG ISC_EXPORT isc_sqlcode(ISC_STATUS *);\r
+\r
+void ISC_EXPORT isc_sql_interprete(short,\r
+ char *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_transaction_info(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_transact_request(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_LONG ISC_EXPORT isc_vax_integer(char *,\r
+ short);\r
+\r
+ISC_INT64 ISC_EXPORT isc_portable_integer(unsigned char *,\r
+ short);\r
+\r
+/*************************************/\r
+/* Security Functions and structures */\r
+/*************************************/\r
+\r
+#define sec_uid_spec 0x01\r
+#define sec_gid_spec 0x02\r
+#define sec_server_spec 0x04\r
+#define sec_password_spec 0x08\r
+#define sec_group_name_spec 0x10\r
+#define sec_first_name_spec 0x20\r
+#define sec_middle_name_spec 0x40\r
+#define sec_last_name_spec 0x80\r
+#define sec_dba_user_name_spec 0x100\r
+#define sec_dba_password_spec 0x200\r
+\r
+#define sec_protocol_tcpip 1\r
+#define sec_protocol_netbeui 2\r
+#define sec_protocol_spx 3 /* -- Deprecated Protocol. Declaration retained for compatibility */\r
+#define sec_protocol_local 4\r
+\r
+typedef struct {\r
+ short sec_flags; /* which fields are specified */\r
+ int uid; /* the user's id */\r
+ int gid; /* the user's group id */\r
+ int protocol; /* protocol to use for connection */\r
+ char *server; /* server to administer */\r
+ char *user_name; /* the user's name */\r
+ char *password; /* the user's password */\r
+ char *group_name; /* the group name */\r
+ char *first_name; /* the user's first name */\r
+ char *middle_name; /* the user's middle name */\r
+ char *last_name; /* the user's last name */\r
+ char *dba_user_name; /* the dba user name */\r
+ char *dba_password; /* the dba password */\r
+} USER_SEC_DATA;\r
+\r
+int ISC_EXPORT isc_add_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+int ISC_EXPORT isc_delete_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+int ISC_EXPORT isc_modify_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+/**********************************/\r
+/* Other OSRI functions */\r
+/**********************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_compile_request(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_req_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_compile_request2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_req_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_ddl(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+\r
+ISC_STATUS ISC_EXPORT isc_receive(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_reconnect_transaction(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_release_request(ISC_STATUS *,\r
+ isc_req_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_request_info(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_seek_blob(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ ISC_LONG,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_send(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_and_send(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_request(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ isc_tr_handle *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_unwind_request(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_wait_for_event(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ char *);\r
+\r
+\r
+/*****************************/\r
+/* Other Sql functions */\r
+/*****************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_close(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_declare(ISC_STATUS *,\r
+ char *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_describe(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_describe_bind(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_execute_immediate(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_fetch(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ short *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+\r
+/*************************************/\r
+/* Other Dynamic sql functions */\r
+/*************************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute2_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate_m(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_exec_immed3_m(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_fetch_m(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_insert_m(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_prepare_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_release(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_close(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_declare(ISC_STATUS *,\r
+ char *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_describe(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_describe_bind(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute_immed(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_fetch(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_open(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_open2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_insert(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_prepare(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_release(ISC_STATUS *,\r
+ char *);\r
+\r
+\r
+/******************************/\r
+/* Other Blob functions */\r
+/******************************/\r
+\r
+BSTREAM *ISC_EXPORT BLOB_open(isc_blob_handle,\r
+ char *,\r
+ int);\r
+\r
+int ISC_EXPORT BLOB_put(char,\r
+ BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_close(BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_get(BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_display(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_dump(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_edit(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_load(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_text_dump(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_text_load(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+BSTREAM *ISC_EXPORT Bopen(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+BSTREAM *ISC_EXPORT Bopen2(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *,\r
+ unsigned short);\r
+\r
+\r
+/******************************/\r
+/* Other Misc functions */\r
+/******************************/\r
+\r
+ISC_LONG ISC_EXPORT isc_ftof(char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_print_blr(char *,\r
+ isc_callback,\r
+ void *,\r
+ short);\r
+\r
+void ISC_EXPORT isc_set_debug(int);\r
+\r
+void ISC_EXPORT isc_qtoq(ISC_QUAD *,\r
+ ISC_QUAD *);\r
+\r
+void ISC_EXPORT isc_vtof(char *,\r
+ char *,\r
+ unsigned short);\r
+\r
+void ISC_EXPORT isc_vtov(char *,\r
+ char *,\r
+ short);\r
+\r
+int ISC_EXPORT isc_version(isc_db_handle *,\r
+ isc_callback,\r
+ void *);\r
+\r
+ISC_LONG ISC_EXPORT isc_reset_fpe(unsigned short);\r
+\r
+\r
+/*****************************************/\r
+/* Service manager functions */\r
+/*****************************************/\r
+\r
+#define ADD_SPB_LENGTH(p, length) {*(p)++ = (length); *(p)++ = (length) >> 8;}\r
+\r
+#define ADD_SPB_NUMERIC(p, data) {*(p)++ = (SCHAR) (data); *(p)++ = (SCHAR) ((data) >> 8); *(p)++ = (SCHAR) ((data) >> 16); *(p)++ = (SCHAR) ((data) >> 24);}\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_attach(ISC_STATUS *,\r
+ unsigned short,\r
+ char *,\r
+ isc_svc_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_detach(ISC_STATUS *,\r
+ isc_svc_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_query(ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_start(ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+\r
+/********************************/\r
+/* Client information functions */\r
+/********************************/\r
+\r
+void ISC_EXPORT isc_get_client_version ( char *);\r
+int ISC_EXPORT isc_get_client_major_version ();\r
+int ISC_EXPORT isc_get_client_minor_version ();\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+\r
+/***************************************************/\r
+/* Actions to pass to the blob filter (ctl_source) */\r
+/***************************************************/\r
+\r
+#define isc_blob_filter_open 0\r
+#define isc_blob_filter_get_segment 1\r
+#define isc_blob_filter_close 2\r
+#define isc_blob_filter_create 3\r
+#define isc_blob_filter_put_segment 4\r
+#define isc_blob_filter_alloc 5\r
+#define isc_blob_filter_free 6\r
+#define isc_blob_filter_seek 7\r
+\r
+/*******************/\r
+/* Blr definitions */\r
+/*******************/\r
+\r
+/*\r
+ * PROGRAM: C preprocessor\r
+ * MODULE: blr.h\r
+ * DESCRIPTION: BLR constants\r
+ *\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ *\r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ *\r
+ * The Original Code was created by Inprise Corporation\r
+ * and its predecessors. Portions created by Inprise Corporation are\r
+ * Copyright (C) Inprise Corporation.\r
+ *\r
+ * All Rights Reserved.\r
+ * Contributor(s): ______________________________________.\r
+ *\r
+ * Claudio Valderrama: 2001.6.18: Add blr_current_role.\r
+ * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced\r
+ * exception handling in SPs/triggers,\r
+ * implemented ROWS_AFFECTED system variable\r
+ * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks\r
+ * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
+ */\r
+\r
+#ifndef _JRD_BLR_H_\r
+#define _JRD_BLR_H_\r
+\r
+/* WARNING: if you add a new BLR representing a data type, and the value\r
+ * is greater than the numerically greatest value which now\r
+ * represents a data type, you must change the define for\r
+ * DTYPE_BLR_MAX in jrd/align.h, and add the necessary entries\r
+ * to all the arrays in that file.\r
+ */\r
+\r
+#define blr_text (unsigned char)14\r
+#define blr_text2 (unsigned char)15 /* added in 3.2 JPN */\r
+#define blr_short (unsigned char)7\r
+#define blr_long (unsigned char)8\r
+#define blr_quad (unsigned char)9\r
+#define blr_float (unsigned char)10\r
+#define blr_double (unsigned char)27\r
+#define blr_d_float (unsigned char)11\r
+#define blr_timestamp (unsigned char)35\r
+#define blr_varying (unsigned char)37\r
+#define blr_varying2 (unsigned char)38 /* added in 3.2 JPN */\r
+#define blr_blob (unsigned short)261\r
+#define blr_cstring (unsigned char)40 \r
+#define blr_cstring2 (unsigned char)41 /* added in 3.2 JPN */\r
+#define blr_blob_id (unsigned char)45 /* added from gds.h */\r
+#define blr_sql_date (unsigned char)12\r
+#define blr_sql_time (unsigned char)13\r
+#define blr_int64 (unsigned char)16\r
+\r
+/* Historical alias for pre V6 applications */\r
+#define blr_date blr_timestamp\r
+\r
+#define blr_inner (unsigned char)0\r
+#define blr_left (unsigned char)1\r
+#define blr_right (unsigned char)2\r
+#define blr_full (unsigned char)3\r
+\r
+#define blr_gds_code (unsigned char)0\r
+#define blr_sql_code (unsigned char)1\r
+#define blr_exception (unsigned char)2\r
+#define blr_trigger_code (unsigned char)3\r
+#define blr_default_code (unsigned char)4\r
+#define blr_raise (unsigned char)5\r
+#define blr_exception_msg (unsigned char)6\r
+\r
+#define blr_version4 (unsigned char)4\r
+#define blr_version5 (unsigned char)5\r
+#define blr_eoc (unsigned char)76\r
+#define blr_end (unsigned char)255 /* note: defined as -1 in gds.h */\r
+\r
+#define blr_assignment (unsigned char)1\r
+#define blr_begin (unsigned char)2\r
+#define blr_dcl_variable (unsigned char)3 /* added from gds.h */\r
+#define blr_message (unsigned char)4\r
+#define blr_erase (unsigned char)5\r
+#define blr_fetch (unsigned char)6\r
+#define blr_for (unsigned char)7\r
+#define blr_if (unsigned char)8\r
+#define blr_loop (unsigned char)9\r
+#define blr_modify (unsigned char)10\r
+#define blr_handler (unsigned char)11\r
+#define blr_receive (unsigned char)12\r
+#define blr_select (unsigned char)13\r
+#define blr_send (unsigned char)14\r
+#define blr_store (unsigned char)15\r
+#define blr_label (unsigned char)17\r
+#define blr_leave (unsigned char)18\r
+#define blr_store2 (unsigned char)19\r
+#define blr_post (unsigned char)20\r
+#define blr_literal (unsigned char)21\r
+#define blr_dbkey (unsigned char)22\r
+#define blr_field (unsigned char)23\r
+#define blr_fid (unsigned char)24\r
+#define blr_parameter (unsigned char)25\r
+#define blr_variable (unsigned char)26\r
+#define blr_average (unsigned char)27\r
+#define blr_count (unsigned char)28\r
+#define blr_maximum (unsigned char)29\r
+#define blr_minimum (unsigned char)30\r
+#define blr_total (unsigned char)31\r
+/* count 2\r
+#define blr_count2 32\r
+*/\r
+#define blr_add (unsigned char)34\r
+#define blr_subtract (unsigned char)35\r
+#define blr_multiply (unsigned char)36\r
+#define blr_divide (unsigned char)37\r
+#define blr_negate (unsigned char)38\r
+#define blr_concatenate (unsigned char)39\r
+#define blr_substring (unsigned char)40\r
+#define blr_parameter2 (unsigned char)41\r
+#define blr_from (unsigned char)42\r
+#define blr_via (unsigned char)43\r
+#define blr_parameter2_old (unsigned char)44 /* Confusion */\r
+#define blr_user_name (unsigned char)44 /* added from gds.h */\r
+#define blr_null (unsigned char)45\r
+\r
+#define blr_eql (unsigned char)47\r
+#define blr_neq (unsigned char)48\r
+#define blr_gtr (unsigned char)49\r
+#define blr_geq (unsigned char)50\r
+#define blr_lss (unsigned char)51\r
+#define blr_leq (unsigned char)52\r
+#define blr_containing (unsigned char)53\r
+#define blr_matching (unsigned char)54\r
+#define blr_starting (unsigned char)55\r
+#define blr_between (unsigned char)56\r
+#define blr_or (unsigned char)57\r
+#define blr_and (unsigned char)58\r
+#define blr_not (unsigned char)59\r
+#define blr_any (unsigned char)60\r
+#define blr_missing (unsigned char)61\r
+#define blr_unique (unsigned char)62\r
+#define blr_like (unsigned char)63\r
+\r
+#define blr_stream (unsigned char)65 /* added from gds.h */\r
+#define blr_set_index (unsigned char)66 /* added from gds.h */\r
+\r
+#define blr_rse (unsigned char)67\r
+#define blr_first (unsigned char)68\r
+#define blr_project (unsigned char)69\r
+#define blr_sort (unsigned char)70\r
+#define blr_boolean (unsigned char)71\r
+#define blr_ascending (unsigned char)72\r
+#define blr_descending (unsigned char)73\r
+#define blr_relation (unsigned char)74\r
+#define blr_rid (unsigned char)75\r
+#define blr_union (unsigned char)76\r
+#define blr_map (unsigned char)77\r
+#define blr_group_by (unsigned char)78\r
+#define blr_aggregate (unsigned char)79\r
+#define blr_join_type (unsigned char)80\r
+\r
+#define blr_agg_count (unsigned char)83\r
+#define blr_agg_max (unsigned char)84\r
+#define blr_agg_min (unsigned char)85\r
+#define blr_agg_total (unsigned char)86\r
+#define blr_agg_average (unsigned char)87\r
+#define blr_parameter3 (unsigned char)88 /* same as Rdb definition */\r
+#define blr_run_max (unsigned char)89\r
+#define blr_run_min (unsigned char)90\r
+#define blr_run_total (unsigned char)91\r
+#define blr_run_average (unsigned char)92\r
+#define blr_agg_count2 (unsigned char)93\r
+#define blr_agg_count_distinct (unsigned char)94\r
+#define blr_agg_total_distinct (unsigned char)95\r
+#define blr_agg_average_distinct (unsigned char)96\r
+\r
+#define blr_function (unsigned char)100\r
+#define blr_gen_id (unsigned char)101\r
+#define blr_prot_mask (unsigned char)102\r
+#define blr_upcase (unsigned char)103\r
+#define blr_lock_state (unsigned char)104\r
+#define blr_value_if (unsigned char)105\r
+#define blr_matching2 (unsigned char)106\r
+#define blr_index (unsigned char)107\r
+#define blr_ansi_like (unsigned char)108\r
+#define blr_bookmark (unsigned char)109\r
+#define blr_crack (unsigned char)110\r
+#define blr_force_crack (unsigned char)111\r
+#define blr_seek (unsigned char)112\r
+#define blr_find (unsigned char)113\r
+ \r
+/* these indicate directions for blr_seek and blr_find */\r
+\r
+#define blr_continue (unsigned char)0\r
+#define blr_forward (unsigned char)1\r
+#define blr_backward (unsigned char)2\r
+#define blr_bof_forward (unsigned char)3\r
+#define blr_eof_backward (unsigned char)4\r
+\r
+#define blr_lock_relation (unsigned char)114\r
+#define blr_lock_record (unsigned char)115\r
+#define blr_set_bookmark (unsigned char)116\r
+#define blr_get_bookmark (unsigned char)117\r
+\r
+#define blr_run_count (unsigned char)118 /* changed from 88 to avoid conflict with blr_parameter3 */\r
+#define blr_rs_stream (unsigned char)119\r
+#define blr_exec_proc (unsigned char)120\r
+#define blr_begin_range (unsigned char)121\r
+#define blr_end_range (unsigned char)122\r
+#define blr_delete_range (unsigned char)123\r
+#define blr_procedure (unsigned char)124\r
+#define blr_pid (unsigned char)125\r
+#define blr_exec_pid (unsigned char)126\r
+#define blr_singular (unsigned char)127\r
+#define blr_abort (unsigned char)128\r
+#define blr_block (unsigned char)129\r
+#define blr_error_handler (unsigned char)130\r
+\r
+#define blr_cast (unsigned char)131\r
+#define blr_release_lock (unsigned char)132\r
+#define blr_release_locks (unsigned char)133\r
+#define blr_start_savepoint (unsigned char)134\r
+#define blr_end_savepoint (unsigned char)135\r
+#define blr_find_dbkey (unsigned char)136\r
+#define blr_range_relation (unsigned char)137\r
+#define blr_delete_ranges (unsigned char)138\r
+\r
+#define blr_plan (unsigned char)139 /* access plan items */\r
+#define blr_merge (unsigned char)140\r
+#define blr_join (unsigned char)141\r
+#define blr_sequential (unsigned char)142\r
+#define blr_navigational (unsigned char)143\r
+#define blr_indices (unsigned char)144\r
+#define blr_retrieve (unsigned char)145\r
+\r
+#define blr_relation2 (unsigned char)146\r
+#define blr_rid2 (unsigned char)147\r
+#define blr_reset_stream (unsigned char)148\r
+#define blr_release_bookmark (unsigned char)149\r
+\r
+#define blr_set_generator (unsigned char)150\r
+\r
+#define blr_ansi_any (unsigned char)151 /* required for NULL handling */\r
+#define blr_exists (unsigned char)152 /* required for NULL handling */\r
+#define blr_cardinality (unsigned char)153\r
+\r
+#define blr_record_version (unsigned char)154 /* get tid of record */\r
+#define blr_stall (unsigned char)155 /* fake server stall */\r
+\r
+#define blr_seek_no_warn (unsigned char)156 \r
+#define blr_find_dbkey_version (unsigned char)157 /* find dbkey with record version */\r
+#define blr_ansi_all (unsigned char)158 /* required for NULL handling */\r
+\r
+#define blr_extract (unsigned char)159\r
+\r
+/* sub parameters for blr_extract */\r
+\r
+#define blr_extract_year (unsigned char)0\r
+#define blr_extract_month (unsigned char)1\r
+#define blr_extract_day (unsigned char)2\r
+#define blr_extract_hour (unsigned char)3\r
+#define blr_extract_minute (unsigned char)4\r
+#define blr_extract_second (unsigned char)5\r
+#define blr_extract_weekday (unsigned char)6\r
+#define blr_extract_yearday (unsigned char)7\r
+\r
+#define blr_current_date (unsigned char)160\r
+#define blr_current_timestamp (unsigned char)161\r
+#define blr_current_time (unsigned char)162\r
+\r
+/* FB 1.0 specific BLR */\r
+\r
+#define blr_current_role (unsigned char)174\r
+#define blr_skip (unsigned char)175\r
+\r
+/* FB 1.5 specific BLR */\r
+\r
+#define blr_exec_sql (unsigned char)176\r
+#define blr_internal_info (unsigned char)177\r
+#define blr_nullsfirst (unsigned char)178\r
+#define blr_writelock (unsigned char)179\r
+#define blr_nullslast (unsigned char)180\r
+\r
+/* These codes reuse BLR code space */\r
+\r
+#define blr_post_arg (unsigned char)163\r
+#define blr_exec_into (unsigned char)164\r
+#define blr_user_savepoint (unsigned char)165\r
+\r
+/* These codes are actions for user-defined savepoints */\r
+\r
+#define blr_savepoint_set (unsigned char)0\r
+#define blr_savepoint_release (unsigned char)1\r
+#define blr_savepoint_undo (unsigned char)2\r
+#define blr_savepoint_release_single (unsigned char)3\r
+\r
+#endif /* _JRD_BLR_H_ */\r
+\r
+\r
+/**********************************/\r
+/* Database parameter block stuff */\r
+/**********************************/\r
+\r
+#define isc_dpb_version1 1\r
+#define isc_dpb_cdd_pathname 1\r
+#define isc_dpb_allocation 2\r
+#define isc_dpb_journal 3\r
+#define isc_dpb_page_size 4\r
+#define isc_dpb_num_buffers 5\r
+#define isc_dpb_buffer_length 6\r
+#define isc_dpb_debug 7\r
+#define isc_dpb_garbage_collect 8\r
+#define isc_dpb_verify 9\r
+#define isc_dpb_sweep 10\r
+#define isc_dpb_enable_journal 11\r
+#define isc_dpb_disable_journal 12\r
+#define isc_dpb_dbkey_scope 13\r
+#define isc_dpb_number_of_users 14\r
+#define isc_dpb_trace 15\r
+#define isc_dpb_no_garbage_collect 16\r
+#define isc_dpb_damaged 17\r
+#define isc_dpb_license 18\r
+#define isc_dpb_sys_user_name 19\r
+#define isc_dpb_encrypt_key 20\r
+#define isc_dpb_activate_shadow 21\r
+#define isc_dpb_sweep_interval 22\r
+#define isc_dpb_delete_shadow 23\r
+#define isc_dpb_force_write 24\r
+#define isc_dpb_begin_log 25\r
+#define isc_dpb_quit_log 26\r
+#define isc_dpb_no_reserve 27\r
+#define isc_dpb_user_name 28\r
+#define isc_dpb_password 29\r
+#define isc_dpb_password_enc 30\r
+#define isc_dpb_sys_user_name_enc 31\r
+#define isc_dpb_interp 32\r
+#define isc_dpb_online_dump 33\r
+#define isc_dpb_old_file_size 34\r
+#define isc_dpb_old_num_files 35\r
+#define isc_dpb_old_file 36\r
+#define isc_dpb_old_start_page 37\r
+#define isc_dpb_old_start_seqno 38\r
+#define isc_dpb_old_start_file 39\r
+#define isc_dpb_drop_walfile 40\r
+#define isc_dpb_old_dump_id 41\r
+#define isc_dpb_wal_backup_dir 42\r
+#define isc_dpb_wal_chkptlen 43\r
+#define isc_dpb_wal_numbufs 44\r
+#define isc_dpb_wal_bufsize 45\r
+#define isc_dpb_wal_grp_cmt_wait 46\r
+#define isc_dpb_lc_messages 47\r
+#define isc_dpb_lc_ctype 48\r
+#define isc_dpb_cache_manager 49\r
+#define isc_dpb_shutdown 50\r
+#define isc_dpb_online 51\r
+#define isc_dpb_shutdown_delay 52\r
+#define isc_dpb_reserved 53\r
+#define isc_dpb_overwrite 54\r
+#define isc_dpb_sec_attach 55\r
+#define isc_dpb_disable_wal 56\r
+#define isc_dpb_connect_timeout 57\r
+#define isc_dpb_dummy_packet_interval 58\r
+#define isc_dpb_gbak_attach 59\r
+#define isc_dpb_sql_role_name 60\r
+#define isc_dpb_set_page_buffers 61\r
+#define isc_dpb_working_directory 62\r
+#define isc_dpb_sql_dialect 63\r
+#define isc_dpb_set_db_readonly 64\r
+#define isc_dpb_set_db_sql_dialect 65\r
+#define isc_dpb_gfix_attach 66\r
+#define isc_dpb_gstat_attach 67\r
+#define isc_dpb_set_db_charset 68\r
+\r
+/*********************************/\r
+/* isc_dpb_verify specific flags */\r
+/*********************************/\r
+\r
+#define isc_dpb_pages 1\r
+#define isc_dpb_records 2\r
+#define isc_dpb_indices 4\r
+#define isc_dpb_transactions 8\r
+#define isc_dpb_no_update 16\r
+#define isc_dpb_repair 32\r
+#define isc_dpb_ignore 64\r
+\r
+/***********************************/\r
+/* isc_dpb_shutdown specific flags */\r
+/***********************************/\r
+\r
+#define isc_dpb_shut_cache 1\r
+#define isc_dpb_shut_attachment 2\r
+#define isc_dpb_shut_transaction 4\r
+#define isc_dpb_shut_force 8\r
+\r
+/**************************************/\r
+/* Bit assignments in RDB$SYSTEM_FLAG */\r
+/**************************************/\r
+\r
+#define RDB_system 1\r
+#define RDB_id_assigned 2\r
+\r
+\r
+/*************************************/\r
+/* Transaction parameter block stuff */\r
+/*************************************/\r
+\r
+#define isc_tpb_version1 1\r
+#define isc_tpb_version3 3\r
+#define isc_tpb_consistency 1\r
+#define isc_tpb_concurrency 2\r
+#define isc_tpb_shared 3\r
+#define isc_tpb_protected 4\r
+#define isc_tpb_exclusive 5\r
+#define isc_tpb_wait 6\r
+#define isc_tpb_nowait 7\r
+#define isc_tpb_read 8\r
+#define isc_tpb_write 9\r
+#define isc_tpb_lock_read 10\r
+#define isc_tpb_lock_write 11\r
+#define isc_tpb_verb_time 12\r
+#define isc_tpb_commit_time 13\r
+#define isc_tpb_ignore_limbo 14\r
+#define isc_tpb_read_committed 15\r
+#define isc_tpb_autocommit 16\r
+#define isc_tpb_rec_version 17\r
+#define isc_tpb_no_rec_version 18\r
+#define isc_tpb_restart_requests 19\r
+#define isc_tpb_no_auto_undo 20\r
+\r
+\r
+/************************/\r
+/* Blob Parameter Block */\r
+/************************/\r
+\r
+#define isc_bpb_version1 1\r
+#define isc_bpb_source_type 1\r
+#define isc_bpb_target_type 2\r
+#define isc_bpb_type 3\r
+#define isc_bpb_source_interp 4\r
+#define isc_bpb_target_interp 5\r
+#define isc_bpb_filter_parameter 6\r
+\r
+#define isc_bpb_type_segmented 0\r
+#define isc_bpb_type_stream 1\r
+\r
+\r
+/*********************************/\r
+/* Service parameter block stuff */\r
+/*********************************/\r
+\r
+#define isc_spb_version1 1\r
+#define isc_spb_current_version 2\r
+#define isc_spb_version isc_spb_current_version\r
+#define isc_spb_user_name isc_dpb_user_name\r
+#define isc_spb_sys_user_name isc_dpb_sys_user_name\r
+#define isc_spb_sys_user_name_enc isc_dpb_sys_user_name_enc\r
+#define isc_spb_password isc_dpb_password\r
+#define isc_spb_password_enc isc_dpb_password_enc\r
+#define isc_spb_command_line 105\r
+#define isc_spb_dbname 106\r
+#define isc_spb_verbose 107\r
+#define isc_spb_options 108\r
+\r
+#define isc_spb_connect_timeout isc_dpb_connect_timeout\r
+#define isc_spb_dummy_packet_interval isc_dpb_dummy_packet_interval\r
+#define isc_spb_sql_role_name isc_dpb_sql_role_name\r
+\r
+\r
+/*********************************/\r
+/* Information call declarations */\r
+/*********************************/\r
+\r
+/****************************/\r
+/* Common, structural codes */\r
+/****************************/\r
+\r
+#define isc_info_end 1\r
+#define isc_info_truncated 2\r
+#define isc_info_error 3\r
+#define isc_info_data_not_ready 4\r
+#define isc_info_flag_end 127\r
+\r
+/******************************/\r
+/* Database information items */\r
+/******************************/\r
+\r
+enum db_info_types\r
+ {\r
+ isc_info_db_id = 4,\r
+ isc_info_reads = 5,\r
+ isc_info_writes = 6,\r
+ isc_info_fetches = 7,\r
+ isc_info_marks = 8,\r
+\r
+ isc_info_implementation = 11,\r
+ isc_info_isc_version = 12,\r
+ isc_info_base_level = 13,\r
+ isc_info_page_size = 14,\r
+ isc_info_num_buffers = 15,\r
+ isc_info_limbo = 16,\r
+ isc_info_current_memory = 17,\r
+ isc_info_max_memory = 18,\r
+ isc_info_window_turns = 19,\r
+ isc_info_license = 20, \r
+\r
+ isc_info_allocation = 21,\r
+ isc_info_attachment_id = 22,\r
+ isc_info_read_seq_count = 23,\r
+ isc_info_read_idx_count = 24,\r
+ isc_info_insert_count = 25,\r
+ isc_info_update_count = 26,\r
+ isc_info_delete_count = 27,\r
+ isc_info_backout_count = 28,\r
+ isc_info_purge_count = 29,\r
+ isc_info_expunge_count = 30, \r
+\r
+ isc_info_sweep_interval = 31,\r
+ isc_info_ods_version = 32,\r
+ isc_info_ods_minor_version = 33,\r
+ isc_info_no_reserve = 34,\r
+ isc_info_logfile = 35,\r
+ isc_info_cur_logfile_name = 36,\r
+ isc_info_cur_log_part_offset = 37,\r
+ isc_info_num_wal_buffers = 38,\r
+ isc_info_wal_buffer_size = 39,\r
+ isc_info_wal_ckpt_length = 40, \r
+\r
+ isc_info_wal_cur_ckpt_interval = 41, \r
+ isc_info_wal_prv_ckpt_fname = 42,\r
+ isc_info_wal_prv_ckpt_poffset = 43,\r
+ isc_info_wal_recv_ckpt_fname = 44,\r
+ isc_info_wal_recv_ckpt_poffset = 45,\r
+ isc_info_wal_grpc_wait_usecs = 47,\r
+ isc_info_wal_num_io = 48,\r
+ isc_info_wal_avg_io_size = 49,\r
+ isc_info_wal_num_commits = 50, \r
+\r
+ isc_info_wal_avg_grpc_size = 51,\r
+ isc_info_forced_writes = 52,\r
+ isc_info_user_names = 53,\r
+ isc_info_page_errors = 54,\r
+ isc_info_record_errors = 55,\r
+ isc_info_bpage_errors = 56,\r
+ isc_info_dpage_errors = 57,\r
+ isc_info_ipage_errors = 58,\r
+ isc_info_ppage_errors = 59,\r
+ isc_info_tpage_errors = 60,\r
+\r
+ isc_info_set_page_buffers = 61,\r
+ isc_info_db_sql_dialect = 62, \r
+ isc_info_db_read_only = 63,\r
+ isc_info_db_size_in_pages = 64,\r
+\r
+ /* Values 65 -100 unused to avoid conflict with InterBase */\r
+ \r
+ frb_info_att_charset = 101,\r
+ isc_info_db_class = 102,\r
+ isc_info_firebird_version = 103,\r
+ isc_info_oldest_transaction = 104,\r
+ isc_info_oldest_active = 105,\r
+ isc_info_oldest_snapshot = 106,\r
+ isc_info_next_transaction = 107,\r
+ isc_info_db_provider = 108,\r
+ isc_info_active_transactions = 109,\r
+\r
+ isc_info_db_last_value /* Leave this LAST! */\r
+ };\r
+\r
+#define isc_info_version isc_info_isc_version\r
+\r
+\r
+/**************************************/\r
+/* Database information return values */\r
+/**************************************/\r
+\r
+enum info_db_implementations\r
+ {\r
+ isc_info_db_impl_rdb_vms = 1,\r
+ isc_info_db_impl_rdb_eln = 2,\r
+ isc_info_db_impl_rdb_eln_dev = 3,\r
+ isc_info_db_impl_rdb_vms_y = 4,\r
+ isc_info_db_impl_rdb_eln_y = 5,\r
+ isc_info_db_impl_jri = 6,\r
+ isc_info_db_impl_jsv = 7,\r
+\r
+ isc_info_db_impl_isc_apl_68K = 25,\r
+ isc_info_db_impl_isc_vax_ultr = 26,\r
+ isc_info_db_impl_isc_vms = 27,\r
+ isc_info_db_impl_isc_sun_68k = 28,\r
+ isc_info_db_impl_isc_os2 = 29,\r
+ isc_info_db_impl_isc_sun4 = 30, /* 30 */\r
+ \r
+ isc_info_db_impl_isc_hp_ux = 31,\r
+ isc_info_db_impl_isc_sun_386i = 32,\r
+ isc_info_db_impl_isc_vms_orcl = 33,\r
+ isc_info_db_impl_isc_mac_aux = 34,\r
+ isc_info_db_impl_isc_rt_aix = 35,\r
+ isc_info_db_impl_isc_mips_ult = 36,\r
+ isc_info_db_impl_isc_xenix = 37,\r
+ isc_info_db_impl_isc_dg = 38,\r
+ isc_info_db_impl_isc_hp_mpexl = 39,\r
+ isc_info_db_impl_isc_hp_ux68K = 40, /* 40 */\r
+\r
+ isc_info_db_impl_isc_sgi = 41,\r
+ isc_info_db_impl_isc_sco_unix = 42,\r
+ isc_info_db_impl_isc_cray = 43,\r
+ isc_info_db_impl_isc_imp = 44,\r
+ isc_info_db_impl_isc_delta = 45,\r
+ isc_info_db_impl_isc_next = 46,\r
+ isc_info_db_impl_isc_dos = 47,\r
+ isc_info_db_impl_m88K = 48,\r
+ isc_info_db_impl_unixware = 49,\r
+ isc_info_db_impl_isc_winnt_x86 = 50,\r
+\r
+ isc_info_db_impl_isc_epson = 51,\r
+ isc_info_db_impl_alpha_osf = 52,\r
+ isc_info_db_impl_alpha_vms = 53,\r
+ isc_info_db_impl_netware_386 = 54, \r
+ isc_info_db_impl_win_only = 55,\r
+ isc_info_db_impl_ncr_3000 = 56,\r
+ isc_info_db_impl_winnt_ppc = 57,\r
+ isc_info_db_impl_dg_x86 = 58,\r
+ isc_info_db_impl_sco_ev = 59,\r
+ isc_info_db_impl_i386 = 60,\r
+\r
+ isc_info_db_impl_freebsd = 61,\r
+ isc_info_db_impl_netbsd = 62,\r
+ isc_info_db_impl_darwin = 63,\r
+ isc_info_db_impl_sinixz = 64,\r
+\r
+ isc_info_db_impl_linux_sparc = 65,\r
+ isc_info_db_impl_linux_amd64 = 66,\r
+\r
+ isc_info_db_impl_last_value /* Leave this LAST! */\r
+ };\r
+\r
+#define isc_info_db_impl_isc_a isc_info_db_impl_isc_apl_68K\r
+#define isc_info_db_impl_isc_u isc_info_db_impl_isc_vax_ultr\r
+#define isc_info_db_impl_isc_v isc_info_db_impl_isc_vms\r
+#define isc_info_db_impl_isc_s isc_info_db_impl_isc_sun_68k\r
+\r
+\r
+enum info_db_class\r
+ {\r
+ isc_info_db_class_access = 1,\r
+ isc_info_db_class_y_valve = 2,\r
+ isc_info_db_class_rem_int = 3,\r
+ isc_info_db_class_rem_srvr = 4,\r
+ isc_info_db_class_pipe_int = 7,\r
+ isc_info_db_class_pipe_srvr = 8,\r
+ isc_info_db_class_sam_int = 9,\r
+ isc_info_db_class_sam_srvr = 10,\r
+ isc_info_db_class_gateway = 11,\r
+ isc_info_db_class_cache = 12,\r
+ isc_info_db_class_classic_access = 13,\r
+ isc_info_db_class_server_access = 14,\r
+\r
+ isc_info_db_class_last_value /* Leave this LAST! */\r
+ };\r
+\r
+enum info_db_provider\r
+ {\r
+ isc_info_db_code_rdb_eln = 1,\r
+ isc_info_db_code_rdb_vms = 2,\r
+ isc_info_db_code_interbase = 3,\r
+ isc_info_db_code_firebird = 4,\r
+\r
+ isc_info_db_code_last_value /* Leave this LAST! */\r
+ };\r
+\r
+\r
+/*****************************/\r
+/* Request information items */\r
+/*****************************/\r
+\r
+#define isc_info_number_messages 4\r
+#define isc_info_max_message 5\r
+#define isc_info_max_send 6\r
+#define isc_info_max_receive 7\r
+#define isc_info_state 8\r
+#define isc_info_message_number 9\r
+#define isc_info_message_size 10\r
+#define isc_info_request_cost 11\r
+#define isc_info_access_path 12\r
+#define isc_info_req_select_count 13\r
+#define isc_info_req_insert_count 14\r
+#define isc_info_req_update_count 15\r
+#define isc_info_req_delete_count 16\r
+\r
+\r
+/*********************/\r
+/* Access path items */\r
+/*********************/\r
+\r
+#define isc_info_rsb_end 0\r
+#define isc_info_rsb_begin 1\r
+#define isc_info_rsb_type 2\r
+#define isc_info_rsb_relation 3\r
+#define isc_info_rsb_plan 4\r
+\r
+/*************/\r
+/* Rsb types */\r
+/*************/\r
+\r
+#define isc_info_rsb_unknown 1\r
+#define isc_info_rsb_indexed 2\r
+#define isc_info_rsb_navigate 3\r
+#define isc_info_rsb_sequential 4\r
+#define isc_info_rsb_cross 5\r
+#define isc_info_rsb_sort 6\r
+#define isc_info_rsb_first 7\r
+#define isc_info_rsb_boolean 8\r
+#define isc_info_rsb_union 9\r
+#define isc_info_rsb_aggregate 10\r
+#define isc_info_rsb_merge 11\r
+#define isc_info_rsb_ext_sequential 12\r
+#define isc_info_rsb_ext_indexed 13\r
+#define isc_info_rsb_ext_dbkey 14\r
+#define isc_info_rsb_left_cross 15\r
+#define isc_info_rsb_select 16\r
+#define isc_info_rsb_sql_join 17\r
+#define isc_info_rsb_simulate 18\r
+#define isc_info_rsb_sim_cross 19\r
+#define isc_info_rsb_once 20\r
+#define isc_info_rsb_procedure 21\r
+\r
+/**********************/\r
+/* Bitmap expressions */\r
+/**********************/\r
+\r
+#define isc_info_rsb_and 1\r
+#define isc_info_rsb_or 2\r
+#define isc_info_rsb_dbkey 3\r
+#define isc_info_rsb_index 4\r
+\r
+#define isc_info_req_active 2\r
+#define isc_info_req_inactive 3\r
+#define isc_info_req_send 4\r
+#define isc_info_req_receive 5\r
+#define isc_info_req_select 6\r
+#define isc_info_req_sql_stall 7\r
+\r
+/**************************/\r
+/* Blob information items */\r
+/**************************/\r
+\r
+#define isc_info_blob_num_segments 4\r
+#define isc_info_blob_max_segment 5\r
+#define isc_info_blob_total_length 6\r
+#define isc_info_blob_type 7\r
+\r
+/*********************************/\r
+/* Transaction information items */\r
+/*********************************/\r
+\r
+#define isc_info_tra_id 4\r
+\r
+/*****************************\r
+ * Service action items *\r
+ *****************************/\r
+\r
+#define isc_action_svc_backup 1 /* Starts database backup process on the server */\r
+#define isc_action_svc_restore 2 /* Starts database restore process on the server */\r
+#define isc_action_svc_repair 3 /* Starts database repair process on the server */\r
+#define isc_action_svc_add_user 4 /* Adds a new user to the security database */\r
+#define isc_action_svc_delete_user 5 /* Deletes a user record from the security database */\r
+#define isc_action_svc_modify_user 6 /* Modifies a user record in the security database */\r
+#define isc_action_svc_display_user 7 /* Displays a user record from the security database */\r
+#define isc_action_svc_properties 8 /* Sets database properties */\r
+#define isc_action_svc_add_license 9 /* Adds a license to the license file */\r
+#define isc_action_svc_remove_license 10 /* Removes a license from the license file */\r
+#define isc_action_svc_db_stats 11 /* Retrieves database statistics */\r
+#define isc_action_svc_get_ib_log 12 /* Retrieves the InterBase log file from the server */\r
+\r
+/*****************************\r
+ * Service information items *\r
+ *****************************/\r
+\r
+#define isc_info_svc_svr_db_info 50 /* Retrieves the number of attachments and databases */\r
+#define isc_info_svc_get_license 51 /* Retrieves all license keys and IDs from the license file */\r
+#define isc_info_svc_get_license_mask 52 /* Retrieves a bitmask representing licensed options on the server */\r
+#define isc_info_svc_get_config 53 /* Retrieves the parameters and values for IB_CONFIG */\r
+#define isc_info_svc_version 54 /* Retrieves the version of the services manager */\r
+#define isc_info_svc_server_version 55 /* Retrieves the version of the InterBase server */\r
+#define isc_info_svc_implementation 56 /* Retrieves the implementation of the InterBase server */\r
+#define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */\r
+#define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */\r
+#define isc_info_svc_get_env 59 /* Retrieves the setting of $INTERBASE */\r
+#define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $INTERBASE_LCK */\r
+#define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $INTERBASE_MSG */\r
+#define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */\r
+#define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */\r
+#define isc_info_svc_timeout 64 /* Sets / signifies a timeout value for reading service information */\r
+#define isc_info_svc_get_licensed_users 65 /* Retrieves the number of users licensed for accessing the server */\r
+#define isc_info_svc_limbo_trans 66 /* Retrieve the limbo transactions */\r
+#define isc_info_svc_running 67 /* Checks to see if a service is running on an attachment */\r
+#define isc_info_svc_get_users 68 /* Returns the user information from isc_action_svc_display_users */\r
+\r
+/******************************************************\r
+ * Parameters for isc_action_{add|delete|modify)_user *\r
+ ******************************************************/\r
+\r
+#define isc_spb_sec_userid 5\r
+#define isc_spb_sec_groupid 6\r
+#define isc_spb_sec_username 7\r
+#define isc_spb_sec_password 8\r
+#define isc_spb_sec_groupname 9\r
+#define isc_spb_sec_firstname 10\r
+#define isc_spb_sec_middlename 11\r
+#define isc_spb_sec_lastname 12\r
+\r
+/*******************************************************\r
+ * Parameters for isc_action_svc_(add|remove)_license, *\r
+ * isc_info_svc_get_license *\r
+ *******************************************************/\r
+\r
+#define isc_spb_lic_key 5\r
+#define isc_spb_lic_id 6\r
+#define isc_spb_lic_desc 7\r
+\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_backup *\r
+ *****************************************/\r
+\r
+#define isc_spb_bkp_file 5\r
+#define isc_spb_bkp_factor 6\r
+#define isc_spb_bkp_length 7\r
+#define isc_spb_bkp_ignore_checksums 0x01\r
+#define isc_spb_bkp_ignore_limbo 0x02\r
+#define isc_spb_bkp_metadata_only 0x04\r
+#define isc_spb_bkp_no_garbage_collect 0x08\r
+#define isc_spb_bkp_old_descriptions 0x10\r
+#define isc_spb_bkp_non_transportable 0x20\r
+#define isc_spb_bkp_convert 0x40\r
+#define isc_spb_bkp_expand 0x80\r
+\r
+/********************************************\r
+ * Parameters for isc_action_svc_properties *\r
+ ********************************************/\r
+\r
+#define isc_spb_prp_page_buffers 5\r
+#define isc_spb_prp_sweep_interval 6\r
+#define isc_spb_prp_shutdown_db 7\r
+#define isc_spb_prp_deny_new_attachments 9\r
+#define isc_spb_prp_deny_new_transactions 10\r
+#define isc_spb_prp_reserve_space 11\r
+#define isc_spb_prp_write_mode 12\r
+#define isc_spb_prp_access_mode 13\r
+#define isc_spb_prp_set_sql_dialect 14\r
+#define isc_spb_prp_activate 0x0100\r
+#define isc_spb_prp_db_online 0x0200\r
+\r
+/********************************************\r
+ * Parameters for isc_spb_prp_reserve_space *\r
+ ********************************************/\r
+\r
+#define isc_spb_prp_res_use_full 35\r
+#define isc_spb_prp_res 36\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_prp_write_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_prp_wm_async 37\r
+#define isc_spb_prp_wm_sync 38\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_prp_access_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_prp_am_readonly 39\r
+#define isc_spb_prp_am_readwrite 40\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_repair *\r
+ *****************************************/\r
+\r
+#define isc_spb_rpr_commit_trans 15\r
+#define isc_spb_rpr_rollback_trans 34\r
+#define isc_spb_rpr_recover_two_phase 17\r
+#define isc_spb_tra_id 18\r
+#define isc_spb_single_tra_id 19\r
+#define isc_spb_multi_tra_id 20\r
+#define isc_spb_tra_state 21\r
+#define isc_spb_tra_state_limbo 22\r
+#define isc_spb_tra_state_commit 23\r
+#define isc_spb_tra_state_rollback 24\r
+#define isc_spb_tra_state_unknown 25\r
+#define isc_spb_tra_host_site 26\r
+#define isc_spb_tra_remote_site 27\r
+#define isc_spb_tra_db_path 28\r
+#define isc_spb_tra_advise 29\r
+#define isc_spb_tra_advise_commit 30\r
+#define isc_spb_tra_advise_rollback 31\r
+#define isc_spb_tra_advise_unknown 33\r
+\r
+#define isc_spb_rpr_validate_db 0x01\r
+#define isc_spb_rpr_sweep_db 0x02\r
+#define isc_spb_rpr_mend_db 0x04\r
+#define isc_spb_rpr_list_limbo_trans 0x08\r
+#define isc_spb_rpr_check_db 0x10\r
+#define isc_spb_rpr_ignore_checksum 0x20\r
+#define isc_spb_rpr_kill_shadows 0x40\r
+#define isc_spb_rpr_full 0x80\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_restore *\r
+ *****************************************/\r
+\r
+#define isc_spb_res_buffers 9\r
+#define isc_spb_res_page_size 10\r
+#define isc_spb_res_length 11\r
+#define isc_spb_res_access_mode 12\r
+#define isc_spb_res_deactivate_idx 0x0100\r
+#define isc_spb_res_no_shadow 0x0200\r
+#define isc_spb_res_no_validity 0x0400\r
+#define isc_spb_res_one_at_a_time 0x0800\r
+#define isc_spb_res_replace 0x1000\r
+#define isc_spb_res_create 0x2000\r
+#define isc_spb_res_use_all_space 0x4000\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_res_access_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_res_am_readonly isc_spb_prp_am_readonly\r
+#define isc_spb_res_am_readwrite isc_spb_prp_am_readwrite\r
+\r
+/*******************************************\r
+ * Parameters for isc_info_svc_svr_db_info *\r
+ *******************************************/\r
+\r
+#define isc_spb_num_att 5\r
+#define isc_spb_num_db 6\r
+\r
+/*****************************************\r
+ * Parameters for isc_info_svc_db_stats *\r
+ *****************************************/\r
+\r
+#define isc_spb_sts_data_pages 0x01\r
+#define isc_spb_sts_db_log 0x02\r
+#define isc_spb_sts_hdr_pages 0x04\r
+#define isc_spb_sts_idx_pages 0x08\r
+#define isc_spb_sts_sys_relations 0x10\r
+#define isc_spb_sts_record_versions 0x20\r
+#define isc_spb_sts_table 0x40\r
+\r
+/*************************/\r
+/* SQL information items */\r
+/*************************/\r
+\r
+#define isc_info_sql_select 4\r
+#define isc_info_sql_bind 5\r
+#define isc_info_sql_num_variables 6\r
+#define isc_info_sql_describe_vars 7\r
+#define isc_info_sql_describe_end 8\r
+#define isc_info_sql_sqlda_seq 9\r
+#define isc_info_sql_message_seq 10\r
+#define isc_info_sql_type 11\r
+#define isc_info_sql_sub_type 12\r
+#define isc_info_sql_scale 13\r
+#define isc_info_sql_length 14\r
+#define isc_info_sql_null_ind 15\r
+#define isc_info_sql_field 16\r
+#define isc_info_sql_relation 17\r
+#define isc_info_sql_owner 18\r
+#define isc_info_sql_alias 19\r
+#define isc_info_sql_sqlda_start 20\r
+#define isc_info_sql_stmt_type 21\r
+#define isc_info_sql_get_plan 22\r
+#define isc_info_sql_records 23\r
+#define isc_info_sql_batch_fetch 24\r
+\r
+/*********************************/\r
+/* SQL information return values */\r
+/*********************************/\r
+\r
+#define isc_info_sql_stmt_select 1\r
+#define isc_info_sql_stmt_insert 2\r
+#define isc_info_sql_stmt_update 3\r
+#define isc_info_sql_stmt_delete 4\r
+#define isc_info_sql_stmt_ddl 5\r
+#define isc_info_sql_stmt_get_segment 6\r
+#define isc_info_sql_stmt_put_segment 7\r
+#define isc_info_sql_stmt_exec_procedure 8\r
+#define isc_info_sql_stmt_start_trans 9\r
+#define isc_info_sql_stmt_commit 10\r
+#define isc_info_sql_stmt_rollback 11\r
+#define isc_info_sql_stmt_select_for_upd 12\r
+#define isc_info_sql_stmt_set_generator 13\r
+#define isc_info_sql_stmt_savepoint 14\r
+\r
+\r
+/***********************************/\r
+/* Server configuration key values */\r
+/***********************************/\r
+\r
+/* Not available in Firebird 1.5 */\r
+\r
+\r
+/**********************************************/\r
+/* Dynamic Data Definition Language operators */\r
+/**********************************************/\r
+\r
+/******************/\r
+/* Version number */\r
+/******************/\r
+\r
+#define isc_dyn_version_1 1\r
+#define isc_dyn_eoc 255\r
+\r
+/******************************/\r
+/* Operations (may be nested) */\r
+/******************************/\r
+\r
+#define isc_dyn_begin 2\r
+#define isc_dyn_end 3\r
+#define isc_dyn_if 4\r
+#define isc_dyn_def_database 5\r
+#define isc_dyn_def_global_fld 6\r
+#define isc_dyn_def_local_fld 7\r
+#define isc_dyn_def_idx 8\r
+#define isc_dyn_def_rel 9\r
+#define isc_dyn_def_sql_fld 10\r
+#define isc_dyn_def_view 12\r
+#define isc_dyn_def_trigger 15\r
+#define isc_dyn_def_security_class 120\r
+#define isc_dyn_def_dimension 140\r
+#define isc_dyn_def_generator 24\r
+#define isc_dyn_def_function 25\r
+#define isc_dyn_def_filter 26\r
+#define isc_dyn_def_function_arg 27\r
+#define isc_dyn_def_shadow 34\r
+#define isc_dyn_def_trigger_msg 17\r
+#define isc_dyn_def_file 36\r
+#define isc_dyn_mod_database 39\r
+#define isc_dyn_mod_rel 11\r
+#define isc_dyn_mod_global_fld 13\r
+#define isc_dyn_mod_idx 102\r
+#define isc_dyn_mod_local_fld 14\r
+#define isc_dyn_mod_sql_fld 216\r
+#define isc_dyn_mod_view 16\r
+#define isc_dyn_mod_security_class 122\r
+#define isc_dyn_mod_trigger 113\r
+#define isc_dyn_mod_trigger_msg 28\r
+#define isc_dyn_delete_database 18\r
+#define isc_dyn_delete_rel 19\r
+#define isc_dyn_delete_global_fld 20\r
+#define isc_dyn_delete_local_fld 21\r
+#define isc_dyn_delete_idx 22\r
+#define isc_dyn_delete_security_class 123\r
+#define isc_dyn_delete_dimensions 143\r
+#define isc_dyn_delete_trigger 23\r
+#define isc_dyn_delete_trigger_msg 29\r
+#define isc_dyn_delete_filter 32\r
+#define isc_dyn_delete_function 33\r
+#define isc_dyn_delete_shadow 35\r
+#define isc_dyn_grant 30\r
+#define isc_dyn_revoke 31\r
+#define isc_dyn_def_primary_key 37\r
+#define isc_dyn_def_foreign_key 38\r
+#define isc_dyn_def_unique 40\r
+#define isc_dyn_def_procedure 164\r
+#define isc_dyn_delete_procedure 165\r
+#define isc_dyn_def_parameter 135\r
+#define isc_dyn_delete_parameter 136\r
+#define isc_dyn_mod_procedure 175\r
+#define isc_dyn_def_log_file 176\r
+#define isc_dyn_def_cache_file 180\r
+#define isc_dyn_def_exception 181\r
+#define isc_dyn_mod_exception 182\r
+#define isc_dyn_del_exception 183\r
+#define isc_dyn_drop_log 194\r
+#define isc_dyn_drop_cache 195\r
+#define isc_dyn_def_default_log 202\r
+\r
+/***********************/\r
+/* View specific stuff */\r
+/***********************/\r
+\r
+#define isc_dyn_view_blr 43\r
+#define isc_dyn_view_source 44\r
+#define isc_dyn_view_relation 45\r
+#define isc_dyn_view_context 46\r
+#define isc_dyn_view_context_name 47\r
+\r
+/**********************/\r
+/* Generic attributes */\r
+/**********************/\r
+\r
+#define isc_dyn_rel_name 50\r
+#define isc_dyn_fld_name 51\r
+#define isc_dyn_new_fld_name 215\r
+#define isc_dyn_idx_name 52\r
+#define isc_dyn_description 53\r
+#define isc_dyn_security_class 54\r
+#define isc_dyn_system_flag 55\r
+#define isc_dyn_update_flag 56\r
+#define isc_dyn_prc_name 166\r
+#define isc_dyn_prm_name 137\r
+#define isc_dyn_sql_object 196\r
+#define isc_dyn_fld_character_set_name 174\r
+\r
+/********************************/\r
+/* Relation specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_rel_dbkey_length 61\r
+#define isc_dyn_rel_store_trig 62\r
+#define isc_dyn_rel_modify_trig 63\r
+#define isc_dyn_rel_erase_trig 64\r
+#define isc_dyn_rel_store_trig_source 65\r
+#define isc_dyn_rel_modify_trig_source 66\r
+#define isc_dyn_rel_erase_trig_source 67\r
+#define isc_dyn_rel_ext_file 68\r
+#define isc_dyn_rel_sql_protection 69\r
+#define isc_dyn_rel_constraint 162\r
+#define isc_dyn_delete_rel_constraint 163\r
+\r
+/************************************/\r
+/* Global field specific attributes */\r
+/************************************/\r
+\r
+#define isc_dyn_fld_type 70\r
+#define isc_dyn_fld_length 71\r
+#define isc_dyn_fld_scale 72\r
+#define isc_dyn_fld_sub_type 73\r
+#define isc_dyn_fld_segment_length 74\r
+#define isc_dyn_fld_query_header 75\r
+#define isc_dyn_fld_edit_string 76\r
+#define isc_dyn_fld_validation_blr 77\r
+#define isc_dyn_fld_validation_source 78\r
+#define isc_dyn_fld_computed_blr 79\r
+#define isc_dyn_fld_computed_source 80\r
+#define isc_dyn_fld_missing_value 81\r
+#define isc_dyn_fld_default_value 82\r
+#define isc_dyn_fld_query_name 83\r
+#define isc_dyn_fld_dimensions 84\r
+#define isc_dyn_fld_not_null 85\r
+#define isc_dyn_fld_precision 86\r
+#define isc_dyn_fld_char_length 172\r
+#define isc_dyn_fld_collation 173\r
+#define isc_dyn_fld_default_source 193\r
+#define isc_dyn_del_default 197\r
+#define isc_dyn_del_validation 198\r
+#define isc_dyn_single_validation 199\r
+#define isc_dyn_fld_character_set 203\r
+\r
+/***********************************/\r
+/* Local field specific attributes */\r
+/***********************************/\r
+\r
+#define isc_dyn_fld_source 90\r
+#define isc_dyn_fld_base_fld 91\r
+#define isc_dyn_fld_position 92\r
+#define isc_dyn_fld_update_flag 93\r
+\r
+/*****************************/\r
+/* Index specific attributes */\r
+/*****************************/\r
+\r
+#define isc_dyn_idx_unique 100\r
+#define isc_dyn_idx_inactive 101\r
+#define isc_dyn_idx_type 103\r
+#define isc_dyn_idx_foreign_key 104\r
+#define isc_dyn_idx_ref_column 105\r
+#define isc_dyn_idx_statistic 204\r
+\r
+/*******************************/\r
+/* Trigger specific attributes */\r
+/*******************************/\r
+\r
+#define isc_dyn_trg_type 110\r
+#define isc_dyn_trg_blr 111\r
+#define isc_dyn_trg_source 112\r
+#define isc_dyn_trg_name 114\r
+#define isc_dyn_trg_sequence 115\r
+#define isc_dyn_trg_inactive 116\r
+#define isc_dyn_trg_msg_number 117\r
+#define isc_dyn_trg_msg 118\r
+\r
+/**************************************/\r
+/* Security Class specific attributes */\r
+/**************************************/\r
+\r
+#define isc_dyn_scl_acl 121\r
+#define isc_dyn_grant_user 130\r
+#define isc_dyn_grant_user_explicit 219\r
+#define isc_dyn_grant_proc 186\r
+#define isc_dyn_grant_trig 187\r
+#define isc_dyn_grant_view 188\r
+#define isc_dyn_grant_options 132\r
+#define isc_dyn_grant_user_group 205\r
+#define isc_dyn_grant_role 218\r
+\r
+\r
+/**********************************/\r
+/* Dimension specific information */\r
+/**********************************/\r
+\r
+#define isc_dyn_dim_lower 141\r
+#define isc_dyn_dim_upper 142\r
+\r
+/****************************/\r
+/* File specific attributes */\r
+/****************************/\r
+\r
+#define isc_dyn_file_name 125\r
+#define isc_dyn_file_start 126\r
+#define isc_dyn_file_length 127\r
+#define isc_dyn_shadow_number 128\r
+#define isc_dyn_shadow_man_auto 129\r
+#define isc_dyn_shadow_conditional 130\r
+\r
+/********************************/\r
+/* Log file specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_log_file_sequence 177\r
+#define isc_dyn_log_file_partitions 178\r
+#define isc_dyn_log_file_serial 179\r
+#define isc_dyn_log_file_overflow 200\r
+#define isc_dyn_log_file_raw 201\r
+\r
+/***************************/\r
+/* Log specific attributes */\r
+/***************************/\r
+\r
+#define isc_dyn_log_group_commit_wait 189\r
+#define isc_dyn_log_buffer_size 190\r
+#define isc_dyn_log_check_point_length 191\r
+#define isc_dyn_log_num_of_buffers 192\r
+\r
+/********************************/\r
+/* Function specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_function_name 145\r
+#define isc_dyn_function_type 146\r
+#define isc_dyn_func_module_name 147\r
+#define isc_dyn_func_entry_point 148\r
+#define isc_dyn_func_return_argument 149\r
+#define isc_dyn_func_arg_position 150\r
+#define isc_dyn_func_mechanism 151\r
+#define isc_dyn_filter_in_subtype 152\r
+#define isc_dyn_filter_out_subtype 153\r
+\r
+\r
+#define isc_dyn_description2 154\r
+#define isc_dyn_fld_computed_source2 155\r
+#define isc_dyn_fld_edit_string2 156\r
+#define isc_dyn_fld_query_header2 157\r
+#define isc_dyn_fld_validation_source2 158\r
+#define isc_dyn_trg_msg2 159\r
+#define isc_dyn_trg_source2 160\r
+#define isc_dyn_view_source2 161\r
+#define isc_dyn_xcp_msg2 184\r
+\r
+/*********************************/\r
+/* Generator specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_generator_name 95\r
+#define isc_dyn_generator_id 96\r
+\r
+/*********************************/\r
+/* Procedure specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_prc_inputs 167\r
+#define isc_dyn_prc_outputs 168\r
+#define isc_dyn_prc_source 169\r
+#define isc_dyn_prc_blr 170\r
+#define isc_dyn_prc_source2 171\r
+\r
+/*********************************/\r
+/* Parameter specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_prm_number 138\r
+#define isc_dyn_prm_type 139\r
+\r
+/********************************/\r
+/* Relation specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_xcp_msg 185\r
+\r
+/**********************************************/\r
+/* Cascading referential integrity values */\r
+/**********************************************/\r
+#define isc_dyn_foreign_key_update 205\r
+#define isc_dyn_foreign_key_delete 206\r
+#define isc_dyn_foreign_key_cascade 207\r
+#define isc_dyn_foreign_key_default 208\r
+#define isc_dyn_foreign_key_null 209\r
+#define isc_dyn_foreign_key_none 210\r
+\r
+/***********************/\r
+/* SQL role values */\r
+/***********************/\r
+#define isc_dyn_def_sql_role 211\r
+#define isc_dyn_sql_role_name 212\r
+#define isc_dyn_grant_admin_options 213\r
+#define isc_dyn_del_sql_role 214\r
+/* 215 & 216 are used some lines above. */\r
+\r
+/**********************************************/\r
+/* Generators again */\r
+/**********************************************/\r
+\r
+#ifndef __cplusplus /* c definitions */\r
+#define gds_dyn_delete_generator 217\r
+#else /* c++ definitions */\r
+const unsigned char gds_dyn_delete_generator = 217;\r
+#endif\r
+\r
+/****************************/\r
+/* Last $dyn value assigned */\r
+/****************************/\r
+\r
+#define isc_dyn_last_dyn_value 219\r
+\r
+/******************************************/\r
+/* Array slice description language (SDL) */\r
+/******************************************/\r
+\r
+#define isc_sdl_version1 1\r
+#define isc_sdl_eoc 255\r
+#define isc_sdl_relation 2\r
+#define isc_sdl_rid 3\r
+#define isc_sdl_field 4\r
+#define isc_sdl_fid 5\r
+#define isc_sdl_struct 6\r
+#define isc_sdl_variable 7\r
+#define isc_sdl_scalar 8\r
+#define isc_sdl_tiny_integer 9\r
+#define isc_sdl_short_integer 10\r
+#define isc_sdl_long_integer 11\r
+#define isc_sdl_literal 12\r
+#define isc_sdl_add 13\r
+#define isc_sdl_subtract 14\r
+#define isc_sdl_multiply 15\r
+#define isc_sdl_divide 16\r
+#define isc_sdl_negate 17\r
+#define isc_sdl_eql 18\r
+#define isc_sdl_neq 19\r
+#define isc_sdl_gtr 20\r
+#define isc_sdl_geq 21\r
+#define isc_sdl_lss 22\r
+#define isc_sdl_leq 23\r
+#define isc_sdl_and 24\r
+#define isc_sdl_or 25\r
+#define isc_sdl_not 26\r
+#define isc_sdl_while 27\r
+#define isc_sdl_assignment 28\r
+#define isc_sdl_label 29\r
+#define isc_sdl_leave 30\r
+#define isc_sdl_begin 31\r
+#define isc_sdl_end 32\r
+#define isc_sdl_do3 33\r
+#define isc_sdl_do2 34\r
+#define isc_sdl_do1 35\r
+#define isc_sdl_element 36\r
+\r
+/********************************************/\r
+/* International text interpretation values */\r
+/********************************************/\r
+\r
+#define isc_interp_eng_ascii 0\r
+#define isc_interp_jpn_sjis 5\r
+#define isc_interp_jpn_euc 6\r
+\r
+/*******************/\r
+/* SQL definitions */\r
+/*******************/\r
+\r
+#define SQL_TEXT 452\r
+#define SQL_VARYING 448\r
+#define SQL_SHORT 500\r
+#define SQL_LONG 496\r
+#define SQL_FLOAT 482\r
+#define SQL_DOUBLE 480\r
+#define SQL_D_FLOAT 530\r
+#define SQL_TIMESTAMP 510\r
+#define SQL_BLOB 520\r
+#define SQL_ARRAY 540\r
+#define SQL_QUAD 550\r
+#define SQL_TYPE_TIME 560\r
+#define SQL_TYPE_DATE 570\r
+#define SQL_INT64 580\r
+\r
+/* Historical alias for pre V6 applications */\r
+#define SQL_DATE SQL_TIMESTAMP\r
+\r
+/*****************/\r
+/* Blob Subtypes */\r
+/*****************/\r
+\r
+/* types less than zero are reserved for customer use */\r
+\r
+#define isc_blob_untyped 0\r
+\r
+/* internal subtypes */\r
+\r
+#define isc_blob_text 1\r
+#define isc_blob_blr 2\r
+#define isc_blob_acl 3\r
+#define isc_blob_ranges 4\r
+#define isc_blob_summary 5\r
+#define isc_blob_format 6\r
+#define isc_blob_tra 7\r
+#define isc_blob_extfile 8\r
+\r
+/* the range 20-30 is reserved for dBASE and Paradox types */\r
+\r
+#define isc_blob_formatted_memo 20\r
+#define isc_blob_paradox_ole 21\r
+#define isc_blob_graphic 22\r
+#define isc_blob_dbase_ole 23\r
+#define isc_blob_typed_binary 24\r
+\r
+/* Deprecated definitions maintained for compatibility only */\r
+\r
+#define isc_info_db_SQL_dialect 62\r
+#define isc_dpb_SQL_dialect 63\r
+#define isc_dpb_set_db_SQL_dialect 65\r
+\r
+\r
+#include "iberror.h"\r
+\r
+#endif /* JRD_IBASE_H */\r
+\r
--- /dev/null
+\r
+#ifndef _JRD_GEN_IBERROR_H\r
+#define _JRD_GEN_IBERROR_H\r
+/*\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ * \r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ * \r
+ * The content of this file was generated by the Firebird project\r
+ * using the program jrd/codes.epp\r
+ */\r
+/*\r
+ * \r
+ * *** WARNING *** - This file is automatically generated by codes.e - do not edit!\r
+ * \r
+ */\r
+/*\r
+ * MODULE: iberror.h\r
+ * DESCRIPTION: ISC error codes\r
+ *\r
+ */\r
+\r
+\r
+\r
+/***********************/\r
+/* ISC Error Codes */\r
+/***********************/\r
+\r
+#define isc_facility 20\r
+#define isc_base 335544320L\r
+#define isc_factor 1\r
+\r
+#define isc_arg_end 0 /* end of argument list */\r
+#define isc_arg_gds 1 /* generic DSRI status value */\r
+#define isc_arg_string 2 /* string argument */\r
+#define isc_arg_cstring 3 /* count & string argument */\r
+#define isc_arg_number 4 /* numeric argument (long) */\r
+#define isc_arg_interpreted 5 /* interpreted status code (string) */\r
+#define isc_arg_vms 6 /* VAX/VMS status code (long) */\r
+#define isc_arg_unix 7 /* UNIX error code */\r
+#define isc_arg_domain 8 /* Apollo/Domain error code */\r
+#define isc_arg_dos 9 /* MSDOS/OS2 error code */\r
+#define isc_arg_mpexl 10 /* HP MPE/XL error code */\r
+#define isc_arg_mpexl_ipc 11 /* HP MPE/XL IPC error code */\r
+#define isc_arg_next_mach 15 /* NeXT/Mach error code */\r
+#define isc_arg_netware 16 /* NetWare error code */\r
+#define isc_arg_win32 17 /* Win32 error code */\r
+#define isc_arg_warning 18 /* warning argument */\r
+\r
+#define isc_arith_except 335544321L\r
+#define isc_bad_dbkey 335544322L\r
+#define isc_bad_db_format 335544323L\r
+#define isc_bad_db_handle 335544324L\r
+#define isc_bad_dpb_content 335544325L\r
+#define isc_bad_dpb_form 335544326L\r
+#define isc_bad_req_handle 335544327L\r
+#define isc_bad_segstr_handle 335544328L\r
+#define isc_bad_segstr_id 335544329L\r
+#define isc_bad_tpb_content 335544330L\r
+#define isc_bad_tpb_form 335544331L\r
+#define isc_bad_trans_handle 335544332L\r
+#define isc_bug_check 335544333L\r
+#define isc_convert_error 335544334L\r
+#define isc_db_corrupt 335544335L\r
+#define isc_deadlock 335544336L\r
+#define isc_excess_trans 335544337L\r
+#define isc_from_no_match 335544338L\r
+#define isc_infinap 335544339L\r
+#define isc_infona 335544340L\r
+#define isc_infunk 335544341L\r
+#define isc_integ_fail 335544342L\r
+#define isc_invalid_blr 335544343L\r
+#define isc_io_error 335544344L\r
+#define isc_lock_conflict 335544345L\r
+#define isc_metadata_corrupt 335544346L\r
+#define isc_not_valid 335544347L\r
+#define isc_no_cur_rec 335544348L\r
+#define isc_no_dup 335544349L\r
+#define isc_no_finish 335544350L\r
+#define isc_no_meta_update 335544351L\r
+#define isc_no_priv 335544352L\r
+#define isc_no_recon 335544353L\r
+#define isc_no_record 335544354L\r
+#define isc_no_segstr_close 335544355L\r
+#define isc_obsolete_metadata 335544356L\r
+#define isc_open_trans 335544357L\r
+#define isc_port_len 335544358L\r
+#define isc_read_only_field 335544359L\r
+#define isc_read_only_rel 335544360L\r
+#define isc_read_only_trans 335544361L\r
+#define isc_read_only_view 335544362L\r
+#define isc_req_no_trans 335544363L\r
+#define isc_req_sync 335544364L\r
+#define isc_req_wrong_db 335544365L\r
+#define isc_segment 335544366L\r
+#define isc_segstr_eof 335544367L\r
+#define isc_segstr_no_op 335544368L\r
+#define isc_segstr_no_read 335544369L\r
+#define isc_segstr_no_trans 335544370L\r
+#define isc_segstr_no_write 335544371L\r
+#define isc_segstr_wrong_db 335544372L\r
+#define isc_sys_request 335544373L\r
+#define isc_stream_eof 335544374L\r
+#define isc_unavailable 335544375L\r
+#define isc_unres_rel 335544376L\r
+#define isc_uns_ext 335544377L\r
+#define isc_wish_list 335544378L\r
+#define isc_wrong_ods 335544379L\r
+#define isc_wronumarg 335544380L\r
+#define isc_imp_exc 335544381L\r
+#define isc_random 335544382L\r
+#define isc_fatal_conflict 335544383L\r
+#define isc_badblk 335544384L\r
+#define isc_invpoolcl 335544385L\r
+#define isc_nopoolids 335544386L\r
+#define isc_relbadblk 335544387L\r
+#define isc_blktoobig 335544388L\r
+#define isc_bufexh 335544389L\r
+#define isc_syntaxerr 335544390L\r
+#define isc_bufinuse 335544391L\r
+#define isc_bdbincon 335544392L\r
+#define isc_reqinuse 335544393L\r
+#define isc_badodsver 335544394L\r
+#define isc_relnotdef 335544395L\r
+#define isc_fldnotdef 335544396L\r
+#define isc_dirtypage 335544397L\r
+#define isc_waifortra 335544398L\r
+#define isc_doubleloc 335544399L\r
+#define isc_nodnotfnd 335544400L\r
+#define isc_dupnodfnd 335544401L\r
+#define isc_locnotmar 335544402L\r
+#define isc_badpagtyp 335544403L\r
+#define isc_corrupt 335544404L\r
+#define isc_badpage 335544405L\r
+#define isc_badindex 335544406L\r
+#define isc_dbbnotzer 335544407L\r
+#define isc_tranotzer 335544408L\r
+#define isc_trareqmis 335544409L\r
+#define isc_badhndcnt 335544410L\r
+#define isc_wrotpbver 335544411L\r
+#define isc_wroblrver 335544412L\r
+#define isc_wrodpbver 335544413L\r
+#define isc_blobnotsup 335544414L\r
+#define isc_badrelation 335544415L\r
+#define isc_nodetach 335544416L\r
+#define isc_notremote 335544417L\r
+#define isc_trainlim 335544418L\r
+#define isc_notinlim 335544419L\r
+#define isc_traoutsta 335544420L\r
+#define isc_connect_reject 335544421L\r
+#define isc_dbfile 335544422L\r
+#define isc_orphan 335544423L\r
+#define isc_no_lock_mgr 335544424L\r
+#define isc_ctxinuse 335544425L\r
+#define isc_ctxnotdef 335544426L\r
+#define isc_datnotsup 335544427L\r
+#define isc_badmsgnum 335544428L\r
+#define isc_badparnum 335544429L\r
+#define isc_virmemexh 335544430L\r
+#define isc_blocking_signal 335544431L\r
+#define isc_lockmanerr 335544432L\r
+#define isc_journerr 335544433L\r
+#define isc_keytoobig 335544434L\r
+#define isc_nullsegkey 335544435L\r
+#define isc_sqlerr 335544436L\r
+#define isc_wrodynver 335544437L\r
+#define isc_funnotdef 335544438L\r
+#define isc_funmismat 335544439L\r
+#define isc_bad_msg_vec 335544440L\r
+#define isc_bad_detach 335544441L\r
+#define isc_noargacc_read 335544442L\r
+#define isc_noargacc_write 335544443L\r
+#define isc_read_only 335544444L\r
+#define isc_ext_err 335544445L\r
+#define isc_non_updatable 335544446L\r
+#define isc_no_rollback 335544447L\r
+#define isc_bad_sec_info 335544448L\r
+#define isc_invalid_sec_info 335544449L\r
+#define isc_misc_interpreted 335544450L\r
+#define isc_update_conflict 335544451L\r
+#define isc_unlicensed 335544452L\r
+#define isc_obj_in_use 335544453L\r
+#define isc_nofilter 335544454L\r
+#define isc_shadow_accessed 335544455L\r
+#define isc_invalid_sdl 335544456L\r
+#define isc_out_of_bounds 335544457L\r
+#define isc_invalid_dimension 335544458L\r
+#define isc_rec_in_limbo 335544459L\r
+#define isc_shadow_missing 335544460L\r
+#define isc_cant_validate 335544461L\r
+#define isc_cant_start_journal 335544462L\r
+#define isc_gennotdef 335544463L\r
+#define isc_cant_start_logging 335544464L\r
+#define isc_bad_segstr_type 335544465L\r
+#define isc_foreign_key 335544466L\r
+#define isc_high_minor 335544467L\r
+#define isc_tra_state 335544468L\r
+#define isc_trans_invalid 335544469L\r
+#define isc_buf_invalid 335544470L\r
+#define isc_indexnotdefined 335544471L\r
+#define isc_login 335544472L\r
+#define isc_invalid_bookmark 335544473L\r
+#define isc_bad_lock_level 335544474L\r
+#define isc_relation_lock 335544475L\r
+#define isc_record_lock 335544476L\r
+#define isc_max_idx 335544477L\r
+#define isc_jrn_enable 335544478L\r
+#define isc_old_failure 335544479L\r
+#define isc_old_in_progress 335544480L\r
+#define isc_old_no_space 335544481L\r
+#define isc_no_wal_no_jrn 335544482L\r
+#define isc_num_old_files 335544483L\r
+#define isc_wal_file_open 335544484L\r
+#define isc_bad_stmt_handle 335544485L\r
+#define isc_wal_failure 335544486L\r
+#define isc_walw_err 335544487L\r
+#define isc_logh_small 335544488L\r
+#define isc_logh_inv_version 335544489L\r
+#define isc_logh_open_flag 335544490L\r
+#define isc_logh_open_flag2 335544491L\r
+#define isc_logh_diff_dbname 335544492L\r
+#define isc_logf_unexpected_eof 335544493L\r
+#define isc_logr_incomplete 335544494L\r
+#define isc_logr_header_small 335544495L\r
+#define isc_logb_small 335544496L\r
+#define isc_wal_illegal_attach 335544497L\r
+#define isc_wal_invalid_wpb 335544498L\r
+#define isc_wal_err_rollover 335544499L\r
+#define isc_no_wal 335544500L\r
+#define isc_drop_wal 335544501L\r
+#define isc_stream_not_defined 335544502L\r
+#define isc_wal_subsys_error 335544503L\r
+#define isc_wal_subsys_corrupt 335544504L\r
+#define isc_no_archive 335544505L\r
+#define isc_shutinprog 335544506L\r
+#define isc_range_in_use 335544507L\r
+#define isc_range_not_found 335544508L\r
+#define isc_charset_not_found 335544509L\r
+#define isc_lock_timeout 335544510L\r
+#define isc_prcnotdef 335544511L\r
+#define isc_prcmismat 335544512L\r
+#define isc_wal_bugcheck 335544513L\r
+#define isc_wal_cant_expand 335544514L\r
+#define isc_codnotdef 335544515L\r
+#define isc_xcpnotdef 335544516L\r
+#define isc_except 335544517L\r
+#define isc_cache_restart 335544518L\r
+#define isc_bad_lock_handle 335544519L\r
+#define isc_jrn_present 335544520L\r
+#define isc_wal_err_rollover2 335544521L\r
+#define isc_wal_err_logwrite 335544522L\r
+#define isc_wal_err_jrn_comm 335544523L\r
+#define isc_wal_err_expansion 335544524L\r
+#define isc_wal_err_setup 335544525L\r
+#define isc_wal_err_ww_sync 335544526L\r
+#define isc_wal_err_ww_start 335544527L\r
+#define isc_shutdown 335544528L\r
+#define isc_existing_priv_mod 335544529L\r
+#define isc_primary_key_ref 335544530L\r
+#define isc_primary_key_notnull 335544531L\r
+#define isc_ref_cnstrnt_notfound 335544532L\r
+#define isc_foreign_key_notfound 335544533L\r
+#define isc_ref_cnstrnt_update 335544534L\r
+#define isc_check_cnstrnt_update 335544535L\r
+#define isc_check_cnstrnt_del 335544536L\r
+#define isc_integ_index_seg_del 335544537L\r
+#define isc_integ_index_seg_mod 335544538L\r
+#define isc_integ_index_del 335544539L\r
+#define isc_integ_index_mod 335544540L\r
+#define isc_check_trig_del 335544541L\r
+#define isc_check_trig_update 335544542L\r
+#define isc_cnstrnt_fld_del 335544543L\r
+#define isc_cnstrnt_fld_rename 335544544L\r
+#define isc_rel_cnstrnt_update 335544545L\r
+#define isc_constaint_on_view 335544546L\r
+#define isc_invld_cnstrnt_type 335544547L\r
+#define isc_primary_key_exists 335544548L\r
+#define isc_systrig_update 335544549L\r
+#define isc_not_rel_owner 335544550L\r
+#define isc_grant_obj_notfound 335544551L\r
+#define isc_grant_fld_notfound 335544552L\r
+#define isc_grant_nopriv 335544553L\r
+#define isc_nonsql_security_rel 335544554L\r
+#define isc_nonsql_security_fld 335544555L\r
+#define isc_wal_cache_err 335544556L\r
+#define isc_shutfail 335544557L\r
+#define isc_check_constraint 335544558L\r
+#define isc_bad_svc_handle 335544559L\r
+#define isc_shutwarn 335544560L\r
+#define isc_wrospbver 335544561L\r
+#define isc_bad_spb_form 335544562L\r
+#define isc_svcnotdef 335544563L\r
+#define isc_no_jrn 335544564L\r
+#define isc_transliteration_failed 335544565L\r
+#define isc_start_cm_for_wal 335544566L\r
+#define isc_wal_ovflow_log_required 335544567L\r
+#define isc_text_subtype 335544568L\r
+#define isc_dsql_error 335544569L\r
+#define isc_dsql_command_err 335544570L\r
+#define isc_dsql_constant_err 335544571L\r
+#define isc_dsql_cursor_err 335544572L\r
+#define isc_dsql_datatype_err 335544573L\r
+#define isc_dsql_decl_err 335544574L\r
+#define isc_dsql_cursor_update_err 335544575L\r
+#define isc_dsql_cursor_open_err 335544576L\r
+#define isc_dsql_cursor_close_err 335544577L\r
+#define isc_dsql_field_err 335544578L\r
+#define isc_dsql_internal_err 335544579L\r
+#define isc_dsql_relation_err 335544580L\r
+#define isc_dsql_procedure_err 335544581L\r
+#define isc_dsql_request_err 335544582L\r
+#define isc_dsql_sqlda_err 335544583L\r
+#define isc_dsql_var_count_err 335544584L\r
+#define isc_dsql_stmt_handle 335544585L\r
+#define isc_dsql_function_err 335544586L\r
+#define isc_dsql_blob_err 335544587L\r
+#define isc_collation_not_found 335544588L\r
+#define isc_collation_not_for_charset 335544589L\r
+#define isc_dsql_dup_option 335544590L\r
+#define isc_dsql_tran_err 335544591L\r
+#define isc_dsql_invalid_array 335544592L\r
+#define isc_dsql_max_arr_dim_exceeded 335544593L\r
+#define isc_dsql_arr_range_error 335544594L\r
+#define isc_dsql_trigger_err 335544595L\r
+#define isc_dsql_subselect_err 335544596L\r
+#define isc_dsql_crdb_prepare_err 335544597L\r
+#define isc_specify_field_err 335544598L\r
+#define isc_num_field_err 335544599L\r
+#define isc_col_name_err 335544600L\r
+#define isc_where_err 335544601L\r
+#define isc_table_view_err 335544602L\r
+#define isc_distinct_err 335544603L\r
+#define isc_key_field_count_err 335544604L\r
+#define isc_subquery_err 335544605L\r
+#define isc_expression_eval_err 335544606L\r
+#define isc_node_err 335544607L\r
+#define isc_command_end_err 335544608L\r
+#define isc_index_name 335544609L\r
+#define isc_exception_name 335544610L\r
+#define isc_field_name 335544611L\r
+#define isc_token_err 335544612L\r
+#define isc_union_err 335544613L\r
+#define isc_dsql_construct_err 335544614L\r
+#define isc_field_aggregate_err 335544615L\r
+#define isc_field_ref_err 335544616L\r
+#define isc_order_by_err 335544617L\r
+#define isc_return_mode_err 335544618L\r
+#define isc_extern_func_err 335544619L\r
+#define isc_alias_conflict_err 335544620L\r
+#define isc_procedure_conflict_error 335544621L\r
+#define isc_relation_conflict_err 335544622L\r
+#define isc_dsql_domain_err 335544623L\r
+#define isc_idx_seg_err 335544624L\r
+#define isc_node_name_err 335544625L\r
+#define isc_table_name 335544626L\r
+#define isc_proc_name 335544627L\r
+#define isc_idx_create_err 335544628L\r
+#define isc_wal_shadow_err 335544629L\r
+#define isc_dependency 335544630L\r
+#define isc_idx_key_err 335544631L\r
+#define isc_dsql_file_length_err 335544632L\r
+#define isc_dsql_shadow_number_err 335544633L\r
+#define isc_dsql_token_unk_err 335544634L\r
+#define isc_dsql_no_relation_alias 335544635L\r
+#define isc_indexname 335544636L\r
+#define isc_no_stream_plan 335544637L\r
+#define isc_stream_twice 335544638L\r
+#define isc_stream_not_found 335544639L\r
+#define isc_collation_requires_text 335544640L\r
+#define isc_dsql_domain_not_found 335544641L\r
+#define isc_index_unused 335544642L\r
+#define isc_dsql_self_join 335544643L\r
+#define isc_stream_bof 335544644L\r
+#define isc_stream_crack 335544645L\r
+#define isc_db_or_file_exists 335544646L\r
+#define isc_invalid_operator 335544647L\r
+#define isc_conn_lost 335544648L\r
+#define isc_bad_checksum 335544649L\r
+#define isc_page_type_err 335544650L\r
+#define isc_ext_readonly_err 335544651L\r
+#define isc_sing_select_err 335544652L\r
+#define isc_psw_attach 335544653L\r
+#define isc_psw_start_trans 335544654L\r
+#define isc_invalid_direction 335544655L\r
+#define isc_dsql_var_conflict 335544656L\r
+#define isc_dsql_no_blob_array 335544657L\r
+#define isc_dsql_base_table 335544658L\r
+#define isc_duplicate_base_table 335544659L\r
+#define isc_view_alias 335544660L\r
+#define isc_index_root_page_full 335544661L\r
+#define isc_dsql_blob_type_unknown 335544662L\r
+#define isc_req_max_clones_exceeded 335544663L\r
+#define isc_dsql_duplicate_spec 335544664L\r
+#define isc_unique_key_violation 335544665L\r
+#define isc_srvr_version_too_old 335544666L\r
+#define isc_drdb_completed_with_errs 335544667L\r
+#define isc_dsql_procedure_use_err 335544668L\r
+#define isc_dsql_count_mismatch 335544669L\r
+#define isc_blob_idx_err 335544670L\r
+#define isc_array_idx_err 335544671L\r
+#define isc_key_field_err 335544672L\r
+#define isc_no_delete 335544673L\r
+#define isc_del_last_field 335544674L\r
+#define isc_sort_err 335544675L\r
+#define isc_sort_mem_err 335544676L\r
+#define isc_version_err 335544677L\r
+#define isc_inval_key_posn 335544678L\r
+#define isc_no_segments_err 335544679L\r
+#define isc_crrp_data_err 335544680L\r
+#define isc_rec_size_err 335544681L\r
+#define isc_dsql_field_ref 335544682L\r
+#define isc_req_depth_exceeded 335544683L\r
+#define isc_no_field_access 335544684L\r
+#define isc_no_dbkey 335544685L\r
+#define isc_jrn_format_err 335544686L\r
+#define isc_jrn_file_full 335544687L\r
+#define isc_dsql_open_cursor_request 335544688L\r
+#define isc_ib_error 335544689L\r
+#define isc_cache_redef 335544690L\r
+#define isc_cache_too_small 335544691L\r
+#define isc_log_redef 335544692L\r
+#define isc_log_too_small 335544693L\r
+#define isc_partition_too_small 335544694L\r
+#define isc_partition_not_supp 335544695L\r
+#define isc_log_length_spec 335544696L\r
+#define isc_precision_err 335544697L\r
+#define isc_scale_nogt 335544698L\r
+#define isc_expec_short 335544699L\r
+#define isc_expec_long 335544700L\r
+#define isc_expec_ushort 335544701L\r
+#define isc_like_escape_invalid 335544702L\r
+#define isc_svcnoexe 335544703L\r
+#define isc_net_lookup_err 335544704L\r
+#define isc_service_unknown 335544705L\r
+#define isc_host_unknown 335544706L\r
+#define isc_grant_nopriv_on_base 335544707L\r
+#define isc_dyn_fld_ambiguous 335544708L\r
+#define isc_dsql_agg_ref_err 335544709L\r
+#define isc_complex_view 335544710L\r
+#define isc_unprepared_stmt 335544711L\r
+#define isc_expec_positive 335544712L\r
+#define isc_dsql_sqlda_value_err 335544713L\r
+#define isc_invalid_array_id 335544714L\r
+#define isc_extfile_uns_op 335544715L\r
+#define isc_svc_in_use 335544716L\r
+#define isc_err_stack_limit 335544717L\r
+#define isc_invalid_key 335544718L\r
+#define isc_net_init_error 335544719L\r
+#define isc_loadlib_failure 335544720L\r
+#define isc_network_error 335544721L\r
+#define isc_net_connect_err 335544722L\r
+#define isc_net_connect_listen_err 335544723L\r
+#define isc_net_event_connect_err 335544724L\r
+#define isc_net_event_listen_err 335544725L\r
+#define isc_net_read_err 335544726L\r
+#define isc_net_write_err 335544727L\r
+#define isc_integ_index_deactivate 335544728L\r
+#define isc_integ_deactivate_primary 335544729L\r
+#define isc_cse_not_supported 335544730L\r
+#define isc_tra_must_sweep 335544731L\r
+#define isc_unsupported_network_drive 335544732L\r
+#define isc_io_create_err 335544733L\r
+#define isc_io_open_err 335544734L\r
+#define isc_io_close_err 335544735L\r
+#define isc_io_read_err 335544736L\r
+#define isc_io_write_err 335544737L\r
+#define isc_io_delete_err 335544738L\r
+#define isc_io_access_err 335544739L\r
+#define isc_udf_exception 335544740L\r
+#define isc_lost_db_connection 335544741L\r
+#define isc_no_write_user_priv 335544742L\r
+#define isc_token_too_long 335544743L\r
+#define isc_max_att_exceeded 335544744L\r
+#define isc_login_same_as_role_name 335544745L\r
+#define isc_reftable_requires_pk 335544746L\r
+#define isc_usrname_too_long 335544747L\r
+#define isc_password_too_long 335544748L\r
+#define isc_usrname_required 335544749L\r
+#define isc_password_required 335544750L\r
+#define isc_bad_protocol 335544751L\r
+#define isc_dup_usrname_found 335544752L\r
+#define isc_usrname_not_found 335544753L\r
+#define isc_error_adding_sec_record 335544754L\r
+#define isc_error_modifying_sec_record 335544755L\r
+#define isc_error_deleting_sec_record 335544756L\r
+#define isc_error_updating_sec_db 335544757L\r
+#define isc_sort_rec_size_err 335544758L\r
+#define isc_bad_default_value 335544759L\r
+#define isc_invalid_clause 335544760L\r
+#define isc_too_many_handles 335544761L\r
+#define isc_optimizer_blk_exc 335544762L\r
+#define isc_invalid_string_constant 335544763L\r
+#define isc_transitional_date 335544764L\r
+#define isc_read_only_database 335544765L\r
+#define isc_must_be_dialect_2_and_up 335544766L\r
+#define isc_blob_filter_exception 335544767L\r
+#define isc_exception_access_violation 335544768L\r
+#define isc_exception_datatype_missalignment 335544769L\r
+#define isc_exception_array_bounds_exceeded 335544770L\r
+#define isc_exception_float_denormal_operand 335544771L\r
+#define isc_exception_float_divide_by_zero 335544772L\r
+#define isc_exception_float_inexact_result 335544773L\r
+#define isc_exception_float_invalid_operand 335544774L\r
+#define isc_exception_float_overflow 335544775L\r
+#define isc_exception_float_stack_check 335544776L\r
+#define isc_exception_float_underflow 335544777L\r
+#define isc_exception_integer_divide_by_zero 335544778L\r
+#define isc_exception_integer_overflow 335544779L\r
+#define isc_exception_unknown 335544780L\r
+#define isc_exception_stack_overflow 335544781L\r
+#define isc_exception_sigsegv 335544782L\r
+#define isc_exception_sigill 335544783L\r
+#define isc_exception_sigbus 335544784L\r
+#define isc_exception_sigfpe 335544785L\r
+#define isc_ext_file_delete 335544786L\r
+#define isc_ext_file_modify 335544787L\r
+#define isc_adm_task_denied 335544788L\r
+#define isc_extract_input_mismatch 335544789L\r
+#define isc_insufficient_svc_privileges 335544790L\r
+#define isc_file_in_use 335544791L\r
+#define isc_service_att_err 335544792L\r
+#define isc_ddl_not_allowed_by_db_sql_dial 335544793L\r
+#define isc_cancelled 335544794L\r
+#define isc_unexp_spb_form 335544795L\r
+#define isc_sql_dialect_datatype_unsupport 335544796L\r
+#define isc_svcnouser 335544797L\r
+#define isc_depend_on_uncommitted_rel 335544798L\r
+#define isc_svc_name_missing 335544799L\r
+#define isc_too_many_contexts 335544800L\r
+#define isc_datype_notsup 335544801L\r
+#define isc_dialect_reset_warning 335544802L\r
+#define isc_dialect_not_changed 335544803L\r
+#define isc_database_create_failed 335544804L\r
+#define isc_inv_dialect_specified 335544805L\r
+#define isc_valid_db_dialects 335544806L\r
+#define isc_sqlwarn 335544807L\r
+#define isc_dtype_renamed 335544808L\r
+#define isc_extern_func_dir_error 335544809L\r
+#define isc_date_range_exceeded 335544810L\r
+#define isc_inv_client_dialect_specified 335544811L\r
+#define isc_valid_client_dialects 335544812L\r
+#define isc_optimizer_between_err 335544813L\r
+#define isc_service_not_supported 335544814L\r
+#define isc_generator_name 335544815L\r
+#define isc_udf_name 335544816L\r
+#define isc_bad_limit_param 335544817L\r
+#define isc_bad_skip_param 335544818L\r
+#define isc_io_32bit_exceeded_err 335544819L\r
+#define isc_invalid_savepoint 335544820L\r
+#define isc_dsql_column_pos_err 335544821L\r
+#define isc_dsql_agg_where_err 335544822L\r
+#define isc_dsql_agg_group_err 335544823L\r
+#define isc_dsql_agg_column_err 335544824L\r
+#define isc_dsql_agg_having_err 335544825L\r
+#define isc_dsql_agg_nested_err 335544826L\r
+#define isc_exec_sql_invalid_arg 335544827L\r
+#define isc_exec_sql_invalid_req 335544828L\r
+#define isc_exec_sql_invalid_var 335544829L\r
+#define isc_exec_sql_max_call_exceeded 335544830L\r
+#define isc_conf_access_denied 335544831L\r
+#define isc_gfix_db_name 335740929L\r
+#define isc_gfix_invalid_sw 335740930L\r
+#define isc_gfix_incmp_sw 335740932L\r
+#define isc_gfix_replay_req 335740933L\r
+#define isc_gfix_pgbuf_req 335740934L\r
+#define isc_gfix_val_req 335740935L\r
+#define isc_gfix_pval_req 335740936L\r
+#define isc_gfix_trn_req 335740937L\r
+#define isc_gfix_full_req 335740940L\r
+#define isc_gfix_usrname_req 335740941L\r
+#define isc_gfix_pass_req 335740942L\r
+#define isc_gfix_subs_name 335740943L\r
+#define isc_gfix_wal_req 335740944L\r
+#define isc_gfix_sec_req 335740945L\r
+#define isc_gfix_nval_req 335740946L\r
+#define isc_gfix_type_shut 335740947L\r
+#define isc_gfix_retry 335740948L\r
+#define isc_gfix_retry_db 335740951L\r
+#define isc_gfix_exceed_max 335740991L\r
+#define isc_gfix_corrupt_pool 335740992L\r
+#define isc_gfix_mem_exhausted 335740993L\r
+#define isc_gfix_bad_pool 335740994L\r
+#define isc_gfix_trn_not_valid 335740995L\r
+#define isc_gfix_unexp_eoi 335741012L\r
+#define isc_gfix_recon_fail 335741018L\r
+#define isc_gfix_trn_unknown 335741036L\r
+#define isc_gfix_mode_req 335741038L\r
+#define isc_gfix_opt_SQL_dialect 335741039L\r
+#define isc_dsql_dbkey_from_non_table 336003074L\r
+#define isc_dsql_transitional_numeric 336003075L\r
+#define isc_dsql_dialect_warning_expr 336003076L\r
+#define isc_sql_db_dialect_dtype_unsupport 336003077L\r
+#define isc_isc_sql_dialect_conflict_num 336003079L\r
+#define isc_dsql_warning_number_ambiguous 336003080L\r
+#define isc_dsql_warning_number_ambiguous1 336003081L\r
+#define isc_dsql_warn_precision_ambiguous 336003082L\r
+#define isc_dsql_warn_precision_ambiguous1 336003083L\r
+#define isc_dsql_warn_precision_ambiguous2 336003084L\r
+#define isc_dsql_ambiguous_field_name 336003085L\r
+#define isc_dsql_udf_return_pos_err 336003086L\r
+#define isc_dsql_invalid_label 336003087L\r
+#define isc_dsql_datatypes_not_comparable 336003088L\r
+#define isc_dyn_role_does_not_exist 336068796L\r
+#define isc_dyn_no_grant_admin_opt 336068797L\r
+#define isc_dyn_user_not_role_member 336068798L\r
+#define isc_dyn_delete_role_failed 336068799L\r
+#define isc_dyn_grant_role_to_user 336068800L\r
+#define isc_dyn_inv_sql_role_name 336068801L\r
+#define isc_dyn_dup_sql_role 336068802L\r
+#define isc_dyn_kywd_spec_for_role 336068803L\r
+#define isc_dyn_roles_not_supported 336068804L\r
+#define isc_dyn_domain_name_exists 336068812L\r
+#define isc_dyn_field_name_exists 336068813L\r
+#define isc_dyn_dependency_exists 336068814L\r
+#define isc_dyn_dtype_invalid 336068815L\r
+#define isc_dyn_char_fld_too_small 336068816L\r
+#define isc_dyn_invalid_dtype_conversion 336068817L\r
+#define isc_dyn_dtype_conv_invalid 336068818L\r
+#define isc_dyn_zero_len_id 336068820L\r
+#define isc_gbak_unknown_switch 336330753L\r
+#define isc_gbak_page_size_missing 336330754L\r
+#define isc_gbak_page_size_toobig 336330755L\r
+#define isc_gbak_redir_ouput_missing 336330756L\r
+#define isc_gbak_switches_conflict 336330757L\r
+#define isc_gbak_unknown_device 336330758L\r
+#define isc_gbak_no_protection 336330759L\r
+#define isc_gbak_page_size_not_allowed 336330760L\r
+#define isc_gbak_multi_source_dest 336330761L\r
+#define isc_gbak_filename_missing 336330762L\r
+#define isc_gbak_dup_inout_names 336330763L\r
+#define isc_gbak_inv_page_size 336330764L\r
+#define isc_gbak_db_specified 336330765L\r
+#define isc_gbak_db_exists 336330766L\r
+#define isc_gbak_unk_device 336330767L\r
+#define isc_gbak_blob_info_failed 336330772L\r
+#define isc_gbak_unk_blob_item 336330773L\r
+#define isc_gbak_get_seg_failed 336330774L\r
+#define isc_gbak_close_blob_failed 336330775L\r
+#define isc_gbak_open_blob_failed 336330776L\r
+#define isc_gbak_put_blr_gen_id_failed 336330777L\r
+#define isc_gbak_unk_type 336330778L\r
+#define isc_gbak_comp_req_failed 336330779L\r
+#define isc_gbak_start_req_failed 336330780L\r
+#define isc_gbak_rec_failed 336330781L\r
+#define isc_gbak_rel_req_failed 336330782L\r
+#define isc_gbak_db_info_failed 336330783L\r
+#define isc_gbak_no_db_desc 336330784L\r
+#define isc_gbak_db_create_failed 336330785L\r
+#define isc_gbak_decomp_len_error 336330786L\r
+#define isc_gbak_tbl_missing 336330787L\r
+#define isc_gbak_blob_col_missing 336330788L\r
+#define isc_gbak_create_blob_failed 336330789L\r
+#define isc_gbak_put_seg_failed 336330790L\r
+#define isc_gbak_rec_len_exp 336330791L\r
+#define isc_gbak_inv_rec_len 336330792L\r
+#define isc_gbak_exp_data_type 336330793L\r
+#define isc_gbak_gen_id_failed 336330794L\r
+#define isc_gbak_unk_rec_type 336330795L\r
+#define isc_gbak_inv_bkup_ver 336330796L\r
+#define isc_gbak_missing_bkup_desc 336330797L\r
+#define isc_gbak_string_trunc 336330798L\r
+#define isc_gbak_cant_rest_record 336330799L\r
+#define isc_gbak_send_failed 336330800L\r
+#define isc_gbak_no_tbl_name 336330801L\r
+#define isc_gbak_unexp_eof 336330802L\r
+#define isc_gbak_db_format_too_old 336330803L\r
+#define isc_gbak_inv_array_dim 336330804L\r
+#define isc_gbak_xdr_len_expected 336330807L\r
+#define isc_gbak_open_bkup_error 336330817L\r
+#define isc_gbak_open_error 336330818L\r
+#define isc_gbak_missing_block_fac 336330934L\r
+#define isc_gbak_inv_block_fac 336330935L\r
+#define isc_gbak_block_fac_specified 336330936L\r
+#define isc_gbak_missing_username 336330940L\r
+#define isc_gbak_missing_password 336330941L\r
+#define isc_gbak_missing_skipped_bytes 336330952L\r
+#define isc_gbak_inv_skipped_bytes 336330953L\r
+#define isc_gbak_err_restore_charset 336330965L\r
+#define isc_gbak_err_restore_collation 336330967L\r
+#define isc_gbak_read_error 336330972L\r
+#define isc_gbak_write_error 336330973L\r
+#define isc_gbak_db_in_use 336330985L\r
+#define isc_gbak_sysmemex 336330990L\r
+#define isc_gbak_restore_role_failed 336331002L\r
+#define isc_gbak_role_op_missing 336331005L\r
+#define isc_gbak_page_buffers_missing 336331010L\r
+#define isc_gbak_page_buffers_wrong_param 336331011L\r
+#define isc_gbak_page_buffers_restore 336331012L\r
+#define isc_gbak_inv_size 336331014L\r
+#define isc_gbak_file_outof_sequence 336331015L\r
+#define isc_gbak_join_file_missing 336331016L\r
+#define isc_gbak_stdin_not_supptd 336331017L\r
+#define isc_gbak_stdout_not_supptd 336331018L\r
+#define isc_gbak_bkup_corrupt 336331019L\r
+#define isc_gbak_unk_db_file_spec 336331020L\r
+#define isc_gbak_hdr_write_failed 336331021L\r
+#define isc_gbak_disk_space_ex 336331022L\r
+#define isc_gbak_size_lt_min 336331023L\r
+#define isc_gbak_svc_name_missing 336331025L\r
+#define isc_gbak_not_ownr 336331026L\r
+#define isc_gbak_mode_req 336331031L\r
+#define isc_gbak_just_data 336331033L\r
+#define isc_gbak_data_only 336331034L\r
+#define isc_gsec_cant_open_db 336723983L\r
+#define isc_gsec_switches_error 336723984L\r
+#define isc_gsec_no_op_spec 336723985L\r
+#define isc_gsec_no_usr_name 336723986L\r
+#define isc_gsec_err_add 336723987L\r
+#define isc_gsec_err_modify 336723988L\r
+#define isc_gsec_err_find_mod 336723989L\r
+#define isc_gsec_err_rec_not_found 336723990L\r
+#define isc_gsec_err_delete 336723991L\r
+#define isc_gsec_err_find_del 336723992L\r
+#define isc_gsec_err_find_disp 336723996L\r
+#define isc_gsec_inv_param 336723997L\r
+#define isc_gsec_op_specified 336723998L\r
+#define isc_gsec_pw_specified 336723999L\r
+#define isc_gsec_uid_specified 336724000L\r
+#define isc_gsec_gid_specified 336724001L\r
+#define isc_gsec_proj_specified 336724002L\r
+#define isc_gsec_org_specified 336724003L\r
+#define isc_gsec_fname_specified 336724004L\r
+#define isc_gsec_mname_specified 336724005L\r
+#define isc_gsec_lname_specified 336724006L\r
+#define isc_gsec_inv_switch 336724008L\r
+#define isc_gsec_amb_switch 336724009L\r
+#define isc_gsec_no_op_specified 336724010L\r
+#define isc_gsec_params_not_allowed 336724011L\r
+#define isc_gsec_incompat_switch 336724012L\r
+#define isc_gsec_inv_username 336724044L\r
+#define isc_gsec_inv_pw_length 336724045L\r
+#define isc_gsec_db_specified 336724046L\r
+#define isc_gsec_db_admin_specified 336724047L\r
+#define isc_gsec_db_admin_pw_specified 336724048L\r
+#define isc_gsec_sql_role_specified 336724049L\r
+#define isc_license_no_file 336789504L\r
+#define isc_license_op_specified 336789523L\r
+#define isc_license_op_missing 336789524L\r
+#define isc_license_inv_switch 336789525L\r
+#define isc_license_inv_switch_combo 336789526L\r
+#define isc_license_inv_op_combo 336789527L\r
+#define isc_license_amb_switch 336789528L\r
+#define isc_license_inv_parameter 336789529L\r
+#define isc_license_param_specified 336789530L\r
+#define isc_license_param_req 336789531L\r
+#define isc_license_syntx_error 336789532L\r
+#define isc_license_dup_id 336789534L\r
+#define isc_license_inv_id_key 336789535L\r
+#define isc_license_err_remove 336789536L\r
+#define isc_license_err_update 336789537L\r
+#define isc_license_err_convert 336789538L\r
+#define isc_license_err_unk 336789539L\r
+#define isc_license_svc_err_add 336789540L\r
+#define isc_license_svc_err_remove 336789541L\r
+#define isc_license_eval_exists 336789563L\r
+#define isc_gstat_unknown_switch 336920577L\r
+#define isc_gstat_retry 336920578L\r
+#define isc_gstat_wrong_ods 336920579L\r
+#define isc_gstat_unexpected_eof 336920580L\r
+#define isc_gstat_open_err 336920605L\r
+#define isc_gstat_read_err 336920606L\r
+#define isc_gstat_sysmemex 336920607L\r
+#define isc_err_max 713\r
+\r
+#endif /* JRD_GEN_IBERROR_H */\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: ibpp.h,v 1.3 2007/10/28 11:17:44 nobunaga Exp $\r
+// Subject : IBPP public header file. This is _the_ only file you include in\r
+// your application files when developing with IBPP.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+// Contributor(s):\r
+//\r
+// Olivier Mascia, main coding\r
+// Matt Hortman, initial linux port\r
+// Mark Jordan, design contributions\r
+// Maxim Abrashkin, enhancement patches\r
+// Torsten Martinsen, enhancement patches\r
+// Michael Hieke, darwin (OS X) port, enhancement patches\r
+// Val Samko, enhancement patches and debugging\r
+// Mike Nordell, invaluable C++ advices\r
+// Claudio Valderrama, help with not-so-well documented IB/FB features\r
+// Many others, excellent suggestions, bug finding, and support\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// Tabulations should be set every four characters when editing this file.\r
+//\r
+// When compiling a project using IBPP, the following defines should be made\r
+// on the command-line (or in makefiles) according to the OS platform and\r
+// compiler used.\r
+//\r
+// Select the platform: IBPP_WINDOWS | IBPP_LINUX | IBPP_DARWIN\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __IBPP_H__\r
+#define __IBPP_H__\r
+\r
+#if !defined(IBPP_WINDOWS) && !defined(IBPP_LINUX) && !defined(IBPP_DARWIN)\r
+#error Please define IBPP_WINDOWS/IBPP_LINUX/IBPP_DARWIN before compiling !\r
+#endif\r
+\r
+#if !defined(__BCPLUSPLUS__) && !defined(__GNUC__) && !defined(_MSC_VER) && !defined(__DMC__)
+#error Your compiler is not recognized.\r
+#endif\r
+\r
+#if defined(IBPP_LINUX) || defined(IBPP_DARWIN)\r
+#define IBPP_UNIX // IBPP_UNIX stands as a common denominator to *NIX flavours\r
+#endif\r
+\r
+// IBPP is written for 32 bits systems or higher.\r
+// The standard type 'int' is assumed to be at least 32 bits.\r
+// And the standard type 'short' is assumed to be exactly 16 bits.\r
+// Everywhere possible, where the exact size of an integer does not matter,\r
+// the standard type 'int' is used. And where an exact integer size is required\r
+// the standard exact precision types definitions of C 99 standard are used.\r
+\r
+#if defined(_MSC_VER) || defined(__DMC__) || defined(__BCPLUSPLUS__)\r
+// C99 §7.18.1.1 Exact-width integer types (only those used by IBPP)\r
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
+ typedef short int16_t;\r
+ typedef int int32_t;\r
+ typedef unsigned int uint32_t;\r
+#else\r
+ typedef __int16 int16_t;\r
+ typedef __int32 int32_t;\r
+ typedef unsigned __int32 uint32_t;\r
+#endif\r
+ typedef __int64 int64_t;\r
+#else\r
+ #include <cstdint> // C99 (§7.18) integer types definitions\r
+#endif\r
+\r
+#if !defined(_)\r
+#define _(s) s\r
+#endif\r
+\r
+#include <exception>\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace IBPP\r
+{\r
+ // Typically you use this constant in a call IBPP::CheckVersion as in:\r
+ // if (! IBPP::CheckVersion(IBPP::Version)) { throw .... ; }\r
+ const uint32_t Version = (2<<24) + (5<<16) + (3<<8) + 0; // Version == 2.5.3.0\r
+\r
+ // Dates range checking\r
+ const int MinDate = -693594; // 1 JAN 0001\r
+ const int MaxDate = 2958464; // 31 DEC 9999\r
+ \r
+ // Transaction Access Modes\r
+ enum TAM {amWrite, amRead};\r
+\r
+ // Transaction Isolation Levels\r
+ enum TIL {ilConcurrency, ilReadDirty, ilReadCommitted, ilConsistency};\r
+\r
+ // Transaction Lock Resolution\r
+ enum TLR {lrWait, lrNoWait};\r
+\r
+ // Transaction Table Reservation\r
+ enum TTR {trSharedWrite, trSharedRead, trProtectedWrite, trProtectedRead};\r
+\r
+ // Prepared Statement Types\r
+ enum STT {stUnknown, stUnsupported,\r
+ stSelect, stInsert, stUpdate, stDelete, stDDL, stExecProcedure,\r
+ stSelectUpdate, stSetGenerator, stSavePoint};\r
+\r
+ // SQL Data Types\r
+ enum SDT {sdArray, sdBlob, sdDate, sdTime, sdTimestamp, sdString,\r
+ sdSmallint, sdInteger, sdLargeint, sdFloat, sdDouble};\r
+\r
+ // Array Data Types\r
+ enum ADT {adDate, adTime, adTimestamp, adString,\r
+ adBool, adInt16, adInt32, adInt64, adFloat, adDouble};\r
+\r
+ // Database::Shutdown Modes\r
+ enum DSM {dsForce, dsDenyTrans, dsDenyAttach};\r
+\r
+ // Service::StartBackup && Service::StartRestore Flags\r
+ enum BRF {\r
+ brVerbose = 0x1,\r
+ // Backup flags\r
+ brIgnoreChecksums = 0x100, brIgnoreLimbo = 0x200,\r
+ brMetadataOnly = 0x400, brNoGarbageCollect = 0x800,\r
+ brNonTransportable = 0x1000, brConvertExtTables = 0x2000,\r
+ // Restore flags\r
+ brReplace = 0x10000, brDeactivateIdx = 0x20000,\r
+ brNoShadow = 0x40000, brNoValidity = 0x80000,\r
+ brPerTableCommit = 0x100000, brUseAllSpace = 0x200000\r
+ };\r
+\r
+ // Service::Repair Flags\r
+ enum RPF\r
+ {\r
+ // Mandatory and mutually exclusives\r
+ rpMendRecords = 0x1, rpValidatePages = 0x2, rpValidateFull = 0x4,\r
+ // Options\r
+ rpReadOnly = 0x100, rpIgnoreChecksums = 0x200, rpKillShadows = 0x400\r
+ };\r
+\r
+ // TransactionFactory Flags\r
+ enum TFF {tfIgnoreLimbo = 0x1, tfAutoCommit = 0x2, tfNoAutoUndo = 0x4};\r
+\r
+ /* IBPP never return any error codes. It throws exceptions.\r
+ * On database engine reported errors, an IBPP::SQLException is thrown.\r
+ * In all other cases, IBPP throws IBPP::LogicException.\r
+ * Also note that the runtime and the language might also throw exceptions\r
+ * while executing some IBPP methods. A failing new operator will throw\r
+ * std::bad_alloc, IBPP does nothing to alter the standard behaviour.\r
+ *\r
+ * std::exception\r
+ * |\r
+ * IBPP::Exception\r
+ * / \\r
+ * IBPP::LogicException IBPP::SQLException\r
+ * |\r
+ * IBPP::WrongType\r
+ */\r
+\r
+ class Exception : public std::exception\r
+ {\r
+ public:\r
+ virtual const char* Origin() const throw() = 0;\r
+ virtual const char* ErrorMessage() const throw() = 0; // Deprecated, use what()\r
+ virtual const char* what() const throw() = 0;\r
+ virtual ~Exception() throw();\r
+ };\r
+\r
+ class LogicException : public Exception\r
+ {\r
+ public:\r
+ virtual ~LogicException() throw();\r
+ };\r
+\r
+ class SQLException : public Exception\r
+ {\r
+ public:\r
+ virtual int SqlCode() const throw() = 0;\r
+ virtual int EngineCode() const throw() = 0;\r
+ \r
+ virtual ~SQLException() throw();\r
+ };\r
+\r
+ class WrongType : public LogicException\r
+ {\r
+ public:\r
+ virtual ~WrongType() throw();\r
+ };\r
+ \r
+ /* Classes Date, Time, Timestamp and DBKey are 'helper' classes. They help\r
+ * in retrieving or setting some special SQL types. Dates, times and dbkeys\r
+ * are often read and written as strings in SQL scripts. When programming\r
+ * with IBPP, we handle those data with these specific classes, which\r
+ * enhance their usefullness and free us of format problems (M/D/Y, D/M/Y,\r
+ * Y-M-D ?, and so on...). */\r
+\r
+ /* Class Date represent purely a Date (no time part specified). It is\r
+ * usefull in interactions with the SQL DATE type of Interbase. You can add\r
+ * or substract a number from a Date, that will modify it to represent the\r
+ * correct date, X days later or sooner. All the Y2K details taken into\r
+ * account.\r
+ * The full range goes from integer values IBPP::MinDate to IBPP::MaxDate\r
+ * which means from 01 Jan 0001 to 31 Dec 9999. ( Which is inherently\r
+ * incorrect as this assumes Gregorian calendar. ) */\r
+ \r
+ class Timestamp; // Cross-reference between Timestamp, Date and Time\r
+ \r
+ class Date\r
+ {\r
+ protected:\r
+ int mDate; // The date : 1 == 1 Jan 1900\r
+\r
+ public:\r
+ void Clear() { mDate = MinDate - 1; }\r
+ void Today();\r
+ void SetDate(int year, int month, int day);\r
+ void SetDate(int dt);\r
+ void GetDate(int& year, int& month, int& day) const;\r
+ int GetDate() const { return mDate; }\r
+ int Year() const;\r
+ int Month() const;\r
+ int Day() const;\r
+ void Add(int days);\r
+ void StartOfMonth();\r
+ void EndOfMonth();\r
+ \r
+ Date() { Clear(); }\r
+ Date(int dt) { SetDate(dt); }\r
+ Date(int year, int month, int day);\r
+ Date(const Date&); // Copy Constructor\r
+ Date& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Date& operator=(const Date&); // Date Assignment operator\r
+\r
+ bool operator==(const Date& rv) const { return mDate == rv.GetDate(); }\r
+ bool operator!=(const Date& rv) const { return mDate != rv.GetDate(); }\r
+ bool operator<(const Date& rv) const { return mDate < rv.GetDate(); }\r
+ bool operator>(const Date& rv) const { return mDate > rv.GetDate(); }\r
+\r
+ virtual ~Date() { }\r
+ };\r
+\r
+ /* Class Time represent purely a Time. It is usefull in interactions\r
+ * with the SQL TIME type of Interbase. */\r
+\r
+ class Time\r
+ {\r
+ protected:\r
+ int mTime; // The time, in ten-thousandths of seconds since midnight\r
+\r
+ public:\r
+ void Clear() { mTime = 0; }\r
+ void Now();\r
+ void SetTime(int hour, int minute, int second, int tenthousandths = 0);\r
+ void SetTime(int tm);\r
+ void GetTime(int& hour, int& minute, int& second) const;\r
+ void GetTime(int& hour, int& minute, int& second, int& tenthousandths) const;\r
+ int GetTime() const { return mTime; }\r
+ int Hours() const;\r
+ int Minutes() const;\r
+ int Seconds() const;\r
+ int SubSeconds() const; // Actually tenthousandths of seconds\r
+ Time() { Clear(); }\r
+ Time(int tm) { SetTime(tm); }\r
+ Time(int hour, int minute, int second, int tenthousandths = 0);\r
+ Time(const Time&); // Copy Constructor\r
+ Time& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Time& operator=(const Time&); // Time Assignment operator\r
+\r
+ bool operator==(const Time& rv) const { return mTime == rv.GetTime(); }\r
+ bool operator!=(const Time& rv) const { return mTime != rv.GetTime(); }\r
+ bool operator<(const Time& rv) const { return mTime < rv.GetTime(); }\r
+ bool operator>(const Time& rv) const { return mTime > rv.GetTime(); }\r
+\r
+ virtual ~Time() { }\r
+ };\r
+\r
+ /* Class Timestamp represent a date AND a time. It is usefull in\r
+ * interactions with the SQL TIMESTAMP type of Interbase. This class\r
+ * inherits from Date and Time and completely inline implements its small\r
+ * specific details. */\r
+\r
+ class Timestamp : public Date, public Time\r
+ {\r
+ public:\r
+ void Clear() { Date::Clear(); Time::Clear(); }\r
+ void Today() { Date::Today(); Time::Clear(); }\r
+ void Now() { Date::Today(); Time::Now(); }\r
+\r
+ Timestamp() { Clear(); }\r
+\r
+ Timestamp(int y, int m, int d)\r
+ { Date::SetDate(y, m, d); Time::Clear(); }\r
+\r
+ Timestamp(int y, int mo, int d, int h, int mi, int s, int t = 0)\r
+ { Date::SetDate(y, mo, d); Time::SetTime(h, mi, s, t); }\r
+\r
+ Timestamp(const Timestamp& rv)\r
+ : Date(rv.mDate), Time(rv.mTime) {} // Copy Constructor\r
+\r
+ Timestamp(const Date& rv)\r
+ { mDate = rv.GetDate(); mTime = 0; }\r
+\r
+ Timestamp(const Time& rv)\r
+ { mDate = 0; mTime = rv.GetTime(); }\r
+\r
+ Timestamp& operator=(const Timestamp& rv) // Timestamp Assignment operator\r
+ { mDate = rv.mDate; mTime = rv.mTime; return *this; }\r
+\r
+ Timestamp& operator=(const Date& rv) // Date Assignment operator\r
+ { mDate = rv.GetDate(); return *this; }\r
+\r
+ Timestamp& operator=(const Time& rv) // Time Assignment operator\r
+ { mTime = rv.GetTime(); return *this; }\r
+\r
+ bool operator==(const Timestamp& rv) const\r
+ { return (mDate == rv.GetDate()) && (mTime == rv.GetTime()); }\r
+\r
+ bool operator!=(const Timestamp& rv) const\r
+ { return (mDate != rv.GetDate()) || (mTime != rv.GetTime()); }\r
+\r
+ bool operator<(const Timestamp& rv) const\r
+ { return (mDate < rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime < rv.GetTime()); }\r
+\r
+ bool operator>(const Timestamp& rv) const\r
+ { return (mDate > rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime > rv.GetTime()); }\r
+\r
+ ~Timestamp() { }\r
+ };\r
+\r
+ /* Class DBKey can store a DBKEY, that special value which the hidden\r
+ * RDB$DBKEY can give you from a select statement. A DBKey is nothing\r
+ * specific to IBPP. It's a feature of the Firebird database engine. See its\r
+ * documentation for more information. */\r
+\r
+ class DBKey\r
+ {\r
+ private:\r
+ std::string mDBKey; // Stores the binary DBKey\r
+ mutable std::string mString;// String (temporary) representation of it\r
+\r
+ public:\r
+ void Clear();\r
+ int Size() const { return (int)mDBKey.size(); }\r
+ void SetKey(const void*, int size);\r
+ void GetKey(void*, int size) const;\r
+ const char* AsString() const;\r
+\r
+ DBKey& operator=(const DBKey&); // Assignment operator\r
+ DBKey(const DBKey&); // Copy Constructor\r
+ DBKey() { }\r
+ ~DBKey() { }\r
+ };\r
+\r
+ /* Class User wraps all the information about a user that the engine can manage. */\r
+\r
+ class User\r
+ {\r
+ public:\r
+ std::string username;\r
+ std::string password;\r
+ std::string firstname;\r
+ std::string middlename;\r
+ std::string lastname;\r
+ uint32_t userid; // Only relevant on unixes\r
+ uint32_t groupid; // Only relevant on unixes\r
+\r
+ private:\r
+ void copyfrom(const User& r);\r
+\r
+ public:\r
+ void clear();\r
+ User& operator=(const User& r) { copyfrom(r); return *this; }\r
+ User(const User& r) { copyfrom(r); }\r
+ User() : userid(0), groupid(0) { }\r
+ ~User() { }\r
+ };\r
+\r
+ // Interface Wrapper\r
+ template <class T>\r
+ class Ptr\r
+ {\r
+ private:\r
+ T* mObject;\r
+\r
+ public:\r
+ void clear()\r
+ {\r
+ if (mObject != 0) { mObject->Release(); mObject = 0; }\r
+ }\r
+\r
+ T* intf() const { return mObject; }\r
+ T* operator->() const { return mObject; }\r
+\r
+ bool operator==(const T* p) const { return mObject == p; }\r
+ bool operator==(const Ptr& r) const { return mObject == r.mObject; }\r
+ bool operator!=(const T* p) const { return mObject != p; }\r
+ bool operator!=(const Ptr& r) const { return mObject != r.mObject; }\r
+\r
+ Ptr& operator=(T* p)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (p == 0 ? 0 : p->AddRef()); // Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr& operator=(const Ptr& r)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (r.intf() == 0 ? 0 : r->AddRef());// Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr(T* p) : mObject(p == 0 ? 0 : p->AddRef()) { }\r
+ Ptr(const Ptr& r) : mObject(r.intf() == 0 ? 0 : r->AddRef()) { }\r
+\r
+ Ptr() : mObject(0) { }\r
+ ~Ptr() { clear(); }\r
+ };\r
+\r
+ // --- Interface Classes --- //\r
+\r
+ /* Interfaces IBlob, IArray, IService, IDatabase, ITransaction and\r
+ * IStatement are at the core of IBPP. Though it is possible to program your\r
+ * applications by using theses interfaces directly (as was the case with\r
+ * IBPP 1.x), you should refrain from using them and prefer the new IBPP\r
+ * Objects Blob, Array, ... (without the I in front). Those new objects are\r
+ * typedef'd right after each interface class definition as you can read\r
+ * below. If you program using the Blob (instead of the IBlob interface\r
+ * itself), you'll never have to care about AddRef/Release and you'll never\r
+ * have to care about deleting your objects. */\r
+\r
+ class IBlob; typedef Ptr<IBlob> Blob;\r
+ class IArray; typedef Ptr<IArray> Array;\r
+ class IService; typedef Ptr<IService> Service;\r
+ class IDatabase; typedef Ptr<IDatabase> Database;\r
+ class ITransaction; typedef Ptr<ITransaction> Transaction;\r
+ class IStatement; typedef Ptr<IStatement> Statement;\r
+ class IEvents; typedef Ptr<IEvents> Events;\r
+ class IRow; typedef Ptr<IRow> Row;\r
+\r
+ /* IBlob is the interface to the blob capabilities of IBPP. Blob is the\r
+ * object class you actually use in your programming. In Firebird, at the\r
+ * row level, a blob is merely a handle to a blob, stored elsewhere in the\r
+ * database. Blob allows you to retrieve such a handle and then read from or\r
+ * write to the blob, much in the same manner than you would do with a file. */\r
+\r
+ class IBlob\r
+ {\r
+ public:\r
+ virtual void Create() = 0;\r
+ virtual void Open() = 0;\r
+ virtual void Close() = 0;\r
+ virtual void Cancel() = 0;\r
+ virtual int Read(void*, int size) = 0;\r
+ virtual void Write(const void*, int size) = 0;\r
+ virtual void Info(int* Size, int* Largest, int* Segments) = 0;\r
+ \r
+ virtual void Save(const std::string& data) = 0;\r
+ virtual void Load(std::string& data) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IBlob* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IBlob() { }\r
+ };\r
+\r
+ /* IArray is the interface to the array capabilities of IBPP. Array is the\r
+ * object class you actually use in your programming. With an Array object, you\r
+ * can create, read and write Interbase Arrays, as a whole or in slices. */\r
+\r
+ class IArray\r
+ {\r
+ public:\r
+ virtual void Describe(const std::string& table, const std::string& column) = 0;\r
+ virtual void ReadTo(ADT, void* buffer, int elemcount) = 0;\r
+ virtual void WriteFrom(ADT, const void* buffer, int elemcount) = 0;\r
+ virtual SDT ElementType() = 0;\r
+ virtual int ElementSize() = 0;\r
+ virtual int ElementScale() = 0;\r
+ virtual int Dimensions() = 0;\r
+ virtual void Bounds(int dim, int* low, int* high) = 0;\r
+ virtual void SetBounds(int dim, int low, int high) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IArray* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IArray() { }\r
+ };\r
+\r
+ /* IService is the interface to the service capabilities of IBPP. Service is\r
+ * the object class you actually use in your programming. With a Service\r
+ * object, you can do some maintenance work of databases and servers\r
+ * (backup, restore, create/update users, ...) */\r
+\r
+ class IService\r
+ {\r
+ public:\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Disconnect() = 0;\r
+\r
+ virtual void GetVersion(std::string& version) = 0;\r
+\r
+ virtual void AddUser(const User&) = 0;\r
+ virtual void GetUser(User&) = 0;\r
+ virtual void GetUsers(std::vector<User>&) = 0;\r
+ virtual void ModifyUser(const User&) = 0;\r
+ virtual void RemoveUser(const std::string& username) = 0;\r
+\r
+ virtual void SetPageBuffers(const std::string& dbfile, int buffers) = 0;\r
+ virtual void SetSweepInterval(const std::string& dbfile, int sweep) = 0;\r
+ virtual void SetSyncWrite(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReadOnly(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReserveSpace(const std::string& dbfile, bool) = 0;\r
+\r
+ virtual void Shutdown(const std::string& dbfile, DSM mode, int sectimeout) = 0;\r
+ virtual void Restart(const std::string& dbfile) = 0;\r
+ virtual void Sweep(const std::string& dbfile) = 0;\r
+ virtual void Repair(const std::string& dbfile, RPF flags) = 0;\r
+\r
+ virtual void StartBackup(const std::string& dbfile,\r
+ const std::string& bkfile, BRF flags = BRF(0)) = 0;\r
+ virtual void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize = 0, BRF flags = BRF(0)) = 0;\r
+\r
+ virtual const char* WaitMsg() = 0; // With reporting (does not block)\r
+ virtual void Wait() = 0; // Without reporting (does block)\r
+\r
+ virtual IService* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IService() { }\r
+ };\r
+\r
+ /* IDatabase is the interface to the database connections in IBPP. Database\r
+ * is the object class you actually use in your programming. With a Database\r
+ * object, you can create/drop/connect databases. */\r
+\r
+ class EventInterface; // Cross-reference between EventInterface and IDatabase\r
+ \r
+ class IDatabase\r
+ {\r
+ public:\r
+ virtual const char* ServerName() const = 0;\r
+ virtual const char* DatabaseName() const = 0;\r
+ virtual const char* Username() const = 0;\r
+ virtual const char* UserPassword() const = 0;\r
+ virtual const char* RoleName() const = 0;\r
+ virtual const char* CharSet() const = 0;\r
+ virtual const char* CreateParams() const = 0;\r
+\r
+ virtual void Info(int* ODS, int* ODSMinor, int* PageSize,\r
+ int* Pages, int* Buffers, int* Sweep, bool* Sync,\r
+ bool* Reserve) = 0;\r
+ virtual void Statistics(int* Fetches, int* Marks,\r
+ int* Reads, int* Writes) = 0;\r
+ virtual void Counts(int* Insert, int* Update, int* Delete, \r
+ int* ReadIdx, int* ReadSeq) = 0;\r
+ virtual void Users(std::vector<std::string>& users) = 0;\r
+ virtual int Dialect() = 0;\r
+\r
+ virtual void Create(int dialect) = 0;\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Inactivate() = 0;\r
+ virtual void Disconnect() = 0;\r
+ virtual void Drop() = 0;\r
+\r
+ virtual IDatabase* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IDatabase() { }\r
+ };\r
+\r
+ /* ITransaction is the interface to the transaction connections in IBPP.\r
+ * Transaction is the object class you actually use in your programming. A\r
+ * Transaction object can be associated with more than one Database,\r
+ * allowing for distributed transactions spanning multiple databases,\r
+ * possibly located on different servers. IBPP is one among the few\r
+ * programming interfaces to Firebird that allows you to support distributed\r
+ * transactions. */\r
+\r
+ class ITransaction\r
+ {\r
+ public:\r
+ virtual void AttachDatabase(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)) = 0;\r
+ virtual void DetachDatabase(Database db) = 0;\r
+ virtual void AddReservation(Database db,\r
+ const std::string& table, TTR tr) = 0;\r
+\r
+ virtual void Start() = 0;\r
+ virtual bool Started() = 0;\r
+ virtual void Commit() = 0;\r
+ virtual void Rollback() = 0;\r
+ virtual void CommitRetain() = 0;\r
+ virtual void RollbackRetain() = 0;\r
+\r
+ virtual ITransaction* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~ITransaction() { }\r
+ };\r
+\r
+ /*\r
+ * Class Row can hold all the values of a row (from a SELECT for instance).\r
+ */\r
+\r
+ class IRow\r
+ {\r
+ public:\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t) = 0;\r
+ virtual void Set(int, int32_t) = 0;\r
+ virtual void Set(int, int64_t) = 0;\r
+ virtual void Set(int, float) = 0;\r
+ virtual void Set(int, double) = 0;\r
+ virtual void Set(int, const Timestamp&) = 0;\r
+ virtual void Set(int, const Date&) = 0;\r
+ virtual void Set(int, const Time&) = 0;\r
+ virtual void Set(int, const DBKey&) = 0;\r
+ virtual void Set(int, const Blob&) = 0;\r
+ virtual void Set(int, const Array&) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp&) = 0;\r
+ virtual bool Get(int, Date&) = 0;\r
+ virtual bool Get(int, Time&) = 0;\r
+ virtual bool Get(int, DBKey&) = 0;\r
+ virtual bool Get(int, Blob&) = 0;\r
+ virtual bool Get(int, Array&) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp&) = 0;\r
+ virtual bool Get(const std::string&, Date&) = 0;\r
+ virtual bool Get(const std::string&, Time&) = 0;\r
+ virtual bool Get(const std::string&, DBKey&) = 0;\r
+ virtual bool Get(const std::string&, Blob&) = 0;\r
+ virtual bool Get(const std::string&, Array&) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+ \r
+ virtual bool ColumnUpdated(int) = 0;\r
+ virtual bool Updated() = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IRow* Clone() = 0;\r
+ virtual IRow* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IRow() {}\r
+ };\r
+\r
+ /* IStatement is the interface to the statements execution in IBPP.\r
+ * Statement is the object class you actually use in your programming. A\r
+ * Statement object is the work horse of IBPP. All your data manipulation\r
+ * statements will be done through it. It is also used to access the result\r
+ * set of a query (when the statement is such), one row at a time and in\r
+ * strict forward direction. */\r
+\r
+ class IStatement\r
+ {\r
+ public:\r
+ virtual void Prepare(const std::string&) = 0;\r
+ virtual void Execute() = 0;\r
+ virtual void Execute(const std::string&) = 0;\r
+ virtual void ExecuteImmediate(const std::string&) = 0;\r
+ virtual void CursorExecute(const std::string& cursor) = 0;\r
+ virtual void CursorExecute(const std::string& cursor, const std::string&) = 0;\r
+ virtual bool Fetch() = 0;\r
+ virtual bool Fetch(Row&) = 0;\r
+ virtual int AffectedRows() = 0;\r
+ virtual void Close() = 0;\r
+ virtual std::string& Sql() = 0;\r
+ virtual STT Type() = 0;\r
+\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t value) = 0;\r
+ virtual void Set(int, int32_t value) = 0;\r
+ virtual void Set(int, int64_t value) = 0;\r
+ virtual void Set(int, float value) = 0;\r
+ virtual void Set(int, double value) = 0;\r
+ virtual void Set(int, const Timestamp& value) = 0;\r
+ virtual void Set(int, const Date& value) = 0;\r
+ virtual void Set(int, const Time& value) = 0;\r
+ virtual void Set(int, const DBKey& value) = 0;\r
+ virtual void Set(int, const Blob& value) = 0;\r
+ virtual void Set(int, const Array& value) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp& value) = 0;\r
+ virtual bool Get(int, Date& value) = 0;\r
+ virtual bool Get(int, Time& value) = 0;\r
+ virtual bool Get(int, DBKey& value) = 0;\r
+ virtual bool Get(int, Blob& value) = 0;\r
+ virtual bool Get(int, Array& value) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp& value) = 0;\r
+ virtual bool Get(const std::string&, Date& value) = 0;\r
+ virtual bool Get(const std::string&, Time& value) = 0;\r
+ virtual bool Get(const std::string&, DBKey& value) = 0;\r
+ virtual bool Get(const std::string&, Blob& value) = 0;\r
+ virtual bool Get(const std::string&, Array& value) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+\r
+ virtual SDT ParameterType(int) = 0;\r
+ virtual int ParameterSubtype(int) = 0;\r
+ virtual int ParameterSize(int) = 0;\r
+ virtual int ParameterScale(int) = 0;\r
+ virtual int Parameters() = 0;\r
+\r
+ virtual void Plan(std::string&) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IStatement* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IStatement() { }\r
+\r
+ // DEPRECATED METHODS (WON'T BE AVAILABLE IN VERSIONS 3.x)\r
+ virtual bool Get(int, char*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, char*) = 0; // DEPRECATED\r
+ virtual bool Get(int, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, float*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, float*) = 0; // DEPRECATED\r
+ virtual bool Get(int, double*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, double*) = 0; // DEPRECATED\r
+ };\r
+ \r
+ class IEvents\r
+ {\r
+ public:\r
+ virtual void Add(const std::string&, EventInterface*) = 0;\r
+ virtual void Drop(const std::string&) = 0;\r
+ virtual void List(std::vector<std::string>&) = 0;\r
+ virtual void Clear() = 0; // Drop all events\r
+ virtual void Dispatch() = 0; // Dispatch events (calls handlers)\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+\r
+ virtual IEvents* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IEvents() { }\r
+ };\r
+ \r
+ /* Class EventInterface is merely a pure interface.\r
+ * It is _not_ implemented by IBPP. It is only a base class definition from\r
+ * which your own event interface classes have to derive from.\r
+ * Please read the reference guide at http://www.ibpp.org for more info. */\r
+\r
+ class EventInterface\r
+ {\r
+ public:\r
+ virtual void ibppEventHandler(Events, const std::string&, int) = 0;\r
+ virtual ~EventInterface() { }\r
+ };\r
+\r
+ // --- Factories ---\r
+ // These methods are the only way to get one of the above\r
+ // Interfaces. They are at the heart of how you program using IBPP. For\r
+ // instance, to get access to a database, you'll write code similar to this:\r
+ // {\r
+ // Database db = DatabaseFactory("server", "databasename",\r
+ // "user", "password");\r
+ // db->Connect();\r
+ // ...\r
+ // db->Disconnect();\r
+ // }\r
+\r
+ Service ServiceFactory(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword);\r
+\r
+ Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword, const std::string& RoleName,\r
+ const std::string& CharSet, const std::string& CreateParams);\r
+\r
+ inline Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword)\r
+ { return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); }\r
+\r
+ Transaction TransactionFactory(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0));\r
+\r
+ Statement StatementFactory(Database db, Transaction tr,\r
+ const std::string& sql);\r
+\r
+ inline Statement StatementFactory(Database db, Transaction tr)\r
+ { return StatementFactory(db, tr, ""); }\r
+\r
+ Blob BlobFactory(Database db, Transaction tr);\r
+ \r
+ Array ArrayFactory(Database db, Transaction tr);\r
+ \r
+ Events EventsFactory(Database db);\r
+\r
+ /* IBPP uses a self initialization system. Each time an object that may\r
+ * require the usage of the Interbase client C-API library is used, the\r
+ * library internal handling details are automatically initialized, if not\r
+ * already done. You can kick this initialization at the start of an\r
+ * application by calling IBPP::CheckVersion(). This is recommended, because\r
+ * IBPP::CheckVersion will assure you that YOUR code has been compiled\r
+ * against a compatible version of the library. */\r
+\r
+ bool CheckVersion(uint32_t);\r
+ int GDSVersion();\r
+ \r
+ /* On Win32 platform, ClientLibSearchPaths() allows to setup\r
+ * one or multiple additional paths (separated with a ';') where IBPP\r
+ * will look for the client library (before the default implicit search\r
+ * locations). This is usefull for applications distributed with a 'private'\r
+ * copy of Firebird, when the registry is useless to identify the location\r
+ * from where to attempt loading the fbclient.dll / gds32.dll.\r
+ * If called, this function must be called *early* by the application,\r
+ * before *any* other function or object methods of IBPP.\r
+ * Currently, this is a NO-OP on platforms other than Win32. */\r
+ \r
+ void ClientLibSearchPaths(const std::string&);\r
+\r
+ /* Finally, here are some date and time conversion routines used by IBPP and\r
+ * that may be helpful at the application level. They do not depend on\r
+ * anything related to Firebird/Interbase. Just a bonus. dtoi and itod\r
+ * return false on invalid parameters or out of range conversions. */\r
+\r
+ bool dtoi(int date, int* py, int* pm, int* pd);\r
+ bool itod(int* pdate, int year, int month, int day);\r
+ void ttoi(int itime, int* phour, int* pminute, int* psecond, int* ptt);\r
+ void itot(int* ptime, int hour, int minute, int second = 0, int tenthousandths = 0);\r
+\r
+}\r
+\r
+#endif\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Row class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <math.h>\r
+#include <time.h>\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void RowImpl::SetNull(int param)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized."));\r
+ if (param < 1 || param > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[param-1]);\r
+ if (! (var->sqltype & 1))\r
+ throw LogicExceptionImpl("Row::SetNull", _("This column can't be null."));\r
+\r
+ *var->sqlind = -1; // Set the column to SQL NULL\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, bool value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivBool, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const char* cstring)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized."));\r
+ if (cstring == 0)\r
+ throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected."));\r
+\r
+ SetValue(param, ivByte, cstring, (int)strlen(cstring));\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const void* bindata, int len)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized."));\r
+ if (bindata == 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected."));\r
+ if (len < 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0"));\r
+ \r
+ SetValue(param, ivByte, bindata, len);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const std::string& s)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivString, (void*)&s);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int16_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized."));\r
+ \r
+ SetValue(param, ivInt16, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int32_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivInt32, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int64_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivInt64, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, float value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivFloat, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, double value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivDouble, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Timestamp& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivTimestamp, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Date& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized."));\r
+\r
+ if (mDialect == 1)\r
+ {\r
+ // In dialect 1, IBPP::Date is supposed to work with old 'DATE'\r
+ // fields which are actually ISC_TIMESTAMP.\r
+ IBPP::Timestamp timestamp(value);\r
+ SetValue(param, ivTimestamp, ×tamp);\r
+ }\r
+ else\r
+ {\r
+ // Dialect 3\r
+ SetValue(param, ivDate, (void*)&value);\r
+ }\r
+\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Time& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized."));\r
+ if (mDialect == 1)\r
+ throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database."));\r
+\r
+ SetValue(param, ivTime, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Blob& blob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized."));\r
+ if (mDatabase != 0 && blob->DatabasePtr() != mDatabase)\r
+ throw LogicExceptionImpl("Row::Set[Blob]",\r
+ _("IBlob and Row attached to different databases"));\r
+ if (mTransaction != 0 && blob->TransactionPtr() != mTransaction)\r
+ throw LogicExceptionImpl("Row::Set[Blob]",\r
+ _("IBlob and Row attached to different transactions"));\r
+\r
+ SetValue(param, ivBlob, blob.intf());\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Array& array)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized."));\r
+ if (mDatabase != 0 && array->DatabasePtr() != mDatabase)\r
+ throw LogicExceptionImpl("Row::Set[Array]",\r
+ _("IArray and Row attached to different databases"));\r
+ if (mTransaction != 0 && array->TransactionPtr() != mTransaction)\r
+ throw LogicExceptionImpl("Row::Set[Array]",\r
+ _("IArray and Row attached to different transactions"));\r
+\r
+ SetValue(param, ivArray, (void*)array.intf());\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::DBKey& key)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivDBKey, (void*)&key);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+/*\r
+void RowImpl::Set(int param, const IBPP::Value& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized."));\r
+\r
+ //SetValue(param, ivDBKey, (void*)&key);\r
+ //mUpdated[param-1] = true;\r
+}\r
+*/\r
+\r
+bool RowImpl::IsNull(int column)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
+ if (column < 1 || column > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[column-1]);\r
+ return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, bool& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivBool);\r
+ if (pvalue != 0)\r
+ retvalue = (*(char*)pvalue == 0 ? false : true);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, char* retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
+\r
+ int sqllen;\r
+ void* pvalue = GetValue(column, ivByte, &sqllen);\r
+ if (pvalue != 0)\r
+ {\r
+ memcpy(retvalue, pvalue, sqllen);\r
+ retvalue[sqllen] = '\0';\r
+ }\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, void* bindata, int& userlen)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+ if (bindata == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
+ if (userlen < 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Length must be >= 0"));\r
+\r
+ int sqllen;\r
+ void* pvalue = GetValue(column, ivByte, &sqllen);\r
+ if (pvalue != 0)\r
+ {\r
+ // userlen says how much bytes the user can accept\r
+ // let's shorten it, if there is less bytes available\r
+ if (sqllen < userlen) userlen = sqllen;\r
+ memcpy(bindata, pvalue, userlen);\r
+ }\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, std::string& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivString, &retvalue);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int16_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt16);\r
+ if (pvalue != 0)\r
+ retvalue = *(int16_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int32_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt32);\r
+ if (pvalue != 0)\r
+ retvalue = *(int32_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int64_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt64);\r
+ if (pvalue != 0)\r
+ retvalue = *(int64_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, float& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivFloat);\r
+ if (pvalue != 0)\r
+ retvalue = *(float*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, double& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivDouble);\r
+ if (pvalue != 0)\r
+ retvalue = *(double*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Timestamp& timestamp)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Date& date)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ if (mDialect == 1)\r
+ {\r
+ // Dialect 1. IBPP::Date is supposed to work with old 'DATE'\r
+ // fields which are actually ISC_TIMESTAMP.\r
+ IBPP::Timestamp timestamp;\r
+ void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
+ if (pvalue != 0) date = timestamp;\r
+ return pvalue == 0 ? true : false;\r
+ }\r
+ else\r
+ {\r
+ void* pvalue = GetValue(column, ivDate, (void*)&date);\r
+ return pvalue == 0 ? true : false;\r
+ }\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Time& time)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivTime, (void*)&time);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Blob& retblob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf());\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::DBKey& retkey)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivDBKey, (void*)&retkey);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Array& retarray)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivArray, (void*)retarray.intf());\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+/*\r
+const IBPP::Value RowImpl::Get(int column)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ //void* value = GetValue(column, ivArray, (void*)retarray.intf());\r
+ //return value == 0 ? true : false;\r
+ return IBPP::Value();\r
+}\r
+*/\r
+\r
+bool RowImpl::IsNull(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
+\r
+ return IsNull(ColumnNum(name));\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, bool& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, char* retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, void* retvalue, int& count)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue, count);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, std::string& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::GetString", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int16_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int32_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int64_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, float& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, double& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retblob);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Array& retarray)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retarray);\r
+}\r
+\r
+/*\r
+const IBPP::Value RowImpl::Get(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name));\r
+}\r
+*/\r
+\r
+int RowImpl::Columns()\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Columns", _("The row is not initialized."));\r
+\r
+ return mDescrArea->sqld;\r
+}\r
+\r
+int RowImpl::ColumnNum(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized."));\r
+ if (name.empty())\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("Column name <empty> not found."));\r
+\r
+ XSQLVAR* var;\r
+ char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0'\r
+\r
+ // Local upper case copy of the column name\r
+ size_t len = name.length();\r
+ if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname);\r
+ strncpy(Uname, name.c_str(), len);\r
+ Uname[len] = '\0';\r
+ char* p = Uname;\r
+ while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
+\r
+ // Loop through the columns of the descriptor\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ var = &(mDescrArea->sqlvar[i]);\r
+ if (var->sqlname_length != (int16_t)len) continue;\r
+ if (strncmp(Uname, var->sqlname, len) == 0) return i+1;\r
+ }\r
+\r
+ // Failed finding the column name, let's retry using the aliases\r
+ char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0'\r
+\r
+ // Local upper case copy of the column name\r
+ len = name.length();\r
+ if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname);\r
+ strncpy(Ualias, name.c_str(), len);\r
+ Ualias[len] = '\0';\r
+ p = Ualias;\r
+ while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
+\r
+ // Loop through the columns of the descriptor\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ var = &(mDescrArea->sqlvar[i]);\r
+ if (var->aliasname_length != (int16_t)len) continue;\r
+ if (strncmp(Ualias, var->aliasname, len) == 0) return i+1;\r
+ }\r
+\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column."));\r
+#ifdef __DMC__\r
+ return 0; // DMC errronously warns here about a missing return\r
+#endif\r
+}\r
+\r
+/*\r
+ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake.\r
+Ideally, the strings should be stored elsewhere (like _Numerics and so on) to\r
+take into account the final '\0' which needs to be added. For now, we insert\r
+the '\0' in the original data, which will cut the 32th character. Not terribly\r
+bad, but should be cleanly rewritten.\r
+*/\r
+\r
+const char* RowImpl::ColumnName(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->sqlname_length >= 31) var->sqlname_length = 31;\r
+ var->sqlname[var->sqlname_length] = '\0';\r
+ return var->sqlname;\r
+}\r
+\r
+const char* RowImpl::ColumnAlias(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->aliasname_length >= 31) var->aliasname_length = 31;\r
+ var->aliasname[var->aliasname_length] = '\0';\r
+ return var->aliasname;\r
+}\r
+\r
+const char* RowImpl::ColumnTable(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->relname_length >= 31) var->relname_length = 31;\r
+ var->relname[var->relname_length] = '\0';\r
+ return var->relname;\r
+}\r
+\r
+IBPP::SDT RowImpl::ColumnType(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range."));\r
+\r
+ IBPP::SDT value;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT : value = IBPP::sdString; break;\r
+ case SQL_VARYING : value = IBPP::sdString; break;\r
+ case SQL_SHORT : value = IBPP::sdSmallint; break;\r
+ case SQL_LONG : value = IBPP::sdInteger; break;\r
+ case SQL_INT64 : value = IBPP::sdLargeint; break;\r
+ case SQL_FLOAT : value = IBPP::sdFloat; break;\r
+ case SQL_DOUBLE : value = IBPP::sdDouble; break;\r
+ case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break;\r
+ case SQL_TYPE_DATE : value = IBPP::sdDate; break;\r
+ case SQL_TYPE_TIME : value = IBPP::sdTime; break;\r
+ case SQL_BLOB : value = IBPP::sdBlob; break;\r
+ case SQL_ARRAY : value = IBPP::sdArray; break;\r
+ default : throw LogicExceptionImpl("Row::ColumnType",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int RowImpl::ColumnSubtype(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return (int)var->sqlsubtype;\r
+}\r
+\r
+int RowImpl::ColumnSize(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return var->sqllen;\r
+}\r
+\r
+int RowImpl::ColumnScale(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return -var->sqlscale;\r
+}\r
+\r
+bool RowImpl::ColumnUpdated(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range."));\r
+\r
+ return mUpdated[varnum-1];\r
+}\r
+\r
+bool RowImpl::Updated()\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
+\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ if (mUpdated[i]) return true;\r
+ return false;\r
+}\r
+\r
+IBPP::Database RowImpl::DatabasePtr() const\r
+{\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction RowImpl::TransactionPtr() const\r
+{\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IRow* RowImpl::Clone()\r
+{\r
+ // By definition the clone of an IBPP Row is a new row (so refcount=0).\r
+\r
+ RowImpl* clone = new RowImpl(*this);\r
+ return clone;\r
+}\r
+\r
+IBPP::IRow* RowImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void RowImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)\r
+{\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));\r
+ if (value == 0)\r
+ throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));\r
+\r
+ int16_t len;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT :\r
+ if (ivType == ivString)\r
+ {\r
+ std::string* svalue = (std::string*)value;\r
+ len = (int16_t)svalue->length();\r
+ if (len > var->sqllen) len = var->sqllen;\r
+ strncpy(var->sqldata, svalue->c_str(), len);\r
+ while (len < var->sqllen) var->sqldata[len++] = ' ';\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ if (userlen > var->sqllen) userlen = var->sqllen;\r
+ memcpy(var->sqldata, value, userlen);\r
+ while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';\r
+ }\r
+ else if (ivType == ivDBKey)\r
+ {\r
+ IBPP::DBKey* key = (IBPP::DBKey*)value;\r
+ key->GetKey(var->sqldata, var->sqllen);\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ var->sqldata[0] = *(bool*)value ? 'T' : 'F';\r
+ len = 1;\r
+ while (len < var->sqllen) var->sqldata[len++] = ' ';\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_VARYING :\r
+ if (ivType == ivString)\r
+ {\r
+ std::string* svalue = (std::string*)value;\r
+ len = (int16_t)svalue->length();\r
+ if (len > var->sqllen) len = var->sqllen;\r
+ *(int16_t*)var->sqldata = (int16_t)len;\r
+ strncpy(var->sqldata+2, svalue->c_str(), len);\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ if (userlen > var->sqllen) userlen = var->sqllen;\r
+ *(int16_t*)var->sqldata = (int16_t)userlen;\r
+ memcpy(var->sqldata+2, value, userlen);\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ *(int16_t*)var->sqldata = (int16_t)1;\r
+ var->sqldata[2] = *(bool*)value ? 'T' : 'F';\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_SHORT :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(int16_t*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int16_t*)var->sqldata =\r
+ (int16_t)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int16_t*)var->sqldata =\r
+ (int16_t)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_LONG :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(ISC_LONG*)var->sqldata =\r
+ (ISC_LONG)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(ISC_LONG*)var->sqldata =\r
+ (ISC_LONG)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_INT64 :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int32_t*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int64_t*)var->sqldata =\r
+ (int64_t)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int64_t*)var->sqldata =\r
+ (int64_t)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_FLOAT :\r
+ if (ivType != ivFloat || var->sqlscale != 0)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ *(float*)var->sqldata = *(float*)value;\r
+ break;\r
+\r
+ case SQL_DOUBLE :\r
+ if (ivType != ivDouble)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ if (var->sqlscale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(double*)var->sqldata =\r
+ floor(*(double*)value * multiplier + 0.5) / multiplier;\r
+ }\r
+ else *(double*)var->sqldata = *(double*)value;\r
+ break;\r
+\r
+ case SQL_TIMESTAMP :\r
+ if (ivType != ivTimestamp)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);\r
+ break;\r
+\r
+ case SQL_TYPE_DATE :\r
+ if (ivType != ivDate)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);\r
+ break;\r
+\r
+ case SQL_TYPE_TIME :\r
+ if (ivType != ivTime)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);\r
+ break;\r
+\r
+ case SQL_BLOB :\r
+ if (ivType == ivBlob)\r
+ {\r
+ BlobImpl* blob = (BlobImpl*)value;\r
+ blob->GetId((ISC_QUAD*)var->sqldata);\r
+ }\r
+ else if (ivType == ivString)\r
+ {\r
+ BlobImpl blob(mDatabase, mTransaction);\r
+ blob.Save(*(std::string*)value);\r
+ blob.GetId((ISC_QUAD*)var->sqldata);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_ARRAY :\r
+ if (ivType != ivArray)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ {\r
+ ArrayImpl* array = (ArrayImpl*)value;\r
+ array->GetId((ISC_QUAD*)var->sqldata);\r
+ // When an array has been affected to a column, we want to reset\r
+ // its ID. This way, the next WriteFrom() on the same Array object\r
+ // will allocate a new ID. This protects against storing the same\r
+ // array ID in multiple columns or rows.\r
+ array->ResetId();\r
+ }\r
+ break;\r
+\r
+ default : throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("The field uses an unsupported SQL type !"));\r
+ }\r
+\r
+ if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag\r
+}\r
+\r
+void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)\r
+{\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));\r
+\r
+ void* value;\r
+ int len;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+\r
+ // When there is no value (SQL NULL)\r
+ if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;\r
+\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT :\r
+ if (ivType == ivString)\r
+ {\r
+ // In case of ivString, 'void* retvalue' points to a std::string where we\r
+ // will directly store the data.\r
+ std::string* str = (std::string*)retvalue;\r
+ str->erase();\r
+ str->append(var->sqldata, var->sqllen);\r
+ value = retvalue; // value != 0 means 'not null'\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ // In case of ivByte, void* retvalue points to an int where we\r
+ // will store the len of the available data\r
+ if (retvalue != 0) *(int*)retvalue = var->sqllen;\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivDBKey)\r
+ {\r
+ IBPP::DBKey* key = (IBPP::DBKey*)retvalue;\r
+ key->SetKey(var->sqldata, var->sqllen);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ mBools[varnum-1] = 0;\r
+ if (var->sqllen >= 1)\r
+ {\r
+ char c = var->sqldata[0];\r
+ if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
+ mBools[varnum-1] = 1;\r
+ }\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_VARYING :\r
+ if (ivType == ivString)\r
+ {\r
+ // In case of ivString, 'void* retvalue' points to a std::string where we\r
+ // will directly store the data.\r
+ std::string* str = (std::string*)retvalue;\r
+ str->erase();\r
+ str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ // In case of ivByte, void* retvalue points to an int where we\r
+ // will store the len of the available data\r
+ if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;\r
+ value = var->sqldata+2;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ mBools[varnum-1] = 0;\r
+ len = *(int16_t*)var->sqldata;\r
+ if (len >= 1)\r
+ {\r
+ char c = var->sqldata[2];\r
+ if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
+ mBools[varnum-1] = 1;\r
+ }\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_SHORT :\r
+ if (ivType == ivInt16)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ mInt32s[varnum-1] = *(int16_t*)var->sqldata;\r
+ value = &mInt32s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ mInt64s[varnum-1] = *(int16_t*)var->sqldata;\r
+ value = &mInt64s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);\r
+\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_LONG :\r
+ if (ivType == ivInt32)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ int32_t tmp = *(int32_t*)var->sqldata;\r
+ if (tmp < consts::min16 || tmp > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt16s[varnum-1] = (int16_t)tmp;\r
+ value = &mInt16s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ mInt64s[varnum-1] = *(int32_t*)var->sqldata;\r
+ value = &mInt64s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_INT64 :\r
+ if (ivType == ivInt64)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ int64_t tmp = *(int64_t*)var->sqldata;\r
+ if (tmp < consts::min16 || tmp > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt16s[varnum-1] = (int16_t)tmp;\r
+ value = &mInt16s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ int64_t tmp = *(int64_t*)var->sqldata;\r
+ if (tmp < consts::min32 || tmp > consts::max32)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt32s[varnum-1] = (int32_t)tmp;\r
+ value = &mInt32s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_FLOAT :\r
+ if (ivType != ivFloat)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ value = var->sqldata;\r
+ break;\r
+\r
+ case SQL_DOUBLE :\r
+ if (ivType != ivDouble)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ if (var->sqlscale != 0)\r
+ {\r
+ // Round to scale y of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] =\r
+ floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else value = var->sqldata;\r
+ break;\r
+\r
+ case SQL_TIMESTAMP :\r
+ if (ivType != ivTimestamp)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_TYPE_DATE :\r
+ if (ivType != ivDate)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_TYPE_TIME :\r
+ if (ivType != ivTime)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_BLOB :\r
+ if (ivType == ivBlob)\r
+ {\r
+ BlobImpl* blob = (BlobImpl*)retvalue;\r
+ blob->SetId((ISC_QUAD*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivString)\r
+ {\r
+ BlobImpl blob(mDatabase, mTransaction);\r
+ blob.SetId((ISC_QUAD*)var->sqldata);\r
+ std::string* str = (std::string*)retvalue;\r
+ blob.Load(*str);\r
+ value = retvalue;\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+ \r
+ case SQL_ARRAY :\r
+ if (ivType != ivArray)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ {\r
+ ArrayImpl* array = (ArrayImpl*)retvalue;\r
+ array->SetId((ISC_QUAD*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ break;\r
+\r
+ default : throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+void RowImpl::Free()\r
+{\r
+ if (mDescrArea != 0)\r
+ {\r
+ for (int i = 0; i < mDescrArea->sqln; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ if (var->sqldata != 0)\r
+ {\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break;\r
+ case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break;\r
+ case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break;\r
+ case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break;\r
+ case SQL_TEXT :\r
+ case SQL_VARYING : delete [] var->sqldata; break;\r
+ case SQL_SHORT : delete (int16_t*) var->sqldata; break;\r
+ case SQL_LONG : delete (int32_t*) var->sqldata; break;\r
+ case SQL_INT64 : delete (int64_t*) var->sqldata; break;\r
+ case SQL_FLOAT : delete (float*) var->sqldata; break;\r
+ case SQL_DOUBLE : delete (double*) var->sqldata; break;\r
+ default : throw LogicExceptionImpl("RowImpl::Free",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ }\r
+ if (var->sqlind != 0) delete var->sqlind;\r
+ }\r
+ delete [] (char*)mDescrArea;\r
+ mDescrArea = 0;\r
+ }\r
+\r
+ mNumerics.clear();\r
+ mFloats.clear();\r
+ mInt64s.clear();\r
+ mInt32s.clear();\r
+ mInt16s.clear();\r
+ mBools.clear();\r
+ mStrings.clear();\r
+ mUpdated.clear();\r
+\r
+ mDialect = 0;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+}\r
+\r
+void RowImpl::Resize(int n)\r
+{\r
+ const int size = XSQLDA_LENGTH(n);\r
+\r
+ Free();\r
+ mDescrArea = (XSQLDA*) new char[size];\r
+\r
+ memset(mDescrArea, 0, size);\r
+ mNumerics.resize(n);\r
+ mFloats.resize(n);\r
+ mInt64s.resize(n);\r
+ mInt32s.resize(n);\r
+ mInt16s.resize(n);\r
+ mBools.resize(n);\r
+ mStrings.resize(n);\r
+ mUpdated.resize(n);\r
+ for (int i = 0; i < n; i++)\r
+ {\r
+ mNumerics[i] = 0.0;\r
+ mFloats[i] = 0.0;\r
+ mInt64s[i] = 0;\r
+ mInt32s[i] = 0;\r
+ mInt16s[i] = 0;\r
+ mBools[i] = 0;\r
+ mStrings[i].erase();\r
+ mUpdated[i] = false;\r
+ }\r
+\r
+ mDescrArea->version = SQLDA_VERSION1;\r
+ mDescrArea->sqln = (int16_t)n;\r
+}\r
+\r
+void RowImpl::AllocVariables()\r
+{\r
+ int i;\r
+ for (i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
+ memset(var->sqldata, 0, sizeof(ISC_QUAD));\r
+ break;\r
+ case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
+ memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP));\r
+ break;\r
+ case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
+ memset(var->sqldata, 0, sizeof(ISC_TIME));\r
+ break;\r
+ case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
+ memset(var->sqldata, 0, sizeof(ISC_DATE));\r
+ break;\r
+ case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
+ memset(var->sqldata, ' ', var->sqllen);\r
+ var->sqldata[var->sqllen] = '\0';\r
+ break;\r
+ case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
+ memset(var->sqldata, 0, 2);\r
+ memset(var->sqldata+2, ' ', var->sqllen);\r
+ var->sqldata[var->sqllen+2] = '\0';\r
+ break;\r
+ case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break;\r
+ case SQL_LONG : var->sqldata = (char*) new int32_t(0); break;\r
+ case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break;\r
+ case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break;\r
+ case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break;\r
+ default : throw LogicExceptionImpl("RowImpl::AllocVariables",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator\r
+ }\r
+}\r
+\r
+bool RowImpl::MissingValues()\r
+{\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ if (! mUpdated[i]) return true;\r
+ return false;\r
+}\r
+\r
+RowImpl& RowImpl::operator=(const RowImpl& copied)\r
+{\r
+ Free();\r
+\r
+ const int n = copied.mDescrArea->sqln;\r
+ const int size = XSQLDA_LENGTH(n);\r
+\r
+ // Initial brute copy\r
+ mDescrArea = (XSQLDA*) new char[size];\r
+ memcpy(mDescrArea, copied.mDescrArea, size);\r
+\r
+ // Copy of the columns data\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD));\r
+ break;\r
+ case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP));\r
+ break;\r
+ case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME));\r
+ break;\r
+ case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE));\r
+ break;\r
+ case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
+ memcpy(var->sqldata, org->sqldata, var->sqllen+1);\r
+ break;\r
+ case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
+ memcpy(var->sqldata, org->sqldata, var->sqllen+3);\r
+ break;\r
+ case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break;\r
+ case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break;\r
+ case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break;\r
+ case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break;\r
+ case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break;\r
+ default : throw LogicExceptionImpl("RowImpl::Ctor",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator\r
+ }\r
+\r
+ // Pointers init, real data copy\r
+ mNumerics = copied.mNumerics;\r
+ mFloats = copied.mFloats;\r
+ mInt64s = copied.mInt64s;\r
+ mInt32s = copied.mInt32s;\r
+ mInt16s = copied.mInt16s;\r
+ mBools = copied.mBools;\r
+ mStrings = copied.mStrings;\r
+\r
+ mDialect = copied.mDialect;\r
+ mDatabase = copied.mDatabase;\r
+ mTransaction = copied.mTransaction;\r
+ \r
+ return *this;\r
+}\r
+\r
+RowImpl::RowImpl(const RowImpl& copied)\r
+ : IBPP::IRow(), mRefCount(0), mDescrArea(0)\r
+{\r
+ // mRefCount and mDescrArea are set to 0 before using the assignment operator\r
+ *this = copied; // The assignment operator does the real copy\r
+}\r
+\r
+RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr)\r
+ : mRefCount(0), mDescrArea(0)\r
+{\r
+ Resize(n);\r
+ mDialect = dialect;\r
+ mDatabase = db;\r
+ mTransaction = tr;\r
+}\r
+\r
+RowImpl::~RowImpl()\r
+{\r
+ try { Free(); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: service.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Service class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+using namespace ibpp_internals;\r
+\r
+#ifdef IBPP_UNIX\r
+#include <unistd.h>\r
+#define Sleep(x) usleep(x)\r
+#endif\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void ServiceImpl::Connect()\r
+{\r
+ if (mHandle != 0) return; // Already connected\r
+ \r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Service::Connect", _("Unspecified user name."));\r
+ if (mUserPassword.empty())\r
+ throw LogicExceptionImpl("Service::Connect", _("Unspecified user password."));\r
+\r
+ // Attach to the Service Manager\r
+ IBS status;\r
+ SPB spb;\r
+ std::string connect;\r
+\r
+ // Build a SPB based on the properties\r
+ spb.Insert(isc_spb_version);\r
+ spb.Insert(isc_spb_current_version);\r
+ spb.InsertString(isc_spb_user_name, 1, mUserName.c_str());\r
+ spb.InsertString(isc_spb_password, 1, mUserPassword.c_str());\r
+\r
+ if (! mServerName.empty())\r
+ {\r
+ connect = mServerName;\r
+ connect += ":";\r
+ }\r
+\r
+ connect += "service_mgr";\r
+\r
+ (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(),\r
+ &mHandle, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));\r
+ }\r
+}\r
+\r
+void ServiceImpl::Disconnect()\r
+{\r
+ if (mHandle == 0) return; // Already disconnected\r
+ \r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ IBS status;\r
+\r
+ // Detach from the service manager\r
+ (*gds.Call()->m_service_detach)(status.Self(), &mHandle);\r
+\r
+ // Set mHandle to 0 now, just in case we need to throw, because Disconnect()\r
+ // is called from Service destructor and we want to maintain a coherent state.\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed"));\r
+}\r
+\r
+void ServiceImpl::GetVersion(std::string& version)\r
+{\r
+ // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock')\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+ RB result(250);\r
+\r
+ spb.Insert(isc_info_svc_server_version);\r
+\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(),\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed"));\r
+\r
+ result.GetString(isc_info_svc_server_version, version);\r
+}\r
+\r
+void ServiceImpl::AddUser(const IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::AddUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::AddUser", _("Username required."));\r
+ if (user.password.empty())\r
+ throw LogicExceptionImpl("Service::AddUser", _("Password required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_add_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+ spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
+ if (! user.firstname.empty())\r
+ spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
+ if (! user.middlename.empty())\r
+ spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
+ if (! user.lastname.empty())\r
+ spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
+ if (user.userid != 0)\r
+ spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
+ if (user.groupid != 0)\r
+ spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::ModifyUser(const IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::ModifyUser", _("Username required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_modify_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+ if (! user.password.empty())\r
+ spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
+ if (! user.firstname.empty())\r
+ spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
+ if (! user.middlename.empty())\r
+ spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
+ if (! user.lastname.empty())\r
+ spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
+ if (user.userid != 0)\r
+ spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
+ if (user.groupid != 0)\r
+ spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::RemoveUser(const std::string& username)\r
+{\r
+\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected."));\r
+ if (username.empty())\r
+ throw LogicExceptionImpl("Service::RemoveUser", _("Username required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_delete_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, username.c_str());\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::GetUser(IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::GetUser", _("Username required."));\r
+\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_display_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed"));\r
+\r
+ RB result(8000);\r
+ char request[] = {isc_info_svc_get_users};\r
+ status.Reset();\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ sizeof(request), request, result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed"));\r
+\r
+ char* p = result.Self();\r
+ if (*p != isc_info_svc_get_users)\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer"));\r
+\r
+ p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
+ user.clear();\r
+ while (*p != isc_info_end)\r
+ {\r
+ if (*p == isc_spb_sec_userid)\r
+ {\r
+ user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else if (*p == isc_spb_sec_groupid)\r
+ {\r
+ user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else\r
+ {\r
+ unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
+ switch (*p)\r
+ {\r
+ case isc_spb_sec_username :\r
+ // For each user, this is the first element returned\r
+ if (len != 0) user.username.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_password :\r
+ if (len != 0) user.password.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_firstname :\r
+ if (len != 0) user.firstname.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_middlename :\r
+ if (len != 0) user.middlename.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_lastname :\r
+ if (len != 0) user.lastname.assign(p+3, len);\r
+ break;\r
+ }\r
+ p += (3 + len);\r
+ }\r
+ }\r
+}\r
+\r
+void ServiceImpl::GetUsers(std::vector<IBPP::User>& users)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected."));\r
+\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_display_user);\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed"));\r
+\r
+ RB result(8000);\r
+ char request[] = {isc_info_svc_get_users};\r
+ status.Reset();\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ sizeof(request), request, result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed"));\r
+\r
+ users.clear();\r
+ char* p = result.Self();\r
+ if (*p != isc_info_svc_get_users)\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer"));\r
+\r
+ p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
+ IBPP::User user;\r
+ while (*p != isc_info_end)\r
+ {\r
+ if (*p == isc_spb_sec_userid)\r
+ {\r
+ user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else if (*p == isc_spb_sec_groupid)\r
+ {\r
+ user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else\r
+ {\r
+ unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
+ switch (*p)\r
+ {\r
+ case isc_spb_sec_username :\r
+ // For each user, this is the first element returned\r
+ if (! user.username.empty()) users.push_back(user); // Flush previous user\r
+ user.clear();\r
+ if (len != 0) user.username.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_password :\r
+ if (len != 0) user.password.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_firstname :\r
+ if (len != 0) user.firstname.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_middlename :\r
+ if (len != 0) user.middlename.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_lastname :\r
+ if (len != 0) user.lastname.assign(p+3, len);\r
+ break;\r
+ }\r
+ p += (3 + len);\r
+ }\r
+ }\r
+ if (! user.username.empty()) users.push_back(user); // Flush last user\r
+}\r
+\r
+void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_prp_page_buffers, buffers);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_prp_sweep_interval, sweep);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync);\r
+ else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly);\r
+ else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res);\r
+ else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ switch (mode)\r
+ {\r
+ case IBPP::dsDenyAttach :\r
+ spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout);\r
+ break;\r
+ case IBPP::dsDenyTrans :\r
+ spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout);\r
+ break;\r
+ case IBPP::dsForce :\r
+ spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout);\r
+ break;\r
+ }\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Restart(const std::string& dbfile)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Restart", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Sweep(const std::string& dbfile)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Sweep", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_repair);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Repair", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_repair);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+\r
+ unsigned int mask;\r
+ if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db);\r
+ else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db;\r
+ else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db;\r
+ else throw LogicExceptionImpl("Service::Repair",\r
+ _("One of rpMendRecords, rpValidatePages, rpValidateFull is required."));\r
+\r
+ if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db;\r
+ if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum;\r
+ if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows;\r
+ \r
+ spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::StartBackup(const std::string& dbfile,\r
+ const std::string& bkfile, IBPP::BRF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Backup", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified."));\r
+ if (bkfile.empty())\r
+ throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_backup);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
+ if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
+\r
+ unsigned int mask = 0;\r
+ if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums;\r
+ if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo;\r
+ if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only;\r
+ if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect;\r
+ if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable;\r
+ if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert;\r
+ if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed"));\r
+}\r
+\r
+void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize, IBPP::BRF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Restore", _("Service is not connected."));\r
+ if (bkfile.empty())\r
+ throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_restore);\r
+ spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
+ if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize);\r
+\r
+ unsigned int mask;\r
+ if (flags & IBPP::brReplace) mask = isc_spb_res_replace;\r
+ else mask = isc_spb_res_create; // Safe default mode\r
+\r
+ if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx;\r
+ if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow;\r
+ if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity;\r
+ if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time;\r
+ if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space;\r
+ if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed"));\r
+}\r
+\r
+const char* ServiceImpl::WaitMsg()\r
+{\r
+ IBS status;\r
+ SPB req;\r
+ RB result(1024);\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ req.Insert(isc_info_svc_line); // Request one line of textual output\r
+\r
+ // _service_query will only block until a line of result is available\r
+ // (or until the end of the task if it does not report information)\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ req.Size(), req.Self(), result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
+\r
+ // If message length is zero bytes, task is finished\r
+ if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;\r
+\r
+ // Task is not finished, but we have something to report\r
+ return mWaitMessage.c_str();\r
+}\r
+\r
+void ServiceImpl::Wait()\r
+{\r
+ IBS status;\r
+ SPB spb;\r
+ RB result(1024);\r
+ std::string msg;\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ spb.Insert(isc_info_svc_line);\r
+ for (;;)\r
+ {\r
+ // Sleeps 1 millisecond upfront. This will release the remaining\r
+ // timeslot of the thread. Doing so will give a good chance for small\r
+ // services tasks to finish before we check if they are still running.\r
+ // The deal is to limit (in that particular case) the number of loops\r
+ // polling _service_query that will happen.\r
+\r
+ Sleep(1);\r
+\r
+ // _service_query will only block until a line of result is available\r
+ // (or until the end of the task if it does not report information) \r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ spb.Size(), spb.Self(), result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
+\r
+ // If message length is zero bytes, task is finished\r
+ if (result.GetString(isc_info_svc_line, msg) == 0) return;\r
+\r
+ status.Reset();\r
+ result.Reset();\r
+ }\r
+}\r
+\r
+IBPP::IService* ServiceImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void ServiceImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void ServiceImpl::SetServerName(const char* newName)\r
+{\r
+ if (newName == 0) mServerName.erase();\r
+ else mServerName = newName;\r
+}\r
+\r
+void ServiceImpl::SetUserName(const char* newName)\r
+{\r
+ if (newName == 0) mUserName.erase();\r
+ else mUserName = newName;\r
+}\r
+\r
+void ServiceImpl::SetUserPassword(const char* newPassword)\r
+{\r
+ if (newPassword == 0) mUserPassword.erase();\r
+ else mUserPassword = newPassword;\r
+}\r
+\r
+ServiceImpl::ServiceImpl(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword)\r
+ : mRefCount(0), mHandle(0),\r
+ mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword)\r
+{\r
+}\r
+\r
+ServiceImpl::~ServiceImpl()\r
+{\r
+ try { if (Connected()) Disconnect(); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// Eof\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: statement.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Service class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void StatementImpl::Prepare(const std::string& sql)\r
+{\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("An IDatabase must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("IDatabase must be connected."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("An ITransaction must be attached."));\r
+ if (mTransaction->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("ITransaction must be started."));\r
+ if (sql.empty())\r
+ throw LogicExceptionImpl("Statement::Prepare", _("SQL statement can't be 0."));\r
+\r
+ // Saves the SQL sentence, only for reporting reasons in case of errors\r
+ mSql = sql;\r
+\r
+ IBS status;\r
+\r
+ // Free all resources currently attached to this Statement, then allocate\r
+ // a new statement descriptor.\r
+ Close();\r
+ (*gds.Call()->m_dsql_allocate_statement)(status.Self(), mDatabase->GetHandlePtr(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_allocate_statement failed"));\r
+\r
+ // Empirical estimate of parameters count and output columns count.\r
+ // This is by far not an exact estimation, which would require parsing the\r
+ // SQL statement. If the SQL statement contains '?' and ',' in string\r
+ // constants, this count will obviously be wrong, but it will be exagerated.\r
+ // It won't hurt. We just try to not have to re-allocate those descriptors later.\r
+ // So we prefer to get them a little bit larger than needed than the other way.\r
+ int16_t inEstimate = 0;\r
+ int16_t outEstimate = 1;\r
+ for (size_t i = 0; i < strlen(sql.c_str()); i++)\r
+ {\r
+ if (sql[i] == '?') ++inEstimate;\r
+ if (sql[i] == ',') ++outEstimate;\r
+ }\r
+\r
+ /*\r
+ DebugStream()<< "Prepare(\""<< sql<< "\")"<< fds;\r
+ DebugStream()<< _("Estimation: ")<< inEstimate<< _(" IN parameters and ")\r
+ << outEstimate<< _(" OUT columns")<< fds;\r
+ */\r
+\r
+ // Allocates output descriptor and prepares the statement\r
+ mOutRow = new RowImpl(mDatabase->Dialect(), outEstimate, mDatabase, mTransaction);\r
+ mOutRow->AddRef();\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_prepare)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, (short)sql.length(), const_cast<char*>(sql.c_str()),\r
+ short(mDatabase->Dialect()), mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ std::string context = "Statement::Prepare( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_prepare failed"));\r
+ }\r
+\r
+ // Read what kind of statement was prepared\r
+ status.Reset();\r
+ char itemsReq[] = {isc_info_sql_stmt_type};\r
+ char itemsRes[8];\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ sizeof(itemsRes), itemsRes);\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_sql_info failed"));\r
+ }\r
+ if (itemsRes[0] == isc_info_sql_stmt_type)\r
+ {\r
+ switch (itemsRes[3])\r
+ {\r
+ case isc_info_sql_stmt_select : mType = IBPP::stSelect; break;\r
+ case isc_info_sql_stmt_insert : mType = IBPP::stInsert; break;\r
+ case isc_info_sql_stmt_update : mType = IBPP::stUpdate; break;\r
+ case isc_info_sql_stmt_delete : mType = IBPP::stDelete; break;\r
+ case isc_info_sql_stmt_ddl : mType = IBPP::stDDL; break;\r
+ case isc_info_sql_stmt_exec_procedure : mType = IBPP::stExecProcedure; break;\r
+ case isc_info_sql_stmt_select_for_upd : mType = IBPP::stSelectUpdate; break;\r
+ case isc_info_sql_stmt_set_generator : mType = IBPP::stSetGenerator; break;\r
+ case isc_info_sql_stmt_savepoint : mType = IBPP::stSavePoint; break;\r
+ default : mType = IBPP::stUnsupported;\r
+ }\r
+ }\r
+ if (mType == IBPP::stUnknown || mType == IBPP::stUnsupported)\r
+ {\r
+ Close();\r
+ throw LogicExceptionImpl("Statement::Prepare",\r
+ _("Unknown or unsupported statement type"));\r
+ }\r
+\r
+ if (mOutRow->Columns() == 0)\r
+ {\r
+ // Get rid of the output descriptor, if it wasn't required (no output)\r
+ mOutRow->Release();\r
+ mOutRow = 0;\r
+ /*\r
+ DebugStream()<< _("Dropped output descriptor which was not required")<< fds;\r
+ */\r
+ }\r
+ else if (mOutRow->Columns() > mOutRow->AllocatedSize())\r
+ {\r
+ // Resize the output descriptor (which is too small).\r
+ // The statement does not need to be prepared again, though the\r
+ // output columns must be described again.\r
+\r
+ /*\r
+ DebugStream()<< _("Resize output descriptor from ")\r
+ << mOutRow->AllocatedSize()<< _(" to ")<< mOutRow->Columns()<< fds;\r
+ */\r
+\r
+ mOutRow->Resize(mOutRow->Columns());\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe)(status.Self(), &mHandle, 1, mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe failed"));\r
+ }\r
+ }\r
+\r
+ if (inEstimate > 0)\r
+ {\r
+ // Ready an input descriptor\r
+ mInRow = new RowImpl(mDatabase->Dialect(), inEstimate, mDatabase, mTransaction);\r
+ mInRow->AddRef();\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe_bind failed"));\r
+ }\r
+\r
+ if (mInRow->Columns() == 0)\r
+ {\r
+ // Get rid of the input descriptor, if it wasn't required (no parameters)\r
+ mInRow->Release();\r
+ mInRow = 0;\r
+ /*\r
+ DebugStream()<< _("Dropped input descriptor which was not required")<< fds;\r
+ */\r
+ }\r
+ else if (mInRow->Columns() > mInRow->AllocatedSize())\r
+ {\r
+ // Resize the input descriptor (which is too small).\r
+ // The statement does not need to be prepared again, though the\r
+ // parameters must be described again.\r
+\r
+ /*\r
+ DebugStream()<< _("Resize input descriptor from ")\r
+ << mInRow->AllocatedSize()<< _(" to ")\r
+ << mInRow->Columns()<< fds;\r
+ */\r
+\r
+ mInRow->Resize(mInRow->Columns());\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe_bind failed"));\r
+ }\r
+ }\r
+ }\r
+\r
+ // Allocates variables of the input descriptor\r
+ if (mInRow != 0)\r
+ {\r
+ // Turn on 'can be NULL' on each input parameter\r
+ for (int i = 0; i < mInRow->Columns(); i++)\r
+ {\r
+ XSQLVAR* var = &(mInRow->Self()->sqlvar[i]);\r
+ if (! (var->sqltype & 1)) var->sqltype += short(1);\r
+ }\r
+ mInRow->AllocVariables();\r
+ }\r
+\r
+ // Allocates variables of the output descriptor\r
+ if (mOutRow != 0) mOutRow->AllocVariables();\r
+}\r
+\r
+void StatementImpl::Plan(std::string& plan)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("No statement has been prepared."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("A Database must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("Database must be connected."));\r
+\r
+ IBS status;\r
+ RB result(4096);\r
+ char itemsReq[] = {isc_info_sql_get_plan};\r
+\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ result.Size(), result.Self());\r
+ if (status.Errors()) throw SQLExceptionImpl(status,\r
+ "Statement::Plan", _("isc_dsql_sql_info failed."));\r
+\r
+ result.GetString(isc_info_sql_get_plan, plan);\r
+ if (plan[0] == '\n') plan.erase(0, 1);\r
+}\r
+\r
+void StatementImpl::Execute(const std::string& sql)\r
+{\r
+ if (! sql.empty()) Prepare(sql);\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Execute",\r
+ _("No statement has been prepared."));\r
+\r
+ // Check that a value has been set for each input parameter\r
+ if (mInRow != 0 && mInRow->MissingValues())\r
+ throw LogicExceptionImpl("Statement::Execute",\r
+ _("All parameters must be specified."));\r
+\r
+ CursorFree(); // Free a previous 'cursor' if any\r
+\r
+ IBS status;\r
+ if (mType == IBPP::stSelect)\r
+ {\r
+ // Could return a result set (none, single or multi rows)\r
+ (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::Execute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute failed"));\r
+ }\r
+ if (mOutRow != 0)\r
+ {\r
+ mResultSetAvailable = true;\r
+ mCursorOpened = true;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Should return at most a single row\r
+ (*gds.Call()->m_dsql_execute2)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self(),\r
+ mOutRow == 0 ? 0 : mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::Execute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute2 failed"));\r
+ }\r
+ }\r
+}\r
+\r
+void StatementImpl::CursorExecute(const std::string& cursor, const std::string& sql)\r
+{\r
+ if (cursor.empty())\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Cursor name can't be 0."));\r
+\r
+ if (! sql.empty()) Prepare(sql);\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("No statement has been prepared."));\r
+ if (mType != IBPP::stSelectUpdate)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Statement must be a SELECT FOR UPDATE."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Statement would return no rows."));\r
+\r
+ // Check that a value has been set for each input parameter\r
+ if (mInRow != 0 && mInRow->MissingValues())\r
+ throw LogicExceptionImpl("Statement::CursorExecute",\r
+ _("All parameters must be specified."));\r
+\r
+ CursorFree(); // Free a previous 'cursor' if any\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::CursorExecute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute failed"));\r
+ }\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_set_cursor_name)(status.Self(), &mHandle, const_cast<char*>(cursor.c_str()), 0);\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ throw SQLExceptionImpl(status, "Statement::CursorExecute",\r
+ _("isc_dsql_set_cursor_name failed"));\r
+ }\r
+\r
+ mResultSetAvailable = true;\r
+ mCursorOpened = true;\r
+}\r
+\r
+void StatementImpl::ExecuteImmediate(const std::string& sql)\r
+{\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An IDatabase must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("IDatabase must be connected."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An ITransaction must be attached."));\r
+ if (mTransaction->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("ITransaction must be started."));\r
+ if (sql.empty())\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("SQL statement can't be 0."));\r
+\r
+ IBS status;\r
+ Close();\r
+ (*gds.Call()->m_dsql_execute_immediate)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), 0, const_cast<char*>(sql.c_str()),\r
+ short(mDatabase->Dialect()), 0);\r
+ if (status.Errors())\r
+ {\r
+ std::string context = "Statement::ExecuteImmediate( ";\r
+ context.append(sql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute_immediate failed"));\r
+ }\r
+}\r
+\r
+int StatementImpl::AffectedRows()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("No statement has been prepared."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("A Database must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("Database must be connected."));\r
+\r
+ int count;\r
+ IBS status;\r
+ RB result;\r
+ char itemsReq[] = {isc_info_sql_records};\r
+\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ result.Size(), result.Self());\r
+ if (status.Errors()) throw SQLExceptionImpl(status,\r
+ "Statement::AffectedRows", _("isc_dsql_sql_info failed."));\r
+\r
+ if (mType == IBPP::stInsert)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_insert_count);\r
+ else if (mType == IBPP::stUpdate)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_update_count);\r
+ else if (mType == IBPP::stDelete)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_delete_count);\r
+ else if (mType == IBPP::stSelect)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_select_count);\r
+ else count = 0; // Returns zero count for unknown cases\r
+\r
+ return count;\r
+}\r
+\r
+bool StatementImpl::Fetch()\r
+{\r
+ if (! mResultSetAvailable)\r
+ throw LogicExceptionImpl("Statement::Fetch",\r
+ _("No statement has been executed or no result set available."));\r
+\r
+ IBS status;\r
+ ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, mOutRow->Self());\r
+ if (code == 100) // This special code means "no more rows"\r
+ {\r
+ mResultSetAvailable = false;\r
+ // Oddly enough, fetching rows up to the last one seems to open\r
+ // an 'implicit' cursor that needs to be closed.\r
+ mCursorOpened = true;\r
+ CursorFree(); // Free the explicit or implicit cursor/result-set\r
+ return false;\r
+ }\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Fetch",\r
+ _("isc_dsql_fetch failed."));\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+bool StatementImpl::Fetch(IBPP::Row& row)\r
+{\r
+ if (! mResultSetAvailable)\r
+ throw LogicExceptionImpl("Statement::Fetch(row)",\r
+ _("No statement has been executed or no result set available."));\r
+\r
+ RowImpl* rowimpl = new RowImpl(*mOutRow);\r
+ row = rowimpl;\r
+\r
+ IBS status;\r
+ ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1,\r
+ rowimpl->Self());\r
+ if (code == 100) // This special code means "no more rows"\r
+ {\r
+ mResultSetAvailable = false;\r
+ // Oddly enough, fetching rows up to the last one seems to open\r
+ // an 'implicit' cursor that needs to be closed.\r
+ mCursorOpened = true;\r
+ CursorFree(); // Free the explicit or implicit cursor/result-set\r
+ row.clear();\r
+ return false;\r
+ }\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ row.clear();\r
+ throw SQLExceptionImpl(status, "Statement::Fetch(row)",\r
+ _("isc_dsql_fetch failed."));\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void StatementImpl::Close()\r
+{\r
+ // Free all statement resources.\r
+ // Used before preparing a new statement or from destructor.\r
+\r
+ if (mInRow != 0) { mInRow->Release(); mInRow = 0; }\r
+ if (mOutRow != 0) { mOutRow->Release(); mOutRow = 0; }\r
+\r
+ mResultSetAvailable = false;\r
+ mCursorOpened = false;\r
+ mType = IBPP::stUnknown;\r
+\r
+ if (mHandle != 0)\r
+ {\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_drop);\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Statement::Close(DSQL_drop)",\r
+ _("isc_dsql_free_statement failed."));\r
+ }\r
+}\r
+\r
+void StatementImpl::SetNull(int param)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::SetNull", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::SetNull", _("The statement does not take parameters."));\r
+\r
+ mInRow->SetNull(param);\r
+}\r
+\r
+void StatementImpl::Set(int param, bool value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[bool]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[bool]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const char* cstring)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[char*]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[char*]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, cstring);\r
+}\r
+\r
+void StatementImpl::Set(int param, const void* bindata, int len)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[void*]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[void*]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, bindata, len);\r
+}\r
+\r
+void StatementImpl::Set(int param, const std::string& s)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[string]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[string]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, s);\r
+}\r
+\r
+void StatementImpl::Set(int param, int16_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int16_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int16_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, int32_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int32_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int32_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, int64_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int64_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int64_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, float value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[float]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[float]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, double value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[double]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[double]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Timestamp& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Timestamp]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Timestamp]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Date& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Date]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Date]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Time& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Time]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Time]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Blob& blob)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Blob]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Blob]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, blob);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Array& array)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Array]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Array]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, array);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::DBKey& key)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[DBKey]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[DBKey]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, key);\r
+}\r
+\r
+/*\r
+void StatementImpl::Set(int param, const IBPP::Value& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Value]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Value]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+*/\r
+\r
+bool StatementImpl::IsNull(int column)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
+\r
+ return mOutRow->IsNull(column);\r
+}\r
+\r
+bool StatementImpl::Get(int column, bool* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, bool& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, char* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, void* bindata, int& userlen)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, bindata, userlen);\r
+}\r
+\r
+bool StatementImpl::Get(int column, std::string& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int16_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int16_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int32_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int32_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int64_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int64_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, float* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, float& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, double* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, double& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Timestamp& timestamp)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, timestamp);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Date& date)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, date);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Time& time)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, time);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Blob& blob)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, blob);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::DBKey& key)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, key);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Array& array)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, array);\r
+}\r
+\r
+/*\r
+const IBPP::Value StatementImpl::Get(int column)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column);\r
+}\r
+*/\r
+\r
+bool StatementImpl::IsNull(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
+\r
+ return mOutRow->IsNull(name);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, bool* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, bool& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, char* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get[char*]", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, void* retvalue, int& count)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get[void*,int]", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue, count);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, std::string& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::GetString", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int16_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int16_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int32_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int32_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int64_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int64_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, float* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, float& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, double* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, double& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retblob);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Array& retarray)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retarray);\r
+}\r
+\r
+/*\r
+const IBPP::Value StatementImpl::Get(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name);\r
+}\r
+*/\r
+\r
+int StatementImpl::Columns()\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->Columns();\r
+}\r
+\r
+int StatementImpl::ColumnNum(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnNum", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnNum(name);\r
+}\r
+\r
+const char* StatementImpl::ColumnName(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnName(varnum);\r
+}\r
+\r
+const char* StatementImpl::ColumnAlias(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnAlias(varnum);\r
+}\r
+\r
+const char* StatementImpl::ColumnTable(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnTable(varnum);\r
+}\r
+\r
+IBPP::SDT StatementImpl::ColumnType(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnType", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnType", _("The statement does not return results."));\r
+\r
+ return mOutRow->ColumnType(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnSubtype(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSubtype", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSubtype", _("The statement does not return results."));\r
+\r
+ return mOutRow->ColumnSubtype(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnSize(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSize", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSize", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnSize(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnScale(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnScale", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnScale", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnScale(varnum);\r
+}\r
+\r
+int StatementImpl::Parameters()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Parameters", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Parameters", _("The statement uses no parameters."));\r
+\r
+ return mInRow->Columns();\r
+}\r
+\r
+IBPP::SDT StatementImpl::ParameterType(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterType", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterType", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnType(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterSubtype(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSubtype", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSubtype", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnSubtype(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterSize(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSize", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSize", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnSize(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterScale(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterScale", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterScale", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnScale(varnum);\r
+}\r
+\r
+IBPP::Database StatementImpl::DatabasePtr() const\r
+{\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction StatementImpl::TransactionPtr() const\r
+{\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IStatement* StatementImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+\r
+ return this;\r
+}\r
+\r
+void StatementImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void StatementImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0)\r
+ throw LogicExceptionImpl("Statement::AttachDatabase",\r
+ _("Can't attach a 0 IDatabase object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachStatementImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachStatementImpl(this);\r
+}\r
+\r
+void StatementImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ Close();\r
+ mDatabase->DetachStatementImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void StatementImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0)\r
+ throw LogicExceptionImpl("Statement::AttachTransaction",\r
+ _("Can't attach a 0 ITransaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachStatementImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachStatementImpl(this);\r
+}\r
+\r
+void StatementImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ Close();\r
+ mTransaction->DetachStatementImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+void StatementImpl::CursorFree()\r
+{\r
+ if (mCursorOpened)\r
+ {\r
+ mCursorOpened = false;\r
+ if (mHandle != 0)\r
+ {\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_close);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "StatementImpl::CursorFree(DSQL_close)",\r
+ _("isc_dsql_free_statement failed."));\r
+ }\r
+ }\r
+}\r
+\r
+StatementImpl::StatementImpl(DatabaseImpl* database, TransactionImpl* transaction,\r
+ const std::string& sql)\r
+ : mRefCount(0), mHandle(0), mDatabase(0), mTransaction(0),\r
+ mInRow(0), mOutRow(0),\r
+ mResultSetAvailable(false), mCursorOpened(false), mType(IBPP::stUnknown)\r
+{\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+ if (! sql.empty()) Prepare(sql);\r
+}\r
+\r
+StatementImpl::~StatementImpl()\r
+{\r
+ try { Close(); }\r
+ catch (...) { }\r
+ try { if (mTransaction != 0) mTransaction->DetachStatementImpl(this); }\r
+ catch (...) { }\r
+ try { if (mDatabase != 0) mDatabase->DetachStatementImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: time.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Time class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
+\r
+using namespace ibpp_internals;\r
+\r
+void IBPP::Time::Now()\r
+{\r
+ time_t systime = time(0);\r
+ tm* loctime = localtime(&systime);\r
+ IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0);\r
+}\r
+\r
+void IBPP::Time::SetTime(int tm)\r
+{\r
+ if (tm < 0 || tm > 863999999)\r
+ throw LogicExceptionImpl("Time::SetTime", _("Invalid time value"));\r
+ mTime = tm;\r
+}\r
+\r
+void IBPP::Time::SetTime(int hour, int minute, int second, int tenthousandths)\r
+{\r
+ if (hour < 0 || hour > 23 ||\r
+ minute < 0 || minute > 59 ||\r
+ second < 0 || second > 59 ||\r
+ tenthousandths < 0 || tenthousandths > 9999)\r
+ throw LogicExceptionImpl("Time::SetTime",\r
+ _("Invalid hour, minute, second values"));\r
+ IBPP::itot(&mTime, hour, minute, second, tenthousandths);\r
+}\r
+\r
+void IBPP::Time::GetTime(int& hour, int& minute, int& second) const\r
+{\r
+ IBPP::ttoi(mTime, &hour, &minute, &second, 0);\r
+}\r
+\r
+void IBPP::Time::GetTime(int& hour, int& minute, int& second, int& tenthousandths) const\r
+{\r
+ IBPP::ttoi(mTime, &hour, &minute, &second, &tenthousandths);\r
+}\r
+\r
+int IBPP::Time::Hours() const\r
+{\r
+ int hours;\r
+ IBPP::ttoi(mTime, &hours, 0, 0, 0);\r
+ return hours;\r
+}\r
+\r
+int IBPP::Time::Minutes() const\r
+{\r
+ int minutes;\r
+ IBPP::ttoi(mTime, 0, &minutes, 0, 0);\r
+ return minutes;\r
+}\r
+\r
+int IBPP::Time::Seconds() const\r
+{\r
+ int seconds;\r
+ IBPP::ttoi(mTime, 0, 0, &seconds, 0);\r
+ return seconds;\r
+}\r
+\r
+int IBPP::Time::SubSeconds() const // Actually tenthousandths of seconds\r
+{\r
+ int tenthousandths;\r
+ IBPP::ttoi(mTime, 0, 0, 0, &tenthousandths);\r
+ return tenthousandths;\r
+}\r
+\r
+IBPP::Time::Time(int hour, int minute, int second, int tenthousandths)\r
+{\r
+ SetTime(hour, minute, second, tenthousandths);\r
+}\r
+\r
+IBPP::Time::Time(const IBPP::Time& copied)\r
+{\r
+ mTime = copied.mTime;\r
+}\r
+\r
+IBPP::Time& IBPP::Time::operator=(const IBPP::Timestamp& assigned)\r
+{\r
+ mTime = assigned.GetTime();\r
+ return *this;\r
+}\r
+\r
+IBPP::Time& IBPP::Time::operator=(const IBPP::Time& assigned)\r
+{\r
+ mTime = assigned.mTime;\r
+ return *this;\r
+}\r
+\r
+// Time calculations. Internal format is the number of seconds elapsed since\r
+// midnight. Splits such a time in its hours, minutes, seconds components.\r
+\r
+void IBPP::ttoi(int itime, int *h, int *m, int *s, int* t)\r
+{\r
+ int hh, mm, ss, tt;\r
+\r
+ hh = (int) (itime / 36000000); itime = itime - hh * 36000000;\r
+ mm = (int) (itime / 600000); itime = itime - mm * 600000;\r
+ ss = (int) (itime / 10000);\r
+ tt = (int) (itime - ss * 10000);\r
+\r
+ if (h != 0) *h = hh;\r
+ if (m != 0) *m = mm;\r
+ if (s != 0) *s = ss;\r
+ if (t != 0) *t = tt;\r
+\r
+ return;\r
+}\r
+\r
+// Get the internal time format, given hour, minute, second.\r
+\r
+void IBPP::itot (int *ptime, int hour, int minute, int second, int tenthousandths)\r
+{\r
+ *ptime = hour * 36000000 + minute * 600000 + second * 10000 + tenthousandths;\r
+ return;\r
+}\r
+\r
+namespace ibpp_internals\r
+{\r
+\r
+//\r
+// The following functions are helper conversions functions between IBPP\r
+// Date, Time, Timestamp and ISC_DATE, ISC_TIME and ISC_TIMESTAMP.\r
+// (They must be maintained if the encoding used by Firebird evolve.)\r
+// These helper functions are used from row.cpp and from array.cpp.\r
+//\r
+\r
+void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt)\r
+{\r
+ // There simply has a shift of 15019 between the native Firebird\r
+ // date model and the IBPP model.\r
+ isc_dt = (ISC_DATE)(dt.GetDate() + 15019);\r
+}\r
+\r
+void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt)\r
+{\r
+ // There simply has a shift of 15019 between the native Firebird\r
+ // date model and the IBPP model.\r
+ dt.SetDate((int)isc_dt - 15019);\r
+}\r
+\r
+void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm)\r
+{\r
+ isc_tm = (ISC_TIME)tm.GetTime();\r
+}\r
+\r
+void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm)\r
+{\r
+ tm.SetTime((int)isc_tm);\r
+}\r
+\r
+void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts)\r
+{\r
+ encodeDate(isc_ts.timestamp_date, ts);\r
+ encodeTime(isc_ts.timestamp_time, ts);\r
+}\r
+\r
+void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts)\r
+{\r
+ decodeDate(ts, isc_ts.timestamp_date);\r
+ decodeTime(ts, isc_ts.timestamp_time);\r
+}\r
+\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
+\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: transaction.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Database class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <algorithm>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void TransactionImpl::AttachDatabase(IBPP::Database db,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+{\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach an unbound Database."));\r
+\r
+ AttachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()), am, il, lr, flags);\r
+}\r
+\r
+void TransactionImpl::DetachDatabase(IBPP::Database db)\r
+{\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach an unbound Database."));\r
+\r
+ DetachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
+}\r
+\r
+void TransactionImpl::AddReservation(IBPP::Database db,\r
+ const std::string& table, IBPP::TTR tr)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Can't add table reservation if Transaction started."));\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Can't add table reservation on an unbound Database."));\r
+\r
+ // Find the TPB associated with this database\r
+ std::vector<DatabaseImpl*>::iterator pos =\r
+ std::find(mDatabases.begin(), mDatabases.end(), dynamic_cast<DatabaseImpl*>(db.intf()));\r
+ if (pos != mDatabases.end())\r
+ {\r
+ size_t index = pos - mDatabases.begin();\r
+ TPB* tpb = mTPBs[index];\r
+ \r
+ // Now add the reservations to the TPB\r
+ switch (tr)\r
+ {\r
+ case IBPP::trSharedWrite :\r
+ tpb->Insert(isc_tpb_lock_write);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_shared);\r
+ break;\r
+ case IBPP::trSharedRead :\r
+ tpb->Insert(isc_tpb_lock_read);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_shared);\r
+ break;\r
+ case IBPP::trProtectedWrite :\r
+ tpb->Insert(isc_tpb_lock_write);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_protected);\r
+ break;\r
+ case IBPP::trProtectedRead :\r
+ tpb->Insert(isc_tpb_lock_read);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_protected);\r
+ break;\r
+ /*default :\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Illegal TTR value detected."));*/\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("The database connection you specified is not attached to this transaction."));\r
+}\r
+\r
+void TransactionImpl::Start()\r
+{\r
+ if (mHandle != 0) return; // Already started anyway\r
+\r
+ if (mDatabases.empty())\r
+ throw LogicExceptionImpl("Transaction::Start", _("No Database is attached."));\r
+\r
+ struct ISC_TEB\r
+ {\r
+ ISC_LONG* db_ptr;\r
+ ISC_LONG tpb_len;\r
+ char* tpb_ptr;\r
+ } * teb = new ISC_TEB[mDatabases.size()];\r
+\r
+ unsigned i;\r
+ for (i = 0; i < mDatabases.size(); i++)\r
+ {\r
+ if (mDatabases[i]->GetHandle() == 0)\r
+ {\r
+ // All Databases must be connected to Start the transaction !\r
+ delete [] teb;\r
+ throw LogicExceptionImpl("Transaction::Start",\r
+ _("All attached Database should have been connected."));\r
+ }\r
+ teb[i].db_ptr = (ISC_LONG*) mDatabases[i]->GetHandlePtr();\r
+ teb[i].tpb_len = mTPBs[i]->Size();\r
+ teb[i].tpb_ptr = mTPBs[i]->Self();\r
+ }\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_start_multiple)(status.Self(), &mHandle, (short)mDatabases.size(), teb);\r
+ delete [] teb;\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Transaction::Start");\r
+ }\r
+}\r
+\r
+void TransactionImpl::Commit()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::Commit", _("Transaction is not started."));\r
+ \r
+ IBS status;\r
+\r
+ (*gds.Call()->m_commit_transaction)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::Commit");\r
+ mHandle = 0; // Should be, better be sure\r
+}\r
+\r
+void TransactionImpl::CommitRetain()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::CommitRetain", _("Transaction is not started."));\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_commit_retaining)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::CommitRetain");\r
+}\r
+\r
+void TransactionImpl::Rollback()\r
+{\r
+ if (mHandle == 0) return; // Transaction not started anyway\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_rollback_transaction)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::Rollback");\r
+ mHandle = 0; // Should be, better be sure\r
+}\r
+\r
+void TransactionImpl::RollbackRetain()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::RollbackRetain", _("Transaction is not started."));\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_rollback_retaining)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::RollbackRetain");\r
+}\r
+\r
+IBPP::ITransaction* TransactionImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void TransactionImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void TransactionImpl::Init()\r
+{\r
+ mHandle = 0;\r
+ mDatabases.clear();\r
+ mTPBs.clear();\r
+ mStatements.clear();\r
+ mBlobs.clear();\r
+ mArrays.clear();\r
+}\r
+\r
+void TransactionImpl::AttachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachStatement",\r
+ _("Can't attach a 0 Statement object."));\r
+\r
+ mStatements.push_back(st);\r
+}\r
+\r
+void TransactionImpl::DetachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachStatement",\r
+ _("Can't detach a 0 Statement object."));\r
+\r
+ mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
+}\r
+\r
+void TransactionImpl::AttachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachBlob",\r
+ _("Can't attach a 0 BlobImpl object."));\r
+\r
+ mBlobs.push_back(bb);\r
+}\r
+\r
+void TransactionImpl::DetachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachBlob",\r
+ _("Can't detach a 0 BlobImpl object."));\r
+\r
+ mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
+}\r
+\r
+void TransactionImpl::AttachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachArray",\r
+ _("Can't attach a 0 ArrayImpl object."));\r
+\r
+ mArrays.push_back(ar);\r
+}\r
+\r
+void TransactionImpl::DetachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachArray",\r
+ _("Can't detach a 0 ArrayImpl object."));\r
+\r
+ mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
+}\r
+\r
+void TransactionImpl::AttachDatabaseImpl(DatabaseImpl* dbi,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach a Database if Transaction started."));\r
+ if (dbi == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach a null Database."));\r
+\r
+ mDatabases.push_back(dbi);\r
+\r
+ // Prepare a new TPB\r
+ TPB* tpb = new TPB;\r
+ if (am == IBPP::amRead) tpb->Insert(isc_tpb_read);\r
+ else tpb->Insert(isc_tpb_write);\r
+\r
+ switch (il)\r
+ {\r
+ case IBPP::ilConsistency : tpb->Insert(isc_tpb_consistency); break;\r
+ case IBPP::ilReadDirty : tpb->Insert(isc_tpb_read_committed);\r
+ tpb->Insert(isc_tpb_rec_version); break;\r
+ case IBPP::ilReadCommitted : tpb->Insert(isc_tpb_read_committed);\r
+ tpb->Insert(isc_tpb_no_rec_version); break;\r
+ case IBPP::ilConcurrency : tpb->Insert(isc_tpb_concurrency); break;\r
+ }\r
+\r
+ if (lr == IBPP::lrNoWait) tpb->Insert(isc_tpb_nowait);\r
+ else tpb->Insert(isc_tpb_wait);\r
+\r
+ if (flags & IBPP::tfIgnoreLimbo) tpb->Insert(isc_tpb_ignore_limbo);\r
+ if (flags & IBPP::tfAutoCommit) tpb->Insert(isc_tpb_autocommit);\r
+ if (flags & IBPP::tfNoAutoUndo) tpb->Insert(isc_tpb_no_auto_undo);\r
+\r
+ mTPBs.push_back(tpb);\r
+\r
+ // Signals the Database object that it has been attached to the Transaction\r
+ dbi->AttachTransactionImpl(this);\r
+}\r
+\r
+void TransactionImpl::DetachDatabaseImpl(DatabaseImpl* dbi)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach a Database if Transaction started."));\r
+ if (dbi == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach a null Database."));\r
+\r
+ std::vector<DatabaseImpl*>::iterator pos =\r
+ std::find(mDatabases.begin(), mDatabases.end(), dbi);\r
+ if (pos != mDatabases.end())\r
+ {\r
+ size_t index = pos - mDatabases.begin();\r
+ TPB* tpb = mTPBs[index];\r
+ mDatabases.erase(pos);\r
+ mTPBs.erase(mTPBs.begin()+index);\r
+ delete tpb;\r
+ }\r
+\r
+ // Signals the Database object that it has been detached from the Transaction\r
+ dbi->DetachTransactionImpl(this);\r
+}\r
+\r
+TransactionImpl::TransactionImpl(DatabaseImpl* db,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(db, am, il, lr, flags);\r
+}\r
+\r
+TransactionImpl::~TransactionImpl()\r
+{\r
+ // Rollback the transaction if it was Started\r
+ try { if (Started()) Rollback(); }\r
+ catch (...) { }\r
+\r
+ // Let's detach cleanly all Blobs from this Transaction.\r
+ // No Blob object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ //\r
+ // We use a reverse traversal of the array to avoid loops.\r
+ // The array shrinks on each loop (mBbCount decreases).\r
+ // And during the deletion, there is a packing of the array through a\r
+ // copy of elements from the end to the beginning of the array.\r
+ try {\r
+ while (mBlobs.size() > 0)\r
+ mBlobs.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Let's detach cleanly all Arrays from this Transaction.\r
+ // No Array object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mArrays.size() > 0)\r
+ mArrays.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Let's detach cleanly all Statements from this Transaction.\r
+ // No Statement object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mStatements.size() > 0)\r
+ mStatements.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Very important : let's detach cleanly all Databases from this\r
+ // Transaction. No Database object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mDatabases.size() > 0)\r
+ {\r
+ size_t i = mDatabases.size()-1;\r
+ DetachDatabaseImpl(mDatabases[i]); // <-- remove link to database from mTPBs\r
+ // array and destroy TPB object\r
+ // Fixed : Maxim Abrashkin on 12 Jun 2002\r
+ //mDatabases.back()->DetachTransaction(this);\r
+ }\r
+ } catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: user.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, User class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <iostream>\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// Private implementation\r
+\r
+void IBPP::User::copyfrom(const IBPP::User& r)\r
+{\r
+ username = r.username;\r
+ password = r.password;\r
+ firstname = r.firstname;\r
+ middlename = r.middlename;\r
+ lastname = r.lastname;\r
+ userid = r.userid;\r
+ groupid = r.groupid;\r
+}\r
+\r
+// Public implementation\r
+\r
+void IBPP::User::clear()\r
+{\r
+ username.erase(); password.erase();\r
+ firstname.erase(); middlename.erase(); lastname.erase();\r
+ userid = groupid = 0;\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+set ( CPP_FILES generator.cpp parser.cpp )
+
+add_library ( json STATIC ${CPP_FILES} )
+
+target_include_directories ( json PUBLIC include )
+
+target_link_libraries ( json common )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "stg/json_generator.h"
+
+#include <yajl/yajl_gen.h>
+
+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<const unsigned char*>(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<const char*>(buf), size);
+
+ yajl_gen_free(handle);
+
+ return res;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_JSON_GENERATOR_H__
+#define __STG_STGLIBS_JSON_GENERATOR_H__
+
+#include <string>
+#include <map>
+#include <vector>
+#include <utility>
+
+#include <boost/scoped_ptr.hpp>
+
+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 <typename T>
+ 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<Gen*, bool> SmartGen;
+ typedef std::map<std::string, SmartGen> 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<Gen*, bool> SmartGen;
+ typedef std::vector<SmartGen> Value;
+ Value m_value;
+};
+
+typedef bool (*Callback)(void* /*data*/, const char* /*buf*/, size_t /*size*/);
+bool generate(Gen& gen, Callback callback, void* data);
+
+}
+}
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_JSON_PARSER_H__
+#define __STG_STGLIBS_JSON_PARSER_H__
+
+#include "stg/common.h"
+
+#include <string>
+#include <map>
+
+#include <boost/scoped_ptr.hpp>
+
+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<Impl> m_impl;
+};
+
+template <typename T>
+class EnumParser : public NodeParser
+{
+ public:
+ typedef std::map<std::string, T> 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<std::string, std::string> 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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "stg/json_parser.h"
+
+#include <yajl/yajl_parse.h>
+
+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<const unsigned char*>(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<const char*>(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<const char*>(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<Impl*>(ctx)->m_parser; }
+ static bool runParser(void* ctx, NodeParser* (NodeParser::*func)())
+ {
+ Impl& p = *static_cast<Impl*>(ctx);
+ NodeParser* next = (p.m_parser->*func)();
+ if (next != NULL)
+ p.m_parser = next;
+ return next != NULL;
+ }
+ template <typename T>
+ static bool runParser(void* ctx, NodeParser* (NodeParser::*func)(const T&), const T& value)
+ {
+ Impl& p = *static_cast<Impl*>(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();
+}
--- /dev/null
+set ( CPP_FILES logger.cpp )
+
+add_library ( logger STATIC ${CPP_FILES} )
+
+target_include_directories ( logger PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#ifndef STG_LOGGER_H
+#define STG_LOGGER_H
+
+#include <string>
+
+#include <pthread.h>
+
+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
--- /dev/null
+#include "stg/logger.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+#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);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+set ( CPP_FILES pinger.cpp )
+
+add_library ( pinger STATIC ${CPP_FILES} )
+
+target_include_directories ( pinger PUBLIC include )
+
+target_link_libraries ( pinger common )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+ /*
+ $Revision: 1.8 $
+ $Date: 2008/05/10 11:59:53 $
+ $Author: nobunaga $
+ */
+
+#ifndef PINGER_H
+#define PINGER_H
+
+#include <ctime>
+#include <string>
+#include <list>
+#include <map>
+
+#ifdef LINUX
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip_icmp.h>
+#endif
+
+#if defined (FREE_BSD) || defined(DARWIN)
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <arpa/inet.h>
+#endif
+
+#include <cstdint>
+
+//-----------------------------------------------------------------------------
+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<uint32_t, time_t> 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<uint32_t, time_t> pingIP;
+ std::list<uint32_t> ipToAdd;
+ std::list<uint32_t> ipToDel;
+
+ mutable pthread_mutex_t mutex;
+};
+//-----------------------------------------------------------------------------
+#endif
--- /dev/null
+#include <pthread.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <cstdlib>
+#include <csignal>
+#include <cstring>
+#include <cerrno>
+#include <cmath>
+#include <cstdio>
+
+#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<uint32_t>::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<uint32_t>::iterator iter;
+std::multimap<uint32_t, time_t>::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<uint32_t, time_t>::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<uint32_t, time_t>::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<uint16_t *>(data);
+uint32_t sum = 0;
+uint32_t result;
+
+for ( sum = 0; len > 1; len -= 2 )
+ sum += *buf++;
+
+if ( len == 1 )
+ sum += *reinterpret_cast<uint8_t*>(buf);
+
+sum = (sum >> 16) + (sum & 0xFFFF);
+sum += (sum >> 16);
+result = ~sum;
+return static_cast<uint16_t>(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<uint16_t>(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<struct sockaddr*>(&addr), &len))
+ {
+ struct IP_HDR * ip = static_cast<struct IP_HDR *>(static_cast<void *>(buf));
+ struct ICMP_HDR *icmp = static_cast<struct ICMP_HDR *>(static_cast<void *>(buf + ip->ihl * 4));
+
+ if (icmp->un.echo.id != pid)
+ return 0;
+
+ ipAddr = *static_cast<uint32_t*>(static_cast<void *>(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<STG_PINGER *>(d);
+
+pinger->isRunningSender = true;
+time_t lastPing = 0;
+while (pinger->nonstop)
+ {
+ pinger->RealAddIP();
+ pinger->RealDelIP();
+
+ std::multimap<uint32_t, time_t>::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<STG_PINGER *>(d);
+
+pinger->isRunningRecver = true;
+
+while (pinger->nonstop)
+ {
+ uint32_t ip = pinger->RecvPing();
+
+ if (ip)
+ {
+ std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
+ std::multimap<uint32_t, time_t>::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;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+set ( C_FILES scriptexecuter.c )
+
+add_library ( scriptexecuter STATIC ${C_FILES} )
+
+target_include_directories ( scriptexecuter PUBLIC include )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#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
--- /dev/null
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#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
+ }
+ }
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ANY.h>
+#include <errno.h>
+
+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;
+}
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <BIT_STRING.h>
+#include <asn_internal.h>
+
+/*
+ * 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("<absent>", 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;
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_codecs_prim.h>
+#include <BOOLEAN.h>
+
+/*
+ * 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:
+ /* "<false/>" */
+ *st = 0;
+ break;
+ case XCT_UNKNOWN_BO:
+ if(xer_check_tag(chunk_buf, chunk_size, "true")
+ != XCT_BOTH)
+ return XPBD_BROKEN_ENCODING;
+ /* "<true/>" */
+ *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("<true/>", 7);
+ er.encoded = 7;
+ } else {
+ _ASN_CALLBACK("<false/>", 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 = "<absent>";
+ 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);
+}
--- /dev/null
+file ( GLOB C_FILES *.c )
+
+add_library ( smux STATIC ${C_FILES} )
+
+target_include_directories ( smux PUBLIC include include/stg )
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <INTEGER.h>
+#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
+#include <errno.h>
+
+/*
+ * 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("<absent>", 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;
+}
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+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
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_codecs_prim.h>
+#include <NULL.h>
+#include <BOOLEAN.h> /* 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("<present>", 9, app_key) < 0) ? -1 : 0;
+ } else {
+ return (cb("<absent>", 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);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. 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 <asn_internal.h>
+#include <NativeEnumerated.h>
+
+/*
+ * 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);
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * 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 <asn_internal.h>
+#include <NativeInteger.h>
+
+/*
+ * 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("<absent>", 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);
+ }
+}
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <OBJECT_IDENTIFIER.h>
+#include <limits.h> /* for CHAR_BIT */
+#include <errno.h>
+
+/*
+ * 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("<absent>", 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<oid_end; oid_text++) {
+ switch(*oid_text) {
+ case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */
+ if(state == ST_SKIPSPACE) {
+ continue;
+ } else {
+ break; /* Finish */
+ }
+ case 0x2e: /* '.' */
+ if(state != ST_DIGITS
+ || (oid_text + 1) == oid_end) {
+ state = ST_WAITDIGITS;
+ break;
+ }
+ if(arcs_count < arcs_slots)
+ arcs[arcs_count] = value;
+ arcs_count++;
+ state = ST_WAITDIGITS;
+ continue;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+ case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
+ if(state != ST_DIGITS) {
+ state = ST_DIGITS;
+ value = 0;
+ }
+ if(1) {
+ long new_value = value * 10;
+ if(new_value / 10 != value
+ || (value = new_value + (*oid_text - 0x30)) < 0) {
+ /* Overflow */
+ state = ST_WAITDIGITS;
+ break;
+ }
+ continue;
+ }
+ default:
+ /* Unexpected symbols */
+ state = ST_WAITDIGITS;
+ break;
+ } /* switch() */
+ break;
+ } /* for() */
+
+
+ if(opt_oid_text_end) *opt_oid_text_end = oid_text;
+
+ /* Finalize last arc */
+ switch(state) {
+ case ST_WAITDIGITS:
+ errno = EINVAL;
+ return -1;
+ case ST_DIGITS:
+ if(arcs_count < arcs_slots)
+ arcs[arcs_count] = value;
+ arcs_count++;
+ /* Fall through */
+ default:
+ return arcs_count;
+ }
+}
+
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <OCTET_STRING.h>
+#include <BIT_STRING.h> /* for .bits_unused member */
+#include <errno.h>
+
+/*
+ * 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 : "<data>",
+ (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: [<tag>] 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"), /* <nul/> */
+ OSXET("\074\163\157\150\057\076"), /* <soh/> */
+ OSXET("\074\163\164\170\057\076"), /* <stx/> */
+ OSXET("\074\145\164\170\057\076"), /* <etx/> */
+ OSXET("\074\145\157\164\057\076"), /* <eot/> */
+ OSXET("\074\145\156\161\057\076"), /* <enq/> */
+ OSXET("\074\141\143\153\057\076"), /* <ack/> */
+ OSXET("\074\142\145\154\057\076"), /* <bel/> */
+ OSXET("\074\142\163\057\076"), /* <bs/> */
+ OSXET("\011"), /* \t */
+ OSXET("\012"), /* \n */
+ OSXET("\074\166\164\057\076"), /* <vt/> */
+ OSXET("\074\146\146\057\076"), /* <ff/> */
+ OSXET("\015"), /* \r */
+ OSXET("\074\163\157\057\076"), /* <so/> */
+ OSXET("\074\163\151\057\076"), /* <si/> */
+ OSXET("\074\144\154\145\057\076"), /* <dle/> */
+ OSXET("\074\144\143\061\057\076"), /* <de1/> */
+ OSXET("\074\144\143\062\057\076"), /* <de2/> */
+ OSXET("\074\144\143\063\057\076"), /* <de3/> */
+ OSXET("\074\144\143\064\057\076"), /* <de4/> */
+ OSXET("\074\156\141\153\057\076"), /* <nak/> */
+ OSXET("\074\163\171\156\057\076"), /* <syn/> */
+ OSXET("\074\145\164\142\057\076"), /* <etb/> */
+ OSXET("\074\143\141\156\057\076"), /* <can/> */
+ OSXET("\074\145\155\057\076"), /* <em/> */
+ OSXET("\074\163\165\142\057\076"), /* <sub/> */
+ OSXET("\074\145\163\143\057\076"), /* <esc/> */
+ OSXET("\074\151\163\064\057\076"), /* <is4/> */
+ OSXET("\074\151\163\063\057\076"), /* <is3/> */
+ OSXET("\074\151\163\062\057\076"), /* <is2/> */
+ OSXET("\074\151\163\061\057\076"), /* <is1/> */
+ { 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("<absent>", 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("<absent>", 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;
+}
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+
+-- WinAgents MIB Extraction Wizard\r
+-- Extracted from rfc1155.txt 17.03.2005 16:16:50\r
+\r
+RFC1155-SMI DEFINITIONS ::= BEGIN\r
+\r
+--EXPORTS EVERYTHING\r
+-- internet, directory, mgmt,\r
+-- experimental, private, enterprises,\r
+-- OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax,\r
+-- ApplicationSyntax, NetworkAddress, IpAddress,\r
+-- Counter, Gauge, TimeTicks, Opaque;\r
+\r
+ -- the path to the root\r
+\r
+ internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }\r
+\r
+ directory OBJECT IDENTIFIER ::= { internet 1 }\r
+\r
+ mgmt OBJECT IDENTIFIER ::= { internet 2 }\r
+\r
+ experimental OBJECT IDENTIFIER ::= { internet 3 }\r
+\r
+ private OBJECT IDENTIFIER ::= { internet 4 }\r
+ enterprises OBJECT IDENTIFIER ::= { private 1 }\r
+\r
+\r
+ -- definition of object types\r
+\r
+-- MIB Extraction: All MACRO definitions are predefined by compiler\r
+-- commented by MIB Extraction: OBJECT-TYPE MACRO ::=\r
+-- commented by MIB Extraction: BEGIN\r
+-- commented by MIB Extraction: TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax)\r
+-- commented by MIB Extraction: "ACCESS" Access\r
+-- commented by MIB Extraction: "STATUS" Status\r
+-- commented by MIB Extraction: VALUE NOTATION ::= value (VALUE ObjectName)\r
+-- commented by MIB Extraction: \r
+-- commented by MIB Extraction: Access ::= "read-only"\r
+-- commented by MIB Extraction: | "read-write"\r
+-- commented by MIB Extraction: | "write-only"\r
+-- commented by MIB Extraction: | "not-accessible"\r
+-- commented by MIB Extraction: Status ::= "mandatory"\r
+-- commented by MIB Extraction: | "optional"\r
+-- commented by MIB Extraction: | "obsolete"\r
+-- commented by MIB Extraction: END\r
+\r
+ -- names of objects in the MIB\r
+\r
+ ObjectName ::=\r
+ OBJECT IDENTIFIER\r
+\r
+\r
+ -- syntax of objects in the MIB\r
+\r
+ ObjectSyntax ::=\r
+ CHOICE {\r
+ simple\r
+ SimpleSyntax,\r
+\r
+ -- note that simple SEQUENCEs are not directly\r
+ -- mentioned here to keep things simple (i.e.,\r
+ -- prevent mis-use). However, application-wide\r
+ -- types which are IMPLICITly encoded simple\r
+ -- SEQUENCEs may appear in the following CHOICE\r
+\r
+ application-wide\r
+ ApplicationSyntax\r
+ }\r
+\r
+ SimpleSyntax ::=\r
+ CHOICE {\r
+ number\r
+ INTEGER,\r
+\r
+ string\r
+ OCTET STRING,\r
+\r
+ object\r
+ OBJECT IDENTIFIER,\r
+\r
+ empty\r
+ NULL\r
+ }\r
+\r
+ ApplicationSyntax ::=\r
+ CHOICE {\r
+ address\r
+ NetworkAddress,\r
+\r
+ counter\r
+ Counter,\r
+\r
+ gauge\r
+ Gauge,\r
+\r
+ ticks\r
+ TimeTicks,\r
+\r
+ arbitrary\r
+ Opaque\r
+\r
+ -- other application-wide types, as they are\r
+ -- defined, will be added here\r
+ }\r
+\r
+\r
+ -- application-wide types\r
+\r
+ NetworkAddress ::=\r
+ CHOICE {\r
+ internet\r
+ IpAddress\r
+ }\r
+\r
+ IpAddress ::=\r
+ [APPLICATION 0] -- in network-byte order\r
+ IMPLICIT OCTET STRING (SIZE (4))\r
+\r
+ Counter ::=\r
+ [APPLICATION 1]\r
+ IMPLICIT INTEGER (0..4294967295)\r
+\r
+ Gauge ::=\r
+ [APPLICATION 2]\r
+ IMPLICIT INTEGER (0..4294967295)\r
+\r
+ TimeTicks ::=\r
+ [APPLICATION 3]\r
+ IMPLICIT INTEGER (0..4294967295)\r
+\r
+ Opaque ::=\r
+ [APPLICATION 4] -- arbitrary ASN.1 value,\r
+ IMPLICIT OCTET STRING -- "double-wrapped"\r
+\r
+ END\r
--- /dev/null
+
+-- WinAgents MIB Extraction Wizard\r
+-- Extracted from rfc1157.txt 16.03.2005 20:20:14\r
+\r
+RFC1157-SNMP DEFINITIONS ::= BEGIN\r
+\r
+ IMPORTS\r
+ ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks\r
+ FROM RFC1155-SMI;\r
+\r
+\r
+ -- top-level message\r
+\r
+ Message ::=\r
+ SEQUENCE {\r
+ version -- version-1 for this RFC\r
+ INTEGER {\r
+ version-1(0)\r
+ },\r
+\r
+ community -- community name\r
+ OCTET STRING,\r
+\r
+ data -- e.g., PDUs if trivial\r
+ ANY -- authentication is being used\r
+ }\r
+\r
+\r
+ -- protocol data units\r
+\r
+ PDUs ::=\r
+ CHOICE {\r
+ get-request\r
+ GetRequest-PDU,\r
+\r
+ get-next-request\r
+ GetNextRequest-PDU,\r
+\r
+ get-response\r
+ GetResponse-PDU,\r
+\r
+ set-request\r
+ SetRequest-PDU,\r
+\r
+ trap\r
+ Trap-PDU\r
+ }\r
+\r
+\r
+\r
+\r
+ -- PDUs\r
+\r
+ GetRequest-PDU ::=\r
+ [0]\r
+ IMPLICIT PDU\r
+\r
+ GetNextRequest-PDU ::=\r
+ [1]\r
+ IMPLICIT PDU\r
+\r
+ GetResponse-PDU ::=\r
+ [2]\r
+ IMPLICIT PDU\r
+\r
+ SetRequest-PDU ::=\r
+ [3]\r
+ IMPLICIT PDU\r
+\r
+ PDU ::=\r
+ SEQUENCE {\r
+ request-id\r
+ INTEGER,\r
+\r
+ error-status -- sometimes ignored\r
+ INTEGER {\r
+ noError(0),\r
+ tooBig(1),\r
+ noSuchName(2),\r
+ badValue(3),\r
+ readOnly(4),\r
+ genErr(5)\r
+ },\r
+\r
+ error-index -- sometimes ignored\r
+ INTEGER,\r
+\r
+ variable-bindings -- values are sometimes ignored\r
+ VarBindList\r
+ }\r
+\r
+ Trap-PDU ::=\r
+ [4]\r
+ IMPLICIT SEQUENCE {\r
+ enterprise -- type of object generating\r
+ -- trap, see sysObjectID in [5]\r
+\r
+\r
+ OBJECT IDENTIFIER,\r
+\r
+ agent-addr -- address of object generating\r
+ NetworkAddress, -- trap\r
+\r
+ generic-trap -- generic trap type\r
+ INTEGER {\r
+ coldStart(0),\r
+ warmStart(1),\r
+ linkDown(2),\r
+ linkUp(3),\r
+ authenticationFailure(4),\r
+ egpNeighborLoss(5),\r
+ enterpriseSpecific(6)\r
+ },\r
+\r
+ specific-trap -- specific code, present even\r
+ INTEGER, -- if generic-trap is not\r
+ -- enterpriseSpecific\r
+\r
+ time-stamp -- time elapsed between the last\r
+ TimeTicks, -- (re)initialization of the network\r
+ -- entity and the generation of the trap\r
+\r
+ variable-bindings -- "interesting" information\r
+ VarBindList\r
+ }\r
+\r
+\r
+ -- variable bindings\r
+\r
+ VarBind ::=\r
+ SEQUENCE {\r
+ name\r
+ ObjectName,\r
+\r
+ value\r
+ ObjectSyntax\r
+ }\r
+\r
+ VarBindList ::=\r
+ SEQUENCE OF\r
+ VarBind\r
+\r
+ END
\ No newline at end of file
--- /dev/null
+
+-- WinAgents MIB Extraction Wizard\r
+-- Extracted from rfc1213.txt 16.03.2005 20:20:14\r
+\r
+RFC1213-MIB DEFINITIONS ::= BEGIN\r
+\r
+IMPORTS\r
+ mgmt, NetworkAddress, IpAddress, Counter, Gauge,\r
+ TimeTicks\r
+ FROM RFC1155-SMI\r
+ OBJECT-TYPE\r
+ FROM RFC-1212;\r
+\r
+-- This MIB module uses the extended OBJECT-TYPE macro as\r
+-- defined in [14];\r
+\r
+\r
+-- MIB-II (same prefix as MIB-I)\r
+\r
+mib-2 OBJECT IDENTIFIER ::= { mgmt 1 }\r
+\r
+-- textual conventions\r
+\r
+DisplayString ::=\r
+ OCTET STRING\r
+-- This data type is used to model textual information taken\r
+-- from the NVT ASCII character set. By convention, objects\r
+-- with this syntax are declared as having\r
+\r
+--\r
+-- SIZE (0..255)\r
+\r
+PhysAddress ::=\r
+ OCTET STRING\r
+-- This data type is used to model media addresses. For many\r
+-- types of media, this will be in a binary representation.\r
+-- For example, an ethernet address would be represented as\r
+-- a string of 6 octets.\r
+\r
+\r
+-- groups in MIB-II\r
+\r
+system OBJECT IDENTIFIER ::= { mib-2 1 }\r
+\r
+interfaces OBJECT IDENTIFIER ::= { mib-2 2 }\r
+\r
+at OBJECT IDENTIFIER ::= { mib-2 3 }\r
+\r
+ip OBJECT IDENTIFIER ::= { mib-2 4 }\r
+\r
+icmp OBJECT IDENTIFIER ::= { mib-2 5 }\r
+\r
+tcp OBJECT IDENTIFIER ::= { mib-2 6 }\r
+\r
+udp OBJECT IDENTIFIER ::= { mib-2 7 }\r
+\r
+egp OBJECT IDENTIFIER ::= { mib-2 8 }\r
+\r
+-- historical (some say hysterical)\r
+-- cmot OBJECT IDENTIFIER ::= { mib-2 9 }\r
+\r
+transmission OBJECT IDENTIFIER ::= { mib-2 10 }\r
+\r
+snmp OBJECT IDENTIFIER ::= { mib-2 11 }\r
+\r
+\r
+-- the System group\r
+\r
+-- Implementation of the System group is mandatory for all\r
+-- systems. If an agent is not configured to have a value\r
+-- for any of these variables, a string of length 0 is\r
+-- returned.\r
+\r
+\r
+IfEntry ::=\r
+ SEQUENCE {\r
+ ifIndex\r
+ INTEGER,\r
+\r
+ ifDescr\r
+ DisplayString,\r
+ ifType\r
+ INTEGER,\r
+ ifMtu\r
+ INTEGER,\r
+ ifSpeed\r
+ Gauge,\r
+ ifPhysAddress\r
+ PhysAddress,\r
+ ifAdminStatus\r
+ INTEGER,\r
+ ifOperStatus\r
+ INTEGER,\r
+ ifLastChange\r
+ TimeTicks,\r
+ ifInOctets\r
+ Counter,\r
+ ifInUcastPkts\r
+ Counter,\r
+ ifInNUcastPkts\r
+ Counter,\r
+ ifInDiscards\r
+ Counter,\r
+ ifInErrors\r
+ Counter,\r
+ ifInUnknownProtos\r
+ Counter,\r
+ ifOutOctets\r
+ Counter,\r
+ ifOutUcastPkts\r
+ Counter,\r
+ ifOutNUcastPkts\r
+ Counter,\r
+ ifOutDiscards\r
+ Counter,\r
+ ifOutErrors\r
+ Counter,\r
+ ifOutQLen\r
+ Gauge,\r
+ ifSpecific\r
+ OBJECT IDENTIFIER\r
+ }\r
+\r
+\r
+-- the Address Translation group\r
+\r
+-- Implementation of the Address Translation group is\r
+-- mandatory for all systems. Note however that this group\r
+-- is deprecated by MIB-II. That is, it is being included\r
+\r
+-- solely for compatibility with MIB-I nodes, and will most\r
+-- likely be excluded from MIB-III nodes. From MIB-II and\r
+-- onwards, each network protocol group contains its own\r
+-- address translation tables.\r
+\r
+-- The Address Translation group contains one table which is\r
+-- the union across all interfaces of the translation tables\r
+-- for converting a NetworkAddress (e.g., an IP address) into\r
+-- a subnetwork-specific address. For lack of a better term,\r
+-- this document refers to such a subnetwork-specific address\r
+-- as a `physical' address.\r
+\r
+-- Examples of such translation tables are: for broadcast\r
+-- media where ARP is in use, the translation table is\r
+-- equivalent to the ARP cache; or, on an X.25 network where\r
+-- non-algorithmic translation to X.121 addresses is\r
+-- required, the translation table contains the\r
+-- NetworkAddress to X.121 address equivalences.\r
+\r
+\r
+AtEntry ::=\r
+ SEQUENCE {\r
+ atIfIndex\r
+ INTEGER,\r
+\r
+ atPhysAddress\r
+ PhysAddress,\r
+ atNetAddress\r
+ NetworkAddress\r
+ }\r
+\r
+\r
+\r
+\r
+\r
+-- the IP address table\r
+\r
+-- The IP address table contains this entity's IP addressing\r
+-- information.\r
+\r
+\r
+IpAddrEntry ::=\r
+ SEQUENCE {\r
+ ipAdEntAddr\r
+ IpAddress,\r
+ ipAdEntIfIndex\r
+ INTEGER,\r
+ ipAdEntNetMask\r
+ IpAddress,\r
+ ipAdEntBcastAddr\r
+ INTEGER,\r
+ ipAdEntReasmMaxSize\r
+ INTEGER (0..65535)\r
+ }\r
+\r
+\r
+IpRouteEntry ::=\r
+ SEQUENCE {\r
+ ipRouteDest\r
+ IpAddress,\r
+ ipRouteIfIndex\r
+ INTEGER,\r
+ ipRouteMetric1\r
+ INTEGER,\r
+ ipRouteMetric2\r
+ INTEGER,\r
+ ipRouteMetric3\r
+ INTEGER,\r
+ ipRouteMetric4\r
+ INTEGER,\r
+ ipRouteNextHop\r
+ IpAddress,\r
+ ipRouteType\r
+ INTEGER,\r
+ ipRouteProto\r
+ INTEGER,\r
+ ipRouteAge\r
+ INTEGER,\r
+ ipRouteMask\r
+ IpAddress,\r
+ ipRouteMetric5\r
+ INTEGER,\r
+\r
+ ipRouteInfo\r
+ OBJECT IDENTIFIER\r
+ }\r
+\r
+\r
+IpNetToMediaEntry ::=\r
+ SEQUENCE {\r
+ ipNetToMediaIfIndex\r
+ INTEGER,\r
+ ipNetToMediaPhysAddress\r
+ PhysAddress,\r
+ ipNetToMediaNetAddress\r
+ IpAddress,\r
+ ipNetToMediaType\r
+ INTEGER\r
+ }\r
+\r
+\r
+\r
+TcpConnEntry ::=\r
+ SEQUENCE {\r
+ tcpConnState\r
+ INTEGER,\r
+ tcpConnLocalAddress\r
+ IpAddress,\r
+ tcpConnLocalPort\r
+ INTEGER (0..65535),\r
+ tcpConnRemAddress\r
+ IpAddress,\r
+ tcpConnRemPort\r
+ INTEGER (0..65535)\r
+ }\r
+\r
+\r
+UdpEntry ::=\r
+ SEQUENCE {\r
+ udpLocalAddress\r
+ IpAddress,\r
+ udpLocalPort\r
+ INTEGER (0..65535)\r
+ }\r
+\r
+\r
+\r
+-- the EGP Neighbor table\r
+\r
+-- The EGP neighbor table contains information about this\r
+-- entity's EGP neighbors.\r
+\r
+\r
+EgpNeighEntry ::=\r
+ SEQUENCE {\r
+ egpNeighState\r
+ INTEGER,\r
+ egpNeighAddr\r
+ IpAddress,\r
+ egpNeighAs\r
+ INTEGER,\r
+ egpNeighInMsgs\r
+ Counter,\r
+ egpNeighInErrs\r
+ Counter,\r
+ egpNeighOutMsgs\r
+ Counter,\r
+ egpNeighOutErrs\r
+ Counter,\r
+\r
+ egpNeighInErrMsgs\r
+ Counter,\r
+ egpNeighOutErrMsgs\r
+ Counter,\r
+ egpNeighStateUps\r
+ Counter,\r
+ egpNeighStateDowns\r
+ Counter,\r
+ egpNeighIntervalHello\r
+ INTEGER,\r
+ egpNeighIntervalPoll\r
+ INTEGER,\r
+ egpNeighMode\r
+ INTEGER,\r
+ egpNeighEventTrigger\r
+ INTEGER\r
+ }\r
+\r
+\r
+\r
+-- the Transmission group\r
+\r
+-- Based on the transmission media underlying each interface\r
+-- on a system, the corresponding portion of the Transmission\r
+-- group is mandatory for that system.\r
+\r
+-- When Internet-standard definitions for managing\r
+-- transmission media are defined, the transmission group is\r
+-- used to provide a prefix for the names of those objects.\r
+\r
+-- Typically, such definitions reside in the experimental\r
+-- portion of the MIB until they are "proven", then as a\r
+-- part of the Internet standardization process, the\r
+-- definitions are accordingly elevated and a new object\r
+-- identifier, under the transmission group is defined. By\r
+-- convention, the name assigned is:\r
+--\r
+-- type OBJECT IDENTIFIER ::= { transmission number }\r
+--\r
+-- where "type" is the symbolic value used for the media in\r
+-- the ifType column of the ifTable object, and "number" is\r
+-- the actual integer value corresponding to the symbol.\r
+\r
+\r
+-- the SNMP group\r
+\r
+-- Implementation of the SNMP group is mandatory for all\r
+-- systems which support an SNMP protocol entity. Some of\r
+-- the objects defined below will be zero-valued in those\r
+-- SNMP implementations that are optimized to support only\r
+-- those functions specific to either a management agent or\r
+-- a management station. In particular, it should be\r
+-- observed that the objects below refer to an SNMP entity,\r
+-- and there may be several SNMP entities residing on a\r
+-- managed node (e.g., if the node is hosting acting as\r
+-- a management station).\r
+\r
+\r
+END\r
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+
+-- WinAgents MIB Extraction Wizard\r
+-- Extracted from rfc1227.txt 16.03.2005 20:20:14\r
+\r
+SMUX DEFINITIONS ::= BEGIN\r
+\r
+IMPORTS\r
+ ObjectName\r
+ FROM RFC1155-SMI\r
+ DisplayString\r
+ FROM RFC1213-MIB\r
+\r
+ PDUs\r
+ FROM RFC1157-SNMP;\r
+\r
+\r
+-- tags for SMUX-specific PDUs are application-wide to\r
+-- avoid conflict with tags for current (and future)\r
+-- SNMP-generic PDUs\r
+\r
+SMUX-PDUs ::=\r
+ CHOICE {\r
+ open -- SMUX peer uses\r
+ OpenPDU, -- immediately after TCP open\r
+\r
+ close -- either uses immediately before TCP close\r
+ ClosePDU,\r
+\r
+ registerRequest -- SMUX peer uses\r
+ RReqPDU,\r
+\r
+ registerResponse -- SNMP agent uses\r
+ RRspPDU,\r
+\r
+ PDUs, -- note that roles are reversed:\r
+ -- SNMP agent does get/get-next/set\r
+ -- SMUX peer does get-response/trap\r
+\r
+ commitOrRollback -- SNMP agent uses\r
+ SOutPDU\r
+ }\r
+\r
+\r
+-- open PDU\r
+-- currently only simple authentication\r
+\r
+OpenPDU ::=\r
+ CHOICE {\r
+ simple\r
+\r
+ SimpleOpen\r
+ }\r
+\r
+SimpleOpen ::=\r
+ [APPLICATION 0] IMPLICIT\r
+ SEQUENCE {\r
+ version -- of SMUX protocol\r
+ INTEGER {\r
+ version-1(0)\r
+ },\r
+\r
+ identity -- of SMUX peer, authoritative\r
+ OBJECT IDENTIFIER,\r
+\r
+ description -- of SMUX peer, implementation-specific\r
+ DisplayString,\r
+\r
+ password -- zero length indicates no authentication\r
+ OCTET STRING\r
+ }\r
+\r
+\r
+-- close PDU\r
+\r
+ClosePDU ::=\r
+ [APPLICATION 1] IMPLICIT\r
+ INTEGER {\r
+ goingDown(0),\r
+ unsupportedVersion(1),\r
+ packetFormat(2),\r
+ protocolError(3),\r
+ internalError(4),\r
+ authenticationFailure(5)\r
+ }\r
+\r
+\r
+-- insert PDU\r
+\r
+RReqPDU ::=\r
+ [APPLICATION 2] IMPLICIT\r
+ SEQUENCE {\r
+ subtree\r
+ ObjectName,\r
+\r
+ priority -- the lower the better, "-1" means default\r
+ INTEGER (-1..2147483647),\r
+\r
+ operation\r
+\r
+ INTEGER {\r
+ delete(0), -- remove registration\r
+ readOnly(1), -- add registration, objects are RO\r
+ readWrite(2) -- .., objects are RW\r
+ }\r
+ }\r
+\r
+RRspPDU ::=\r
+ [APPLICATION 3] IMPLICIT\r
+ INTEGER {\r
+ failure(-1)\r
+\r
+ -- on success the non-negative priority is returned\r
+ }\r
+\r
+SOutPDU ::=\r
+ [APPLICATION 4] IMPLICIT\r
+ INTEGER {\r
+ commit(0),\r
+ rollback(1)\r
+ }\r
+\r
+END
\ No newline at end of file
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
+ * From ASN.1 module "SMUX"
+ * found in "SMUX.asn1"
+ * `asn1c -fskeletons-copy`
+ */
+
+#include <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*
+ * 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 <asn_internal.h>
+
+#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 */
+};
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_SEQUENCE_OF.h>
+
+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);
+ }
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_SET_OF.h>
+#include <errno.h>
+
+/*
+ * 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;
+ }
+
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_codecs_prim.h>
+#include <errno.h>
+
+/*
+ * 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:
+ * "1<tag_start..."
+ */
+ arg->want_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;
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+
+#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 <TL<TL<TL...>>> 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);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ber_tlv_length.h>
+#include <ber_tlv_tag.h>
+
+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;
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ber_tlv_tag.h>
+#include <errno.h>
+
+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;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_CHOICE.h>
+
+/*
+ * 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 <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * 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
+ * <opening> tags.
+ */
+ if(tcv & XCT_CLOSING) {
+ /* Found </extension> 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("</", 2, mname, mlen, ">", 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("<absent>", 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("<absent>", 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("<absent>", 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));
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SEQUENCE.h>
+
+/*
+ * 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 <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * 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 = (<member_number> * 2 + <microphase>).
+ */
+ 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
+ * <opening> tags.
+ */
+ if(tcv & XCT_CLOSING) {
+ /* Found </extension> 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("</", 2, mname, mlen, ">", 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("<absent>", 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 <absent> 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);
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SEQUENCE_OF.h>
+#include <asn_SEQUENCE_OF.h>
+
+/*
+ * 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("</", 2, mname, mlen, ">", 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);
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SET_OF.h>
+#include <asn_SET_OF.h>
+
+/*
+ * 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 <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * 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("</", 2, mname, mlen, ">", 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("<absent>", 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;
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_TYPE.h>
+#include <errno.h>
+
+/*
+ * 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);
+}
--- /dev/null
+#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("<broken vsnprintf>") - 1;
+ maxlen--;
+ arg->errlen = vlen < maxlen ? vlen : maxlen;
+ memcpy(arg->errbuf, "<broken vsnprintf>", 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;
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <errno.h>
+
+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;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef ASN_TYPE_ANY_H
+#define ASN_TYPE_ANY_H
+
+#include <OCTET_STRING.h> /* 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 */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "NetworkAddress.h"
+#include "Counter.h"
+#include "Gauge.h"
+#include "TimeTicks.h"
+#include "Opaque.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "PhysAddress.h"
+#include "NetworkAddress.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _BIT_STRING_H_
+#define _BIT_STRING_H_
+
+#include <OCTET_STRING.h> /* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _BOOLEAN_H_
+#define _BOOLEAN_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "IpAddress.h"
+#include "Counter.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* 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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* 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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _INTEGER_H_
+#define _INTEGER_H_
+
+#include <asn_application.h>
+#include <asn_codecs_prim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
+
+/* Map with <tag> 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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "DisplayString.h"
+#include "Gauge.h"
+#include "PhysAddress.h"
+#include "TimeTicks.h"
+#include "Counter.h"
+#include <OBJECT_IDENTIFIER.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "IpAddress.h"
+#include <INTEGER.h>
+#include <NativeInteger.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "PhysAddress.h"
+#include "IpAddress.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "IpAddress.h"
+#include <INTEGER.h>
+#include <OBJECT_IDENTIFIER.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include <OCTET_STRING.h>
+#include <ANY.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef ASN_TYPE_NULL_H
+#define ASN_TYPE_NULL_H
+
+#include <asn_application.h>
+
+#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 */
--- /dev/null
+/*-
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * 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 <NativeInteger.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. 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 <asn_application.h>
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "IpAddress.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _OBJECT_IDENTIFIER_H_
+#define _OBJECT_IDENTIFIER_H_
+
+#include <asn_application.h>
+#include <asn_codecs_prim.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _OCTET_STRING_H_
+#define _OCTET_STRING_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "SimpleSyntax.h"
+#include "ApplicationSyntax.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "SimpleOpen.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "VarBindList.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "GetRequest-PDU.h"
+#include "GetNextRequest-PDU.h"
+#include "GetResponse-PDU.h"
+#include "SetRequest-PDU.h"
+#include "Trap-PDU.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "ObjectName.h"
+#include <NativeInteger.h>
+#include <INTEGER.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "OpenPDU.h"
+#include "ClosePDU.h"
+#include "RReqPDU.h"
+#include "RRspPDU.h"
+#include "PDUs.h"
+#include "SOutPDU.h"
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* 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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include <OBJECT_IDENTIFIER.h>
+#include "DisplayString.h"
+#include <OCTET_STRING.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include <OCTET_STRING.h>
+#include <OBJECT_IDENTIFIER.h>
+#include <NULL.h>
+#include <constr_CHOICE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "IpAddress.h"
+#include <NativeInteger.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include "NetworkAddress.h"
+#include <INTEGER.h>
+#include "TimeTicks.h"
+#include "VarBindList.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "IpAddress.h"
+#include <NativeInteger.h>
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include "ObjectName.h"
+#include "ObjectSyntax.h"
+#include <constr_SEQUENCE.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef ASN_SEQUENCE_OF_H
+#define ASN_SEQUENCE_OF_H
+
+#include <asn_SET_OF.h>
+
+#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 */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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 */
--- /dev/null
+/*-
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef ASN_CODECS_PRIM_H
+#define ASN_CODECS_PRIM_H
+
+#include <asn_application.h>
+
+#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 */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * 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 <assert.h> /* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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 <stdio.h> /* For snprintf(3) */
+#include <stdlib.h> /* For *alloc(3) */
+#include <string.h> /* For memcpy(3) */
+#include <sys/types.h> /* For size_t */
+#include <stdarg.h> /* For va_start */
+#include <stddef.h> /* for offsetof and ptrdiff_t */
+
+#ifdef WIN32
+
+#include <malloc.h>
+#include <stdint.h>
+#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 <windows.h>
+#include <float.h>
+#define isnan _isnan
+#define finite _finite
+#define copysign _copysign
+#define ilogb _logb
+#endif /* _MSC_VER */
+
+#else /* !WIN32 */
+
+#if defined(__vxworks)
+#include <types/vxTypes.h>
+#else /* !defined(__vxworks) */
+
+#include <inttypes.h> /* C99 specifies this file */
+/*
+ * 1. Earlier FreeBSD version didn't have <stdint.h>,
+ * but <inttypes.h> was present.
+ * 2. Sun Solaris requires <alloca.h> for alloca(3),
+ * but does not have <stdint.h>.
+ */
+#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
+#if defined(sun)
+#include <alloca.h> /* For alloca(3) */
+#include <ieeefp.h> /* for finite(3) */
+#elif defined(__hpux)
+#ifdef __GNUC__
+#include <alloca.h> /* For alloca(3) */
+#else /* !__GNUC__ */
+#define inline
+#endif /* __GNUC__ */
+#else
+#include <stdint.h> /* 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 <stddef.h> */
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _BER_DECODER_H_
+#define _BER_DECODER_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _CONSTR_CHOICE_H_
+#define _CONSTR_CHOICE_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _CONSTR_SEQUENCE_H_
+#define _CONSTR_SEQUENCE_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _CONSTR_SEQUENCE_OF_H_
+#define _CONSTR_SEQUENCE_OF_H_
+
+#include <asn_application.h>
+#include <constr_SET_OF.h> /* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _CONSTR_SET_OF_H_
+#define _CONSTR_SET_OF_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * 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 <ber_tlv_length.h>
+#include <ber_tlv_tag.h>
+
+#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 <ber_decoder.h> /* Basic Encoding Rules decoder */
+#include <der_encoder.h> /* Distinguished Encoding Rules encoder */
+#include <xer_decoder.h> /* Decoder of XER (XML, text) */
+#include <xer_encoder.h> /* Encoder into XER (XML, text) */
+#include <per_decoder.h> /* Packet Encoding Rules decoder */
+#include <per_encoder.h> /* Packet Encoding Rules encoder */
+#include <constraints.h> /* 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;
+
+\f
+/*
+ * 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; /* <optional, internal> */
+ 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 <value> */
+ 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _ASN1_CONSTRAINTS_VALIDATOR_H_
+#define _ASN1_CONSTRAINTS_VALIDATOR_H_
+
+#include <asn_system.h> /* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _DER_ENCODER_H_
+#define _DER_ENCODER_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _PER_DECODER_H_
+#define _PER_DECODER_H_
+
+#include <asn_application.h>
+#include <per_support.h>
+
+#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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _PER_ENCODER_H_
+#define _PER_ENCODER_H_
+
+#include <asn_application.h>
+#include <per_support.h>
+
+#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_ */
--- /dev/null
+/*
+ * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _PER_SUPPORT_H_
+#define _PER_SUPPORT_H_
+
+#include <asn_system.h> /* 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _XER_DECODER_H_
+#define _XER_DECODER_H_
+
+#include <asn_application.h>
+
+#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 <opening> tag */
+ XCT_CLOSING = 2, /* This is the </closing> tag */
+ XCT_BOTH = 3, /* This is the <modified/> tag */
+ XCT__UNK__MASK = 4, /* Mask of everything unexpected */
+ XCT_UNKNOWN_OP = 5, /* Unexpected <opening> tag */
+ XCT_UNKNOWN_CL = 6, /* Unexpected </closing> tag */
+ XCT_UNKNOWN_BO = 7 /* Unexpected <modified/> 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_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _XER_ENCODER_H_
+#define _XER_ENCODER_H_
+
+#include <asn_application.h>
+
+#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_ */
--- /dev/null
+/*
+ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _XER_SUPPORT_H_
+#define _XER_SUPPORT_H_
+
+#include <asn_system.h> /* 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 "<!--" and "-->". */
+ /*
+ * 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_ */
--- /dev/null
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_decoder.h>
+
+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 <limits.h> */
+ 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;
+}
+
--- /dev/null
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_encoder.h>
+
+/* 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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_system.h>
+#include <asn_internal.h>
+#include <per_support.h>
+
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <xer_support.h> /* 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 "</" */
+ size -= 3; /* strip "</" and ">" */
+ ct = XCT_CLOSING;
+ if(size > 0 && buf[size-1] == CSLASH)
+ return XCT_BROKEN; /* </abc/> */
+ } 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:
+ /* "<abc def/>": 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;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * 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("</", 2, mname, mlen, ">\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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_system.h>
+#include <xer_support.h>
+
+/* 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, /* "<!--"[1] */
+ ST_COMMENT_WAIT_DASH2, /* "<!--"[2] */
+ ST_COMMENT,
+ ST_COMMENT_CLO_DASH2, /* "-->"[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;
+}
+
--- /dev/null
+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 )
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SERVCONF_H__
+#define __STG_STGLIBS_SERVCONF_H__
+
+#include "stg/servconf_types.h"
+
+#include "stg/admin_conf.h"
+
+#include <string>
+#include <cstdint>
+
+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<GET_ADMIN::INFO>::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<GET_TARIFF::INFO>::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<GET_USER::INFO>::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<GET_SERVICE::INFO>::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<GET_CORP::INFO>::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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_TYPES_H__
+#define __STG_STGLIBS_SRVCONF_TYPES_H__
+
+#include "stg/array.h"
+#include "stg/const.h" // DIR_NUM
+
+#include <string>
+#include <vector>
+#include <ctime>
+#include <cstdint>
+
+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 <typename INFO>
+struct CALLBACK
+{
+typedef void (* TYPE)(bool result, const std::string & reason, const std::vector<INFO> & info, void * data);
+};
+
+} // namespace GET_CONTAINER
+
+namespace AUTH_BY
+{
+
+typedef std::vector<std::string> 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<std::string, DIR_NUM> 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<long long, DIR_NUM> su;
+ ARRAY<long long, DIR_NUM> sd;
+ ARRAY<long long, DIR_NUM> mu;
+ ARRAY<long long, DIR_NUM> 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<std::string, USERDATA_NUM> userData;
+ std::vector<std::string> services;
+ std::vector<std::string> 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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#include "netunit.h"
+
+#include "stg/servconf_types.h"
+#include "stg/common.h"
+#include "stg/blowfish.h"
+#include "stg/bfstream.h"
+
+#include <algorithm> // std::min
+
+#include <cerrno>
+#include <cstring>
+#include <cassert>
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+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<size_t>(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<NETTRANSACT *>(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<ReadState *>(data);
+
+const char * buffer = static_cast<const char *>(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;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#ifndef NetUnitH
+#define NetUnitH
+
+#include <cstdint>
+
+#include <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "auth_by.h"
+
+#include <strings.h> // 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();
+ }
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_PARSER_H__
+#define __STG_STGLIBS_SRVCONF_PARSER_H__
+
+#include <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "chg_admin.h"
+
+#include "stg/admin_conf.h"
+#include "stg/common.h"
+
+#include <strings.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "chg_corp.h"
+
+#include "resetable_utils.h"
+
+#include "stg/corp_conf.h"
+#include "stg/common.h"
+
+#include <sstream>
+
+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();
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "chg_service.h"
+
+#include "resetable_utils.h"
+
+#include "stg/service_conf.h"
+#include "stg/common.h"
+
+#include <sstream>
+
+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();
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "chg_tariff.h"
+
+#include "resetable_utils.h"
+
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+
+#include <sstream>
+
+#include <strings.h>
+
+using namespace STG;
+
+namespace
+{
+
+template <typename A, typename T>
+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 << "<traffType value=\"" + TARIFF::TraffTypeToString(data.tariffConf.traffType.data()) + "\"/>";
+
+if (!data.tariffConf.period.empty())
+ switch (data.tariffConf.period.data())
+ {
+ case TARIFF::DAY: stream << "<period value=\"day\"/>"; break;
+ case TARIFF::MONTH: stream << "<period value=\"month\"/>"; break;
+ }
+
+if (!data.tariffConf.changePolicy.empty())
+ switch (data.tariffConf.changePolicy.data())
+ {
+ case TARIFF::ALLOW: stream << "<changePolicy value=\"allow\"/>"; break;
+ case TARIFF::TO_CHEAP: stream << "<changePolicy value=\"to_cheap\"/>"; break;
+ case TARIFF::TO_EXPENSIVE: stream << "<changePolicy value=\"to_expensive\"/>"; break;
+ case TARIFF::DENY: stream << "<changePolicy value=\"deny\"/>"; 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 << "<time" << i << " value=\"" << data.dirPrice[i].hDay.data() << ":"
+ << data.dirPrice[i].mDay.data() << "-"
+ << data.dirPrice[i].hNight.data() << ":"
+ << data.dirPrice[i].mNight.data() << "\"/>";
+
+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();
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "chg_user.h"
+
+#include "resetable_utils.h"
+
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/common.h"
+
+#include <sstream>
+#include <iostream>
+
+#include <strings.h>
+
+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 << "<tariff delayed=\"" << conf.nextTariff.data() << "\"/>";
+else if (!conf.tariffName.empty())
+ stream << "<tariff now=\"" << conf.tariffName.data() << "\"/>";
+
+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 << "<services>";
+ for (size_t i = 0; i < conf.services.data().size(); ++i)
+ stream << "<service name=\"" << conf.services.data()[i] << "\"/>";
+ stream << "</services>";
+ }
+
+// Stat
+
+if (!stat.cashAdd.empty())
+ stream << "<cash add=\"" << stat.cashAdd.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashAdd.data().second), encoding, "koi8-ru") << "\"/>";
+else if (!stat.cashSet.empty())
+ stream << "<cash set=\"" << stat.cashSet.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashSet.data().second), encoding, "koi8-ru") << "\"/>";
+
+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 << "<traff" << traffData << "/>";
+
+std::cerr << stream.str() << "\n";
+return stream.str();
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "get_admin.h"
+
+#include "stg/common.h"
+
+#include <map>
+#include <utility>
+
+#include <strings.h>
+
+using namespace STG;
+
+namespace STG
+{
+
+template <>
+inline
+bool GetValue<PRIV>(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.";
+}*/
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__
+#define __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__
+
+#include "base.h"
+
+#include <string>
+
+#include <strings.h>
+
+namespace STG
+{
+namespace GET_CONTAINER
+{
+
+template <typename ELEMENT_PARSER>
+class PARSER: public STG::PARSER
+{
+public:
+ typedef std::vector<typename ELEMENT_PARSER::INFO> 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<ELEMENT_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<ELEMENT_PARSER> * parser = static_cast<PARSER<ELEMENT_PARSER> *>(data);
+ if (!result)
+ parser->SetError(reason);
+ else
+ parser->AddElement(info);
+ }
+};
+
+} // namespace GET_CONTAINER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "get_corp.h"
+
+//#include "parsers/property.h"
+
+#include "stg/common.h"
+
+#include <strings.h>
+
+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.";
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "get_service.h"
+
+//#include "parsers/property.h"
+
+#include "stg/common.h"
+
+#include <strings.h>
+
+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.";
+}*/
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "get_tariff.h"
+
+//#include "parsers/property.h"
+
+#include "stg/common.h"
+
+#include <utility>
+
+#include <strings.h>
+
+using namespace STG;
+
+namespace
+{
+
+template <typename A, typename T>
+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 <typename A, typename T>
+inline
+void AddAOSParser(PROPERTY_PARSERS & parsers, const std::string & name, A & array, T A::value_type:: * field, const typename AOS_PARSER<A, T>::FUNC & func)
+{
+ parsers.insert(std::make_pair(ToLower(name), new AOS_PARSER<A, T>(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 <typename T>
+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 <typename T>
+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 <typename T>
+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 <typename A, typename T>
+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 + "'.";
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "get_user.h"
+
+#include "stg/common.h"
+
+#include <map>
+#include <utility>
+
+#include <strings.h>
+
+using namespace STG;
+
+namespace STG
+{
+
+template <>
+bool GetValue<GET_USER::STAT>(const char ** attr, GET_USER::STAT & value, const std::string & /*attrName*/)
+{
+if (!attr)
+ return false;
+std::map<std::string, long long *> props;
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ props.insert(std::pair<std::string, long long *>("su" + unsigned2str(i), &value.su[i]));
+ props.insert(std::pair<std::string, long long *>("sd" + unsigned2str(i), &value.sd[i]));
+ props.insert(std::pair<std::string, long long *>("mu" + unsigned2str(i), &value.mu[i]));
+ props.insert(std::pair<std::string, long long *>("md" + unsigned2str(i), &value.md[i]));
+ }
+size_t pos = 0;
+while (attr[pos])
+ {
+ std::string name(ToLower(attr[pos++]));
+ std::map<std::string, long long *>::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]);
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "property.h"
+
+#include <strings.h>
+
+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.
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__
+#define __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__
+
+#include "stg/common.h"
+
+#include <map>
+#include <string>
+
+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 <typename T>
+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<std::string>::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<std::string, BASE_PROPERTY_PARSER *> PROPERTY_PARSERS;
+
+bool CheckValue(const char ** attr, const std::string & attrName);
+
+template <typename T>
+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<std::string>(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<double>(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 <typename T>
+inline
+void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
+{
+ parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(value, func)));
+}
+
+template <typename T>
+inline
+void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const std::string & toEncoding, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
+{
+ parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__
+#define __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__
+
+#include "stg/resetable.h"
+#include "stg/common.h"
+
+#include <string>
+#include <ostream>
+
+namespace STG
+{
+
+template <typename T>
+inline
+void appendTag(std::ostream & stream, const std::string & name, const T & value)
+{
+ stream << "<" << name << " value=\"" << value << "\"/>";
+}
+
+template <typename T>
+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<uint8_t>(std::ostream & stream, const std::string & name, const uint8_t & value)
+{
+ stream << "<" << name << " value=\"" << static_cast<unsigned>(value) << "\"/>";
+}
+
+template <>
+inline
+void appendTag<int8_t>(std::ostream & stream, const std::string & name, const int8_t & value)
+{
+ stream << "<" << name << " value=\"" << static_cast<int>(value) << "\"/>";
+}
+
+template <typename T>
+inline
+void appendAttr(std::ostream & stream, const std::string & name, const T & value)
+{
+ stream << " " << name << "=\"" << value << "\"";
+}
+
+template <typename T>
+inline
+void appendAttr(std::ostream & stream, const std::string & name, size_t suffix, const T & value)
+{
+ stream << " " << name << suffix << "=\"" << value << "\"";
+}
+
+template <>
+inline
+void appendAttr<uint8_t>(std::ostream & stream, const std::string & name, const uint8_t & value)
+{
+ stream << " " << name << "=\"" << static_cast<unsigned>(value) << "\"";
+}
+
+template <>
+inline
+void appendAttr<int8_t>(std::ostream & stream, const std::string & name, const int8_t & value)
+{
+ stream << " " << name << "=\"" << static_cast<int>(value) << "\"";
+}
+
+template <typename T>
+inline
+void appendResetableTag(std::ostream & stream, const std::string & name, const T & value)
+{
+if (!value.empty())
+ appendTag(stream, name, value.const_data());
+}
+
+template <typename T>
+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 <typename T>
+inline
+void appendResetableAttr(std::ostream & stream, const std::string & name, const T & value)
+{
+if (!value.empty())
+ appendAttr(stream, name, value.const_data());
+}
+
+template <typename T>
+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<std::string> MaybeEncode(const RESETABLE<std::string> & value)
+{
+RESETABLE<std::string> res;
+if (!value.empty())
+ res = Encode12str(value.data());
+return res;
+}
+
+inline
+RESETABLE<std::string> MaybeIconv(const RESETABLE<std::string> & value, const std::string & fromEncoding, const std::string & toEncoding)
+{
+RESETABLE<std::string> res;
+if (!value.empty())
+ res = IconvString(value.data(), fromEncoding, toEncoding);
+return res;
+}
+
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "server_info.h"
+
+#include "stg/common.h"
+
+#include <cstdio> // sprintf
+
+#include <strings.h>
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "simple.h"
+
+#include <strings.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__
+#define __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__
+
+#include "base.h"
+
+#include "stg/servconf_types.h"
+
+#include <string>
+
+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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#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 <cstdio>
+#include <cstring>
+#include <clocale>
+
+#include <expat.h>
+#include <langinfo.h>
+
+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 <class P, typename C>
+ int Exec(const std::string & request, C callback, void * data)
+ {
+ P cp(callback, data, encoding);
+ return ExecImpl(request, cp);
+ }
+
+ template <class P, typename C>
+ 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<SERVCONF::IMPL *>(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<int>(XML_GetCurrentLineNumber(sc->parser)),
+ static_cast<int>(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<std::string *>(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<SERVER_INFO::PARSER>("<GetServerInfo/>", 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<GET_ADMIN::INFO>::TYPE f, void * data)
+{
+return pImpl->Exec<GET_CONTAINER::PARSER<GET_ADMIN::PARSER> >("admins", "<GetAdmins/>", f, data);
+}
+
+int SERVCONF::GetAdmin(const std::string & login, GET_ADMIN::CALLBACK f, void * data)
+{
+return pImpl->Exec<GET_ADMIN::PARSER>("<GetAdmin login=\"" + login + "\"/>", f, data);
+}
+
+int SERVCONF::ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
+}
+
+int SERVCONF::AddAdmin(const std::string & login,
+ const ADMIN_CONF_RES & conf,
+ SIMPLE::CALLBACK f, void * data)
+{
+int res = pImpl->Exec<SIMPLE::PARSER>("AddAdmin", "<AddAdmin login=\"" + login + "\"/>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
+}
+
+int SERVCONF::DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("DelAdmin", "<DelAdmin login=\"" + login + "\"/>", f, data);
+}
+
+// -- Tariffs --
+
+int SERVCONF::GetTariffs(GET_CONTAINER::CALLBACK<GET_TARIFF::INFO>::TYPE f, void * data)
+{
+return pImpl->Exec<GET_CONTAINER::PARSER<GET_TARIFF::PARSER> >("tariffs", "<GetTariffs/>", f, data);
+}
+
+int SERVCONF::GetTariff(const std::string & name, GET_TARIFF::CALLBACK f, void * data)
+{
+return pImpl->Exec<GET_TARIFF::PARSER>("<GetTariff name=\"" + name + "\"/>", f, data);
+}
+
+int SERVCONF::ChgTariff(const TARIFF_DATA_RES & tariffData, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + tariffData.tariffConf.name.data() + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
+}
+
+int SERVCONF::AddTariff(const std::string & name,
+ const TARIFF_DATA_RES & tariffData,
+ SIMPLE::CALLBACK f, void * data)
+{
+int res = pImpl->Exec<SIMPLE::PARSER>("AddTariff", "<AddTariff name=\"" + name + "\"/>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + name + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
+}
+
+int SERVCONF::DelTariff(const std::string & name, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("DelTariff", "<DelTariff name=\"" + name + "\"/>", f, data);
+}
+
+// -- Users --
+
+int SERVCONF::GetUsers(GET_CONTAINER::CALLBACK<GET_USER::INFO>::TYPE f, void * data)
+{
+return pImpl->Exec<GET_CONTAINER::PARSER<GET_USER::PARSER> >("users", "<GetUsers/>", f, data);
+}
+
+int SERVCONF::GetUser(const std::string & login, GET_USER::CALLBACK f, void * data)
+{
+return pImpl->Exec<GET_USER::PARSER>("<GetUser login=\"" + login + "\"/>", 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::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
+}
+
+int SERVCONF::DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("DelUser", "<DelUser login=\"" + login + "\"/>", 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<SIMPLE::PARSER>("AddUser", "<AddUser><Login value=\"" + login + "\"/></AddUser>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
+}
+
+int SERVCONF::AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data)
+{
+return pImpl->Exec<AUTH_BY::PARSER>("<GetUserAuthBy login=\"" + login + "\"/>", f, data);
+}
+
+int SERVCONF::SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("SendMessageResult", "<Message login=\"" + login + "\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"" + Encode12str(text) + "\"/>", f, data);
+}
+
+int SERVCONF::CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("CheckUser", "<CheckUser login=\"" + login + "\" password=\"" + password + "\"/>", f, data);
+}
+
+// -- Services --
+
+int SERVCONF::GetServices(GET_CONTAINER::CALLBACK<GET_SERVICE::INFO>::TYPE f, void * data)
+{
+return pImpl->Exec<GET_CONTAINER::PARSER<GET_SERVICE::PARSER> >("services", "<GetServices/>", f, data);
+}
+
+int SERVCONF::GetService(const std::string & name, GET_SERVICE::CALLBACK f, void * data)
+{
+return pImpl->Exec<GET_SERVICE::PARSER>("<GetService name=\"" + name + "\"/>", f, data);
+}
+
+int SERVCONF::ChgService(const SERVICE_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService " + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
+}
+
+int SERVCONF::AddService(const std::string & name,
+ const SERVICE_CONF_RES & conf,
+ SIMPLE::CALLBACK f, void * data)
+{
+int res = pImpl->Exec<SIMPLE::PARSER>("AddService", "<AddService name=\"" + name + "\"/>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService " + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
+}
+
+int SERVCONF::DelService(const std::string & name, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("DelService", "<DelService name=\"" + name + "\"/>", f, data);
+}
+
+// -- Corporations --
+
+int SERVCONF::GetCorporations(GET_CONTAINER::CALLBACK<GET_CORP::INFO>::TYPE f, void * data)
+{
+return pImpl->Exec<GET_CONTAINER::PARSER<GET_CORP::PARSER> >("corporations", "<GetCorporations/>", f, data);
+}
+
+int SERVCONF::GetCorp(const std::string & name, GET_CORP::CALLBACK f, void * data)
+{
+return pImpl->Exec<GET_CORP::PARSER>("<GetCorp name=\"" + name + "\"/>", f, data);
+}
+
+int SERVCONF::ChgCorp(const CORP_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + conf.name.data() + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
+}
+
+int SERVCONF::AddCorp(const std::string & name,
+ const CORP_CONF_RES & conf,
+ SIMPLE::CALLBACK f, void * data)
+{
+int res = pImpl->Exec<SIMPLE::PARSER>("AddCorp", "<AddCorp name=\"" + name + "\"/>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + name + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
+}
+
+int SERVCONF::DelCorp(const std::string & name, SIMPLE::CALLBACK f, void * data)
+{
+return pImpl->Exec<SIMPLE::PARSER>("DelCorp", "<DelCorp name=\"" + name + "\"/>", 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<PARSER *>(data);
+currParser->ParseStart(el, attr);
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::IMPL::End(void * data, const char * el)
+{
+PARSER * currParser = static_cast<PARSER *>(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;
+}
--- /dev/null
+#!/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 "<h3><font color=red>cvs checkout $module failed. Incorrect password</font></h3>";
+ exit 1
+ }
+ "aborted" {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
+ exit 1
+ }
+ expect eof {
+ if {[lindex [wait] 3]} {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>"
+ exit 1
+ }
+ }
+ }
+ }
+
+ "aborted" {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
+ exit 1
+ }
+ }
+
+
+
+
--- /dev/null
+#!/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
--- /dev/null
+#!/bin/bash
+
+
+cvs_host=stgteam.dp.ua
+cvs_user=<user>
+cvs_pass=<password>
+
+#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
+++ /dev/null
-#
-# 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 <faust@stargazer.dp.ua>
-#
-
-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
+++ /dev/null
-#!/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 <expat.h>\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 <iconv.h>\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
+++ /dev/null
-#!/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 "<h3><font color=red>cvs checkout $module failed. Incorrect password</font></h3>";
- exit 1
- }
- "aborted" {
- send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
- exit 1
- }
- expect eof {
- if {[lindex [wait] 3]} {
- send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>"
- exit 1
- }
- }
- }
- }
-
- "aborted" {
- send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
- exit 1
- }
- }
-
-
-
-
+++ /dev/null
-#!/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
+++ /dev/null
-#!/bin/bash
-
-
-cvs_host=stgteam.dp.ua
-cvs_user=<user>
-cvs_pass=<password>
-
-#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
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#!/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 <iconv.h>\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 <stdio.h>\n" > build_check.c
- printf "#include <yajl/yajl_version.h>\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 <boost/scoped_ptr.hpp>\nint main() { boost::scoped_ptr<int> 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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "conn.h"
-
-#include "radlog.h"
-#include "stgpair.h"
-
-#include "stg/json_parser.h"
-#include "stg/json_generator.h"
-#include "stg/locker.h"
-
-#include <cerrno>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h> // UNIX
-#include <netinet/in.h> // IP
-#include <netinet/tcp.h> // TCP
-#include <netdb.h>
-
-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<std::string, Packet> packetCodes;
-std::map<std::string, bool> resultCodes;
-std::map<std::string, int> returnCodes;
-
-class PacketParser : public EnumParser<Packet>
-{
- 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<bool>
-{
- 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<int>
-{
- 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<struct sockaddr*>(&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<char> 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<Impl*>(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<Conn::Impl*>(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<Impl*>(data);
- impl.runImpl();
- return NULL;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_RLM_CONN_H__
-#define __STG_RLM_CONN_H__
-
-#include "types.h"
-
-#include "stg/os_int.h"
-
-#include <boost/scoped_ptr.hpp>
-
-#include <string>
-#include <stdexcept>
-
-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<Impl> m_impl;
-};
-
-}
-}
-
-#endif
+++ /dev/null
-#include "iface.h"
-
-#include "stg_client.h"
-#include "types.h"
-#include "radlog.h"
-
-#include <stdexcept>
-#include <cstring>
-
-#include <strings.h>
-
-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<std::string, std::string>(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);
-}
+++ /dev/null
-#ifndef __STG_IFACE_H__
-#define __STG_IFACE_H__
-
-#include <stdint.h>
-
-#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
+++ /dev/null
-#include "radlog.h"
-
-//#ifndef NDEBUG
-//#define NDEBUG
-#include <freeradius/ident.h>
-#include <freeradius/radiusd.h>
-#include <freeradius/modules.h>
-//#undef NDEBUG
-//#endif
-
-#include <stdarg.h>
-
-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);
-}
+++ /dev/null
-#ifndef __STG_RADLOG_H__
-#define __STG_RADLOG_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void RadLog(const char* format, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * FreeRADIUS module for data access via Stargazer
- *
- * $Revision: 1.8 $
- * $Date: 2010/08/14 04:15:08 $
- *
- */
-
-#include "iface.h"
-#include "stgpair.h"
-
-#include <freeradius/ident.h>
-#include <freeradius/radiusd.h>
-#include <freeradius/modules.h>
-
-#include <stddef.h> // 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 */
- },
-};
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "stg_client.h"
-
-#include "conn.h"
-#include "radlog.h"
-
-#include "stg/locker.h"
-#include "stg/common.h"
-
-#include <map>
-#include <utility>
-
-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<Conn> 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<Impl*>(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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_RLM_CLIENT_H__
-#define __STG_RLM_CLIENT_H__
-
-#include "types.h"
-
-#include "stg/os_int.h"
-
-#include <boost/scoped_ptr.hpp>
-
-#include <string>
-
-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<Impl> m_impl;
-};
-
-} // namespace RLM
-} // namespace STG
-
-#endif
+++ /dev/null
-#ifndef __STG_STGPAIR_H__
-#define __STG_STGPAIR_H__
-
-#include <stddef.h>
-
-#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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_RLM_CLIENT_CONN_H__
-#define __STG_RLM_CLIENT_CONN_H__
-
-#include <vector>
-#include <string>
-
-namespace STG
-{
-namespace RLM
-{
-
-typedef std::vector<std::pair<std::string, std::string> > PAIRS;
-
-struct RESULT
-{
- PAIRS modify;
- PAIRS reply;
- int returnCode;
-};
-
-enum REQUEST_TYPE {
- AUTHORIZE,
- AUTHENTICATE,
- POST_AUTH,
- PRE_ACCT,
- ACCOUNT
-};
-
-} // namespace RLM
-} // namespace STG
-
-#endif
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#!/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 <iconv.h>\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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <arpa/inet.h>
-#include <sys/uio.h> // readv
-#include <sys/types.h> // for historical versions of BSD
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <csignal>
-#include <cerrno>
-#include <ctime>
-#include <cstring>
-#include <sstream>
-#include <algorithm>
-
-#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<LISTENER *>(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<LISTENER *>(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<char *>(&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<PendingData>::iterator it(pending.begin());
-size_t count = 0;
-printfd(__FILE__, "Pending: %d\n", pending.size());
-while (it != pending.end() && count < 256)
- {
- std::vector<AliveData>::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<UserData>(*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<AliveData>::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));
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <pthread.h>
-
-#include <string>
-#include <vector>
-#include <list>
-#include <functional>
-
-#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<const AliveData &, bool> {
- 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<AliveData> users;
- std::list<PendingData> 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<const UserData &, void> {
- public:
- explicit DisconnectUser(LISTENER & l) : listener(l) {};
- void operator()(const UserData & data)
- {
- listener.Disconnect(data);
- };
- private:
- LISTENER & listener;
-};
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.19 $
- $Author: faust $
- $Date: 2010/09/10 06:37:45 $
- */
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h> // creat
-#include <unistd.h>
-
-#include <cstdlib>
-#include <cstdio>
-#include <csignal>
-#include <cerrno>
-#include <cstring> // strerror
-#include <set>
-
-#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<pid_t> executersPid;
-volatile time_t stgTime = time(NULL);
-
-//-----------------------------------------------------------------------------
-void KillExecuters()
-{
-std::set<pid_t>::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;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.1 $
- $Date: 2010/02/11 12:32:25 $
- $Author: faust $
- */
-
-/*
- * An implementation of RAII pid-file writer
- */
-
-#include <fstream>
-#include <unistd.h>
-
-#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());
- }
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * 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 <string>
-
-class PIDFile {
-public:
- explicit PIDFile(const std::string & fn);
- ~PIDFile();
-private:
- std::string fileName;
-};
-
-#endif
+++ /dev/null
-################################################################################
-# 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
-
-################################################################################
+++ /dev/null
-css.h
-sgauth
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#!/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 <iconv.h>\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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.13 $
- $Date: 2010/04/14 09:01:29 $
- $Author: faust $
- */
-
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <csignal>
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <vector>
-
-#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 <path_to_config>\n");
-}
-//-----------------------------------------------------------------------------
-void SetDirName(const std::vector<std::string> & 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;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-#!/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
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include <iostream>
-#include <cstring>
-
-#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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef SETTINGS_IMPL_H
-#define SETTINGS_IMPL_H
-
-#include <string>
-
-#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
+++ /dev/null
-################################################################################
-# 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
-
-################################################################################
+++ /dev/null
-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;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.7 $
- $Date: 2010/03/15 12:58:17 $
- */
-
-#include <libintl.h>
-
-#include <csignal>
-#include <cstdio>
-#include <cstring>
-#include <ctime>
-
-#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"
- "<html>\n"
- "<head>\n"
- "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
- "</head>\n"
- "<body>\n"
- "</body></html>\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"
- "<html>\n"
- "<head>\n"
- "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
- "<title>sgauth</title>\n"
- "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
- "</head>\n"
- "<body>\n"
- "<H3>Stargazer</H3><p>\n";
-
-const char * replyFooter = "</body></html>\n\n";
-
-char replyHeaderBuffer[2000];
-sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
-
-send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
-
-char str[512];
-
-int st = clnp->GetAuthorized();
-
-sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
- gettext("PrepaidTraffic"),
- ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<TABLE id=\"TraffTable\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str, " <TR id=\"TraffTableCaptionRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str, " <TD id=\"TraffTableCaptionCellC\"> </TD>\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, " <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
- send(outerSocket, str, strlen(str), 0);
- }
-
-sprintf(str," </TR>\n");
-send(outerSocket, str, strlen(str), 0);
-
-sprintf(str," <TR id=\"TraffTableUMRow\">\n");
-send(outerSocket, str, strlen(str), 0);
-
-sprintf(str," <TD id=\"TraffTableUMCellC\">%s</TD>\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," <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
- res = send(outerSocket, str, strlen(str), 0);
- }
-
-sprintf(str," </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str," <TR id=\"TraffTableDMRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str," <TD id=\"TraffTableDMCellC\">%s</TD>\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," <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
- res = send(outerSocket, str, strlen(str), 0);
- }
-sprintf(str," </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-
-sprintf(str," <TR id=\"TraffTableUSRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str," <TD id=\"TraffTableUSCellC\">%s</TD>\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," <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
- res = send(outerSocket, str, strlen(str), 0);
- }
-
-sprintf(str," </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str," <TR id=\"TraffTableDSRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str," <TD id=\"TraffTableDSCellC\">%s</TD>\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," <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
- res = send(outerSocket, str, strlen(str), 0);
- }
-
-sprintf(str," </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str,"</TABLE>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-if (!messages.empty())
- {
- sprintf(str," <TABLE id=\"MessagesTable\">\n");
- res = send(outerSocket, str, strlen(str), 0);
-
- sprintf(str," <TR id=\"MessagesTableRowC\">\n");
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," <TD>Date</TD>\n");
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," <TD>Text</TD>\n");
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," </TR>\n");
- send(outerSocket, str, strlen(str), 0);
-
- std::list<STG_MESSAGE>::reverse_iterator it;
- it = messages.rbegin();
- while (it != messages.rend())
- {
- sprintf(str," <TR id=\"MessagesTableRow%d\">\n", rowNum);
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," <TD>%s</TD>\n", it->recvTime.c_str());
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," <TD>%s</TD>\n", it->msg.c_str());
- send(outerSocket, str, strlen(str), 0);
- sprintf(str," </TR>\n");
- send(outerSocket, str, strlen(str), 0);
- ++it;
- ++rowNum;
- }
-
- sprintf(str," </TABLE>\n");
- res = send(outerSocket, str, strlen(str), 0);
- }
-
-time_t t = time(NULL);
-sprintf(str,"Îáíîâëåíî: %s</b>" , 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));
-}
-//---------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.3 $
- $Date: 2007/12/17 08:39:08 $
- */
-
-#ifndef WIN32
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include <string>
-#include <list>
-
-#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<STG_MESSAGE> messages;
-};
-//-----------------------------------------------------------------------------
+++ /dev/null
-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
+++ /dev/null
-#!/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 <iconv.h>\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 <libpq-fe.h>\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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.13 $
- $Date: 2010/04/14 09:01:29 $
- $Author: faust $
- */
-
-#include <unistd.h>
-
-#include <csignal>
-#include <iostream>
-#include <vector>
-#include <list>
-
-#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 <path_to_config>" << 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<std::string> userList;
-if (dataStore->GetUsersList(&userList))
- {
- std::cerr << "Failed to get user list: '" << dataStore->GetStrError() << "'" << std::endl;
- return -1;
- }
-
-std::list<uint32_t> ips;
- {
- std::vector<std::string>::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<uint32_t>::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;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-#!/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
+++ /dev/null
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-#include <cassert>
-#include <stdexcept>
-#include <algorithm>
-
-#include "stg/common.h"
-#include "stg/ia_packets.h"
-#include "stg/locker.h"
-
-#include "proto.h"
-
-class HasIP : public std::unary_function<std::pair<uint32_t, USER>, bool> {
- public:
- explicit HasIP(uint32_t i) : ip(i) {}
- bool operator()(const std::pair<uint32_t, USER> & 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<char *>(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<PROTO *>(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<std::pair<uint32_t, USER> >::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<std::pair<uint32_t, USER> >::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<std::pair<uint32_t, USER> >::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<struct pollfd>::iterator it;
-std::list<std::pair<uint32_t, USER> >::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<std::string, PacketProcessor>::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<const CONN_SYN_ACK_8 *>(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<const ALIVE_SYN_8 *>(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<const DISCONN_SYN_ACK_8 *>(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<const INFO_8 *>(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);
-}
+++ /dev/null
-#ifndef __PROTO_H__
-#define __PROTO_H__
-
-#ifndef LINUX
-#include <netinet/in_systm.h>
-#endif
-#include <netinet/ip.h>
-#include <pthread.h>
-#include <poll.h>
-
-#include <string>
-#include <list>
-#include <vector>
-#include <map>
-
-#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<std::pair<uint32_t, USER> > users;
- std::vector<struct pollfd> pollFds;
-
- bool running;
- bool stopped;
-
- pthread_t tid;
- pthread_mutex_t mutex;
-
- std::string errorStr;
-
- std::map<std::string, PacketProcessor> 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
+++ /dev/null
-#!/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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include <cstring>
-#include <cassert>
-#include <vector>
-
-#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<PARAM_VALUE> * 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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef SETTINGS_H
-#define SETTINGS_H
-
-#include <string>
-
-#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
+++ /dev/null
-#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
-
-<StoreModule store_files>
- WorkDir = /var/stargazer
-
- ConfOwner = root
- ConfGroup = root
- ConfMode = 600
-
- StatOwner = root
- StatGroup = root
- StatMode = 640
-
- UserLogOwner = root
- UserLogGroup = root
- UserLogMode = 640
-</StoreModule>
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.6 $
- $Date: 2010/03/04 12:24:19 $
- $Author: faust $
- */
-
-/*
- * An implementation of RAII store plugin loader
- */
-
-#include <dlfcn.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $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 <string>
-
-#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
+++ /dev/null
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <unistd.h> // close
-
-#include <cstring>
-#include <cerrno>
-#include <stdexcept>
-
-#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;
-}
+++ /dev/null
-#ifndef __USER_H__
-#define __USER_H__
-
-#include <ctime>
-#include <string>
-
-#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
+++ /dev/null
-
-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
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-Compiling:
-> ./build
-
-
+++ /dev/null
-1. No default value for server.
-2. No default value for port.
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_ACTION_H__
-#define __STG_SGCONF_ACTION_H__
-
-#include <string>
-#include <map>
-#include <stdexcept>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-#include <cassert>
-
-namespace SGCONF
-{
-
-typedef void (* FUNC0)();
-
-template <typename F>
-class FUNC0_ACTION : public ACTION
-{
- public:
- FUNC0_ACTION(const F & func) : m_func(func) {}
-
- virtual ACTION * Clone() const { return new FUNC0_ACTION<F>(*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 <typename F>
-inline
-FUNC0_ACTION<F> * MakeFunc0Action(F func)
-{
-return new FUNC0_ACTION<F>(func);
-}
-
-template <typename T>
-class PARAM_ACTION : public ACTION
-{
- public:
- PARAM_ACTION(RESETABLE<T> & param,
- const T & defaultValue,
- const std::string & paramDescription)
- : m_param(param),
- m_defaltValue(defaultValue),
- m_description(paramDescription),
- m_hasDefault(true)
- {}
- PARAM_ACTION(RESETABLE<T> & param)
- : m_param(param),
- m_hasDefault(false)
- {}
- PARAM_ACTION(RESETABLE<T> & param,
- const std::string & paramDescription)
- : m_param(param),
- m_description(paramDescription),
- m_hasDefault(false)
- {}
-
- virtual ACTION * Clone() const { return new PARAM_ACTION<T>(*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<T> & m_param;
- T m_defaltValue;
- std::string m_description;
- bool m_hasDefault;
- OPTION_BLOCK m_suboptions;
-};
-
-template <typename T>
-inline
-std::string PARAM_ACTION<T>::DefaultDescription() const
-{
-return m_hasDefault ? " (default: '" + x2str(m_defaltValue) + "')"
- : "";
-}
-
-template <>
-inline
-std::string PARAM_ACTION<std::string>::DefaultDescription() const
-{
-return m_hasDefault ? " (default: '" + m_defaltValue + "')"
- : "";
-}
-
-template <typename T>
-inline
-PARSER_STATE PARAM_ACTION<T>::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<bool>::Parse(int argc, char ** argv, void * /*data*/)
-{
-m_param = true;
-return PARSER_STATE(false, argc, argv);
-}
-
-template <typename T>
-inline
-void PARAM_ACTION<T>::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<std::string>::ParseValue(const std::string & stringValue)
-{
-m_param = stringValue;
-}
-
-template <>
-inline
-PARSER_STATE PARAM_ACTION<std::string>::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 <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param,
- const T & defaultValue,
- const std::string & paramDescription)
-{
-return new PARAM_ACTION<T>(param, defaultValue, paramDescription);
-}
-
-template <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param)
-{
-return new PARAM_ACTION<T>(param);
-}
-
-template <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param,
- const std::string & paramDescription)
-{
-return new PARAM_ACTION<T>(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<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(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
+++ /dev/null
-#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 <iostream>
-#include <string>
-#include <map>
-#include <cassert>
-
-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<SGCONF::API_ACTION::PARAM> GetAdminParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
-params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
-return params;
-}
-
-void ConvPriv(const std::string & value, RESETABLE<PRIV> & 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<STG::GET_ADMIN::INFO> & 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<STG::GET_ADMIN::INFO> & info,
- void * data)
-{
-assert(data != NULL && "Expecting pointer to std::string with the admin's login.");
-const std::string & login = *static_cast<const std::string *>(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<std::string, std::string> & /*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<std::string, std::string> & /*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 <GetAdmin login="..."/>.
-// 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<std::string, std::string> & /*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<std::string, std::string> & 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<std::string, std::string> & 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<API_ACTION::PARAM> params(GetAdminParams());
-blocks.Add("Admin management options")
- .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list")
- .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", GetAdminFunction), "get admin")
- .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", params, AddAdminFunction), "add admin")
- .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", DelAdminFunction), "del admin")
- .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", params, ChgAdminFunction), "change admin");
-}
+++ /dev/null
-#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
+++ /dev/null
-#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<PARAM> & params,
- API_FUNCTION funPtr)
- : m_commands(commands),
- m_description(paramDescription),
- m_argument(needArgument ? "1" : ""), // Hack
- m_funPtr(funPtr)
-{
-std::vector<PARAM>::const_iterator it(params.begin());
-while (it != params.end())
- {
- m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
- ++it;
- }
-}
+++ /dev/null
-#ifndef __STG_SGCONF_API_ACTION_H__
-#define __STG_SGCONF_API_ACTION_H__
-
-#include "action.h"
-
-#include "options.h"
-
-#include <string>
-#include <map>
-#include <vector>
-
-namespace SGCONF
-{
-
-typedef bool (* API_FUNCTION) (const CONFIG &,
- const std::string &,
- const std::map<std::string, std::string> &);
-
-class COMMAND
-{
- public:
- COMMAND(API_FUNCTION funPtr,
- const std::string & arg,
- const std::map<std::string, std::string> & 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<std::string, std::string> m_options;
-};
-
-class COMMANDS
-{
- public:
- void Add(API_FUNCTION funPtr,
- const std::string & arg,
- const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
- bool Execute(const SGCONF::CONFIG & config) const
- {
- std::vector<COMMAND>::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<COMMAND> 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<PARAM> & 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<std::string, std::string> m_params;
- API_FUNCTION m_funPtr;
-};
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
- const std::string & paramDescription,
- const std::vector<API_ACTION::PARAM> & params,
- API_FUNCTION funPtr)
-{
-return new API_ACTION(commands, paramDescription, true, params, funPtr);
-}
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
- const std::vector<API_ACTION::PARAM> & 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
+++ /dev/null
-#!/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 <iconv.h>\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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_CONFIG_H__
-#define __STG_SGCONF_CONFIG_H__
-
-#include "stg/common.h"
-#include "stg/resetable.h"
-#include "stg/os_int.h"
-
-#include <string>
-
-namespace SGCONF
-{
-
-struct CONFIG
-{
- RESETABLE<std::string> configFile;
- RESETABLE<std::string> server;
- RESETABLE<uint16_t> port;
- RESETABLE<std::string> localAddress;
- RESETABLE<uint16_t> localPort;
- RESETABLE<std::string> userName;
- RESETABLE<std::string> userPass;
- RESETABLE<bool> 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
+++ /dev/null
-#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 <iostream>
-#include <string>
-#include <map>
-
-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<SGCONF::API_ACTION::PARAM> GetCorpParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("cash", "<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<STG::GET_CORP::INFO> & 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<std::string, std::string> & /*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<std::string, std::string> & /*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<std::string, std::string> & /*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<std::string, std::string> & 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<std::string, std::string> & 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<API_ACTION::PARAM> params(GetCorpParams());
-blocks.Add("Corporation management options")
- .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list")
- .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", GetCorpFunction), "get corporation")
- .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", params, AddCorpFunction), "add corporation")
- .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", DelCorpFunction), "delete corporation")
- .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", params, ChgCorpFunction), "change corporation");
-}
+++ /dev/null
-#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
+++ /dev/null
-#include "info.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-
-#include "stg/servconf.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-#include <expat.h>
-
-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<std::string, std::string> & /*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");
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-#include <iostream>
-
-#include <cstdlib> // getenv
-#include <cstring> // str*
-
-#include <unistd.h> // access
-#include <libgen.h> // basename
-
-namespace
-{
-
-template <typename T>
-struct nullary_function
-{
-typedef T result_type;
-};
-
-template <typename F>
-class binder0 : public nullary_function<typename F::result_type>
-{
- 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 <typename F>
-inline
-binder0<F> bind0(const F & func, const typename F::argument_type & arg)
-{
-return binder0<F>(func, arg);
-}
-
-template <typename A, typename R>
-class FUNC1_ADAPTER : public std::unary_function<A, R>
-{
- 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 <typename C, typename A, typename R>
-class METHOD1_ADAPTER : public std::unary_function<A, R>
-{
- 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 <typename C, typename A, typename R>
-class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
-{
- 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 <typename A, typename R>
-FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
-{
-return FUNC1_ADAPTER<A, R>(func);
-}
-
-template <typename C, typename A, typename R>
-METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
-{
-return METHOD1_ADAPTER<C, A, R>(func, obj);
-}
-
-template <typename C, typename A, typename R>
-CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
-{
-return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
-}
-
-void Version(const std::string & self)
-{
-std::cout << self << ", version: 2.0.0.\n";
-}
-
-void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
-{
-std::vector<std::string> 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<std::string>::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"), "<config file>"), "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"), "<address>"), "\t\thost to connect")
- .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
- .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "<address>"), "\tlocal address to bind")
- .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), "<port>"), "\t\tlocal port to bind")
- .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
- .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
- .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
-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 <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 <name>\t\t\tname of the tariff to add\n"
- << "\t\t--fee <fee>\t\t\tstariff's fee\n"
- << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
- << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
- << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
- << "\t\t--times <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 <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
- << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
- << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
- << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
- << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
- << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
- << "\t\t--thresholds <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 <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 <name>\t\t\tname of the tariff to change\n"
- << "\t\t--fee <fee>\t\t\tstariff's fee\n"
- << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
- << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
- << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
- << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
- << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
- << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
- << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
- << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
- << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
- << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
- << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
- << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageUsers(bool full)
-{
-std::cout << "Users management options:\n"
- << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--get-user\t\t\t\tget the information about user\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--add-user\t\t\t\tadd a new user\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
-if (full)
- std::cout << "\n\n";
-std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
-if (full)
- std::cout << "\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageServices(bool full)
-{
-std::cout << "Services management options:\n"
- << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
-if (full)
- std::cout << "\t\t--name\t\t\t\tshow service's name\n"
- << "\t\t--comment\t\t\tshow a comment to the service\n"
- << "\t\t--cost\t\t\t\tshow service's cost\n"
- << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
-std::cout << "\t--get-service\t\t\t\tget the information about service\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
- << "\t\t--comment\t\t\tshow a comment to the service\n"
- << "\t\t--cost\t\t\t\tshow service's cost\n"
- << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
-std::cout << "\t--add-service\t\t\t\tadd a new service\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
- << "\t\t--comment <comment>\t\ta comment to the service\n"
- << "\t\t--cost <cost>\t\t\tservice's cost\n"
- << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
-std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
-std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
- << "\t\t--comment <comment>\t\ta comment to the service\n"
- << "\t\t--cost <cost>\t\t\tservice's cost\n"
- << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageCorporations(bool full)
-{
-std::cout << "Corporations management options:\n"
- << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
-if (full)
- std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
- << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
-std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
- << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
-std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
- << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
-std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
-std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
-if (full)
- std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
- << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
- << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
-}*/
-
-} // namespace anonymous
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "options.h"
-
-#include "action.h"
-#include "parser_state.h"
-
-#include "stg/common.h"
-
-#include <fstream>
-#include <sstream>
-#include <iostream>
-#include <functional>
-#include <algorithm>
-
-#include <unistd.h>
-
-namespace
-{
-
-template <class C>
-void ReadConfigFile(const std::string & filePath, void (C::* callback)(const std::string&, const std::string&), C * obj)
-{
-std::ifstream stream(filePath.c_str());
-std::string line;
-size_t num = 0;
-while (std::getline(stream, line))
- {
- ++num;
- line = Trim(line);
- std::string::size_type pos = line.find_first_of('#');
- if (pos != std::string::npos)
- line = line.substr(0, pos);
- if (line.empty())
- continue;
- pos = line.find_first_of('=');
- if (pos == std::string::npos)
- {
- std::ostringstream error;
- error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'.";
- throw std::runtime_error(error.str().c_str());
- }
- (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1)));
- }
-}
-
-} // namespace anonymous
-
-using SGCONF::OPTION;
-using SGCONF::OPTION_BLOCK;
-using SGCONF::OPTION_BLOCKS;
-using SGCONF::ACTION;
-using SGCONF::PARSER_STATE;
-
-OPTION::OPTION(const std::string & shortName,
- const std::string & longName,
- ACTION * action,
- const std::string & description)
- : m_shortName(shortName),
- m_longName(longName),
- m_action(action),
- m_description(description)
-{
-}
-
-OPTION::OPTION(const std::string & longName,
- ACTION * action,
- const std::string & description)
- : m_longName(longName),
- m_action(action),
- m_description(description)
-{
-}
-
-OPTION::OPTION(const OPTION & rhs)
- : m_shortName(rhs.m_shortName),
- m_longName(rhs.m_longName),
- m_action(rhs.m_action->Clone()),
- m_description(rhs.m_description)
-{
-}
-
-OPTION::~OPTION()
-{
-delete m_action;
-}
-
-OPTION & OPTION::operator=(const OPTION & rhs)
-{
-m_shortName = rhs.m_shortName;
-m_longName = rhs.m_longName;
-m_action = rhs.m_action->Clone();
-m_description = rhs.m_description;
-return *this;
-}
-
-void OPTION::Help(size_t level) const
-{
-if (!m_action)
- throw ERROR("Option is not defined.");
-std::string indent(level, '\t');
-std::cout << indent;
-if (!m_shortName.empty())
- std::cout << "-" << m_shortName << ", ";
-std::cout << "--" << m_longName << " " << m_action->ParamDescription()
- << "\t" << m_description << m_action->DefaultDescription() << "\n";
-m_action->Suboptions().Help(level);
-}
-
-bool OPTION::Check(const char * arg) const
-{
-if (arg == NULL)
- return false;
-
-if (*arg++ != '-')
- return false;
-
-if (*arg == '-')
-{
- return m_longName == arg + 1;
-}
-
-return m_shortName == arg;
-}
-
-PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
-{
-if (!m_action)
- throw ERROR("Option is not defined.");
-try
- {
- return m_action->Parse(argc, argv, data);
- }
-catch (const ACTION::ERROR & ex)
- {
- if (m_longName.empty())
- throw ERROR("-" + m_shortName + ": " + ex.what());
- else
- throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what())
- : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
- }
-}
-
-void OPTION::ParseValue(const std::string & value)
-{
-if (!m_action)
- throw ERROR("Option is not defined.");
-try
- {
- return m_action->ParseValue(value);
- }
-catch (const ACTION::ERROR & ex)
- {
- throw ERROR(m_longName + ": " + ex.what());
- }
-}
-
-OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & shortName,
- const std::string & longName,
- ACTION * action,
- const std::string & description)
-{
-m_options.push_back(OPTION(shortName, longName, action, description));
-return *this;
-}
-
-OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & longName,
- ACTION * action,
- const std::string & description)
-{
-m_options.push_back(OPTION(longName, action, description));
-return *this;
-}
-
-void OPTION_BLOCK::Help(size_t level) const
-{
-if (m_options.empty())
- return;
-if (!m_description.empty())
- std::cout << m_description << ":\n";
-std::for_each(m_options.begin(),
- m_options.end(),
- std::bind2nd(std::mem_fun_ref(&OPTION::Help), level + 1));
-}
-
-PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
-{
-PARSER_STATE state(false, argc, argv);
-if (state.argc == 0)
- return state;
-while (state.argc > 0 && !state.stop)
- {
- std::vector<OPTION>::iterator it = std::find_if(m_options.begin(), m_options.end(), std::bind2nd(std::mem_fun_ref(&OPTION::Check), *state.argv));
- if (it != m_options.end())
- state = it->Parse(--state.argc, ++state.argv, data);
- else
- break;
- ++it;
- }
-return state;
-}
-
-void OPTION_BLOCK::ParseFile(const std::string & filePath)
-{
-if (access(filePath.c_str(), R_OK))
- throw ERROR("File '" + filePath + "' does not exists.");
-ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this);
-}
-
-void OPTION_BLOCK::OptionCallback(const std::string & key, const std::string & value)
-{
-for (std::vector<OPTION>::iterator it = m_options.begin(); it != m_options.end(); ++it)
- if (it->Name() == key)
- it->ParseValue(value);
-}
-
-void OPTION_BLOCKS::Help(size_t level) const
-{
-std::list<OPTION_BLOCK>::const_iterator it(m_blocks.begin());
-while (it != m_blocks.end())
- {
- it->Help(level);
- std::cout << "\n";
- ++it;
- }
-}
-
-PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv)
-{
-PARSER_STATE state(false, argc, argv);
-std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
-while (state.argc > 0 && !state.stop && it != m_blocks.end())
- {
- state = it->Parse(state.argc, state.argv);
- ++it;
- }
-return state;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_OPTIONS_H__
-#define __STG_SGCONF_OPTIONS_H__
-
-#include <string>
-#include <vector>
-#include <list>
-#include <utility>
-#include <stdexcept>
-#include <cstddef> // size_t
-
-namespace SGCONF
-{
-
-class ACTION;
-struct PARSER_STATE;
-
-class OPTION
-{
- public:
- OPTION(const std::string & shortName,
- const std::string & longName,
- ACTION * action,
- const std::string & description);
- OPTION(const std::string & longName,
- ACTION * action,
- const std::string & description);
- OPTION(const OPTION & rhs);
- ~OPTION();
-
- OPTION & operator=(const OPTION & rhs);
-
- void Help(size_t level = 0) const;
- PARSER_STATE Parse(int argc, char ** argv, void * data);
- void ParseValue(const std::string & value);
- bool Check(const char * arg) const;
- const std::string & Name() const { return m_longName; }
-
- class ERROR : public std::runtime_error
- {
- public:
- ERROR(const std::string & message)
- : std::runtime_error(message.c_str()) {}
- };
-
- private:
- std::string m_shortName;
- std::string m_longName;
- ACTION * m_action;
- std::string m_description;
-};
-
-class OPTION_BLOCK
-{
- public:
- OPTION_BLOCK() {}
- OPTION_BLOCK(const std::string & description)
- : m_description(description) {}
- OPTION_BLOCK & Add(const std::string & shortName,
- const std::string & longName,
- ACTION * action,
- const std::string & description);
- OPTION_BLOCK & Add(const std::string & longName,
- ACTION * action,
- const std::string & description);
-
- void Help(size_t level) const;
-
- PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
- void ParseFile(const std::string & filePath);
-
- class ERROR : public std::runtime_error
- {
- public:
- ERROR(const std::string & message)
- : std::runtime_error(message.c_str()) {}
- };
-
- private:
- std::vector<OPTION> m_options;
- std::string m_description;
-
- void OptionCallback(const std::string & key, const std::string & value);
-};
-
-class OPTION_BLOCKS
-{
- public:
- OPTION_BLOCK & Add(const std::string & description)
- { m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); }
- void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); }
- void Help(size_t level) const;
- PARSER_STATE Parse(int argc, char ** argv);
-
- private:
- std::list<OPTION_BLOCK> m_blocks;
-};
-
-} // namespace SGCONF
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_PARSER_STATE_H__
-#define __STG_SGCONF_PARSER_STATE_H__
-
-namespace SGCONF
-{
-
-struct PARSER_STATE
-{
- PARSER_STATE(bool s, int c, char ** v) : stop(s), argc(c), argv(v) {}
- bool stop;
- int argc;
- char ** argv;
-};
-
-}
-
-#endif
+++ /dev/null
-#include "services.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/service_conf.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-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 PrintService(const STG::GET_SERVICE::INFO & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "name: " << info.name << "\n"
- << Indent(level) << "cost: " << info.cost << "\n"
- << Indent(level) << "payment day: " << static_cast<unsigned>(info.payDay) << "\n"
- << Indent(level) << "comment: " << info.comment << "\n";
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
-params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
-params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
-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 GetServicesCallback(bool result,
- const std::string & reason,
- const std::vector<STG::GET_SERVICE::INFO> & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get service list. Reason: '" << reason << "'." << std::endl;
- return;
- }
-std::cout << "Services:\n";
-for (size_t i = 0; i < info.size(); ++i)
- PrintService(info[i], 1);
-}
-
-void GetServiceCallback(bool result,
- const std::string & reason,
- const STG::GET_SERVICE::INFO & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get service. Reason: '" << reason << "'." << std::endl;
- return;
- }
-PrintService(info);
-}
-
-bool GetServicesFunction(const SGCONF::CONFIG & config,
- const std::string & /*arg*/,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.GetServices(GetServicesCallback, NULL) == STG::st_ok;
-}
-
-bool GetServiceFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.GetService(arg, GetServiceCallback, NULL) == STG::st_ok;
-}
-
-bool DelServiceFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.DelService(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddServiceFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-SERVICE_CONF_RES conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cost", conf.cost);
-SGCONF::MaybeSet(options, "pay-day", conf.payDay);
-SGCONF::MaybeSet(options, "comment", conf.comment);
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.AddService(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgServiceFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-SERVICE_CONF_RES conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cost", conf.cost);
-SGCONF::MaybeSet(options, "pay-day", conf.payDay);
-SGCONF::MaybeSet(options, "comment", conf.comment);
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.ChgService(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetServiceParams());
-blocks.Add("Service management options")
- .Add("get-services", SGCONF::MakeAPIAction(commands, GetServicesFunction), "\tget service list")
- .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", GetServiceFunction), "get service")
- .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", params, AddServiceFunction), "add service")
- .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", DelServiceFunction), "delete service")
- .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", params, ChgServiceFunction), "change service");
-}
+++ /dev/null
-#ifndef __STG_SGCONF_SERVICES_H__
-#define __STG_SGCONF_SERVICES_H__
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
-
-#endif
+++ /dev/null
-#include "tariffs.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/tariff_conf.h"
-#include "stg/common.h"
-#include "stg/os_int.h"
-
-#include <iostream>
-#include <algorithm>
-#include <sstream>
-#include <string>
-#include <map>
-#include <cassert>
-
-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 ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy)
-{
-switch (changePolicy)
- {
- case TARIFF::ALLOW: return "allow";
- case TARIFF::TO_CHEAP: return "to_cheap";
- case TARIFF::TO_EXPENSIVE: return "to_expensive";
- case TARIFF::DENY: return "deny";
- }
-return "unknown";
-}
-
-std::string PeriodToString(TARIFF::PERIOD period)
-{
-switch (period)
- {
- case TARIFF::DAY:
- return "daily";
- case TARIFF::MONTH:
- return "monthly";
- }
-return "unknown";
-}
-
-std::string TraffTypeToString(TARIFF::TRAFF_TYPE traffType)
-{
-switch (traffType)
- {
- case TARIFF::TRAFF_UP:
- return "upload";
- case TARIFF::TRAFF_DOWN:
- return "download";
- case TARIFF::TRAFF_UP_DOWN:
- return "upload + download";
- case TARIFF::TRAFF_MAX:
- return "max(upload, download)";
- }
-return "unknown";
-}
-
-void ConvPeriod(const std::string & value, RESETABLE<TARIFF::PERIOD> & res)
-{
-std::string lowered = ToLower(value);
-if (lowered == "daily")
- res = TARIFF::DAY;
-else if (lowered == "monthly")
- res = TARIFF::MONTH;
-else
- throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
-}
-
-void ConvChangePolicy(const std::string & value, RESETABLE<TARIFF::CHANGE_POLICY> & res)
-{
-std::string lowered = ToLower(value);
-if (lowered == "allow")
- res = TARIFF::ALLOW;
-else if (lowered == "to_cheap")
- res = TARIFF::TO_CHEAP;
-else if (lowered == "to_expensive")
- res = TARIFF::TO_EXPENSIVE;
-else if (lowered == "deny")
- res = TARIFF::DENY;
-else
- throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'");
-}
-
-void ConvChangePolicyTimeout(const std::string & value, RESETABLE<time_t> & res)
-{
-struct tm brokenTime;
-if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
- throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
-res = stg_timegm(&brokenTime);
-}
-
-void ConvTraffType(const std::string & value, RESETABLE<TARIFF::TRAFF_TYPE> & res)
-{
-std::string lowered = ToLower(value);
-lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end());
-if (lowered == "upload")
- res = TARIFF::TRAFF_UP;
-else if (lowered == "download")
- res = TARIFF::TRAFF_DOWN;
-else if (lowered == "upload+download")
- res = TARIFF::TRAFF_UP_DOWN;
-else if (lowered.substr(0, 3) == "max")
- res = TARIFF::TRAFF_MAX;
-else
- throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'");
-}
-
-DIRPRICE_DATA_RES ConvTimeSpan(const std::string & value)
-{
-size_t dashPos = value.find_first_of('-');
-if (dashPos == std::string::npos)
- throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-size_t fromColon = value.find_first_of(':');
-if (fromColon == std::string::npos || fromColon > dashPos)
- throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-size_t toColon = value.find_first_of(':', dashPos);
-if (toColon == std::string::npos)
- throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-DIRPRICE_DATA_RES res;
-res.hDay = FromString<int>(value.substr(0, fromColon));
-if (res.hDay.data() < 0 || res.hDay.data() > 23)
- throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'");
-res.mDay = FromString<int>(value.substr(fromColon + 1, dashPos - fromColon - 1));
-if (res.mDay.data() < 0 || res.mDay.data() > 59)
- throw SGCONF::ACTION::ERROR("Invalid 'from' minutes. Got: '" + value.substr(fromColon + 1, dashPos - fromColon - 1) + "'");
-res.hNight = FromString<int>(value.substr(dashPos + 1, toColon - dashPos - 1));
-if (res.hNight.data() < 0 || res.hNight.data() > 23)
- throw SGCONF::ACTION::ERROR("Invalid 'to' hours. Got: '" + value.substr(dashPos + 1, toColon - dashPos - 1) + "'");
-res.mNight = FromString<int>(value.substr(toColon + 1, value.length() - toColon));
-if (res.mNight.data() < 0 || res.mNight.data() > 59)
- throw SGCONF::ACTION::ERROR("Invalid 'to' minutes. Got: '" + value.substr(toColon + 1, value.length() - toColon) + "'");
-return res;
-}
-
-void Splice(std::vector<DIRPRICE_DATA_RES> & lhs, const std::vector<DIRPRICE_DATA_RES> & rhs)
-{
-for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
- lhs[i].Splice(rhs[i]);
-}
-
-void ConvTimes(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvTimeSpan));
-}
-
-struct ConvPrice : public std::unary_function<std::string, DIRPRICE_DATA_RES>
-{
- typedef RESETABLE<double> (DIRPRICE_DATA_RES::* MemPtr);
- ConvPrice(MemPtr before, MemPtr after)
- : m_before(before), m_after(after)
- {}
-
- DIRPRICE_DATA_RES operator()(const std::string & value)
- {
- DIRPRICE_DATA_RES res;
- size_t slashPos = value.find_first_of('/');
- if (slashPos == std::string::npos)
- {
- double price = 0;
- if (str2x(value, price) < 0)
- throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value + "'");
- (res.*m_before) = (res.*m_after) = price;
- res.noDiscount = true;
- }
- else
- {
- double price = 0;
- if (str2x(value.substr(0, slashPos), price) < 0)
- throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(0, slashPos) + "'");
- (res.*m_before) = price;
- if (str2x(value.substr(slashPos + 1, value.length() - slashPos), price) < 0)
- throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
- (res.*m_after) = price;
- res.noDiscount = false;
- }
- return res;
- }
-
- MemPtr m_before;
- MemPtr m_after;
-};
-
-void ConvDayPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceDayA, &DIRPRICE_DATA_RES::priceDayB)));
-}
-
-void ConvNightPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceNightA, &DIRPRICE_DATA_RES::priceNightB)));
-}
-
-DIRPRICE_DATA_RES ConvThreshold(std::string value)
-{
-DIRPRICE_DATA_RES res;
-double threshold = 0;
-if (str2x(value, threshold) < 0)
- throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'");
-res.threshold = threshold;
-return res;
-}
-
-void ConvThresholds(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvThreshold));
-}
-
-std::string TimeToString(int h, int m)
-{
-std::ostringstream stream;
-stream << (h < 10 ? "0" : "") << h << ":"
- << (m < 10 ? "0" : "") << m;
-return stream.str();
-}
-
-void PrintDirPriceData(size_t dir, const DIRPRICE_DATA & data, size_t level)
-{
-std::string night = TimeToString(data.hNight, data.mNight);
-std::string day = TimeToString(data.hDay, data.mDay);
-std::cout << Indent(level, true) << "dir: " << dir << "\n"
- << Indent(level) << "'" << night << "' - '" << day << "': " << data.priceDayA << "/" << data.priceDayB << "\n"
- << Indent(level) << "'" << day << "' - '" << night << "': " << data.priceNightA << "/" << data.priceNightB << "\n"
- << Indent(level) << "threshold: " << data.threshold << "\n"
- << Indent(level) << "single price: " << (data.singlePrice ? "yes" : "no") << "\n"
- << Indent(level) << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention!
-}
-
-void PrintTariffConf(const TARIFF_CONF & conf, size_t level)
-{
-std::cout << Indent(level, true) << "name: " << conf.name << "\n"
- << Indent(level) << "fee: " << conf.fee << "\n"
- << Indent(level) << "free mb: " << conf.free << "\n"
- << Indent(level) << "passive cost: " << conf.passiveCost << "\n"
- << Indent(level) << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
- << Indent(level) << "period: " << PeriodToString(conf.period) << "\n"
- << Indent(level) << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n"
- << Indent(level) << "change policy timeout: " << formatTime(conf.changePolicyTimeout) << "\n";
-}
-
-void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0)
-{
-PrintTariffConf(info.tariffConf, level);
-std::cout << Indent(level) << "dir prices:\n";
-for (size_t i = 0; i < info.dirPrice.size(); ++i)
- PrintDirPriceData(i, info.dirPrice[i], level + 1);
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
-params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
-params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
-params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
-params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
-params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "<policy>", "tariff change policy (allow, to_cheap, to_expensive, deny)"));
-params.push_back(SGCONF::API_ACTION::PARAM("change-policy-timeout", "<yyyy-mm-dd hh:mm:ss>", "tariff change policy timeout"));
-params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
-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 GetTariffsCallback(bool result,
- const std::string & reason,
- const std::vector<STG::GET_TARIFF::INFO> & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get tariff list. Reason: '" << reason << "'." << std::endl;
- return;
- }
-std::cout << "Tariffs:\n";
-for (size_t i = 0; i < info.size(); ++i)
- PrintTariff(info[i], 1);
-}
-
-void GetTariffCallback(bool result,
- const std::string & reason,
- const std::vector<STG::GET_TARIFF::INFO> & info,
- void * data)
-{
-assert(data != NULL && "Expecting pointer to std::string with the tariff's name.");
-const std::string & name = *static_cast<const std::string *>(data);
-if (!result)
- {
- std::cerr << "Failed to get tariff. Reason: '" << reason << "'." << std::endl;
- return;
- }
-for (size_t i = 0; i < info.size(); ++i)
- if (info[i].tariffConf.name == name)
- PrintTariff(info[i]);
-}
-
-bool GetTariffsFunction(const SGCONF::CONFIG & config,
- const std::string & /*arg*/,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.GetTariffs(GetTariffsCallback, NULL) == STG::st_ok;
-}
-
-bool GetTariffFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*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 <GetTariff name="..."/>.
-// So get a list of tariffs and filter it. 'data' param holds a pointer to 'name'.
-std::string name(arg);
-return proto.GetTariffs(GetTariffCallback, &name) == STG::st_ok;
-}
-
-bool DelTariffFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.DelTariff(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddTariffFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-TARIFF_DATA_RES conf;
-conf.tariffConf.name = arg;
-SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
-SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
-SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
-SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
-SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
-SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
-SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
-SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
-SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
-SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
-SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
-for (size_t i = 0; i < conf.dirPrice.size(); ++i)
- {
- if (!conf.dirPrice[i].priceDayA.empty() &&
- !conf.dirPrice[i].priceNightA.empty() &&
- !conf.dirPrice[i].priceDayB.empty() &&
- !conf.dirPrice[i].priceNightB.empty())
- conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
- conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
- }
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.AddTariff(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgTariffFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-TARIFF_DATA_RES conf;
-conf.tariffConf.name = arg;
-SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
-SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
-SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
-SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
-SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
-SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
-SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
-SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
-SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
-SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
-SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
-for (size_t i = 0; i < conf.dirPrice.size(); ++i)
- {
- if (!conf.dirPrice[i].priceDayA.empty() &&
- !conf.dirPrice[i].priceNightA.empty() &&
- !conf.dirPrice[i].priceDayB.empty() &&
- !conf.dirPrice[i].priceNightB.empty())
- conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
- conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
- }
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.ChgTariff(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetTariffParams());
-blocks.Add("Tariff management options")
- .Add("get-tariffs", SGCONF::MakeAPIAction(commands, GetTariffsFunction), "\tget tariff list")
- .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", GetTariffFunction), "get tariff")
- .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, AddTariffFunction), "add tariff")
- .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", DelTariffFunction), "delete tariff")
- .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, ChgTariffFunction), "change tariff");
-}
+++ /dev/null
-#ifndef __STG_SGCONF_TARIFFS_H__
-#define __STG_SGCONF_TARIFFS_H__
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
-
-#endif
+++ /dev/null
-#include "users.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/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/user_ips.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <algorithm>
-#include <string>
-#include <map>
-
-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 PrintUser(const STG::GET_USER::INFO & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "login: " << info.login << "\n"
- << Indent(level) << "password: " << info.password << "\n"
- << Indent(level) << "cash: " << info.cash << "\n"
- << Indent(level) << "credit: " << info.credit << "\n"
- << Indent(level) << "credit expire: " << TimeToString(info.creditExpire) << "\n"
- << Indent(level) << "last cash add: " << info.lastCashAdd << "\n"
- << Indent(level) << "last cash add time: " << TimeToString(info.lastCashAddTime) << "\n"
- << Indent(level) << "prepaid traffic: " << info.prepaidTraff << "\n"
- << Indent(level) << "disabled: " << (info.disabled ? "t" : "f") << "\n"
- << Indent(level) << "passive: " << (info.passive ? "t" : "f") << "\n"
- << Indent(level) << "disabled detail stat: " << (info.disableDetailStat ? "t" : "f") << "\n"
- << Indent(level) << "connected: " << (info.connected ? "t" : "f") << "\n"
- << Indent(level) << "always on-line: " << (info.alwaysOnline ? "t" : "f") << "\n"
- << Indent(level) << "IP: " << inet_ntostring(info.ip) << "\n"
- << Indent(level) << "IPs: " << info.ips << "\n"
- << Indent(level) << "tariff: " << info.tariff << "\n"
- << Indent(level) << "group: " << info.group << "\n"
- << Indent(level) << "note: " << info.note << "\n"
- << Indent(level) << "email: " << info.email << "\n"
- << Indent(level) << "name: " << info.name << "\n"
- << Indent(level) << "address: " << info.address << "\n"
- << Indent(level) << "phone: " << info.phone << "\n"
- << Indent(level) << "corporation: " << info.corp << "\n"
- << Indent(level) << "last ping time: " << TimeToString(info.pingTime) << "\n"
- << Indent(level) << "last activity time: " << TimeToString(info.lastActivityTime) << "\n"
- << Indent(level) << "traffic:\n";
-for (size_t i = 0; i < DIR_NUM; ++i)
- {
- std::cout << Indent(level + 1, true) << "dir: " << i << "\n"
- << Indent(level + 1) << "session upload: " << info.stat.su[i] << "\n"
- << Indent(level + 1) << "session download: " << info.stat.sd[i] << "\n"
- << Indent(level + 1) << "month upload: " << info.stat.mu[i] << "\n"
- << Indent(level + 1) << "month download: " << info.stat.md[i] << "\n";
- }
-std::cout << Indent(level) << "user data:\n";
-for (size_t i = 0; i < USERDATA_NUM; ++i)
- std::cout << Indent(level + 1, true) << "user data " << i << ": " << info.userData[i] << "\n";
-if (!info.services.empty())
- {
- std::cout << Indent(level) << "services:\n";
- for (size_t i = 0; i < info.services.size(); ++i)
- std::cout << Indent(level + 1, true) << info.services[i] << "\n";
- }
-if (!info.authBy.empty())
- {
- std::cout << Indent(level) << "auth by:\n";
- for (size_t i = 0; i < info.authBy.size(); ++i)
- std::cout << Indent(level + 1, true) << info.authBy[i] << "\n";
- }
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
-params.push_back(SGCONF::API_ACTION::PARAM("cash-add", "<cash[:message]>", "cash to add (with optional comment)"));
-params.push_back(SGCONF::API_ACTION::PARAM("cash-set", "<cash[:message]>", "cash to set (with optional comment)"));
-params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
-params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
-params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
-params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
-params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
-params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
-params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
-params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
-params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
-params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
-params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
-params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
-params.push_back(SGCONF::API_ACTION::PARAM("corp", "<corp name>", "\tcorporation name"));
-params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
-params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
-params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
-return params;
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
-return params;
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
-params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
-return params;
-}
-
-void ConvBool(const std::string & value, RESETABLE<int> & res)
-{
-res = !value.empty() && value[0] == 'y';
-}
-
-void Splice(std::vector<RESETABLE<std::string> > & lhs, const std::vector<RESETABLE<std::string> > & rhs)
-{
-for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
- lhs[i].splice(rhs[i]);
-}
-
-RESETABLE<std::string> ConvString(const std::string & value)
-{
-return RESETABLE<std::string>(value);
-}
-
-void ConvStringList(std::string value, std::vector<RESETABLE<std::string> > & res)
-{
-Splice(res, Split<std::vector<RESETABLE<std::string> > >(value, ',', ConvString));
-}
-
-void ConvServices(std::string value, RESETABLE<std::vector<std::string> > & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-res = Split<std::vector<std::string> >(value, ',');
-}
-
-void ConvCreditExpire(const std::string & value, RESETABLE<time_t> & res)
-{
-struct tm brokenTime;
-if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
- throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
-res = stg_timegm(&brokenTime);
-}
-
-void ConvIPs(const std::string & value, RESETABLE<USER_IPS> & res)
-{
-res = StrToIPS(value);
-}
-
-struct TRAFF
-{
- uint64_t up;
- uint64_t down;
-};
-
-TRAFF ConvTraff(const std::string & value)
-{
-TRAFF res;
-size_t slashPos = value.find_first_of('/');
-if (slashPos == std::string::npos)
- throw SGCONF::ACTION::ERROR("Traffic record should be in format 'upload/download'. Got: '" + value + "'");
-
-if (str2x(value.substr(0, slashPos), res.up) < 0)
- throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(0, slashPos) + "'");
-if (str2x(value.substr(slashPos + 1, value.length() - slashPos), res.down) < 0)
- throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
-return res;
-}
-
-void ConvSessionTraff(std::string value, USER_STAT_RES & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
-if (traff.size() != DIR_NUM)
- throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of session traffic.");
-for (size_t i = 0; i < DIR_NUM; ++i)
- {
- res.sessionUp[i] = traff[i].up;
- res.sessionDown[i] = traff[i].down;
- }
-}
-
-void ConvMonthTraff(std::string value, USER_STAT_RES & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
-if (traff.size() != DIR_NUM)
- throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of month traffic.");
-for (size_t i = 0; i < DIR_NUM; ++i)
- {
- res.monthUp[i] = traff[i].up;
- res.monthDown[i] = traff[i].down;
- }
-}
-
-void ConvCashInfo(const std::string & value, RESETABLE<CASH_INFO> & res)
-{
-CASH_INFO info;
-size_t pos = value.find_first_of(':');
-if (pos == std::string::npos)
- {
- if (str2x(value, info.first) < 0)
- throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
- }
-else
- {
- if (str2x(value.substr(0, pos), info.first) < 0)
- throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
- info.second = value.substr(pos + 1);
- }
-res = info;
-}
-
-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 GetUsersCallback(bool result,
- const std::string & reason,
- const std::vector<STG::GET_USER::INFO> & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get user list. Reason: '" << reason << "'." << std::endl;
- return;
- }
-std::cout << "Users:\n";
-for (size_t i = 0; i < info.size(); ++i)
- PrintUser(info[i], 1);
-}
-
-void GetUserCallback(bool result,
- const std::string & reason,
- const STG::GET_USER::INFO & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get user. Reason: '" << reason << "'." << std::endl;
- return;
- }
-PrintUser(info);
-}
-
-void AuthByCallback(bool result,
- const std::string & reason,
- const std::vector<std::string> & info,
- void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get authorizer list. Reason: '" << reason << "'." << std::endl;
- return;
- }
-std::cout << "Authorized by:\n";
-for (size_t i = 0; i < info.size(); ++i)
- std::cout << Indent(1, true) << info[i] << "\n";
-}
-
-bool GetUsersFunction(const SGCONF::CONFIG & config,
- const std::string & /*arg*/,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.GetUsers(GetUsersCallback, NULL) == STG::st_ok;
-}
-
-bool GetUserFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.GetUser(arg, GetUserCallback, NULL) == STG::st_ok;
-}
-
-bool DelUserFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.DelUser(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddUserFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-USER_CONF_RES conf;
-SGCONF::MaybeSet(options, "password", conf.password);
-SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
-SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
-SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
-SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
-SGCONF::MaybeSet(options, "tariff", conf.tariffName);
-SGCONF::MaybeSet(options, "address", conf.address);
-SGCONF::MaybeSet(options, "phone", conf.phone);
-SGCONF::MaybeSet(options, "email", conf.email);
-SGCONF::MaybeSet(options, "note", conf.note);
-SGCONF::MaybeSet(options, "name", conf.realName);
-SGCONF::MaybeSet(options, "corp", conf.corp);
-SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
-SGCONF::MaybeSet(options, "group", conf.group);
-SGCONF::MaybeSet(options, "credit", conf.credit);
-SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
-SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
-SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
-SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
-USER_STAT_RES stat;
-SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
-SGCONF::MaybeSet(options, "free", stat.freeMb);
-SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
-SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.AddUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgUserFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-USER_CONF_RES conf;
-SGCONF::MaybeSet(options, "password", conf.password);
-SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
-SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
-SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
-SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
-SGCONF::MaybeSet(options, "tariff", conf.tariffName);
-SGCONF::MaybeSet(options, "address", conf.address);
-SGCONF::MaybeSet(options, "phone", conf.phone);
-SGCONF::MaybeSet(options, "email", conf.email);
-SGCONF::MaybeSet(options, "note", conf.note);
-SGCONF::MaybeSet(options, "name", conf.realName);
-SGCONF::MaybeSet(options, "corp", conf.corp);
-SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
-SGCONF::MaybeSet(options, "group", conf.group);
-SGCONF::MaybeSet(options, "credit", conf.credit);
-SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
-SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
-SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
-SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
-USER_STAT_RES stat;
-SGCONF::MaybeSet(options, "cash-add", stat.cashAdd, ConvCashInfo);
-SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
-SGCONF::MaybeSet(options, "free", stat.freeMb);
-SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
-SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.ChgUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool CheckUserFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & options)
-{
-std::map<std::string, std::string>::const_iterator it(options.find("password"));
-if (it == options.end())
- throw SGCONF::ACTION::ERROR("Password is not specified.");
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.CheckUser(arg, it->second, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool SendMessageFunction(const SGCONF::CONFIG & config,
- const std::string & /*arg*/,
- const std::map<std::string, std::string> & options)
-{
-std::map<std::string, std::string>::const_iterator it(options.find("logins"));
-if (it == options.end())
- throw SGCONF::ACTION::ERROR("Logins are not specified.");
-std::string logins = it->second;
-for (size_t i = 0; i < logins.length(); ++i)
- if (logins[i] == ',')
- logins[i] = ':';
-it = options.find("text");
-if (it == options.end())
- throw SGCONF::ACTION::ERROR("Message text is not specified.");
-std::string text = it->second;
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.SendMessage(logins, text, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AuthByFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.AuthBy(arg, AuthByCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetUserParams());
-blocks.Add("User management options")
- .Add("get-users", SGCONF::MakeAPIAction(commands, GetUsersFunction), "\tget user list")
- .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", GetUserFunction), "get user")
- .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", params, AddUserFunction), "add user")
- .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", DelUserFunction), "delete user")
- .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", params, ChgUserFunction), "change user")
- .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", GetCheckParams(), CheckUserFunction), "check user existance and credentials")
- .Add("send-message", SGCONF::MakeAPIAction(commands, GetMessageParams(), SendMessageFunction), "send message")
- .Add("auth-by", SGCONF::MakeAPIAction(commands, "<login>", AuthByFunction), "a list of authorizers user authorized by");
-}
+++ /dev/null
-#ifndef __STG_SGCONF_USERS_H__
-#define __STG_SGCONF_USERS_H__
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-}
-
-#endif
+++ /dev/null
-#ifndef __STG_SGCONF_UTILS_H__
-#define __STG_SGCONF_UTILS_H__
-
-#include "stg/common.h"
-#include "stg/resetable.h"
-
-#include <string>
-#include <map>
-
-namespace SGCONF
-{
-
-template <typename T>
-inline
-void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
- return;
-T value;
-if (str2x(it->second, value) < 0)
- return;
-res = value;
-}
-
-template <typename T, typename F>
-inline
-void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, T & res, F conv)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
- return;
-conv(it->second, res);
-}
-
-template <>
-inline
-void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<std::string> & res)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
- return;
-res = it->second;
-}
-
-} // namespace SGCONF
-
-#endif
+++ /dev/null
-#include "xml.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-
-#include "stg/servconf.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-#include <expat.h>
-
-namespace
-{
-
-struct ParserState
-{
-size_t level;
-};
-
-std::string Indent(size_t level)
-{
-return std::string(level * 4, ' ');
-}
-
-std::string PrintAttr(const char ** attr)
-{
-std::string res;
-if (attr == NULL)
- return res;
-while (*attr)
- {
- if (*(attr + 1) == NULL)
- return res;
- res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
- ++attr; ++attr;
- }
-return res;
-}
-
-void Start(void * data, const char * el, const char ** attr)
-{
-ParserState * state = static_cast<ParserState *>(data);
-if (el != NULL)
- std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
-++state->level;
-}
-
-void End(void * data, const char * el)
-{
-ParserState * state = static_cast<ParserState *>(data);
---state->level;
-if (el != NULL)
- std::cout << Indent(state->level) << "</" << el << ">\n";
-}
-
-void PrintXML(const std::string& xml)
-{
-ParserState state = { 0 };
-
-XML_Parser parser = XML_ParserCreate(NULL);
-XML_ParserReset(parser, NULL);
-XML_SetElementHandler(parser, Start, End);
-XML_SetUserData(parser, &state);
-
-if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
- std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
- << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
- << std::endl;
-
-XML_ParserFree(parser);
-}
-
-void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
-{
-if (!result)
- {
- std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
- return;
- }
-PrintXML(response);
-}
-
-bool RawXMLFunction(const SGCONF::CONFIG & config,
- const std::string & arg,
- const std::map<std::string, std::string> & /*options*/)
-{
-STG::SERVCONF proto(config.server.data(),
- config.port.data(),
- config.localAddress.data(),
- config.localPort.data(),
- config.userName.data(),
- config.userPass.data());
-return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
-}
-
-}
-
-void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-blocks.Add("Raw XML")
- .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_XML_H__
-#define __STG_SGCONF_XML_H__
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-}
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.3 2008/05/11 09:30:43 nobunaga Exp $
-###############################################################################
-
-include ../../Makefile.conf
-
-PROG = sgconf_xml
-
-SRCS = ./main.cpp \
- ./parser.cpp
-
-STGLIBS = conffiles \
- 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) $(LIBICONV)
-
-ifeq ($(OS),linux)
-else
-LIBS += -lc
-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 += -Wl,-E $(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) $^ $(LIBS) $(LDFLAGS) -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
-
-uninstall: uninstall-bin uninstall-data
-
-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
+++ /dev/null
-Compiling:
-> ./build
-
+++ /dev/null
-#!/bin/sh
-
-# $Author: nobunaga $
-# $Revision: 1.2 $
-# $Date: 2008/01/05 12:11: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
- MAKE="gmake"
-fi
-
-if [ "$OS" = "unknown" ]
-then
- printf "#############################################################################\n"
- printf "# Sorry, but sgconf_xml is currently supported by Linux, FreeBSD and Darwin.#\n"
- printf "#############################################################################\n"
- exit 1
-fi
-
-printf "#############################################################################\n"
-printf " Building sgconf_xml 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
- 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 -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 <iconv.h>\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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
-$Revision: 1.2 $
-$Author: nobunaga $
-$Date: 2008/01/05 12:11:34 $
-*/
-
-#include "stg/common.h"
-#include "stg/netunit.h"
-#include "request.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-#define FN_LEN (512)
-#define REQ_STR_LEN (300)
-char fileName[FN_LEN];
-char strReq[2048];
-
-int ParseReply(void * data, list<string> * ans);
-
-struct option long_options[] = {
-{"server", 1, 0, 's'}, //Server
-{"port", 1, 0, 'p'}, //Port
-{"admin", 1, 0, 'a'}, //Admin
-{"admin_pass", 1, 0, 'w'}, //passWord
-{"file", 1, 0, 'f'}, //File
-{"strreq", 1, 0, 'r'}, //String request
-{0, 0, 0, 0}};
-
-//-----------------------------------------------------------------------------
-int CheckLogin(const char * login)
-{
-for (int i = 0; i < (int)strlen(login); i++)
- {
- if (!(( login[i] >= 'a' && login[i] <= 'z')
- || (login[i] >= 'A' && login[i] <= 'Z')
- || (login[i] >= '0' && login[i] <= '9')
- || login[i] == '_'
- || login[i] == '-'))
- {
- return 1;
- }
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-short int ParseServerPort(const char * p)
-{
-int port;
-if (str2x(p, port) != 0)
- {
- printf("Incorresct server port %s\n", p);
- exit(NETWORK_ERR_CODE);
- }
-return(short)port;
-}
-//-----------------------------------------------------------------------------
-char * ParseAdminLogin(char * adm)
-{
-if (CheckLogin(adm))
- {
- printf("Incorrect admin login %s\n", adm);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-return adm;
-}
-//-----------------------------------------------------------------------------
-char * ParsePassword(char * pass)
-{
-if (strlen(pass) >= ADM_PASSWD_LEN)
- {
- printf("Password too big %s\n", pass);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return pass;
-}
-//-----------------------------------------------------------------------------
-void CreateRequest(REQUEST * req, char * r)
-{
-r[0] = 0;
-
-if (!req->strReq.empty())
- {
- char str[10024];
- sprintf(str, "%s", req->strReq.const_data().c_str());
- strcat(r, str);
- return;
- } else
- {
- FILE *f = fopen(fileName, "rt");
- if (!f)
- {
- printf("Can't open request file\n");
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
- char ts[REQ_STR_LEN];
- while (fgets(ts, REQ_STR_LEN, f))
- {
- strncat(r, ts, REQ_STR_LEN);
- }
- fclose(f);
- }
-}
-//-----------------------------------------------------------------------------
-int Process(REQUEST * r)
-{
-int ret;
-char str[2048];
-
-NETTRANSACT nt;
-nt.SetServer(r->server.const_data().c_str());
-nt.SetServerPort(r->port.const_data());
-nt.SetLogin(r->admLogin.const_data().c_str());
-nt.SetPassword(r->admPasswd.const_data().c_str());
-nt.SetRxCallback(NULL, ParseReply);
-
-CreateRequest(r, str);
-
-if ((ret = nt.Connect()) != st_ok)
- {
- printf("%s\n", nt.GetError().c_str());
- return ret;
- }
-if ((ret = nt.Transact(str)) != st_ok)
- {
- printf("%s\n", nt.GetError().c_str());
- return ret;
- }
-if ((ret = nt.Disconnect()) != st_ok)
- {
- printf("%s\n", nt.GetError().c_str());
- return ret;
- }
-
-printf("<!-- Ok -->\n");
-return 0;
-}
-//-----------------------------------------------------------------------------
-int CheckParameters(REQUEST * req)
-{
-int a = !req->admLogin.empty()
- && !req->admPasswd.empty()
- && !req->server.empty()
- && !req->port.empty();
-
-int b = !req->fileReq.empty()
- || !req->strReq.empty();
-
-return a && b;
-}
-//-----------------------------------------------------------------------------
-void Usage()
-{
-printf("Sgconf version: 1.05.9_XML\n\n");
-
-printf("Use: sgconf -s <server> -p <port> -a <admin> -w <admin_pass> -r <request_string>\n");
-printf("Use: sgconf -s <server> -p <port> -a <admin> -w <admin_pass> -f <request_file>\n\n");
-
-printf("Request file or string content:\n\n");
-
-printf(" <GetServerInfo/>\n\n");
-
-printf(" <GetTariffs/>\n");
-printf(" <AddTariff name=\"NEW_TARIFF\"/>\n");
-printf(" <DelTariff name=\"DELETED_TARIFF\"/>\n\n");
-
-printf(" <SetTariff name=\"TARIFF\"/>\n");
-printf(" <Time[0...9] value=\"HH:MM-HH:MM\"/> Day-Night time for each DIR\n");
-printf(" <PriceDayA value=\"PriceDayA0/PriceDayA1/PriceDayA2/PriceDayA3/PriceDayA4/PriceDayA5/PriceDayA6/PriceDayA7/PriceDayA8/PriceDayA9\"/>\n");
-printf(" <PriceDayB value=\"PriceDayB0/PriceDayB1/PriceDayB2/PriceDayB3/PriceDayB4/PriceDayB5/PriceDayB6/PriceDayB7/PriceDayB8/PriceDayB9\"/>\n");
-printf(" <PriceNightA value=\"PriceNightA0/PriceNightA1/PriceNightA2/PriceNightA3/PriceNightA4/PriceNightA5/PriceNightA6/PriceNightA7/PriceNightA8/PriceNightA9\"/>\n");
-printf(" <PriceNightB value=\"PriceNightB0/PriceNightB1/PriceNightB2/PriceNightB3/PriceNightB4/PriceNightB5/PriceNightB6/PriceNightB7/PriceNightB8/PriceNightB9\"/>\n");
-printf(" <SinglePrice value=\"SinglePrice0/SinglePrice1/SinglePrice2/SinglePrice3/SinglePrice4/SinglePrice5/SinglePrice6/SinglePrice7/SinglePrice8/SinglePrice9\"/>\n");
-printf(" <NoDiscount value=\"NoDiscount0/NoDiscount1/NoDiscount2/NoDiscount3/NoDiscount4/NoDiscount5/NoDiscount6/NoDiscount7/NoDiscount8/NoDiscount9\"/>\n");
-printf(" <Threshold value=\"NEW_Threshold\"/>\n");
-printf(" <Fee value=\"NEW_Fee\"/>\n");
-printf(" <PassiveCost value=\"NEW_PassiveCost\"/>\n");
-printf(" <Free value=\"NEW_Free\"/>\n");
-printf(" <TraffType value=\"NEW_TraffType\"/> New TraffType value: [up|down|up+down|max]\n");
-printf(" </SetTariff/>\n\n");
-
-printf(" <GetAdmins/>\n");
-printf(" <AddAdmin login=\"LOGIN\"/>\n");
-printf(" <DelAdmin login=\"LOGIN\"/>\n");
-printf(" <ChgAdmin login=\"LOGIN\" priv=\"NEW_PRIV\" password=\"NEW_PASSWORD\"/>\n\n");
-
-printf(" <GetUsers/>\n");
-printf(" <GetUser login=\"LOGIN\"/>\n");
-printf(" <AddUser login=\"LOGIN\"/>\n");
-printf(" <DelUser login=\"LOGIN\"/>\n");
-printf(" <CheckUser login=\"LOGIN\" password=\"PASSWORD\"/> Checking login and password in database. Return Ok or Err.\n\n");
-
-printf(" <SetUser>\n");
-printf(" <login value=\"LOGIN\" />\n");
-printf(" <ip value=\"NEW_IP\" />\n");
-printf(" <password value=\"NEW_Password\" />\n");
-printf(" <tariff [ delayed | now ]=\"NEW_Tariff\" /> delayed - change tariff from 1st day of new month; now - change tariff NOW.\n");
-printf(" <group value=\"NEW_Group\" /> Encode12() -> value\n");
-printf(" <name value=\"NEW_RealName\" /> Encode12() -> value\n");
-printf(" <address value=\"NEW_Address\" /> Encode12() -> value\n");
-printf(" <phone value=\"NEW_Phone\" /> Encode12() -> value\n");
-printf(" <email value=\"NEW_Email\" /> Encode12() -> value\n");
-printf(" <note value=\"NEW_Note\" /> Encode12() -> value\n");
-printf(" <userdata[0...9] value=\"NEW_Userdata[0...9]\" /> Encode12() -> value\n");
-printf(" <cash [ add | set ]=\"Cash\" msg=\"MESSAGE\" /> add - add money on account; set - set money on account; Message - message for log\n");
-printf(" <credit value=\"NEW_Credit\" />\n");
-printf(" <CreditExpire value=\"NEW_CreditExpire\" />\n");
-printf(" <freemb value=\"NEW_FreeMB\" />\n");
-printf(" <aonline value=\"AlwaysOnline\" /> 1 - turn ON AlwaysOnline; 0 - turn OFF AlwaysOnline\n");
-printf(" <down value=\"Down\" /> 1 - turn ON Down; 0 - turn OFF Down\n");
-printf(" <passive value=\"Passive\" /> 1 - turn ON Passive; 0 - turn OFF Passive\n");
-printf(" <traff MU[0...9]=\"NEW_MU[0...9]\" MD[0...9]=\"NEW_MD[0...9]\" /> MU[0...9] - Set upload traffic value; MU[0...9] - Set download traffic value; \n");
-printf(" </SetUser>\n\n");
-
-printf(" <Message login=\"LOGIN\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"MESSAGE\" />\n");
-}
-//---------------------------------------------------------------------------
-int main(int argc, char **argv)
-{
-REQUEST req;
-
-while (1)
- {
- int option_index = -1;
-
- int c = getopt_long(argc, argv, "s:p:a:w:f:r:", long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 's': //server
- req.server = optarg;
- break;
-
- case 'p': //port
- req.port = ParseServerPort(optarg);
- break;
-
- case 'a': //admin
- req.admLogin = ParseAdminLogin(optarg);
- break;
-
- case 'w': //admin password
- req.admPasswd = ParsePassword(optarg);
- break;
-
- case 'f': //file
- strcpy(fileName,optarg);
- req.fileReq = 1;
- break;
-
- case 'r': //string request
- req.strReq = optarg;
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
-if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (CheckParameters(&req) == 0)
- {
- Usage();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-Process(&req);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-#include "stg/common.h"
-#include "stg/netunit.h"
-#include "request.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <expat.h>
-#include <string.h>
-
-int parse_depth = 0;
-XML_Parser parser;
-//---------------------------------------------------------------------------
-int ParseAns(void *, const char *el, const char **attr)
-{
-if (strcasecmp(el, "ServerInfo") == 0 || strcasecmp(el, "Tariffs") == 0 || strcasecmp(el, "Admins") == 0 || strcasecmp(el, "Users") == 0 || strcasecmp(el, "user") == 0)
- {
- return 0;
- }
-if (strcasecmp(attr[1], "ok") == 0)
- {
- return 0;
- }
-if (strcasecmp(attr[1], "error") == 0)
- {
- return 1;
- }
-if (strcasecmp(attr[1], "err") == 0)
- {
- return 1;
- }
-return -1;
-}
-//---------------------------------------------------------------------------
-void StartElement(void *data, const char *el, const char **attr)
-{
-if (strcasecmp(el, "ServerInfo") == 0 || strcasecmp(el, "Tariffs") == 0 || strcasecmp(el, "Admins") == 0 || strcasecmp(el, "Users") == 0)
- {
- printf ("<%s>\n", el);
- return;
- }
-
-if (strcasecmp(el, "tariff") == 0)
- {
- if (strcasecmp(attr[0], "name") == 0)
- {
- printf ("<%s %s=\"%s\">\n", el, attr[0], attr[1]);
- printf ("<%s>%s</%s>\n", attr[0], attr[1], attr[0]);
- }
- else
- {
- printf ("<%s>%s", el, attr[1]);
- }
- return;
- }
-
-if (strcasecmp(el, "admin") == 0)
- {
- printf ("<%s %s=\"%s\">\n", el, attr[0], attr[1]);
- int i = 0;
- while (attr[i])
- {
- printf ("<%s>%s</%s>\n", attr[i], attr[i+1], attr[i]);
- i+=2;
- }
- printf ("</admin>\n");
- return;
- }
-
-if (strcasecmp(el, "user") == 0)
- {
- if (strcasecmp(attr[0], "login") == 0)
- {
- printf ("<%s %s=\"%s\">\n", el, attr[0], attr[1]);
- printf ("<%s>%s</%s>\n", attr[0], attr[1], attr[0]);
- }
- else
- {
- printf ("<%s>\n", el);
- }
- return;
- }
-
-if (strncasecmp(el, "dir_name_", 9) == 0 || strcasecmp(el, "address") == 0 || strcasecmp(el, "email") == 0 || strcasecmp(el, "group") == 0 || strcasecmp(el, "note") == 0 || strcasecmp(el, "phone") == 0 || strcasecmp(el, "name") == 0 || strncasecmp(el, "UserData", 8) == 0)
- {
- char * str_tmp;
- str_tmp = new char[strlen(attr[1]) + 1];
- Decode21(str_tmp, attr[1]);
- printf ("<%s>%s</%s>\n", el, str_tmp, el);
- delete[] str_tmp;
- return;
- }
-
-if (strcasecmp(el, "traff") == 0)
- {
- int j = 0;
- while (attr[j])
- {
- uint64_t t;
- str2x(attr[j+1], t);
- printf ("<%s>%lld</%s>\n", attr[j], t, attr[j]);
- j+=2;
- }
- return;
- }
-else
- {
- printf ("<%s>%s</%s>\n", el, attr[1], el);
- return;
- }
-parse_depth++;
-if (parse_depth == 1)
- {
- if (ParseAns(data, el, attr) < 0)
- {
- printf("Unexpected token\n");
- exit(UNKNOWN_ERR_CODE);
- }
- if (ParseAns(data, el, attr) == 1)
- {
- printf("User not found\n");
- exit(USER_NOT_FOUND_ERR_CODE);
- }
- return;
- }
-}
-//-----------------------------------------------------------------------------
-void EndElement(void *, const char *el)
-{
-parse_depth--;
-if (strcasecmp(el, "ServerInfo") == 0 ||
- strcasecmp(el, "Tariffs") == 0 ||
- strcasecmp(el, "Admins") == 0 ||
- strcasecmp(el, "Users") == 0 ||
- strcasecmp(el, "tariff") == 0 ||
- strcasecmp(el, "user") == 0)
- printf ("</%s>\n", el);
-}
-//---------------------------------------------------------------------------
-int ParseReply(void *, list<string> * ans)
-{
-int done = 0;
-
-parse_depth = 0;
-parser = XML_ParserCreate(NULL);
-
-if (!parser)
- {
- printf("Couldn't allocate memory for parser\n");
- exit(UNKNOWN_ERR_CODE);
- }
-
-XML_ParserReset(parser, NULL);
-XML_SetElementHandler(parser, StartElement, EndElement);
-
-list<string>::iterator n = ans->begin();
-while (n != ans->end())
- {
- int len = strlen(n->c_str());
-
- if (++n == ans->end())
- done = 1;
- --n;
-
- if (XML_Parse(parser, n->c_str(), len, done) == XML_STATUS_ERROR)
- {
- printf("Parse error at line %d: %s",
- XML_GetCurrentLineNumber(parser),
- XML_ErrorString(XML_GetErrorCode(parser)));
- return st_xml_parse_error;
- }
-
- ++n;
- }
-XML_ParserFree(parser);
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@ua.fm>
- */
-
- /*
- $Revision: 1.1 $
- $Date: 2007/12/29 17:24:07 $
- */
-
-#ifndef request_h
-#define request_h
-
-#include <string>
-
-#include "stg/resetable.h"
-#include "stg/os_int.h"
-#include "stg/const.h"
-
-#ifndef ENODATA
-#define ENODATA 61
-#endif
-
-#ifndef EBADMSG
-#define EBADMSG 74
-#endif
-
-#define NETWORK_ERR_CODE (1)
-#define LOGIN_OR_PASS_ERR_CODE (2)
-#define USER_NOT_FOUND_ERR_CODE (3)
-#define TARIFF_NOT_FOUND_ERR_CODE (4)
-#define PARAMETER_PARSING_ERR_CODE (5)
-#define UNKNOWN_ERR_CODE (6)
-
-using namespace std;
-//-----------------------------------------------------------------------------
-struct REQUEST
-{
-RESETABLE<string> server;
-RESETABLE<short> port;
-RESETABLE<string> admLogin;
-RESETABLE<string> admPasswd;
-RESETABLE<int> fileReq;
-RESETABLE<string> strReq;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-<GetUser login="uz-000-012" />
\ No newline at end of file
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.12 2009/03/03 15:49:34 faust Exp $
-###############################################################################
-
-include ../../Makefile.conf
-
-PROG = sgconv
-
-SRCS = ./main.cpp \
- ./settings_impl.cpp
-
-STGLIBS = dotconfpp \
- 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)
-
-ifeq ($(OS),linux)
-LIBS += -ldl
-else
-LIBS += -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)
-
-ifneq ($(OS),darwin)
-LDFLAGS += -Wl,-E
-endif
-
-LDFLAGS += $(STGLIBS_LIBS)
-
-.PHONY: all clean distclean libs plugins install uninstall
-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 tags *.*~ .OS
- rm -f .OS
- rm -f .store
- rm -f .db.sql
- rm -f core*
- $(MAKE) -C $(DIR_LIBSRC) clean
- $(MAKE) -C $(DIR_PLUGINS) clean
-
-distclean: clean
- rm -f ../../Makefile.conf
-
-install: install-bin
-
-install-bin:
-ifeq ($(DEBUG), yes)
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/bin
- install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/bin/$(PROG)
-else
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/bin
- install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/bin/$(PROG)
-endif
- $(MAKE) -C $(DIR_PLUGINS) install
-
-uninstall: uninstall-bin
-
-uninstall-bin:
- rm -f $(PREFIX)/usr/bin/$(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
+++ /dev/null
-#!/bin/sh
-
-# $Revision: 1.20 $
-# $Author: faust $
-# $Date: 2010/04/14 08:58:43 $
-######################################################
-
-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
-VAR_DIR="./inst/var/stargazer"
-
-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 -ggdb3 -W -Wall -I/usr/local/include"
-CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -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 sgconv is currently supported by Linux, FreeBSD and Darwin. #\n"
- printf "#############################################################################\n"
- exit 1
-fi
-
-printf "#############################################################################\n"
-printf " Building sgconv 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
- 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 -L/usr/lib/mysql -L/usr/local/lib/mysql 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 <iconv.h>\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
-
-printf "Checking for mysql_config... "
-printf "#include <mysql.h>\nint main() { return 0; }\n" > build_check.c
-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 <libpq-fe.h>\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 "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
-printf "VAR_DIR=$VAR_DIR\n" >> $CONFFILE
-
-mkdir -p ../stargazer/modules
-
-if [ "$1" != "debug" ]
-then
- $MAKE $MAKEOPTS
-else
- printf "\n\n\nDebug build. Type $MAKE explicitly\n"
-fi
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.11 $
- $Date: 2010/03/25 12:32:30 $
- $Author: faust $
- */
-
-#include <dlfcn.h>
-
-#include <string>
-#include <vector>
-#include <iostream>
-#include <ctime>
-#include <algorithm>
-
-#include "stg/common.h"
-#include "stg/store.h"
-#include "stg/conffiles.h"
-
-#include "stg/user_stat.h"
-#include "stg/user_conf.h"
-#include "stg/corp_conf.h"
-#include "stg/service_conf.h"
-#include "stg/admin_conf.h"
-#include "stg/tariff_conf.h"
-#include "stg/settings.h"
-#include "stg/message.h"
-
-#include "settings_impl.h"
-
-volatile time_t stgTime = time(NULL);
-
-int main(int argc, char **argv)
-{
-printfd(__FILE__, "Start\n");
-
-STORE * fromStore = NULL;
-STORE * toStore = NULL;
-
-SETTINGS_IMPL * settings = NULL;
-
-std::string modulePath;
-
-MODULE_SETTINGS fromStoreSettings;
-MODULE_SETTINGS toStoreSettings;
-
-ADMIN_CONF ac;
-USER_CONF uc;
-USER_STAT us;
-STG_MSG msg;
-TARIFF_DATA td;
-CORP_CONF cc;
-SERVICE_CONF sc;
-std::vector<STG_MSG_HDR> hdrs;
-
-if (argc == 2)
- settings = new SETTINGS_IMPL(argv[1]);
-else
- settings = new SETTINGS_IMPL();
-
-if (settings->ReadSettings())
- {
- printfd(__FILE__, "Error reading settings\n");
- delete settings;
- return -1;
- }
-
-fromStoreSettings = settings->GetSourceStoreModuleSettings();
-toStoreSettings = settings->GetDestStoreModuleSettings();
-modulePath = settings->GetModulesPath();
-
-std::string sourcePlugin(modulePath + "/mod_" + fromStoreSettings.moduleName + ".so");
-std::string destPlugin(modulePath + "/mod_" + toStoreSettings.moduleName + ".so");
-
-void * src_lh = dlopen(sourcePlugin.c_str(), RTLD_NOW);
-if (!src_lh)
- {
- printfd(__FILE__, "Source storage plugin loading failed: %s\n", dlerror());
- delete settings;
- return -1;
- }
-
-void * dst_lh = dlopen(destPlugin.c_str(), RTLD_NOW);
-if (!dst_lh)
- {
- printfd(__FILE__, "Destination storage plugin loading failed: %s\n", dlerror());
- delete settings;
- return -1;
- }
-
-STORE * (*GetSourceStore)();
-STORE * (*GetDestStore)();
-GetSourceStore = (STORE * (*)())dlsym(src_lh, "GetStore");
-if (!GetSourceStore)
- {
- printfd(__FILE__, "Source storage plugin loading failed. GetStore not found: %s\n", dlerror());
- delete settings;
- return -1;
- }
-GetDestStore = (STORE * (*)())dlsym(dst_lh, "GetStore");
-if (!GetDestStore)
- {
- printfd(__FILE__, "Storage plugin (firebird) loading failed. GetStore not found: %s\n", dlerror());
- delete settings;
- return -1;
- }
-
-fromStore = GetSourceStore();
-toStore = GetDestStore();
-
-std::vector<std::string> entities;
-std::vector<std::string> ready;
-fromStore->SetSettings(fromStoreSettings);
-fromStore->ParseSettings();
-toStore->SetSettings(toStoreSettings);
-toStore->ParseSettings();
-
-printfd(__FILE__, "Importing admins:\n");
-entities.erase(entities.begin(), entities.end());
-ready.erase(ready.begin(), ready.end());
-if (fromStore->GetAdminsList(&entities))
- {
- printfd(__FILE__, "Error getting admins list: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-if (toStore->GetAdminsList(&ready))
- {
- printfd(__FILE__, "Error getting admins list: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-
-std::vector<std::string>::const_iterator it;
-for (it = entities.begin(); it != entities.end(); ++it)
- {
- printfd(__FILE__, "\t - %s\n", it->c_str());
- if (find(ready.begin(), ready.end(), *it) == ready.end())
- if (toStore->AddAdmin(*it))
- {
- printfd(__FILE__, "Error adding admin: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (fromStore->RestoreAdmin(&ac, *it))
- {
- printfd(__FILE__, "Error getting admin's confi: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- ac.login = *it;
- if (toStore->SaveAdmin(ac))
- {
- printfd(__FILE__, "Error saving admin's conf: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- }
-
-printfd(__FILE__, "Importing tariffs:\n");
-entities.erase(entities.begin(), entities.end());
-ready.erase(ready.begin(), ready.end());
-if (fromStore->GetTariffsList(&entities))
- {
- printfd(__FILE__, "Error getting tariffs list: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-if (toStore->GetTariffsList(&ready))
- {
- printfd(__FILE__, "Error getting tariffs list: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-
-for (it = entities.begin(); it != entities.end(); ++it)
- {
- printfd(__FILE__, "\t - %s\n", it->c_str());
- if (find(ready.begin(), ready.end(), *it) == ready.end())
- if (toStore->AddTariff(*it))
- {
- printfd(__FILE__, "Error adding tariff: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (fromStore->RestoreTariff(&td, *it))
- {
- printfd(__FILE__, "Error getting tariff's data: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (toStore->SaveTariff(td, *it))
- {
- printfd(__FILE__, "Error saving tariff's data: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- }
-
-printfd(__FILE__, "Importing services:\n");
-entities.erase(entities.begin(), entities.end());
-ready.erase(ready.begin(), ready.end());
-if (fromStore->GetServicesList(&entities))
- {
- printfd(__FILE__, "Error getting service list: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-if (toStore->GetServicesList(&ready))
- {
- printfd(__FILE__, "Error getting service list: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-
-for (it = entities.begin(); it != entities.end(); ++it)
- {
- printfd(__FILE__, "\t - %s\n", it->c_str());
- if (find(ready.begin(), ready.end(), *it) == ready.end())
- if (toStore->AddService(*it))
- {
- printfd(__FILE__, "Error adding service: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (fromStore->RestoreService(&sc, *it))
- {
- printfd(__FILE__, "Error getting service's data: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (toStore->SaveService(sc))
- {
- printfd(__FILE__, "Error saving service's data: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- }
-
-printfd(__FILE__, "Importing corporations:\n");
-entities.erase(entities.begin(), entities.end());
-ready.erase(ready.begin(), ready.end());
-if (fromStore->GetCorpsList(&entities))
- {
- printfd(__FILE__, "Error getting corporations list: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-if (toStore->GetCorpsList(&ready))
- {
- printfd(__FILE__, "Error getting corporations list: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-
-for (it = entities.begin(); it != entities.end(); ++it)
- {
- printfd(__FILE__, "\t - %s\n", it->c_str());
- if (find(ready.begin(), ready.end(), *it) == ready.end())
- if (toStore->AddCorp(*it))
- {
- printfd(__FILE__, "Error adding corporation: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (fromStore->RestoreCorp(&cc, *it))
- {
- printfd(__FILE__, "Error getting corporation's data: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (toStore->SaveCorp(cc))
- {
- printfd(__FILE__, "Error saving corporation's data: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- }
-
-printfd(__FILE__, "Importing users:\n");
-entities.erase(entities.begin(), entities.end());
-ready.erase(ready.begin(), ready.end());
-if (fromStore->GetUsersList(&entities))
- {
- printfd(__FILE__, "Error getting users list: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-if (toStore->GetUsersList(&ready))
- {
- printfd(__FILE__, "Error getting users list: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
-
-sort(ready.begin(), ready.end());
-for (it = entities.begin(); it != entities.end(); ++it)
- {
- printfd(__FILE__, "\t - %s\n", it->c_str());
- if (!binary_search(ready.begin(), ready.end(), *it)) {
- if (toStore->AddUser(*it))
- {
- printfd(__FILE__, "Error adding user: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- } else {
- printfd(__FILE__, "\t\t(adding passed)\n");
- }
- if (fromStore->RestoreUserConf(&uc, *it))
- {
- printfd(__FILE__, "Error getting user's conf: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (fromStore->RestoreUserStat(&us, *it))
- {
- printfd(__FILE__, "Error getting user's stat: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (toStore->SaveUserConf(uc, *it))
- {
- printfd(__FILE__, "Error saving user's conf: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- if (toStore->SaveUserStat(us, *it))
- {
- printfd(__FILE__, "Error saving user's stat: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- hdrs.erase(hdrs.begin(), hdrs.end());
- if (fromStore->GetMessageHdrs(&hdrs, *it))
- {
- printfd(__FILE__, "Error getting user's messages: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- std::vector<STG_MSG_HDR>::iterator mit;
- for (mit = hdrs.begin(); mit != hdrs.end(); ++mit)
- {
- if (fromStore->GetMessage(mit->id, &msg, *it))
- {
- printfd(__FILE__, "Error getting message for a user: %s\n", fromStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- printfd(__FILE__, "\t\t * %s\n", msg.text.c_str());
- if (toStore->AddMessage(&msg, *it))
- {
- printfd(__FILE__, "Error adding message to a user: %s\n", toStore->GetStrError().c_str());
- dlclose(src_lh);
- dlclose(dst_lh);
- delete settings;
- return -1;
- }
- }
- }
-
-dlclose(src_lh);
-dlclose(dst_lh);
-printfd(__FILE__, "Done\n");
-delete settings;
-return 0;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
-$Revision: 1.6 $
-$Date: 2009/06/22 16:26:54 $
-*/
-
-#include "stg/dotconfpp.h"
-#include "stg/module_settings.h"
-#include "stg/common.h"
-
-#include "settings_impl.h"
-
-int SETTINGS_IMPL::ParseModuleSettings(const DOTCONFDocumentNode * node, std::vector<PARAM_VALUE> * params)
-{
-if (!node)
- return 0;
-
-PARAM_VALUE pv;
-
-pv.param = node->getName();
-
-if (node->getValue(1))
- {
- strError = "Unexpected value \'" + std::string(node->getValue(1)) + "\'.";
- printfd(__FILE__, "SETTINGS_IMPL::ParseModuleSettings() - %s\n", strError.c_str());
- return -1;
- }
-
-const char * value = node->getValue(0);
-
-if (!value)
- {
- strError = "Module name expected.";
- printfd(__FILE__, "SETTINGS_IMPL::ParseModuleSettings() - %s\n", strError.c_str());
- return -1;
- }
-
-const DOTCONFDocumentNode * childNode = node->getChildNode();
-while (childNode)
- {
- pv.param = childNode->getName();
- int i = 0;
- while ((value = childNode->getValue(i)) != NULL)
- {
- pv.value.push_back(value);
- ++i;
- }
- params->push_back(pv);
- pv.value.clear();
- childNode = childNode->getNextNode();
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int SETTINGS_IMPL::ReadSettings()
-{
-const char * requiredOptions[] = {
- "ModulesPath",
- "SourceStoreModule",
- "DestStoreModule",
- NULL
- };
-int sourceStoreModulesCount = 0;
-int destStoreModulesCount = 0;
-
-DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
-conf.setRequiredOptionNames(requiredOptions);
-
-if(conf.setContent(confFile.c_str()) != 0)
- {
- strError = "Cannot read file " + confFile + ".";
- printfd(__FILE__, "SETTINGS_IMPL::ReadSettings() - %s\n", strError.c_str());
- return -1;
- }
-
-const DOTCONFDocumentNode * node = conf.getFirstNode();
-
-while (node)
- {
- if (strcasecmp(node->getName(), "ModulesPath") == 0)
- {
- modulesPath = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "SourceStoreModule") == 0)
- {
- if (node->getValue(1))
- {
- strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
- printfd(__FILE__, "SETTINGS_IMPL::ReadSettings() - %s\n", strError.c_str());
- return -1;
- }
-
- if (sourceStoreModulesCount)
- {
- strError = "Should be only one source StoreModule.";
- printfd(__FILE__, "SETTINGS_IMPL::ReadSettings() - %s\n", strError.c_str());
- return -1;
- }
- ++sourceStoreModulesCount;
-
- sourceStoreModuleSettings.moduleName = node->getValue(0);
- ParseModuleSettings(node, &sourceStoreModuleSettings.moduleParams);
- }
-
- if (strcasecmp(node->getName(), "DestStoreModule") == 0)
- {
- if (node->getValue(1))
- {
- strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
- printfd(__FILE__, "SETTINGS_IMPL::ReadSettings() - %s\n", strError.c_str());
- return -1;
- }
-
- if (destStoreModulesCount)
- {
- strError = "Should be only one dest StoreModule.";
- printfd(__FILE__, "SETTINGS_IMPL::ReadSettings() - %s\n", strError.c_str());
- return -1;
- }
- ++destStoreModulesCount;
-
- destStoreModuleSettings.moduleName = node->getValue(0);
- ParseModuleSettings(node, &destStoreModuleSettings.moduleParams);
- }
-
- node = node->getNextNode();
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
- /*
- $Revision: 1.6 $
- $Date: 2009/06/22 16:26:54 $
- */
-
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#ifndef SETTINGS_IMPL_H
-#define SETTINGS_IMPL_H
-
-#include <string>
-#include <vector>
-
-struct MODULE_SETTINGS;
-class DOTCONFDocumentNode;
-
-class SETTINGS_IMPL {
-public:
- SETTINGS_IMPL() : confFile("./sgconv.conf") {}
- explicit SETTINGS_IMPL(const std::string & cf) : confFile(cf) {}
- ~SETTINGS_IMPL() {}
- int ReadSettings();
-
- std::string GetStrError() const { return strError; }
-
- const std::string & GetConfDir() const;
-
- const std::string & GetModulesPath() const { return modulesPath; }
- const MODULE_SETTINGS & GetSourceStoreModuleSettings() const { return sourceStoreModuleSettings; }
- const MODULE_SETTINGS & GetDestStoreModuleSettings() const { return destStoreModuleSettings; }
-
-private:
- int ParseModuleSettings(const DOTCONFDocumentNode * dirNameNode, std::vector<PARAM_VALUE> * params);
-
- std::string strError;
- std::string modulesPath;
- std::string confFile;
-
- MODULE_SETTINGS sourceStoreModuleSettings;
- MODULE_SETTINGS destStoreModuleSettings;
-};
-
-#endif
+++ /dev/null
-################################################################################
-# Stargazer Convertor Configuration file #
-################################################################################
-
-# The path to directory with server modules
-# Parameter: required
-# Value: directory path
-# Default: /usr/lib/stg
-ModulesPath = /usr/lib/stg
-
-#################################################################################
-Store module
-# Configure the module that works with the database server
-# Option - the name of the module without 'mod_' at the beginning and '.so'
-# in the end ie full name of the module mod_store_files.so
-<SourceStoreModule store_files>
-
- # Working server directory, provides data on tariffs, users, administrators.
- # Parameter: required
- # Value: directory path
- WorkDir = /var/stargazer
-
- # Owner, group and permissions of the files of user statistics (stat)
- # Parameter: required
- # Values: any, supported by OS
- ConfOwner = root
- ConfGroup = root
- ConfMode = 600
-
- # Owner, group and permissions on user configuration files (conf)
- # Parameter: required
- # Values: any, supported by OS
- StatOwner = root
- StatGroup = root
- StatMode = 640
-
- # Owner, group and permissions for user log files (log)
- # Parameter: required
- # Values: any, supported by OS
- UserLogOwner = root
- UserLogGroup = root
- UserLogMode = 640
-
-</SourceStoreModule>
-
-#<DestStoreModule store_firebird>
- # Database server address
- # Parameter: required
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Path to the database on the server or its alias
- # Parameter: required
- # Value: file path
- # Default: /var/stg/stargazer.fdb
- # Database = /var/stg/stargazer.fdb
-
- # Database username
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: required
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-#</DestStoreModule>
-
-<DestStoreModule store_postgresql>
- # Database server address
- # Parameter: required
- # Value: IP address or DNS name
- # Default: localhost
- Server = localhost
-
- # Database name
- # Parameter: required
- # Value: any, supported by database
- # Default: stargazer
- Database = stargazer
-
- # Database username
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- User = stg
-
- # Database password
- # Parameter: required
- # Value: any, supported by database
- # Default: 123456
- Password = 123456
-
-</DestStoreModule>
-
-#<DestStoreModule store_mysql>
- # Database server address
- # Parameter: required
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Database name
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- # Database = stg
-
- # Database username
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: required
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-
-#</DestStoreModule>
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.50 2010/10/07 18:27:27 faust Exp $
-###############################################################################
-
-include ../../Makefile.conf
-
-PROG = stargazer
-
-SRCS = ./admin_impl.cpp \
- ./admins_impl.cpp \
- ./corps_impl.cpp \
- ./eventloop.cpp \
- ./main.cpp \
- ./pidfile.cpp \
- ./plugin_runner.cpp \
- ./plugin_mgr.cpp \
- ./settings_impl.cpp \
- ./services_impl.cpp \
- ./stg_timer.cpp \
- ./store_loader.cpp \
- ./tariff_impl.cpp \
- ./tariffs_impl.cpp \
- ./traffcounter_impl.cpp \
- ./user_impl.cpp \
- ./user_property.cpp \
- ./users_impl.cpp
-
-STGLIBS = scriptexecuter \
- dotconfpp \
- logger \
- 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 += -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)
-
-ifneq ($(OS),darwin)
-LDFLAGS += -Wl,-E
-endif
-
-LDFLAGS += $(STGLIBS_LIBS)
-
-.PHONY: all clean distclean libs plugins install uninstall install-bin install-data
-all: libs plugins $(PROG)
-
-libs:
- $(MAKE) -C $(DIR_LIBSRC)
-
-plugins: libs
- $(MAKE) -C $(DIR_PLUGINS)
-
-$(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
- $(MAKE) -C $(DIR_PLUGINS) clean
-
-distclean: clean
- rm -f $(DIR_MOD)/*
- rm -f ../../Makefile.conf
-
-install: install-bin install-data
-
-install-bin: $(PROG)
-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_INCLUDE) install
- $(MAKE) -C $(DIR_LIBSRC) install
- $(MAKE) -C $(DIR_PLUGINS) install
-
-install-data:
- # Install etc
- mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer
- mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer/conf-available.d
- mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer/conf-enabled.d
- install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/stargazer.conf $(PREFIX)/etc/stargazer/stargazer.conf
- install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/conf-available.d/*.conf $(PREFIX)/etc/stargazer/conf-available.d
- ln -sf ../conf-available.d/mod_ao.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ao.conf
- ln -sf ../conf-available.d/mod_ia.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ia.conf
- ln -sf ../conf-available.d/mod_ping.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ping.conf
- ln -sf ../conf-available.d/mod_sg.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_sg.conf
- ln -sf ../conf-available.d/store_files.conf $(PREFIX)/etc/stargazer/conf-enabled.d/store_files.conf
-
-ifeq ($(OS),linux)
- ln -sf ../conf-available.d/mod_cap_ether.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_cap_ether.conf
-else
- ln -sf ../conf-available.d/mod_cap_bpf.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf
-endif
-
- install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/rules $(PREFIX)/etc/stargazer/rules
- install -m $(BIN_MODE) -o $(OWNER) $(ETC_DIR)/On* $(PREFIX)/etc/stargazer/
-
- # Install file db
- mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/admins
- mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/tariffs
- mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/users/test
- install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/admins/admin.adm $(PREFIX)/var/stargazer/admins/admin.adm
- install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/tariffs/tariff.tf $(PREFIX)/var/stargazer/tariffs/tariff.tf
- install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/conf $(PREFIX)/var/stargazer/users/test/conf
- install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/stat $(PREFIX)/var/stargazer/users/test/stat
-
-uninstall: uninstall-bin uninstall-data
-
-uninstall-bin:
- rm -f $(PREFIX)/usr/sbin/$(PROG)
- $(MAKE) -C $(DIR_LIBSRC) uninstall
- $(MAKE) -C $(DIR_PLUGINS) uninstall
- rm -rf $(PREFIX)/usr/lib/stg
-
-uninstall-data:
- # Uninstall etc
- rm -rf $(PREFIX)/etc/stargazer
- rm -rf $(PREFIX)/var/stargazer
-
-
-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
+++ /dev/null
-Инсталяция и запуск.
-1. > ./build
-2. > make install
-3. Правка конфигурационных файлов
-4. > stargazer
-
+++ /dev/null
-#ifndef __ACTIONS_H__
-#define __ACTIONS_H__
-
-// Usage:
-//
-// ACTIONS_LIST actionsList;
-// CLASS myClass;
-// DATA1 myData1;
-// DATA2 myData2;
-//
-// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
-// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
-//
-// actionsList.InvokeAll();
-
-#include <pthread.h>
-#include <list>
-#include <functional>
-
-// Generalized actor type - a method of some class with one argument
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-struct ACTOR
-{
-typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
-};
-
-// Abstract base action class for polymorphic action invocation
-class BASE_ACTION
-{
-public:
- virtual ~BASE_ACTION() {}
- virtual void Invoke() = 0;
-};
-
-// Concrete generalized action type - an actor with it's data and owner
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-class ACTION : public BASE_ACTION,
- public std::unary_function<ACTIVE_CLASS &, void>
-{
-public:
- ACTION(ACTIVE_CLASS & ac,
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
- DATA_TYPE d)
- : activeClass(ac), actor(a), data(d) {}
- void Invoke();
-private:
- ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
- ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
-
- ACTIVE_CLASS & activeClass;
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
- DATA_TYPE data;
-};
-
-// A list of an actions
-// All methods are thread-safe
-class ACTIONS_LIST : private std::list<BASE_ACTION *>
-{
-public:
- // Just a typedef for parent class
- typedef std::list<BASE_ACTION *> parent;
-
- // Initialize mutex
- ACTIONS_LIST();
- // Delete actions and destroy mutex
- virtual ~ACTIONS_LIST();
-
- parent::iterator begin();
- parent::iterator end();
- parent::const_iterator begin() const;
- parent::const_iterator end() const;
-
- bool empty() const;
- size_t size() const;
- void swap(ACTIONS_LIST & list);
-
- // Add an action to list
- template <class ACTIVE_CLASS, typename DATA_TYPE>
- void Enqueue(ACTIVE_CLASS & ac,
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
- DATA_TYPE d);
- // Invoke all actions in the list
- void InvokeAll();
-private:
- mutable pthread_mutex_t mutex;
-};
-
-#include "actions.inl.h"
-
-#endif
+++ /dev/null
-#ifndef __ACTIONS_INL_H__
-#define __ACTIONS_INL_H__
-
-#include <algorithm>
-
-#include "stg/locker.h"
-
-// Polymorphick action invocation
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-inline
-void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
-{
-(activeClass.*actor)(data);
-}
-
-inline
-ACTIONS_LIST::ACTIONS_LIST()
- : mutex()
-{
-pthread_mutex_init(&mutex, NULL);
-}
-
-// Delete all actions before deleting list
-inline
-ACTIONS_LIST::~ACTIONS_LIST()
-{
-
- {
- STG_LOCKER lock(&mutex);
-
- parent::iterator it(parent::begin());
- while (it != parent::end())
- {
- delete *it++;
- }
- }
-
-pthread_mutex_destroy(&mutex);
-}
-
-inline
-ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
-{
-STG_LOCKER lock(&mutex);
-return parent::begin();
-}
-
-inline
-ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
-{
-STG_LOCKER lock(&mutex);
-return parent::end();
-}
-
-inline
-ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
-{
-STG_LOCKER lock(&mutex);
-return parent::begin();
-}
-
-inline
-ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
-{
-STG_LOCKER lock(&mutex);
-return parent::end();
-}
-
-inline
-bool ACTIONS_LIST::empty() const
-{
-STG_LOCKER lock(&mutex);
-return parent::empty();
-}
-
-inline
-size_t ACTIONS_LIST::size() const
-{
-STG_LOCKER lock(&mutex);
-return parent::size();
-}
-
-inline
-void ACTIONS_LIST::swap(ACTIONS_LIST & list)
-{
-STG_LOCKER lock(&mutex);
-parent::swap(list);
-}
-
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-inline
-void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac,
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
- DATA_TYPE d)
-{
-STG_LOCKER lock(&mutex);
-push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
-}
-
-inline
-void ACTIONS_LIST::InvokeAll()
-{
-STG_LOCKER lock(&mutex);
-std::for_each(
- parent::begin(),
- parent::end(),
- std::mem_fun(&BASE_ACTION::Invoke)
-);
-}
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.13 $
- $Date: 2010/10/04 20:16:09 $
- $Author: faust $
- */
-
-#include "admin_impl.h"
-
-#include "stg/common.h"
-
-//-----------------------------------------------------------------------------
-ADMIN_IMPL::ADMIN_IMPL()
- : ip(0)
-{
-}
-//-----------------------------------------------------------------------------
-ADMIN_IMPL::ADMIN_IMPL(const ADMIN_CONF & ac)
- : conf(ac),
- ip(0)
-{
-}
-//-----------------------------------------------------------------------------
-ADMIN_IMPL::ADMIN_IMPL(const PRIV & priv,
- const std::string & login,
- const std::string & password)
- : conf(priv, login, password),
- ip(0)
-{
-}
-//-----------------------------------------------------------------------------
-ADMIN_IMPL & ADMIN_IMPL::operator=(const ADMIN_CONF & ac)
-{
-conf = ac;
-return *this;
-}
-//-----------------------------------------------------------------------------
-bool ADMIN_IMPL::operator==(const ADMIN_IMPL & rhs) const
-{
-return conf.login == rhs.conf.login;
-}
-//-----------------------------------------------------------------------------
-bool ADMIN_IMPL::operator!=(const ADMIN_IMPL & rhs) const
-{
-return conf.login != rhs.conf.login;
-}
-//-----------------------------------------------------------------------------
-bool ADMIN_IMPL::operator<(const ADMIN_IMPL & rhs) const
-{
-return conf.login < rhs.conf.login;
-}
-//-----------------------------------------------------------------------------
-bool ADMIN_IMPL::operator<=(const ADMIN_IMPL & rhs) const
-{
-return conf.login <= rhs.conf.login;
-}
-//-----------------------------------------------------------------------------
-std::string ADMIN_IMPL::GetIPStr() const
-{
-return inet_ntostring(ip);
-}
-//-----------------------------------------------------------------------------
-void ADMIN_IMPL::Print() const
-{
-printfd(__FILE__, "=======================================\n");
-printfd(__FILE__, "login %s\n", conf.login.c_str());
-printfd(__FILE__, "password %s\n", conf.password.c_str());
-printfd(__FILE__, "ChgConf %d\n", conf.priv.userConf);
-printfd(__FILE__, "ChgStat %d\n", conf.priv.userStat);
-printfd(__FILE__, "ChgCash %d\n", conf.priv.userCash);
-printfd(__FILE__, "UsrAddDel %d\n", conf.priv.userAddDel);
-printfd(__FILE__, "ChgAdmin %d\n", conf.priv.adminChg);
-printfd(__FILE__, "ChgTariff %d\n", conf.priv.tariffChg);
-printfd(__FILE__, "=======================================\n");
-}
-//-----------------------------------------------------------------------------
-const std::string ADMIN_IMPL::GetLogStr() const
-{
-return "Admin \'" + conf.login + "\', " + GetIPStr() + ":";
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.14 $
- $Date: 2010/10/04 20:15:43 $
- $Author: faust $
- */
-
-#ifndef ADMIN_IMPL_H
-#define ADMIN_IMPL_H
-
-#include "stg/admin.h"
-#include "stg/os_int.h"
-#include "stg/admin_conf.h"
-
-#include <string>
-
-class ADMIN_IMPL : public ADMIN {
-public:
- ADMIN_IMPL();
- explicit ADMIN_IMPL(const ADMIN_CONF & ac);
- ADMIN_IMPL(const PRIV & priv,
- const std::string & login,
- const std::string & password);
- virtual ~ADMIN_IMPL() {}
-
- ADMIN_IMPL & operator=(const ADMIN_CONF &);
- bool operator==(const ADMIN_IMPL & rhs) const;
- bool operator!=(const ADMIN_IMPL & rhs) const;
- bool operator<(const ADMIN_IMPL & rhs) const;
- bool operator<=(const ADMIN_IMPL & rhs) const;
-
- const std::string & GetPassword() const { return conf.password; }
- const std::string & GetLogin() const { return conf.login; }
- PRIV const * GetPriv() const { return &conf.priv; }
- uint32_t GetPrivAsInt() const { return conf.priv.ToInt(); }
- const ADMIN_CONF & GetConf() const { return conf; }
- void Print() const;
- uint32_t GetIP() const { return ip; }
- std::string GetIPStr() const;
- void SetIP(uint32_t v) { ip = v; }
- const std::string GetLogStr() const;
-
-private:
- ADMIN_CONF conf;
- uint32_t ip;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.15 $
- $Date: 2010/10/04 20:17:12 $
- $Author: faust $
- */
-
-#include "stg/common.h"
-#include "admins_impl.h"
-#include "admin_impl.h"
-
-#include <cerrno>
-#include <cassert>
-#include <algorithm>
-
-//-----------------------------------------------------------------------------
-ADMINS_IMPL::ADMINS_IMPL(STORE * st)
- : ADMINS(),
- stg(PRIV(0xFFFF), "@stargazer", ""),
- noAdmin(PRIV(0xFFFF), "NO-ADMIN", ""),
- data(),
- store(st),
- WriteServLog(GetStgLogger()),
- searchDescriptors(),
- handle(0),
- mutex(),
- strError()
-{
-pthread_mutex_init(&mutex, NULL);
-Read();
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::Add(const std::string & login, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->adminChg)
- {
- std::string s = admin->GetLogStr() + " Add administrator \'" + login + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-ADMIN_IMPL adm(PRIV(0), login, "");
-admin_iter ai(find(data.begin(), data.end(), adm));
-
-if (ai != data.end())
- {
- strError = "Administrator \'" + login + "\' cannot not be added. Administrator already exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-data.push_back(adm);
-
-if (store->AddAdmin(login) == 0)
- {
- WriteServLog("%s Administrator \'%s\' added.",
- admin->GetLogStr().c_str(), login.c_str());
- return 0;
- }
-
-strError = "Administrator \'" + login + "\' was not added. Error: " + store->GetStrError();
-WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::Del(const std::string & login, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->adminChg)
- {
- std::string s = admin->GetLogStr() + " Delete administrator \'" + login + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
-
-if (ai == data.end())
- {
- strError = "Administrator \'" + login + "\' cannot be deleted. Administrator does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-std::map<int, const_admin_iter>::iterator si;
-si = searchDescriptors.begin();
-while (si != searchDescriptors.end())
- {
- if (si->second == ai)
- (si->second)++;
- ++si;
- }
-
-data.remove(*ai);
-if (store->DelAdmin(login) < 0)
- {
- strError = "Administrator \'" + login + "\' was not deleted. Error: " + store->GetStrError();
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-WriteServLog("%s Administrator \'%s\' deleted.", admin->GetLogStr().c_str(), login.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::Change(const ADMIN_CONF & ac, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->adminChg)
- {
- std::string s = admin->GetLogStr() + " Change administrator \'" + ac.login + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), ac.login, "")));
-
-if (ai == data.end())
- {
- strError = "Administrator \'" + ac.login + "\' cannot be changed " + ". Administrator does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-*ai = ac;
-if (store->SaveAdmin(ac))
- {
- WriteServLog("Cannot write admin %s.", ac.login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
-
-WriteServLog("%s Administrator \'%s\' changed.",
- admin->GetLogStr().c_str(), ac.login.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::Read()
-{
-STG_LOCKER lock(&mutex);
-std::vector<std::string> adminsList;
-if (store->GetAdminsList(&adminsList) < 0)
- {
- WriteServLog(store->GetStrError().c_str());
- return -1;
- }
-
-for (unsigned int i = 0; i < adminsList.size(); i++)
- {
- ADMIN_CONF ac(PRIV(0), adminsList[i], "");
-
- if (store->RestoreAdmin(&ac, adminsList[i]))
- {
- WriteServLog(store->GetStrError().c_str());
- return -1;
- }
-
- data.push_back(ADMIN_IMPL(ac));
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool ADMINS_IMPL::Find(const std::string & l, ADMIN ** admin)
-{
-assert(admin != NULL && "Pointer to admin is not null");
-
-STG_LOCKER lock(&mutex);
-if (data.empty())
- {
- printfd(__FILE__, "No admin in system!\n");
- *admin = &noAdmin;
- return false;
- }
-
-admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), l, "")));
-
-if (ai != data.end())
- {
- *admin = &(*ai);
- return false;
- }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool ADMINS_IMPL::Exists(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-if (data.empty())
- {
- printfd(__FILE__, "no admin in system!\n");
- return true;
- }
-
-const_admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
-
-if (ai != data.end())
- return true;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool ADMINS_IMPL::Correct(const std::string & login, const std::string & password, ADMIN ** admin)
-{
-STG_LOCKER lock(&mutex);
-if (data.empty())
- {
- printfd(__FILE__, "no admin in system!\n");
- return true;
- }
-
-admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
-
-if (ai == data.end())
- {
- return false;
- }
-
-if (ai->GetPassword() != password)
- {
- return false;
- }
-
-*admin = &(*ai);
-
-return true;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::OpenSearch() const
-{
-STG_LOCKER lock(&mutex);
-handle++;
-searchDescriptors[handle] = data.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::SearchNext(int h, ADMIN_CONF * ac) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) == searchDescriptors.end())
- {
- WriteServLog("ADMINS. Incorrect search handle.");
- return -1;
- }
-
-if (searchDescriptors[h] == data.end())
- return -1;
-
-ADMIN_IMPL a = *searchDescriptors[h]++;
-
-*ac = a.GetConf();
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ADMINS_IMPL::CloseSearch(int h) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
- {
- searchDescriptors.erase(searchDescriptors.find(h));
- return 0;
- }
-
-WriteServLog("ADMINS. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.10 $
- $Date: 2010/10/04 20:17:12 $
- $Author: faust $
- */
-
-#ifndef ADMINS_IMPL_H
-#define ADMINS_IMPL_H
-
-#include "admin_impl.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/locker.h"
-#include "stg/store.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include <list>
-#include <map>
-#include <string>
-
-#include <pthread.h>
-
-class ADMINS_IMPL : private NONCOPYABLE, public ADMINS {
-public:
- explicit ADMINS_IMPL(STORE * st);
- virtual ~ADMINS_IMPL() {}
-
- int Add(const std::string & login, const ADMIN * admin);
- int Del(const std::string & login, const ADMIN * admin);
- int Change(const ADMIN_CONF & ac, const ADMIN * admin);
- const ADMIN * GetSysAdmin() const { return &stg; }
- const ADMIN * GetNoAdmin() const { return &noAdmin; }
- bool Find(const std::string & l, ADMIN ** admin);
- bool Exists(const std::string & login) const;
- bool Correct(const std::string & login,
- const std::string & password,
- ADMIN ** admin);
- const std::string & GetStrError() const { return strError; }
-
- size_t Count() const { return data.size(); }
-
- int OpenSearch() const;
- int SearchNext(int, ADMIN_CONF * ac) const;
- int CloseSearch(int) const;
-
-private:
- ADMINS_IMPL(const ADMINS_IMPL & rvalue);
- ADMINS_IMPL & operator=(const ADMINS_IMPL & rvalue);
-
- typedef std::list<ADMIN_IMPL>::iterator admin_iter;
- typedef std::list<ADMIN_IMPL>::const_iterator const_admin_iter;
-
- int Read();
-
- ADMIN_IMPL stg;
- ADMIN_IMPL noAdmin;
- std::list<ADMIN_IMPL> data;
- STORE * store;
- STG_LOGGER & WriteServLog;
- mutable std::map<int, const_admin_iter> searchDescriptors;
- mutable unsigned int handle;
- mutable pthread_mutex_t mutex;
- std::string strError;
-};
-
-#endif
+++ /dev/null
-#!/bin/sh
-
-# $Revision: 1.57 $
-# $Author: faust $
-# $Date: 2010/05/09 12:39:01 $
-######################################################
-
-# 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"
-VAR_DIR="./inst/var/stargazer"
-MIN_XMLRPCC_VERSION="1.06.27"
-XMLRPC_FEATURES="c++2 abyss-server"
-
-
-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
- ETC_DIR="./inst/linux/etc/stargazer"
- 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
- ETC_DIR="./inst/freebsd/etc/stargazer"
- 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 stargazer is currently supported by Linux, FreeBSD and Darwin. #\n"
- printf "#############################################################################\n"
- exit 1
-fi
-
-printf "#############################################################################\n"
-printf " Building STG 2.4 for $sys $release\n"
-printf "#############################################################################\n"
-
-STG_LIBS="logger.lib
- crypto.lib
- common.lib
- scriptexecuter.lib
- conffiles.lib
- pinger.lib
- dotconfpp.lib
- smux.lib"
-
-PLUGINS="authorization/ao
- authorization/inetaccess
- configuration/sgconfig
- other/ping
- other/rscript
- other/smux
- store/files
- capture/cap_nf"
-
-if [ "$OS" = "linux" ]
-then
- DEFS="$DEFS -DLINUX"
- PLUGINS="$PLUGINS
- capture/ether_linux"
- LIB_THREAD=-lpthread
-else
- LIBICONV="-liconv"
- if [ "$OS" = "bsd" ]
- then
- DEFS="$DEFS -DFREE_BSD"
- LIB_THREAD=-lc_r
- 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
- PLUGINS="$PLUGINS
- capture/ether_freebsd
- capture/divert_freebsd"
-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 <expat.h>\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 <iconv.h>\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
-
-
-printf "Checking for mysql_config... "
-printf "#include <mysql.h>\nint main() { return 0; }\n" > build_check.c
-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
- MYSQL_CFLAGS=""
- MYSQL_LDFLAGS="-lmysqlclient_r"
- 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 <libpq-fe.h>\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
-
-printf "Checking for xmlrpc-c-config... "
-printf "#include <xmlrpc-c/base.hpp>\nint main() { return 0; }\n" > build_check.c
-XMLRPCC_VERSION=`xmlrpc-c-config $XMLRPC_FEATURES --version 2> /dev/null`
-if [ $? != 0 ]
-then
- printf "no\n";
- printf "Checking for -lxmlrpc... "
- $CC $CFLAGS $LDFLAGS build_check.c -lxmlrpc $LIB_THREAD -o fake > /dev/null 2> /dev/null
- if [ $? != 0 ]
- then
- CHECK_XMLRPC=no
- printf "no\n"
- else
- CHECK_XMLRPC=yes
- printf "yes\n"
- fi
- rm -f fake
-elif [ "$XMLRPCC_VERSION" \< "$MIN_XMLRPCC_VERSION" ]
-then
- printf "no (need at least $MIN_XMLRPCC_VERSION, actual $XMLRPCC_VERSION)\n";
- CHECK_XMLRPC=no
-else
- printf "yes (version $XMLRPCC_VERSION)\n";
- printf "Checking for xmlrpc-c-config --cflags... "
- XMLRPC_CFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --cflags 2> /dev/null`
- if [ $? != 0 ]
- then
- CHECK_XMLRPC=no
- printf "no\n"
- else
- printf "[$XMLRPC_CFLAGS]\n"
- printf "Checking for xmlrpc-c-config --libs... "
- XMLRPC_LDFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --libs 2> /dev/null`
- if [ $? != 0 ]
- then
- CHECK_XMLRPC=no
- printf "no\n"
- else
- CHECK_XMLRPC=yes
- printf "[$XMLRPC_LDFLAGS]\n"
- fi
- fi
-fi
-
-printf "Checking for -lpcap... "
-printf "#include <pcap.h>\nint main() { return 0; }\n" > build_check.c
-$CC $CFLAGS $LDFLAGS build_check.c -lpcap -o fake > /dev/null 2> /dev/null
-if [ $? != 0 ]
-then
- CHECK_PCAP=no
- printf "no\n"
-else
- CHECK_PCAP=yes
- printf "yes\n"
-fi
-rm -f fake
-
-printf "Checking for -lnfnetlink... "
-printf "#include <stdint.h>\n#include <netinet/in.h>\n#include <linux/netfilter.h>\nint main() { return 0; }\n" > build_check.c
-$CC $CFLAGS $LDFLAGS build_check.c -lnfnetlink -o fake > /dev/null 2> /dev/null
-if [ $? != 0 ]
-then
- CHECK_NFNETLINK=no
- printf "no\n"
-else
- CHECK_NFNETLINK=yes
- NETLINK_LDFLAGS="-lnfnetlink"
- printf "yes\n"
-fi
-rm -f fake
-
-printf "Checking for -lnetfilter_queue... "
-printf "#include <stdint.h>\n#include <libnetfilter_queue/libnetfilter_queue.h>\nint main() { return 0; }\n" > build_check.c
-$CC $CFLAGS $LDFLAGS build_check.c -lnetfilter_queue -o fake > /dev/null 2> /dev/null
-if [ $? != 0 ]
-then
- CHECK_NFQ=no
- printf "no\n"
-else
- CHECK_NFQ=yes
- NFQ_LDFLAGS="-lnetfilter_queue"
- printf "yes\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"
- else
- CHECK_YAJL=yes
- printf `pkg-config --modversion yajl`"\n"
- fi
-else
- printf "#include <stdio.h>\n" > build_check.c
- printf "#include <yajl/yajl_version.h>\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"
- 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"
- fi
- fi
- rm -f fake
-fi
-
-printf "Checking for boost::scoped_ptr... "
-printf "#include <boost/scoped_ptr.hpp>\nint main() { boost::scoped_ptr<int> 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"
-else
- CHECK_BOOST_SCOPED_PTR=yes
- printf "yes\n"
-fi
-rm -f fake
-
-if [ "$OS" = "linux" ]
-then
- printf "Checking for linux/netfilter_ipv4/ip_queue.h... "
- printf "#include <linux/types.h>\n" > build_check.c
- printf "#include <linux/netfilter_ipv4/ip_queue.h>\n" >> build_check.c
- printf "int main() { return 0; }\n" >> build_check.c
- $CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
- if [ $? != 0 ]
- then
- CHECK_IP_QUEUE_H=no
- printf "no\n"
- else
- CHECK_IP_QUEUE_H=yes
- DEFS="$DEFS -DHAS_IP_QUEUE_H"
- PLUGINS="$PLUGINS
- capture/ipq_linux"
- printf "yes\n"
- fi
- rm -f fake
-fi
-
-rm -f build_check.c
-rm -f build_check.cpp
-
-if [ "$CHECK_EXPAT" != "yes" ]
-then
- printf -- "-lexpat not found!\n"
- exit 1
-fi
-
-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
-
-if [ "$CHECK_XMLRPC" = "yes" ]
-then
- PLUGINS="$PLUGINS
- configuration/rpcconfig"
-fi
-
-if [ "$CHECK_PCAP" = "yes" ]
-then
- PLUGINS="$PLUGINS
- capture/pcap"
-fi
-
-if [ "$CHECK_NFNETLINK" = "yes" -a "$CHECK_NFQ" = "yes" ]
-then
- PLUGINS="$PLUGINS
- capture/nfqueue"
-fi
-
-if [ "$CHECK_YAJL" = "yes" -a "$CHECK_BOOST_SCOPED_PTR" = "yes" ]
-then
- PLUGINS="$PLUGINS
- other/radius"
- 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 "DIR_MOD=\$(DIR_BUILD)/modules\n" >> $CONFFILE
-printf "DIR_PLUGINS=\$(DIR_BUILD)/plugins\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 "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 "CHECK_XMLRPC=$CHECK_XMLRPC\n" >> $CONFFILE
-if [ "$CHECK_XMLRPC" = "yes" ]
-then
- printf "XMLRPC_CFLAGS=$XMLRPC_CFLAGS\n" >> $CONFFILE
- printf "XMLRPC_LDFLAGS=$XMLRPC_LDFLAGS\n" >> $CONFFILE
-fi
-printf "CHECK_PCAP=$CHECK_PCAP\n" >> $CONFFILE
-printf "CHECK_NFNETLINK=$CHECK_NFNETLINK\n" >> $CONFFILE
-if [ "$CHECK_NFNETLINK" = "yes" ]
-then
- printf "NETLINK_LDFLAGS=$NETLINK_LDFLAGS\n" >> $CONFFILE
-fi
-printf "CHECK_NFQ=$CHECK_NFQ\n" >> $CONFFILE
-if [ "$CHECK_NFQ" = "yes" ]
-then
- printf "NFQ_LDFLAGS=$NFQ_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 "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
-printf "VAR_DIR=$VAR_DIR\n" >> $CONFFILE
-printf "ETC_DIR=$ETC_DIR\n" >> $CONFFILE
-
-mkdir -p modules
-
-if [ "$1" != "debug" ]
-then
- $MAKE $MAKEOPTS
-else
- printf "\n\n\nDebug build. Type $MAKE explicitly\n"
-fi
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "corps_impl.h"
-
-#include "stg/admin.h"
-#include "stg/common.h"
-
-#include <cerrno>
-#include <cassert>
-#include <algorithm>
-
-//-----------------------------------------------------------------------------
-CORPORATIONS_IMPL::CORPORATIONS_IMPL(STORE * st)
- : CORPORATIONS(),
- data(),
- store(st),
- WriteServLog(GetStgLogger()),
- searchDescriptors(),
- handle(0),
- mutex(),
- strError()
-{
-pthread_mutex_init(&mutex, NULL);
-Read();
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::Add(const CORP_CONF & corp, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->corpChg)
- {
- std::string s = admin->GetLogStr() + " Add corporation \'" + corp.name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-crp_iter si(find(data.begin(), data.end(), corp));
-
-if (si != data.end())
- {
- strError = "Corporation \'" + corp.name + "\' cannot not be added. Corporation already exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-data.push_back(corp);
-
-if (store->AddCorp(corp.name) == 0)
- {
- WriteServLog("%s Corporation \'%s\' added.",
- admin->GetLogStr().c_str(), corp.name.c_str());
- return 0;
- }
-
-strError = "Corporation \'" + corp.name + "\' was not added. Error: " + store->GetStrError();
-WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::Del(const std::string & name, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->corpChg)
- {
- std::string s = admin->GetLogStr() + " Delete corporation \'" + name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
-
-if (si == data.end())
- {
- strError = "Corporation \'" + name + "\' cannot be deleted. Corporation does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-std::map<int, const_crp_iter>::iterator csi;
-csi = searchDescriptors.begin();
-while (csi != searchDescriptors.end())
- {
- if (csi->second == si)
- (csi->second)++;
- ++csi;
- }
-
-data.remove(*si);
-if (store->DelCorp(name) < 0)
- {
- strError = "Corporation \'" + name + "\' was not deleted. Error: " + store->GetStrError();
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-WriteServLog("%s Corporation \'%s\' deleted.", admin->GetLogStr().c_str(), name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::Change(const CORP_CONF & corp, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->corpChg)
- {
- std::string s = admin->GetLogStr() + " Change corporation \'" + corp.name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-crp_iter si(find(data.begin(), data.end(), corp));
-
-if (si == data.end())
- {
- strError = "Corporation \'" + corp.name + "\' cannot be changed " + ". Corporation does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-*si = corp;
-if (store->SaveCorp(corp))
- {
- WriteServLog("Cannot write corporation %s.", corp.name.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
-
-WriteServLog("%s Corporation \'%s\' changed.",
- admin->GetLogStr().c_str(), corp.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool CORPORATIONS_IMPL::Read()
-{
-STG_LOCKER lock(&mutex);
-std::vector<std::string> corpsList;
-if (store->GetCorpsList(&corpsList) < 0)
- {
- WriteServLog(store->GetStrError().c_str());
- return true;
- }
-
-for (size_t i = 0; i < corpsList.size(); i++)
- {
- CORP_CONF corp;
-
- if (store->RestoreCorp(&corp, corpsList[i]))
- {
- WriteServLog(store->GetStrError().c_str());
- return true;
- }
-
- data.push_back(corp);
- }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool CORPORATIONS_IMPL::Find(const std::string & name, CORP_CONF * corp)
-{
-assert(corp != NULL && "Pointer to corporation is not null");
-
-STG_LOCKER lock(&mutex);
-if (data.empty())
- return false;
-
-crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
-
-if (si != data.end())
- {
- *corp = *si;
- return false;
- }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool CORPORATIONS_IMPL::Exists(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-if (data.empty())
- {
- printfd(__FILE__, "no admin in system!\n");
- return true;
- }
-
-const_crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
-
-if (si != data.end())
- return true;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::OpenSearch() const
-{
-STG_LOCKER lock(&mutex);
-handle++;
-searchDescriptors[handle] = data.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::SearchNext(int h, CORP_CONF * corp) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) == searchDescriptors.end())
- {
- WriteServLog("CORPORATIONS. Incorrect search handle.");
- return -1;
- }
-
-if (searchDescriptors[h] == data.end())
- return -1;
-
-*corp = *searchDescriptors[h]++;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int CORPORATIONS_IMPL::CloseSearch(int h) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
- {
- searchDescriptors.erase(searchDescriptors.find(h));
- return 0;
- }
-
-WriteServLog("CORPORATIONS. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef CORPORATIONS_IMPL_H
-#define CORPORATIONS_IMPL_H
-
-#include "stg/corporations.h"
-#include "stg/corp_conf.h"
-#include "stg/locker.h"
-#include "stg/store.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include <list>
-#include <map>
-#include <string>
-
-#include <pthread.h>
-
-class ADMIN;
-
-class CORPORATIONS_IMPL : private NONCOPYABLE, public CORPORATIONS {
-public:
- explicit CORPORATIONS_IMPL(STORE * st);
- virtual ~CORPORATIONS_IMPL() {}
-
- int Add(const CORP_CONF & corp, const ADMIN * admin);
- int Del(const std::string & name, const ADMIN * admin);
- int Change(const CORP_CONF & corp, const ADMIN * admin);
- bool Find(const std::string & name, CORP_CONF * corp);
- bool Exists(const std::string & name) const;
- const std::string & GetStrError() const { return strError; }
-
- size_t Count() const { return data.size(); }
-
- int OpenSearch() const;
- int SearchNext(int, CORP_CONF * corp) const;
- int CloseSearch(int) const;
-
-private:
- CORPORATIONS_IMPL(const CORPORATIONS_IMPL & rvalue);
- CORPORATIONS_IMPL & operator=(const CORPORATIONS_IMPL & rvalue);
-
- typedef std::list<CORP_CONF>::iterator crp_iter;
- typedef std::list<CORP_CONF>::const_iterator const_crp_iter;
-
- bool Read();
-
- std::list<CORP_CONF> data;
- STORE * store;
- STG_LOGGER & WriteServLog;
- mutable std::map<int, const_crp_iter> searchDescriptors;
- mutable unsigned int handle;
- mutable pthread_mutex_t mutex;
- std::string strError;
-};
-
-#endif
+++ /dev/null
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include "stg/locker.h"
-#include "stg/common.h"
-#include "eventloop.h"
-
-EVENT_LOOP::EVENT_LOOP()
- : ACTIONS_LIST(),
- _running(false),
- _stopped(true),
- _tid(),
- _mutex(),
- _condition()
-{
-pthread_mutex_init(&_mutex, NULL);
-pthread_cond_init(&_condition, NULL);
-}
-
-EVENT_LOOP::~EVENT_LOOP()
-{
-pthread_cond_destroy(&_condition);
-pthread_mutex_destroy(&_mutex);
-}
-
-bool EVENT_LOOP::Start()
-{
-_running = true;
-if (pthread_create(&_tid, NULL, Run, this))
- {
- printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
- return true;
- }
-return false;
-}
-
-bool EVENT_LOOP::Stop()
-{
-_running = false;
-// Wake up thread
-pthread_cond_signal(&_condition);
-// Wait until thread exit
-pthread_join(_tid, NULL);
-return false;
-}
-
-void * EVENT_LOOP::Run(void * self)
-{
-EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
-ev->Runner();
-return NULL;
-}
-
-void EVENT_LOOP::Runner()
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-_stopped = false;
-printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
-while (_running)
- {
- {
- STG_LOCKER lock(&_mutex);
- // Check for any actions...
- if (empty())
- {
- // ... and sleep until new actions added
- printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
- pthread_cond_wait(&_condition, &_mutex);
- }
- // Check for running after wake up
- if (!_running)
- {
- // Don't process any actions if stopping
- break;
- }
- }
- // Create new empty actions list
- ACTIONS_LIST local;
- // Fast swap with current
- swap(local);
- // Invoke all current actions
- printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
- local.InvokeAll();
- }
-printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
-_stopped = true;
-}
-
-namespace {
-
-pthread_mutex_t singletonMutex;
-
-}
-
-EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
-{
-// Double-checking technique
-if (!_instance)
- {
- STG_LOCKER lock(&singletonMutex);
- if (!_instance)
- {
- CreateInstance();
- }
- }
-return *_instance;
-}
-
-void EVENT_LOOP_SINGLETON::CreateInstance()
-{
-static EVENT_LOOP loop;
-_instance = &loop;
-}
-
-EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;
+++ /dev/null
-#ifndef __EVENT_LOOP_H__
-#define __EVENT_LOOP_H__
-
-#include <pthread.h>
-
-#include "stg/noncopyable.h"
-#include "actions.h"
-
-class EVENT_LOOP : private NONCOPYABLE,
- private ACTIONS_LIST
-{
- public:
- bool Start();
- bool Stop();
- bool IsRunning() const { return _running; }
-
- template <class ACTIVE_CLASS, typename DATA_TYPE>
- void Enqueue(ACTIVE_CLASS & ac,
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
- DATA_TYPE d);
-
- private:
- bool _running;
- bool _stopped;
- pthread_t _tid;
- pthread_mutex_t _mutex;
- pthread_cond_t _condition;
-
- EVENT_LOOP();
- virtual ~EVENT_LOOP();
-
- static void * Run(void *);
- void Runner();
-
- friend class EVENT_LOOP_SINGLETON;
-};
-
-class EVENT_LOOP_SINGLETON : private NONCOPYABLE
-{
- public:
- static EVENT_LOOP & GetInstance();
-
- private:
- static EVENT_LOOP * _instance;
- static void CreateInstance();
-
- EVENT_LOOP_SINGLETON() {}
- ~EVENT_LOOP_SINGLETON() {}
-};
-
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac,
- typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
- DATA_TYPE d)
-{
-STG_LOCKER lock(&_mutex);
-// Add new action
-ACTIONS_LIST::Enqueue(ac, a, d);
-// Signal about new action
-pthread_cond_signal(&_condition);
-}
-
-#endif
+++ /dev/null
-#! /bin/sh
-
-login=$1
-param=$2
-oldValue=$3
-newValue=$4
-
-#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
+++ /dev/null
-#! /bin/sh
-
-#Этот скрипт вызывается в момент, когда пользователь
-#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
-#файрвол так, что бы пользователь получил доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-
-#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
+++ /dev/null
-#! /bin/sh
-
-# Этот скрипт вызывается в момент, когда пользователь
-# желает отключится от интернета или вышел таймаут у пользователя
-# и сервер сам отключает пользователя
-# Задача скрипта подобна задаче скрипта OnConnect - перестроить
-# файрвол так, что бы пользователю закрыть доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$5
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+++ /dev/null
-#! /bin/sh
-
-# Использование (неиспользование) этого скрипта дело вкуса.
-# Он не выполняет критических функций. Его задача автматизировать
-# действия характерные при добавлении пользователя сети, например добавлекние
-# пользователю почты
-
-# Login
-login=$1
-
-#echo "added user $login" >> /var/stargazer/add_del.log
-
-
-
+++ /dev/null
-#! /bin/sh
-
-# Login
-login=$1
-
-#echo "deleted user $login" >> /var/stargazer/add_del.log
-
+++ /dev/null
-# Enable the authorization module Always Online "mod_auth_ao.so"
-<Module auth_ao>
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the traffic capture module "mod_cap_ipq.so" using Berkeley Packet Filter
-<Module cap_bpf>
- # Define interface(s) for traffic capture
- iface = rl0
- iface = rl1
- iface = dc0
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the traffic capture module "mod_cap_divert.so" using Divert-sockets
-<Module cap_divert>
- # Port for traffic
- # Parameter: optional
- # Value: 1 ... 65535
- # Default: 15701
- Port = 15701
-
- # Disable packet forwarding
- # Parameter: optional
- # Value: yes, no
- # Default: no
- DisableForwarding = no
-</Module>
+++ /dev/null
-# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
-<Module cap_nf>
- # Port for TCP connections
- # Note: Parameters TCPPort and UDPPort can be equal
- # Parameter: optional
- # Value: 1 ... 65535
- # Default: 9996
- #TCPPort = 9996
-
- # Port for UDP connections
- # Note: Parameters TCPPort and UDPPort can be equal
- # Parameter: optional
- # Value: 1 ... 65535
- # Default: 9996
- UDPPort = 9996
-</Module>
+++ /dev/null
-# Enable the authorization module InetAccess "mod_auth_ia.so"
-<Module auth_ia>
- # Port on which the server interacts with authorizator
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 5555
- Port = 5555
-
- # The time interval between sending an alive query to the user
- # and updating statistics
- # Parameter: required
- # Values: 5 ... 600 (seconds)
- # Default: 60
- UserDelay = 60
-
- # User timeout. If authorizer does not respond during this time,
- # the user will be disconnected
- # Parameter: required
- # Values: 5 ... 600
- # Default: 60
- UserTimeout = 65
-
- # Define which information will be transmitted from the server to InetAccess
- # as a residue of prepaid traffic
- # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
- # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
- # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
- # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
- # ........................
- # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
- # FreeMb = cash - amount of money for which the user can download for free
- # FreeMb = none - no transfer
- # Default: cash
- # Parameter: required
- # Values: different, see above
- # Default: cash
- FreeMb = cash
-
- # Enable protocol errors logging
- # Parameter: optional
- # Values: yes, no
- # Default: no
- # LogProtocolErrors = no
-</Module>
+++ /dev/null
-# Enable the module that pings users "mod_ping.so"
-<Module ping>
- # The time interval between pings
- # Parameter: required
- # Value: 10 ... 3600 (seconds)
- # Default: 15
- PingDelay = 15
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the interaction module for FreeRADIUS "mod_radius.so"
-<Module radius>
- # FreeRADIUS password
- # Parameter: required
- # Values: any, supported by software
- # Default: 123456
- Password = 123456
-
- # FreeRADIUS server
- # Parameter: required
- # Values: IP address or DNS name
- # Default: 127.0.0.1
- ServerIP = 127.0.0.1
-
- # FreeRADIUS port
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 6666
- Port = 6666
-
- # List of services for which will be carried out FreeRADIUS authentication
- # Note: Parameter can be blank
- # Parameter: required
- # Value: any, supported by software
- # Default: Login-User
- AuthServices = Login-User
-
- # List of services for which will be carried out FreeRADIUS Accounting
- # Note: Parameter can be blank
- # Parameter: required
- # Value: any, supported by software
- # Default: Framed-User
- AcctServices = Framed-User
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
-<Module remote_script>
- # The time interval between sending confirmations that the user is online
- # Parametr: required
- # Values: 10 ... 600 (seconds)
- # Default: 60
- SendPeriod = 15
-
- # Define mapping between subnet(s) and remote server(s)
- # File format: <subnet> <Router1> <Router2> ...
- # Example:
- # 192.168.1.0/24 192.168.1.7 192.168.1.8
- # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
- # 192.168.3.0/24 192.168.3.5
- # 192.168.4.0/24 192.168.4.5
- # Parametr: required
- # Values: file path
- # Default: subnets
- SubnetFile = subnets
-
- # The password to encrypt packets between the stg-server and remote server
- # Parameter: required
- # Values: any
- # Default: 123456
- Password = 123456
-
- # Define which user parameters are transferred to a remote server in addition to
- # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
- # Note: Parameter can be blank.
- # Parameter: required
- # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName,
- # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs,
- # Userdata0...Userdata9
- # Default: Cash Tariff EnabledDirs
- UserParams = Cash Tariff EnabledDirs
-
- # Port on which the server interacts with remote server
- # Parameter: required
- # Value: 1...65535
- # Default: 9999
- Port = 9999
-</Module>
+++ /dev/null
-# Enable the configuration module ConfRPC "mod_conf_rpc.so"
-<Module conf_rpc>
- # Port on which the server interacts with configurator
- # Parameter: required
- # Value: 1...65535
- # Default:
- Port = 8080
-
- # Session timeout in seconds
- # Parameter: required
- # Value: positive integer
- # Default: 1800
- CookieTimeout = 1800
-</Module>
+++ /dev/null
-# Enable the configuration module SgConfig "mod_conf_sg.so"
-<Module conf_sg>
- # Port on which the server interacts with configurator
- # Parameter: required
- # Value: 1...65535
- # Default: 5555
- Port = 5555
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enables SMUX-peer for SNMPd.
-<Module smux>
- # IP-address of a server to connect to
- # Parameter: required
- # Value: X.X.X.X
- # Default: 127.0.0.1
- Server = 127.0.0.1
-
- # Port number on a server to connect to
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 199
- Port = 199
-
- # Password for authentication on a server
- # Parameter: required
- # Value: any text
- Password =
-</Module>
+++ /dev/null
-# Enables plain file backend.
-<StoreModule store_files>
-
- # Working server directory, provides data on tariffs, users, administrators.
- # Parameter: required
- # Value: directory path
- WorkDir = /var/stargazer
-
- # Owner, group and permissions of the files of user statistics (stat)
- # Parameter: required
- # Values: any, supported by OS
- ConfOwner = root
- ConfGroup = root
- ConfMode = 640
-
- # Owner, group and permissions on user configuration files (conf)
- # Parameter: required
- # Values: any, supported by OS
- StatOwner = root
- StatGroup = root
- StatMode = 640
-
- # Owner, group and permissions for user log files (log)
- # Parameter: required
- # Values: any, supported by OS
- UserLogOwner = root
- UserLogGroup = root
- UserLogMode = 640
-
-</StoreModule>
+++ /dev/null
-# Enables Firebird backend.
-<StoreModule store_firebird>
- # Database server address
- # Parameter: optional
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Path to the database on the server or its alias
- # Parameter: optional
- # Value: file path
- # Default: /var/stg/stargazer.fdb
- # Database = /var/stg/stargazer.fdb
-
- # Database username
- # Parameter: optional
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: optional
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-
- # The transaction isolation level
- # Parameter: optional
- # Values: concurrency, dirtyread, readcommitted, consistency
- # Defalt: concurrency
- # IsolationLevel = concurrency
-
- # Responding to lock (optional, defaults to wait):
- # Parameter: optional
- # Values: wait, nowait
- # Defalt: wait
- # LockResolution = wait
-</StoreModule>
+++ /dev/null
-# Enables MySQL backend.
-<StoreModule store_mysql>
- # Database server address
- # Parameter: required
- # Value: IP address or DNS name
- # Default: localhost
- Server = localhost
-
- # Database name
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- Database = stg
-
- # Database username
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- User = stg
-
- # Database password
- # Parameter: required
- # Value: any, supported by database
- # Default: 123456
- Password = 123456
-</StoreModule>
+++ /dev/null
-# Enables PostgreSQL backend.
-<StoreModule store_postgresql>
- # Database server address
- # Parameter: optional
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Database name
- # Parameter: optional
- # Value: any, supported by database
- # Default: stargazer
- # Database = stargazer
-
- # Database username
- # Parameter: optional
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: optional
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-
- # Number of tries to reconnect
- # Parameter: optional
- # Value: positive integer
- # Default: 3
- # Retries = 3
-</StoreModule>
+++ /dev/null
-../conf-available.d/mod_ao.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_cap_bpf.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_ia.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_ping.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_sg.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/store_files.conf
\ No newline at end of file
+++ /dev/null
-ALL 192.168.0.0/16 DIR1
-ALL 10.0.0.0/8 DIR2
-ALL 0.0.0.0/0 DIR0
\ No newline at end of file
+++ /dev/null
-################################################################################
-# Stargazer Configuration file #
-################################################################################
-
-# LOG file name
-# Parameter: required
-# Value: file path
-# Default: /var/log/stargazer.log
-LogFile = /var/log/stargazer.log
-
-# PID file name
-# Parameter: optional
-# Value: file path
-# Default: /var/run/stargazer.pid
-PIDFile = /var/run/stargazer.pid
-
-# Traffic classification rules
-# Parameter: required
-# Value: file path
-# Default: /etc/stargazer/rules
-Rules = /etc/stargazer/rules
-
-# The time interval between writing detailed user's statistics into the database
-# Note: With a large number of users this value should be increased,
-# since writting into the database can take a long time.
-# Parameter: required
-# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
-# Default: 1/2
-DetailStatWritePeriod = 1/2
-
-# The time interval between writing summary user's statistics into the database
-# Parameter: optional
-# Value: 1 ... 1440 (minutes)
-# Default: 10
-StatWritePeriod = 10
-
-# Day of charging fee
-# Note: 0 - The last day of the month
-# Parameter: required
-# Value: 0 ... 31
-# Default: 1
-DayFee = 1
-
-# When set to 'no' Stargazer will continue reading database after error and show all of them.
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# StopOnError = yes
-
-# Fee charged at the last (yes) or first (no) day of tariffication period.
-# Defines how the fee will be charged in the transition to the new tariff.
-# User has tariff A with fee 100. Changing it to tariff B with fee 200
-# will result in charging user's account at 100 if DayFeeIsLastDay = yes
-# and at 200, if DayFeeIsLastDay = no
-# Parameter: required
-# Values: yes, no
-# Default: no
-DayFeeIsLastDay = no
-
-# Day of changing delayed tariffs and resetting summary user's statistics.
-# Defines the edge of the tariffication period.
-# Parameter: required
-# Value: 0 ... 31. 0 - The last day of the month
-# Default: 1
-DayResetTraff = 1
-
-# Defines whether to charge fee daily (yes) or monthly (no)
-# Parameter: required
-# Values: yes, no
-# Default: no
-SpreadFee = no
-
-# Defines whether the user can access the internet if it has no cash,
-# but remained prepaid traffic
-# Parameter: required
-# Values: yes, no
-# Default: no
-FreeMbAllowInet = no
-
-# Defines what will be written in the traffic cost in detail_stat.
-# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost willn't be written in detail_stat.
-# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost will be written in detail_stat.
-# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
-# Parameter: required
-# Values: yes, no
-# Default: yes
-WriteFreeMbTraffCost = yes
-
-# Charge a full monthly fee even if user was "frozen" a part
-# of the tariffication period
-# Parameter: optional
-# Values: yes, no
-# Default: no
-FullFee = no
-
-# Allow user to see and use a full cash (yes) or hide a part of it (no)
-# for the next fee charge
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# ShowFeeInCash=yes
-
-# The names of directions. Direction without names will not appear in
-# authorizer and configurator.
-# Note: Names consisting of several words should be quoted
-# Parameter: optional
-# Values:
-<DirNames>
- DirName0 = Internet
- DirName1 =
- DirName2 =
- DirName3 =
- DirName4 =
- DirName5 =
- DirName6 =
- DirName7 =
- DirName8 =
- DirName9 =
-</DirNames>
-
-# Amount of stg-exec processes.
-# These processes are responsible for the execution of scripts OnConnect,
-# OnDisconnect, etc.
-# 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 stargazer.
-# 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 with server modules
-# Parameter: required
-# Value: directory path
-# Default: /usr/lib/stg
-ModulesPath = /usr/lib/stg
-
-# Directory where the "monitor" files are located.
-# A blank files will be created in this directory. The modification time of such
-# files will be changed about once a minute. If server crashes or some of server
-# component hang, the files will stop refreshing, and on this basis we can define
-# the failure of the server and if necessary restart.
-# If option is omitted or blank, the monitoring is not performed.
-# Parameter: optional
-# Value: file path
-# Default: /var/stargazer/monitor
-#MonitorDir=/var/stargazer/monitor
-
-# Defines message maximum lifetime
-# Note: 0 - unlimited
-# Parameter: optional
-# Value: any numeric
-# Default: 0 (day)
-# MessagesTimeout = 0
-
-# Defines fee charging rules.
-# 0 - classic rules, allow fee charge even cash is negative;
-# 1 - disallow fee charge if cash value is negative;
-# 2 - disallow fee charge if there is not enought cash (cash < fee).
-# Parameter: optional
-# Value: 0 ... 2
-# Default: 0 (classic)
-# FeeChargeType = 0
-
-# Enable or disable reconnect on tariff change
-# Parameter: optional
-# Values: yes, no
-# Default: no
-# ReconnectOnTariffChange = no
-
-# Definest set of parameters passed to OnConnect and OnDisconnect scripts
-# This set is added to the end of the default param list, which are, respectively:
-# login, ip, cash, id, dirs
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive
-# Default:
-# ScriptParams =
-
-# Enable or disable writing session log
-# Parameter: optional
-# Values: yes, no
-# Default: no (session log is enabled)
-# DisableSessionLog = no
-
-# Filter for logging parameter changes
-# Defines which parameters will be logged to parameter log in database. Allows
-# to specify multiuple parameter names or asterisk (*), which means "log all params".
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive, or "*"
-# Default: *
-# FilterParamsLog = *
-
-################################################################################
-# Store module
-# Configure the module that works with the database server
-
-# Warning: Only one store module could be used at the same time!
-
-<IncludeFile "conf-enabled.d/store_*.conf">
-</IncludeFile>
-
-
-################################################################################
-# Other modules
-
-<Modules>
-
- <IncludeFile "conf-enabled.d/mod_*.conf">
- </IncludeFile>
-
-</Modules>
-################################################################################
+++ /dev/null
-#!/sbin/runscript
-
-extra_commands="reload"
-
-DAEMON=/usr/sbin/stargazer
-STARGAZER_OPTS=""
-PIDFILE=/var/run/stargazer.pid
-
-depend() {
- need net
- use postgresql firebird mysql
- provide stargazer
-}
-
-start() {
- ebegin "Starting stargazer"
- start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} -- ${STARGAZER_OPTS}
- eend $?
-}
-
-stop() {
- ebegin "Stopping stargazer"
- start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --retry=INT/120/KILL/5
- rm -f ${PIDFILE}
- eend $?
-}
-
-reload() {
- ebegin "Reloading stargazer rules"
- start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
- return 0
- eend $?
-}
+++ /dev/null
-#!/bin/bash
-#
-# processname: stargazer
-# config: /etc/stargazer/stargazer.conf
-# pidfile: /var/run/stargazer.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-# Source networking configuration.
-. /etc/sysconfig/network
-
-# Source stargazer configureation.
-DAEMON=yes
-QUEUE=1h
-
-# Check that networking is up.
-[ ${NETWORKING} = "no" ] && exit 0
-
-[ -f /sbin/stargazer ] || exit 0
-
-RETVAL=0
-prog="stargazer"
-
-start() {
- # Start daemons.
-
- echo -n $"Starting $prog: "
- /etc/stargazer/first 2> /dev/null
- daemon /sbin/stargazer
- RETVAL=$?
- /etc/stargazer/last 2> /dev/null
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/stargazer
- return $RETVAL
-}
-
-stop() {
- # Stop daemons.
- echo -n $"Shutting down $prog: "
- killproc stargazer
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/stargazer
- return $RETVAL
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart|reload)
- stop
- start
- RETVAL=$?
- ;;
- status)
- status stargazer
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|status}"
- exit 1
-esac
-
-exit $RETVAL
+++ /dev/null
-#! /bin/sh
-### BEGIN INIT INFO
-# Provides: stargazer
-# Required-Start: $local_fs $remote_fs
-# Required-Stop: $local_fs $remote_fs
-# Default-Start: 2 3 4 5
-# Default-Stop: S 0 1 6
-# Short-Description: Stargazer initscript
-# Description: This file should be used to start and stop stargazer daemon
-### END INIT INFO
-
-# Author: Boris Mikhailenko <stg34@stg.dp.ua>
-
-# Do NOT "set -e"
-
-# PATH should only include /usr/* if it runs after the mountnfs.sh script
-PATH=/usr/sbin:/usr/bin:/sbin:/bin
-DESC="Billing system"
-NAME=stargazer
-DAEMON=/usr/sbin/$NAME
-DAEMON_ARGS=""
-PIDFILE=/var/run/$NAME.pid
-SCRIPTNAME=/etc/init.d/$NAME
-
-# Exit if the package is not installed
-[ -x "$DAEMON" ] || exit 0
-
-# Read configuration variable file if it is present
-[ -r /etc/default/$NAME ] && . /etc/default/$NAME
-
-# Load the VERBOSE setting and other rcS variables
-[ -f /etc/default/rcS ] && . /etc/default/rcS
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
-. /lib/lsb/init-functions
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
- # Return
- # 0 if daemon has been started
- # 1 if daemon was already running
- # 2 if daemon could not be started
- start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
- || return 1
-
- # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
-
- start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
- $DAEMON_ARGS \
- || return 2
-
- # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
- # Add code here, if necessary, that waits for the process to be ready
- # to handle requests from services started subsequently which depend
- # on this one. As a last resort, sleep for some time.
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
- # Return
- # 0 if daemon has been stopped
- # 1 if daemon was already stopped
- # 2 if daemon could not be stopped
- # other if a failure occurred
- start-stop-daemon --stop --quiet --retry=INT/60/KILL/5 --pidfile $PIDFILE --name $NAME
- RETVAL="$?"
- [ "$RETVAL" = 2 ] && return 2
- # Wait for children to finish too if this is a daemon that forks
- # and if the daemon is only ever run from this initscript.
- # If the above conditions are not satisfied then add some other code
- # that waits for the process to drop all resources that could be
- # needed by services started subsequently. A last resort is to
- # sleep for some time.
- start-stop-daemon --stop --quiet --oknodo --retry=0/60/KILL/5 --exec $DAEMON
- [ "$?" = 2 ] && return 2
- # Many daemons don't delete their pidfiles when they exit.
- rm -f $PIDFILE
- return "$RETVAL"
-}
-
-#
-# Function that sends a SIGHUP to the daemon/service
-#
-do_reload() {
- # If the daemon can reload its configuration without
- # restarting (for example, when it is sent a SIGHUP),
- # then implement that here.
- start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
- return 0
-}
-
-case "$1" in
- start)
- [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
- do_start
- case "$?" in
- 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
- 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
- esac
- ;;
- stop)
- [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
- do_stop
- case "$?" in
- 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
- 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
- esac
- ;;
- reload)
- # If do_reload() is not implemented then leave this commented out
- # and leave 'force-reload' as an alias for 'restart'.
- log_daemon_msg "Reloading $DESC" "$NAME"
- do_reload
- log_end_msg $?
- ;;
- restart)
- #
- # If the "reload" option is implemented then remove the
- # 'force-reload' alias
- #
- log_daemon_msg "Restarting $DESC" "$NAME"
- do_stop
- case "$?" in
- 0|1)
- do_start
- case "$?" in
- 0) log_end_msg 0 ;;
- 1) log_end_msg 1 ;; # Old process is still running
- *) log_end_msg 1 ;; # Failed to start
- esac
- ;;
- *)
- # Failed to stop
- log_end_msg 1
- ;;
- esac
- ;;
- *)
- #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
- echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
- exit 3
- ;;
-esac
-
-:
+++ /dev/null
-#! /bin/sh
-
-# About: This script is called when user account is changed.
-# Common Task: Notify about various events.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# User parameter
-PARAMETER=$2
-
-# User parameter old value
-OLDVALUE=$3
-
-# User parameter new value
-NEWVALUE=$4
-
-# Usage examples:
-#echo "User: '$LOGIN'. Parameter $PARAMETER changed from '$OLDVALUE' to '$NEWVALUE'" >> /var/stargazer/user.change.log
\ No newline at end of file
+++ /dev/null
-#! /bin/sh
-
-# About: This script is called when the user successfully authenticated on the server.
-# Common Task: Rebuild firewall to allow user to access the Internet.
-# Priority: required
-
-# User login
-LOGIN=$1
-
-# User IP
-IP=$2
-
-# User cash
-CASH=$3
-
-# User ID
-ID=$4
-
-# Selected DIRs (from rules file) to connect
-DIRS=$5
-
-# Usage examples:
-#echo "Connected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
\ No newline at end of file
+++ /dev/null
-#! /bin/sh
-
-# About: This script is called when the user wants to disconnect or authorization timeout has passed.
-# Common task: Rebuild firewall to disallow user to access the Internet.
-# Priority: required
-
-# User login
-LOGIN=$1
-
-# User IP
-IP=$2
-
-# User cash
-CASH=$3
-
-# User ID
-ID=$4
-
-# Selected DIRs (from rules file) to disconnect
-DIRS=$5
-
-# Usage examples:
-#echo "Disconnected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+++ /dev/null
-#! /bin/sh
-
-# About: This script is called when the user is added to the Stargazer.
-# Common task: Automate typical actions on adding user to the network,
-# such as creating email or IM account.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# Usage examples:
-#echo "Added user $login" >> /var/stargazer/add_del.log
\ No newline at end of file
+++ /dev/null
-#! /bin/sh
-
-# About: This script is called when the user is removed from the Stargazer.
-# Common task: Automate typical actions on removing user from the network,
-# such as removing email or IM account.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# Usage examples:
-#echo "Deleted user $LOGIN" >> /var/stargazer/add_del.log
-
+++ /dev/null
-# Enable the authorization module Always Online "mod_auth_ao.so"
-<Module auth_ao>
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the traffic capture module "mod_cap_ether.so" using Packet-sockets
-<Module cap_ether>
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the traffic capture module "mod_cap_ipq.so" using mechanism of IP Queueing
-<Module cap_ipq>
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
-<Module cap_nf>
- # Port for TCP connections
- # Note: Parameters TCPPort and UDPPort can be equal
- # Parameter: optional
- # Value: 1 ... 65535
- # Default: 9996
- #TCPPort = 9996
-
- # Port for UDP connections
- # Note: Parameters TCPPort and UDPPort can be equal
- # Parameter: optional
- # Value: 1 ... 65535
- # Default: 9996
- UDPPort = 9996
-</Module>
+++ /dev/null
-# Enable the authorization module InetAccess "mod_auth_ia.so"
-<Module auth_ia>
- # Port on which the server interacts with authorizator
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 5555
- Port = 5555
-
- # The time interval between sending an alive query to the user
- # and updating statistics
- # Parameter: required
- # Values: 5 ... 600 (seconds)
- # Default: 60
- UserDelay = 60
-
- # User timeout. If authorizer does not respond during this time,
- # the user will be disconnected
- # Parameter: required
- # Values: 5 ... 600
- # Default: 60
- UserTimeout = 65
-
- # Define which information will be transmitted from the server to InetAccess
- # as a residue of prepaid traffic
- # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
- # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
- # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
- # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
- # ........................
- # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
- # FreeMb = cash - amount of money for which the user can download for free
- # FreeMb = none - no transfer
- # Default: cash
- # Parameter: required
- # Values: different, see above
- # Default: cash
- FreeMb = cash
-
- # Enable protocol errors logging
- # Parameter: optional
- # Values: yes, no
- # Default: no
- # LogProtocolErrors = no
-</Module>
+++ /dev/null
-# Enable the module that pings users "mod_ping.so"
-<Module ping>
- # The time interval between pings
- # Parameter: required
- # Value: 10 ... 3600 (seconds)
- # Default: 15
- PingDelay = 15
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the interaction module for FreeRADIUS "mod_radius.so"
-<Module radius>
- # FreeRADIUS password
- # Parameter: required
- # Values: any, supported by software
- # Default: 123456
- Password = 123456
-
- # FreeRADIUS server
- # Parameter: required
- # Values: IP address or DNS name
- # Default: 127.0.0.1
- ServerIP = 127.0.0.1
-
- # FreeRADIUS port
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 6666
- Port = 6666
-
- # List of services for which will be carried out FreeRADIUS authentication
- # Note: Parameter can be blank
- # Parameter: required
- # Value: any, supported by software
- # Default: Login-User
- AuthServices = Login-User
-
- # List of services for which will be carried out FreeRADIUS Accounting
- # Note: Parameter can be blank
- # Parameter: required
- # Value: any, supported by software
- # Default: Framed-User
- AcctServices = Framed-User
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
-<Module remote_script>
- # The time interval between sending confirmations that the user is online
- # Parametr: required
- # Values: 10 ... 600 (seconds)
- # Default: 60
- SendPeriod = 15
-
- # Define mapping between subnet(s) and remote server(s)
- # File format: <subnet> <Router1> <Router2> ...
- # Example:
- # 192.168.1.0/24 192.168.1.7 192.168.1.8
- # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
- # 192.168.3.0/24 192.168.3.5
- # 192.168.4.0/24 192.168.4.5
- # Parametr: required
- # Values: file path
- # Default: subnets
- SubnetFile = subnets
-
- # The password to encrypt packets between the stg-server and remote server
- # Parameter: required
- # Values: any
- # Default: 123456
- Password = 123456
-
- # Define which user parameters are transferred to a remote server in addition to
- # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
- # Note: Parameter can be blank.
- # Parameter: required
- # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName,
- # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs,
- # Userdata0...Userdata9
- # Default: Cash Tariff EnabledDirs
- UserParams = Cash Tariff EnabledDirs
-
- # Port on which the server interacts with remote server
- # Parameter: required
- # Value: 1...65535
- # Default: 9999
- Port = 9999
-</Module>
+++ /dev/null
-# Enable the configuration module ConfRPC "mod_conf_rpc.so"
-<Module conf_rpc>
- # Port on which the server interacts with configurator
- # Parameter: required
- # Value: 1...65535
- # Default:
- Port = 8080
-
- # Session timeout in seconds
- # Parameter: required
- # Value: positive integer
- # Default: 1800
- CookieTimeout = 1800
-</Module>
+++ /dev/null
-# Enable the configuration module SgConfig "mod_conf_sg.so"
-<Module conf_sg>
- # Port on which the server interacts with configurator
- # Parameter: required
- # Value: 1...65535
- # Default: 5555
- Port = 5555
-</Module>
\ No newline at end of file
+++ /dev/null
-# Enables SMUX-peer for SNMPd.
-<Module smux>
- # IP-address of a server to connect to
- # Parameter: required
- # Value: X.X.X.X
- # Default: 127.0.0.1
- Server = 127.0.0.1
-
- # Port number on a server to connect to
- # Parameter: required
- # Value: 1 ... 65535
- # Default: 199
- Port = 199
-
- # Password for authentication on a server
- # Parameter: required
- # Value: any text
- Password =
-</Module>
+++ /dev/null
-# Enables plain file backend.
-<StoreModule store_files>
-
- # Working server directory, provides data on tariffs, users, administrators.
- # Parameter: required
- # Value: directory path
- WorkDir = /var/stargazer
-
- # Owner, group and permissions of the files of user statistics (stat)
- # Parameter: required
- # Values: any, supported by OS
- ConfOwner = root
- ConfGroup = root
- ConfMode = 640
-
- # Owner, group and permissions on user configuration files (conf)
- # Parameter: required
- # Values: any, supported by OS
- StatOwner = root
- StatGroup = root
- StatMode = 640
-
- # Owner, group and permissions for user log files (log)
- # Parameter: required
- # Values: any, supported by OS
- UserLogOwner = root
- UserLogGroup = root
- UserLogMode = 640
-
-</StoreModule>
+++ /dev/null
-# Enables Firebird backend.
-<StoreModule store_firebird>
- # Database server address
- # Parameter: optional
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Path to the database on the server or its alias
- # Parameter: optional
- # Value: file path
- # Default: /var/stg/stargazer.fdb
- # Database = /var/stg/stargazer.fdb
-
- # Database username
- # Parameter: optional
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: optional
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-
- # The transaction isolation level
- # Parameter: optional
- # Values: concurrency, dirtyread, readcommitted, consistency
- # Defalt: concurrency
- # IsolationLevel = concurrency
-
- # Responding to lock (optional, defaults to wait):
- # Parameter: optional
- # Values: wait, nowait
- # Defalt: wait
- # LockResolution = wait
-</StoreModule>
+++ /dev/null
-# Enables MySQL backend.
-<StoreModule store_mysql>
- # Database server address
- # Parameter: required
- # Value: IP address or DNS name
- # Default: localhost
- Server = localhost
-
- # Database name
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- Database = stg
-
- # Database username
- # Parameter: required
- # Value: any, supported by database
- # Default: stg
- User = stg
-
- # Database password
- # Parameter: required
- # Value: any, supported by database
- # Default: 123456
- Password = 123456
-</StoreModule>
+++ /dev/null
-# Enables PostgreSQL backend.
-<StoreModule store_postgresql>
- # Database server address
- # Parameter: optional
- # Value: IP address or DNS name
- # Default: localhost
- # Server = localhost
-
- # Database name
- # Parameter: optional
- # Value: any, supported by database
- # Default: stargazer
- # Database = stargazer
-
- # Database username
- # Parameter: optional
- # Value: any, supported by database
- # Default: stg
- # User = stg
-
- # Database password
- # Parameter: optional
- # Value: any, supported by database
- # Default: 123456
- # Password = 123456
-
- # Number of tries to reconnect
- # Parameter: optional
- # Value: positive integer
- # Default: 3
- # Retries = 3
-</StoreModule>
+++ /dev/null
-../conf-available.d/mod_ao.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_cap_ether.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_ia.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_ping.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/mod_sg.conf
\ No newline at end of file
+++ /dev/null
-../conf-available.d/store_files.conf
\ No newline at end of file
+++ /dev/null
-ALL 192.168.0.0/16 DIR1
-ALL 10.0.0.0/8 DIR2
-ALL 0.0.0.0/0 DIR0
\ No newline at end of file
+++ /dev/null
-################################################################################
-# Stargazer Configuration file #
-################################################################################
-
-# LOG file name
-# Parameter: required
-# Value: file path
-# Default: /var/log/stargazer.log
-LogFile = /var/log/stargazer.log
-
-# PID file name
-# Parameter: optional
-# Value: file path
-# Default: /var/run/stargazer.pid
-PIDFile = /var/run/stargazer.pid
-
-# Traffic classification rules
-# Parameter: required
-# Value: file path
-# Default: /etc/stargazer/rules
-Rules = /etc/stargazer/rules
-
-# The time interval between writing detailed user's statistics into the database
-# Note: With a large number of users this value should be increased,
-# since writting into the database can take a long time.
-# Parameter: required
-# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
-# Default: 1/2
-DetailStatWritePeriod = 1/2
-
-# The time interval between writing summary user's statistics into the database
-# Parameter: optional
-# Value: 1 ... 1440 (minutes)
-# Default: 10
-StatWritePeriod = 10
-
-# Day of charging fee
-# Note: 0 - The last day of the month
-# Parameter: required
-# Value: 0 ... 31
-# Default: 1
-DayFee = 1
-
-# When set to 'no' Stargazer will continue reading database after error and show all of them.
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# StopOnError = yes
-
-# Fee charged at the last (yes) or first (no) day of tariffication period.
-# Defines how the fee will be charged in the transition to the new tariff.
-# User has tariff A with fee 100. Changing it to tariff B with fee 200
-# will result in charging user's account at 100 if DayFeeIsLastDay = yes
-# and at 200, if DayFeeIsLastDay = no
-# Parameter: required
-# Values: yes, no
-# Default: no
-DayFeeIsLastDay = no
-
-# Day of changing delayed tariffs and resetting summary user's statistics.
-# Defines the edge of the tariffication period.
-# Parameter: required
-# Value: 0 ... 31. 0 - The last day of the month
-# Default: 1
-DayResetTraff = 1
-
-# Defines whether to charge fee daily (yes) or monthly (no)
-# Parameter: required
-# Values: yes, no
-# Default: no
-SpreadFee = no
-
-# Defines whether the user can access the internet if it has no cash,
-# but remained prepaid traffic
-# Parameter: required
-# Values: yes, no
-# Default: no
-FreeMbAllowInet = no
-
-# Defines what will be written in the traffic cost in detail_stat.
-# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost willn't be written in detail_stat.
-# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost will be written in detail_stat.
-# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
-# Parameter: required
-# Values: yes, no
-# Default: yes
-WriteFreeMbTraffCost = yes
-
-# Charge a full monthly fee even if user was "frozen" a part
-# of the tariffication period
-# Parameter: optional
-# Values: yes, no
-# Default: no
-FullFee = no
-
-# Allow user to see and use a full cash (yes) or hide a part of it (no)
-# for the next fee charge
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# ShowFeeInCash=yes
-
-# The names of directions. Direction without names will not appear in
-# authorizer and configurator.
-# Note: Names consisting of several words should be quoted
-# Parameter: optional
-# Values:
-<DirNames>
- DirName0 = Internet
- DirName1 =
- DirName2 =
- DirName3 =
- DirName4 =
- DirName5 =
- DirName6 =
- DirName7 =
- DirName8 =
- DirName9 =
-</DirNames>
-
-# Amount of stg-exec processes.
-# These processes are responsible for the execution of scripts OnConnect,
-# OnDisconnect, etc.
-# 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 stargazer.
-# 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 with server modules
-# Parameter: required
-# Value: directory path
-# Default: /usr/lib/stg
-ModulesPath = /usr/lib/stg
-
-# Directory where the "monitor" files are located.
-# A blank files will be created in this directory. The modification time of such
-# files will be changed about once a minute. If server crashes or some of server
-# component hang, the files will stop refreshing, and on this basis we can define
-# the failure of the server and if necessary restart.
-# If option is omitted or blank, the monitoring is not performed.
-# Parameter: optional
-# Value: file path
-# Default: /var/stargazer/monitor
-#MonitorDir=/var/stargazer/monitor
-
-# Defines message maximum lifetime
-# Note: 0 - unlimited
-# Parameter: optional
-# Value: any numeric
-# Default: 0 (day)
-# MessagesTimeout = 0
-
-# Defines fee charging rules.
-# 0 - classic rules, allow fee charge even cash is negative;
-# 1 - disallow fee charge if cash value is negative;
-# 2 - disallow fee charge if there is not enought cash (cash < fee).
-# Parameter: optional
-# Value: 0 ... 2
-# Default: 0 (classic)
-# FeeChargeType = 0
-
-# Enable or disable reconnect on tariff change
-# Parameter: optional
-# Values: yes, no
-# Default: no
-# ReconnectOnTariffChange = no
-
-# Definest set of parameters passed to OnConnect and OnDisconnect scripts
-# This set is added to the end of the default param list, which are, respectively:
-# login, ip, cash, id, dirs
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive
-# Default:
-# ScriptParams =
-
-# Enable or disable writing session log
-# Parameter: optional
-# Values: yes, no
-# Default: no (session log is enabled)
-# DisableSessionLog = no
-
-# Filter for logging parameter changes
-# Defines which parameters will be logged to parameter log in database. Allows
-# to specify multiuple parameter names or asterisk (*), which means "log all params".
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive, or "*"
-# Default: *
-# FilterParamsLog = *
-
-################################################################################
-# Store module
-# Configure the module that works with the database server
-
-# Warning: Only one store module could be used at the same time!
-
-<IncludeFile "conf-enabled.d/store_*.conf">
-</IncludeFile>
-
-
-################################################################################
-# Other modules
-
-<Modules>
-
- <IncludeFile "conf-enabled.d/mod_*.conf">
- </IncludeFile>
-
-</Modules>
-################################################################################
+++ /dev/null
-/*
- * DB migration from v00 to v01 (postgres)
- */
-
-ALTER TABLE tb_sessions_log ADD free_mb dm_money;
-ALTER TABLE tb_sessions_log ADD reason TEXT;
-
-DROP FUNCTION sp_add_session_log_entry ( dm_name, timestamp without time zone, dm_session_event_type, inet, dm_money);
-
-CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
- _event_time TIMESTAMP,
- _event_type dm_session_event_type,
- _ip INET,
- _cash dm_money,
- _free_mb dm_money,
- _reason TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
- _pk_user INTEGER;
- _pk_session_log INTEGER;
-BEGIN
- SELECT pk_user INTO _pk_user
- FROM tb_users
- WHERE name = _login;
- IF _pk_user IS NULL THEN
- RAISE EXCEPTION 'User % not found', _login;
- RETURN -1;
- END IF;
-
- INSERT INTO tb_sessions_log
- (fk_user,
- event_time,
- event_type,
- ip,
- cash,
- free_mb,
- reason)
- VALUES
- (_pk_user,
- _event_time,
- _event_type,
- _ip,
- _cash,
- _free_mb,
- _reason);
-
- SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
-
- RETURN _pk_session_log;
-END;
-$$ LANGUAGE plpgsql;
-
-UPDATE tb_info SET version = 6;
+++ /dev/null
-/*
- * DB migration from v00 to v01 (firebird)
- */
-
-alter table tb_users add disabled_detail_stat dm_bool;
-
-drop procedure sp_add_user;
-
-set term !! ;
-create procedure sp_add_user(name varchar(32), dirs integer)
-as
-declare variable pk_user integer;
-declare variable pk_stat integer;
-begin
- pk_user = gen_id(gn_pk_user, 1);
- insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
- pk_stat = gen_id(gn_pk_stat, 1);
- insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
- while (dirs > 0) do
- begin
- insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
- dirs = dirs - 1;
- end
-end!!
-set term ; !!
+++ /dev/null
-/*
- * 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
- */
-
-/*
- *****************************************************************************
- *
- * Скрипт генерации структуры базы для хранения данных Stargazer-a
- *
- * Примечание.
- * * dm_permission_flag. Представляет собой битовую маску - rw.
- * r - чтение, w - изменение параметра.
- * 0 - дествие запрещено, 1 - действие разрешено
- *
- * * dm_traff_type. Число определяющее тип подсчета трафика:
- * 0 - up - считается по upload
- * 1 - down - считается по download
- * 2 - max - считается по максимальному среди upload/download
- * 3 - up+down - считается по сумме upload и download
- *
- * * dm_session_event_type. Указывает тип записи в логе о сессии.
- * 'c' - connect, 'd' - disconnect.
- *
- *****************************************************************************
- */
-
-/*
- * $Revision: 1.12 $
- * $Date: 2009/08/20 14:58:43 $
- */
-
-
-/*
- *****************************************************************************
- * -= Создание типов и доменов =-
- *****************************************************************************
- */
-
-CREATE DOMAIN dm_name AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
-CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
- CHECK ( value BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_money AS NUMERIC(12, 4) NOT NULL DEFAULT 0;
-CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
- CHECK ( value BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_day AS SMALLINT NOT NULL
- CHECK ( value BETWEEN 0 AND 31 )
- DEFAULT 0;
-CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
- CHECK ( value = 'c' OR value = 'd' );
-
-/*
- *****************************************************************************
- * -= Создание таблиц =-
- *****************************************************************************
- */
-
-CREATE TABLE tb_info
-(
- version INTEGER NOT NULL
-);
-
-CREATE TABLE tb_admins
-(
- pk_admin SERIAL PRIMARY KEY,
- login dm_name UNIQUE,
- passwd dm_password NOT NULL,
- chg_conf dm_permission_flag,
- chg_password dm_permission_flag,
- chg_stat dm_permission_flag,
- chg_cash dm_permission_flag,
- usr_add_del dm_permission_flag,
- chg_tariff dm_permission_flag,
- chg_admin dm_permission_flag,
- chg_service dm_permission_flag,
- chg_corporation dm_permission_flag
-);
-
-CREATE TABLE tb_tariffs
-(
- pk_tariff SERIAL PRIMARY KEY,
- name dm_name UNIQUE,
- fee dm_money,
- free dm_money,
- passive_cost dm_money,
- traff_type dm_traff_type
-);
-
-CREATE TABLE tb_tariffs_params
-(
- pk_tariff_param SERIAL PRIMARY KEY,
- fk_tariff INTEGER NOT NULL,
- dir_num SMALLINT NOT NULL,
- price_day_a dm_money,
- price_day_b dm_money,
- price_night_a dm_money,
- price_night_b dm_money,
- threshold INTEGER NOT NULL,
- time_day_begins TIME NOT NULL,
- time_day_ends TIME NOT NULL,
-
- FOREIGN KEY (fk_tariff)
- REFERENCES tb_tariffs (pk_tariff)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_corporations
-(
- pk_corporation SERIAL PRIMARY KEY,
- name dm_name UNIQUE,
- cash dm_money
-);
-
-CREATE TABLE tb_users
-(
- pk_user SERIAL PRIMARY KEY,
- fk_tariff INTEGER,
- fk_tariff_change INTEGER,
- fk_corporation INTEGER,
- address VARCHAR(256) NOT NULL,
- always_online BOOLEAN NOT NULL,
- credit dm_money,
- credit_expire TIMESTAMP NOT NULL,
- disabled BOOLEAN NOT NULL,
- disabled_detail_stat BOOLEAN NOT NULL,
- email VARCHAR(256) NOT NULL,
- grp dm_name,
- note TEXT NOT NULL,
- passive BOOLEAN NOT NULL,
- passwd dm_password,
- phone VARCHAR(256) NOT NULL,
- name dm_name UNIQUE,
- real_name VARCHAR(256) NOT NULL,
- cash dm_money,
- free_mb dm_money,
- last_activity_time TIMESTAMP NOT NULL,
- last_cash_add dm_money,
- last_cash_add_time TIMESTAMP NOT NULL,
- passive_time INTEGER NOT NULL,
-
- FOREIGN KEY (fk_tariff)
- REFERENCES tb_tariffs (pk_tariff)
- ON DELETE CASCADE,
- FOREIGN KEY (fk_tariff_change)
- REFERENCES tb_tariffs (pk_tariff)
- ON DELETE CASCADE,
- FOREIGN KEY (fk_corporation)
- REFERENCES tb_corporations (pk_corporation)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_detail_stats
-(
- pk_detail_stat BIGSERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- dir_num SMALLINT NOT NULL,
- ip INET NOT NULL,
- download BIGINT NOT NULL,
- upload BIGINT NOT NULL,
- cost dm_money,
- from_time TIMESTAMP NOT NULL,
- till_time TIMESTAMP NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_services
-(
- pk_service SERIAL PRIMARY KEY,
- name dm_name UNIQUE,
- comment TEXT NOT NULL,
- cost dm_money,
- pay_day dm_day
-);
-
-CREATE TABLE tb_users_services
-(
- pk_user_service SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- fk_service INTEGER NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE,
- FOREIGN KEY (fk_service)
- REFERENCES tb_services (pk_service)
-);
-
-CREATE TABLE tb_messages
-(
- pk_message SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- ver SMALLINT NOT NULL,
- msg_type SMALLINT NOT NULL,
- last_send_time TIMESTAMP NOT NULL,
- creation_time TIMESTAMP NOT NULL,
- show_time INTEGER NOT NULL,
- repeat SMALLINT NOT NULL,
- repeat_period INTEGER NOT NULL,
- msg_text TEXT NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_stats_traffic
-(
- pk_stat_traffic BIGSERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- stats_date DATE NOT NULL,
- dir_num SMALLINT NOT NULL,
- download BIGINT NOT NULL,
- upload BIGINT NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE,
- UNIQUE (fk_user, stats_date, dir_num)
-);
-
-CREATE TABLE tb_users_data
-(
- pk_user_data SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- num SMALLINT NOT NULL,
- data VARCHAR(256) NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_allowed_ip
-(
- pk_allowed_ip SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- ip INET NOT NULL,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_sessions_log
-(
- pk_session_log SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- event_time TIMESTAMP NOT NULL,
- event_type dm_session_event_type,
- ip INET NOT NULL,
- cash dm_money,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_sessions_data
-(
- pk_session_data SERIAL PRIMARY KEY,
- fk_session_log INTEGER NOT NULL,
- dir_num SMALLINT NOT NULL,
- session_upload BIGINT NOT NULL,
- session_download BIGINT NOT NULL,
- month_upload BIGINT NOT NULL,
- month_download BIGINT NOT NULL,
-
- FOREIGN KEY (fk_session_log)
- REFERENCES tb_sessions_log (pk_session_log)
- ON DELETE CASCADE
-);
-
-CREATE TABLE tb_parameters
-(
- pk_parameter SERIAL PRIMARY KEY,
- name dm_name UNIQUE
-);
-
-CREATE TABLE tb_params_log
-(
- pk_param_log SERIAL PRIMARY KEY,
- fk_user INTEGER NOT NULL,
- fk_parameter INTEGER NOT NULL,
- fk_admin INTEGER NOT NULL,
- ip INET NOT NULL,
- event_time TIMESTAMP NOT NULL,
- from_val VARCHAR(256),
- to_val VARCHAR(256),
- comment TEXT,
-
- FOREIGN KEY (fk_user)
- REFERENCES tb_users (pk_user)
- ON DELETE CASCADE,
- FOREIGN KEY (fk_parameter)
- REFERENCES tb_parameters (pk_parameter),
- FOREIGN KEY (fk_admin)
- REFERENCES tb_admins (pk_admin)
- ON DELETE CASCADE
-);
-
-/*
- *****************************************************************************
- * -= Создание хранимых процедур =-
- *****************************************************************************
- */
-
-CREATE FUNCTION sp_add_message(_login dm_name,
- _ver SMALLINT,
- _msg_type SMALLINT,
- _last_send_time TIMESTAMP,
- _creation_time TIMESTAMP,
- _show_time INTEGER,
- _repeat SMALLINT,
- _repeat_period INTEGER,
- _msg_text TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
- _pk_user INTEGER;
-BEGIN
- SELECT pk_user INTO _pk_user
- FROM tb_users
- WHERE name = _login;
- IF _pk_user IS NULL THEN
- RAISE EXCEPTION 'User % not found', _login;
- RETURN -1;
- END IF;
- INSERT INTO tb_messages
- (fk_user,
- ver,
- msg_type,
- last_send_time,
- creation_time,
- show_time,
- repeat,
- repeat_period,
- msg_text)
- VALUES
- (_pk_user,
- _ver,
- _msg_type,
- _last_send_time,
- _creation_time,
- _show_time,
- _repeat,
- _repeat_period,
- _msg_text);
- RETURN CURRVAL('tb_messages_pk_message_seq');
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_tariff(_name dm_name, _dirs INTEGER)
-RETURNS INTEGER
-AS $$
-DECLARE
- pk_tariff INTEGER;
-BEGIN
- INSERT INTO tb_tariffs
- (name,
- fee,
- free,
- passive_cost,
- traff_type)
- VALUES
- (_name,
- 0, 0, 0, 0);
- SELECT CURRVAL('tb_tariffs_pk_tariff_seq') INTO pk_tariff;
- FOR i IN 1.._dirs LOOP
- INSERT INTO tb_tariffs_params
- (fk_tariff,
- dir_num,
- price_day_a,
- price_day_b,
- price_night_a,
- price_night_b,
- threshold,
- time_day_begins,
- time_day_ends)
- VALUES
- (pk_tariff,
- i - 1,
- 0, 0, 0, 0, 0,
- CAST('1970-01-01 00:00:00+00' AS TIMESTAMP),
- CAST('1970-01-01 00:00:00+00' AS TIMESTAMP));
- END LOOP;
- RETURN pk_tariff;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_user(_name dm_name)
-RETURNS INTEGER
-AS $$
-DECLARE
- pk_user INTEGER;
-BEGIN
- INSERT INTO tb_users
- (fk_tariff,
- fk_tariff_change,
- fk_corporation,
- address,
- always_online,
- credit,
- credit_expire,
- disabled,
- disabled_detail_stat,
- email,
- grp,
- note,
- passive,
- passwd,
- phone,
- name,
- real_name,
- cash,
- free_mb,
- last_activity_time,
- last_cash_add,
- last_cash_add_time,
- passive_time)
- VALUES
- (NULL, NULL, NULL, '', FALSE, 0, CAST('now' AS TIMESTAMP),
- FALSE, FALSE, '', '', '', FALSE, '', '', _name, '', 0, 0,
- CAST('now' AS TIMESTAMP), 0, CAST('now' AS TIMESTAMP), 0);
- SELECT CURRVAL('tb_users_pk_user_seq') INTO pk_user;
- RETURN pk_user;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_stats_traffic (_login dm_name,
- _stats_date DATE,
- _dir_num SMALLINT,
- _upload BIGINT,
- _download BIGINT)
-RETURNS INTEGER
-AS $$
-DECLARE
- _pk_user INTEGER;
-BEGIN
- SELECT pk_user INTO _pk_user
- FROM tb_users
- WHERE name = _login;
-
- IF _pk_user IS NULL THEN
- RAISE EXCEPTION 'User % not found', _login;
- RETURN -1;
- END IF;
-
- UPDATE tb_stats_traffic SET
- upload = _upload,
- download = _download
- WHERE fk_user = _pk_user AND
- dir_num = _dir_num AND
- stats_date = _stats_date;
-
- IF NOT FOUND THEN
- INSERT INTO tb_stats_traffic
- (fk_user,
- dir_num,
- stats_date,
- upload,
- download)
- VALUES
- (_pk_user,
- _dir_num,
- _stats_date,
- _upload,
- _download);
- END IF;
-
- RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_set_user_data (_pk_user INTEGER,
- _num SMALLINT,
- _data VARCHAR(256))
-RETURNS INTEGER
-AS $$
-BEGIN
- UPDATE tb_users_data SET
- data = _data
- WHERE fk_user = _pk_user AND num = _num;
-
- IF NOT FOUND THEN
- INSERT INTO tb_users_data
- (fk_user,
- num,
- data)
- VALUES
- (_pk_user,
- _num,
- _data);
- END IF;
-
- RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_param_log_entry(_login dm_name,
- _admin_login dm_name,
- _ip INET,
- _param_name dm_name,
- _event_time TIMESTAMP,
- _from VARCHAR(256),
- _to VARCHAR(256),
- _comment TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
- _pk_user INTEGER;
- _pk_admin INTEGER;
- _pk_param INTEGER;
-BEGIN
- SELECT pk_user INTO _pk_user
- FROM tb_users
- WHERE name = _login;
- IF _pk_user IS NULL THEN
- RAISE EXCEPTION 'User % not found', _login;
- RETURN -1;
- END IF;
-
- SELECT pk_admin INTO _pk_admin
- FROM tb_admins
- WHERE login = _admin_login;
- IF _pk_admin IS NULL THEN
- RAISE EXCEPTION 'Admin % not found', _admin_login;
- RETURN -1;
- END IF;
-
- SELECT pk_parameter INTO _pk_param
- FROM tb_parameters
- WHERE name = _param_name;
-
- IF NOT FOUND THEN
- INSERT INTO tb_parameters (name) VALUES (_param_name);
- SELECT CURRVAL('tb_parameters_pk_parameter_seq') INTO _pk_param;
- END IF;
-
- INSERT INTO tb_params_log
- (fk_user,
- fk_parameter,
- fk_admin,
- ip,
- event_time,
- from_val,
- to_val,
- comment)
- VALUES
- (_pk_user,
- _pk_param,
- _pk_admin,
- _ip,
- _event_time,
- _from,
- _to,
- _comment);
-
- RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
- _event_time TIMESTAMP,
- _event_type dm_session_event_type,
- _ip INET,
- _cash dm_money)
-RETURNS INTEGER
-AS $$
-DECLARE
- _pk_user INTEGER;
- _pk_session_log INTEGER;
-BEGIN
- SELECT pk_user INTO _pk_user
- FROM tb_users
- WHERE name = _login;
- IF _pk_user IS NULL THEN
- RAISE EXCEPTION 'User % not found', _login;
- RETURN -1;
- END IF;
-
- INSERT INTO tb_sessions_log
- (fk_user,
- event_time,
- event_type,
- ip,
- cash)
- VALUES
- (_pk_user,
- _event_time,
- _event_type,
- _ip,
- _cash);
-
- SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
-
- RETURN _pk_session_log;
-END;
-$$ LANGUAGE plpgsql;
-
-/*
- *****************************************************************************
- * -= Создание администратора =-
- *
- * Двоичные права доступа пока не поддерживаются, по этому используются флаги
- *****************************************************************************
- */
-INSERT INTO tb_admins
- (login, passwd,
- chg_conf, chg_password, chg_stat,
- chg_cash, usr_add_del, chg_tariff,
- chg_admin, chg_service, chg_corporation)
-VALUES
- ('admin',
- 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk',
- 1, 1, 1, 1, 1, 1, 1, 1, 1);
-INSERT INTO tb_admins
- (login, passwd,
- chg_conf, chg_password, chg_stat,
- chg_cash, usr_add_del, chg_tariff,
- chg_admin, chg_service, chg_corporation)
-VALUES
- ('@stargazer',
- '',
- 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-INSERT INTO tb_info
- (version)
-VALUES
- (5);
+++ /dev/null
-/*
- * 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
- */
-
-/*
- *****************************************************************************
- *
- * Скрипт генерации структуры базы для хранения данных Stargazer-a
- *
- * $Id: 00-base-00.sql,v 1.7 2010/01/06 14:41:13 faust Exp $
- *
- * Примечание.
- * * dm_permission_flag. Представляет собой битовую маску - rw.
- * r - чтение, w - изменение параметра.
- * 0 - дествие запрещено, 1 - действие разрешено
- *
- * * dm_traff_type. Число определяющее тип подсчета трафика:
- * 0 - up - считается по upload
- * 1 - down - считается по download
- * 2 - max - считается по максимальному среди upload/download
- * 3 - up+down - считается по сумме upload и download
- *
- * * dm_ip. IP адресс в виде четырех байтового целого числа со знаком.
- * Выполнять приведение к знаковуму целому при занесении IP в БД!!!
- *
- * * dm_period. Задает периодичность показа сообщения пользователю.
- * Период задается целым числом (int16). Если значение равно 0 то
- * сообщение показывается только при подключении пользователя.
- * Также этот домен определяет промежуток времени в течении которого
- * сообщение показывается пользователю.
- *
- * * dm_session_event_type. Указывает тип записи в логе о сессии.
- * 'c' - connect, 'd' - disconnect.
- *
- *****************************************************************************
- */
-
-/*
- * CONNECT 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456';
- * DROP DATABASE;
- *
- * CREATE DATABASE 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456' DEFAULT CHARACTER SET UTF8;
- */
-
-
-
-/*
- *****************************************************************************
- * -= Создание ДОМЕНОВ =-
- *****************************************************************************
- */
-
-CREATE DOMAIN dm_id AS INTEGER NOT NULL;
-CREATE DOMAIN dm_null_id AS INTEGER;
-CREATE DOMAIN dm_login AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_tariff_name AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_group_name AS VARCHAR(32);
-CREATE DOMAIN dm_corporation_name AS VARCHAR(32);
-CREATE DOMAIN dm_parameter_name AS VARCHAR(32);
-
-CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
-/* bitmask - rw => Read, Write */
-CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
- CHECK ( VALUE BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_money AS NUMERIC(10,6) NOT NULL;
-/* (0, 1, 2, 3) => (up, down, max, up+down) */
-CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
- CHECK ( VALUE BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_dir_num AS SMALLINT NOT NULL;
-CREATE DOMAIN dm_num AS SMALLINT NOT NULL;
-CREATE DOMAIN dm_traffic_mb AS INTEGER NOT NULL;
-CREATE DOMAIN dm_traffic_byte AS BIGINT NOT NULL;
-CREATE DOMAIN dm_time AS TIME NOT NULL;
-CREATE DOMAIN dm_moment AS TIMESTAMP NOT NULL;
-CREATE DOMAIN dm_credit_moment AS TIMESTAMP;
-CREATE DOMAIN dm_ip AS INTEGER NOT NULL;
-CREATE DOMAIN dm_mask AS INTEGER NOT NULL;
-CREATE DOMAIN dm_user_address AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_bool AS CHAR(1) NOT NULL
- CHECK ( VALUE IN ('0', '1', 't', 'f', 'T', 'F') );
-CREATE DOMAIN dm_email AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_note AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_phone AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_user_name AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_service_comment AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_service_name AS VARCHAR(32) DEFAULT '';
-
-CREATE DOMAIN dm_pay_day AS SMALLINT NOT NULL
- CHECK ( VALUE BETWEEN 0 AND 31 );
-CREATE DOMAIN dm_period AS INTEGER NOT NULL;
-CREATE DOMAIN dm_counter AS SMALLINT NOT NULL;
-
-CREATE DOMAIN dm_message_ver AS INTEGER NOT NULL;
-CREATE DOMAIN dm_message_type AS INTEGER NOT NULL;
-
-CREATE DOMAIN dm_message AS VARCHAR(256) NOT NULL;
-CREATE DOMAIN dm_user_data AS VARCHAR(256) NOT NULL;
-CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
- CHECK ( VALUE IN ('c', 'd') );
-CREATE DOMAIN dm_char_value AS VARCHAR(64) NOT NULL;
-CREATE DOMAIN dm_date AS DATE NOT NULL;
-
-
-
-/*
- *****************************************************************************
- * -= Создание ТАБЛИЦ =-
- *****************************************************************************
- */
-
-CREATE TABLE tb_admins
-(
- pk_admin dm_id PRIMARY KEY,
- login dm_login UNIQUE,
- passwd dm_password,
- chg_conf dm_permission_flag,
- chg_password dm_permission_flag,
- chg_stat dm_permission_flag,
- chg_cash dm_permission_flag,
- usr_add_del dm_permission_flag,
- chg_tariff dm_permission_flag,
- chg_admin dm_permission_flag,
- chg_service dm_permission_flag,
- chg_corporation dm_permission_flag
-);
-
-CREATE TABLE tb_tariffs
-(
- pk_tariff dm_id PRIMARY KEY,
- name dm_tariff_name UNIQUE,
- fee dm_money,
- free dm_money,
- passive_cost dm_money,
- traff_type dm_traff_type
-);
-
-CREATE TABLE tb_tariffs_params
-(
- pk_tariff_param dm_id PRIMARY KEY,
- fk_tariff dm_id,
- dir_num dm_dir_num,
- price_day_a dm_money,
- price_day_b dm_money,
- price_night_a dm_money,
- price_night_b dm_money,
- threshold dm_traffic_mb,
- time_day_begins dm_time,
- time_day_ends dm_time,
-
- FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff)
-);
-
-CREATE TABLE tb_corporations
-(
- pk_corporation dm_id PRIMARY KEY,
- name dm_corporation_name UNIQUE,
- cash dm_money
-);
-
-CREATE TABLE tb_users
-(
- pk_user dm_id PRIMARY KEY,
- fk_tariff dm_null_id,
- fk_tariff_change dm_null_id,
- fk_corporation dm_null_id,
- address dm_user_address,
- always_online dm_bool,
- credit dm_money,
- credit_expire dm_credit_moment,
- disabled dm_bool,
- disabled_detail_stat dm_bool,
- email dm_email,
- grp dm_group_name,
- note dm_note,
- passive dm_bool,
- passwd dm_password,
- phone dm_phone,
- name dm_login UNIQUE,
- real_name dm_user_name,
-
- FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff),
- FOREIGN KEY (fk_tariff_change) REFERENCES tb_tariffs (pk_tariff),
- FOREIGN KEY (fk_corporation) REFERENCES tb_corporations (pk_corporation)
-);
-
-CREATE TABLE tb_detail_stats
-(
- pk_detail_stat dm_id PRIMARY KEY,
- fk_user dm_id,
- dir_num dm_dir_num,
- ip dm_ip,
- download dm_traffic_byte,
- upload dm_traffic_byte,
- cost dm_money,
- from_time dm_moment,
- till_time dm_moment,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_services
-(
- pk_service dm_id PRIMARY KEY,
- name dm_service_name UNIQUE,
- comment dm_service_comment,
- cost dm_money,
- pay_day dm_pay_day
-);
-
-CREATE TABLE tb_users_services
-(
- pk_user_service dm_id PRIMARY KEY,
- fk_user dm_id,
- fk_service dm_id,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
- FOREIGN KEY (fk_service) REFERENCES tb_services (pk_service)
-);
-
-CREATE TABLE tb_messages
-(
- pk_message dm_id PRIMARY KEY,
- fk_user dm_id,
- ver dm_message_ver,
- msg_type dm_message_type,
- last_send_time dm_period,
- creation_time dm_period,
- show_time dm_period,
- repeat dm_counter,
- repeat_period dm_period,
- msg_text dm_message,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_stats
-(
- pk_stat dm_id PRIMARY KEY,
- fk_user dm_id,
- cash dm_money,
- free_mb dm_money,
- last_activity_time dm_moment,
- last_cash_add dm_money,
- last_cash_add_time dm_moment,
- passive_time dm_period,
- stats_date dm_date,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_stats_traffic
-(
- pk_stat_traffic dm_id PRIMARY KEY,
- fk_stat dm_id,
- dir_num dm_dir_num,
- download dm_traffic_byte,
- upload dm_traffic_byte,
-
- FOREIGN KEY (fk_stat) REFERENCES tb_stats (pk_stat)
-);
-
-CREATE TABLE tb_users_data
-(
- pk_user_data dm_id PRIMARY KEY,
- fk_user dm_id,
- num dm_num,
- data dm_user_data,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_allowed_ip
-(
- pk_allowed_ip dm_id PRIMARY KEY,
- fk_user dm_id,
- ip dm_ip,
- mask dm_mask,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_sessions_log
-(
- pk_session_log dm_id PRIMARY KEY,
- fk_user dm_id,
- event_time dm_moment,
- event_type dm_session_event_type,
- ip dm_ip,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_sessions_data
-(
- pk_session_data dm_id PRIMARY KEY,
- fk_session_log dm_id,
- dir_num dm_dir_num,
- session_upload dm_traffic_byte,
- session_download dm_traffic_byte,
- month_upload dm_traffic_byte,
- month_download dm_traffic_byte,
-
- FOREIGN KEY (fk_session_log) REFERENCES tb_sessions_log (pk_session_log)
-);
-
-CREATE TABLE tb_parameters
-(
- pk_parameter dm_id PRIMARY KEY,
- name dm_parameter_name UNIQUE
-);
-
-CREATE TABLE tb_params_log
-(
- pk_param_log dm_id PRIMARY KEY,
- fk_user dm_id,
- fk_parameter dm_id,
- event_time dm_moment,
- from_val dm_char_value,
- to_val dm_char_value,
- comment dm_service_comment,
-
- FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
- FOREIGN KEY (fk_parameter) REFERENCES tb_parameters (pk_parameter)
-);
-
-
-/*
- *****************************************************************************
- * -= Создание ИНДЕКСОВ =-
- *****************************************************************************
- */
-
-
-
-/*
- *****************************************************************************
- * -= Создание ГЕНЕРАТОРОВ =-
- *****************************************************************************
- */
-
-CREATE GENERATOR gn_pk_admin;
-SET GENERATOR gn_pk_admin TO 0;
-CREATE GENERATOR gn_pk_tariff;
-SET GENERATOR gn_pk_tariff TO 0;
-CREATE GENERATOR gn_pk_tariff_param;
-SET GENERATOR gn_pk_tariff_param TO 0;
-CREATE GENERATOR gn_pk_corporation;
-SET GENERATOR gn_pk_corporation TO 0;
-CREATE GENERATOR gn_pk_user;
-SET GENERATOR gn_pk_user TO 0;
-CREATE GENERATOR gn_pk_detail_stat;
-SET GENERATOR gn_pk_detail_stat TO 0;
-CREATE GENERATOR gn_pk_service;
-SET GENERATOR gn_pk_service TO 0;
-CREATE GENERATOR gn_pk_user_service;
-SET GENERATOR gn_pk_user_service TO 0;
-CREATE GENERATOR gn_pk_message;
-SET GENERATOR gn_pk_message TO 0;
-CREATE GENERATOR gn_pk_stat;
-SET GENERATOR gn_pk_stat TO 0;
-CREATE GENERATOR gn_pk_stat_traffic;
-SET GENERATOR gn_pk_stat_traffic TO 0;
-CREATE GENERATOR gn_pk_user_data;
-SET GENERATOR gn_pk_user_data TO 0;
-CREATE GENERATOR gn_pk_allowed_ip;
-SET GENERATOR gn_pk_allowed_ip TO 0;
-CREATE GENERATOR gn_pk_session;
-SET GENERATOR gn_pk_session TO 0;
-CREATE GENERATOR gn_pk_session_log;
-SET GENERATOR gn_pk_session_log TO 0;
-CREATE GENERATOR gn_pk_session_data;
-SET GENERATOR gn_pk_session_data TO 0;
-CREATE GENERATOR gn_pk_parameter;
-SET GENERATOR gn_pk_parameter TO 0;
-CREATE GENERATOR gn_pk_param_log;
-SET GENERATOR gn_pk_param_log TO 0;
-
-
-/*
- *****************************************************************************
- * -= Создание ТРИГГЕРОВ =-
- *****************************************************************************
- */
-
-SET TERM !! ;
-CREATE TRIGGER tr_admin_bi FOR tb_admins
-ACTIVE BEFORE INSERT POSITION 0
-AS
-BEGIN
- IF (new.pk_admin IS NULL)
- THEN new.pk_admin = GEN_ID(gn_pk_admin, 1);
-END !!
-SET TERM ; !!
-
-set term !! ;
-create trigger tr_tariff_param_bi for tb_tariffs_params active
-before insert position 0
-as
-begin
- if (new.pk_tariff_param is null)
- then new.pk_tariff_param = gen_id(gn_pk_tariff_param, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_corporation_bi for tb_corporations active
-before insert position 0
-as
-begin
- if (new.pk_corporation is null)
- then new.pk_corporation = gen_id(gn_pk_corporation, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_detail_stat_bi for tb_detail_stats active
-before insert position 0
-as
-begin
- if (new.pk_detail_stat is null)
- then new.pk_detail_stat = gen_id(gn_pk_detail_stat, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_service_bi for tb_services active
-before insert position 0
-as
-begin
- if (new.pk_service is null)
- then new.pk_service = gen_id(gn_pk_service, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_user_service_bi for tb_users_services active
-before insert position 0
-as
-begin
- if (new.pk_user_service is null)
- then new.pk_user_service = gen_id(gn_pk_user_service, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_stat_traffic_bi for tb_stats_traffic active
-before insert position 0
-as
-begin
- if (new.pk_stat_traffic is null)
- then new.pk_stat_traffic = gen_id(gn_pk_stat_traffic, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_user_data_bi for tb_users_data active
-before insert position 0
-as
-begin
- if (new.pk_user_data is null)
- then new.pk_user_data = gen_id(gn_pk_user_data, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_allowed_ip_bi for tb_allowed_ip active
-before insert position 0
-as
-begin
- if (new.pk_allowed_ip is null)
- then new.pk_allowed_ip = gen_id(gn_pk_allowed_ip, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_session_data_bi for tb_sessions_data active
-before insert position 0
-as
-begin
- if (new.pk_session_data is null)
- then new.pk_session_data = gen_id(gn_pk_session_data, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_parameter_bi for tb_parameters active
-before insert position 0
-as
-begin
- if (new.pk_parameter is null)
- then new.pk_parameter = gen_id(gn_pk_parameter, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_param_log_bi for tb_params_log active
-before insert position 0
-as
-begin
- if (new.pk_param_log is null)
- then new.pk_param_log = gen_id(gn_pk_param_log, 1);
-end !!
-set term ; !!
-
-/*
- *****************************************************************************
- * -= Создание stored procedure =-
- *****************************************************************************
- */
-
-/*
- * Add a message returning it's ID
- */
-set term !! ;
-create procedure sp_add_message(pk_message integer, login varchar(32), ver integer, msg_type integer, last_send_time integer, creation_time integer, show_time integer, repeat integer, repeat_period integer, msg_text varchar(256))
-returns(res integer)
-as
-begin
- if (:pk_message is null) then
- begin
- pk_message = gen_id(gn_pk_message, 1);
- insert into tb_messages values (:pk_message,
- (select pk_user from tb_users where name = :login),
- :ver,
- :msg_type,
- :last_send_time,
- :creation_time,
- :show_time,
- :repeat,
- :repeat_period,
- :msg_text);
- end
- else
- begin
- update tb_messages set fk_user = (select pk_user from tb_users where name = :login),
- ver = :ver,
- msg_type = :msg_type,
- last_send_time = :last_send_time,
- creation_time = :creation_time,
- show_time = :show_time,
- repeat = :repeat_period,
- repeat_period = :repeat_period,
- msg_text = :msg_text
- where pk_message = :pk_message;
- end
- res = :pk_message;
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_service(name varchar(32))
-as
-declare variable pk_service integer;
-begin
- select pk_service from tb_services where name = :name into pk_service;
- if (pk_service is not null) then
- begin
- delete from tb_users_services where fk_service = :pk_service;
- delete from tb_services where pk_service = :pk_service;
- end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_tariff(name varchar(32), dirs integer)
-as
-declare variable pk_tariff integer;
-begin
- pk_tariff = gen_id(gn_pk_tariff, 1);
- insert into tb_tariffs (pk_tariff, name, fee, free, passive_cost, traff_type) values (:pk_tariff, :name, 0, 0, 0, 0);
- while (dirs > 0) do
- begin
- insert into tb_tariffs_params (fk_tariff, dir_num, price_day_a,
- price_day_b, price_night_a, price_night_b,
- threshold, time_day_begins, time_day_ends)
- values (:pk_tariff, :dirs - 1, 0, 0, 0, 0, 0, '0:0', '0:0');
- dirs = dirs - 1;
- end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_tariff(name varchar(32))
-as
-declare variable pk_tariff integer;
-begin
- select pk_tariff from tb_tariffs where name = :name into pk_tariff;
- if (pk_tariff is not null) then
- begin
- delete from tb_tariffs_params where fk_tariff = :pk_tariff;
- delete from tb_tariffs where pk_tariff = :pk_tariff;
- end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_user(name varchar(32), dirs integer)
-as
-declare variable pk_user integer;
-declare variable pk_stat integer;
-begin
- pk_user = gen_id(gn_pk_user, 1);
- insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
- pk_stat = gen_id(gn_pk_stat, 1);
- insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
- while (dirs > 0) do
- begin
- insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
- dirs = dirs - 1;
- end
-end!!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_user(name varchar(32))
-as
-declare variable pk_user integer;
-begin
- select pk_user from tb_users where name = :name into pk_user;
- if (pk_user is not null) then
- begin
- delete from tb_users_services where fk_user = :pk_user;
- delete from tb_params_log where fk_user = :pk_user;
- delete from tb_detail_stats where fk_user = :pk_user;
- delete from tb_stats_traffic where fk_stat in (select pk_stat from tb_stats where fk_user = :pk_user);
- delete from tb_stats where fk_user = :pk_user;
- delete from tb_sessions_data where fk_session_log in (select pk_session_log from tb_sessions_log where fk_user = :pk_user);
- delete from tb_sessions_log where fk_user = :pk_user;
- delete from tb_allowed_ip where fk_user = :pk_user;
- delete from tb_users_data where fk_user = :pk_user;
- delete from tb_messages where fk_user = :pk_user;
- delete from tb_users where pk_user = :pk_user;
- end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_append_session_log(name varchar(32), event_time timestamp, event_type char(1), ip integer)
-returns(pk_session_log integer)
-as
-begin
- pk_session_log = gen_id(gn_pk_session_log, 1);
- insert into tb_sessions_log (pk_session_log, fk_user, event_time, event_type, ip) values (:pk_session_log, (select pk_user from tb_users where name = :name), :event_time, :event_type, :ip);
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_stat(name varchar(32), cash numeric(10,6), free_mb numeric(10,6), last_activity_time timestamp, last_cash_add numeric(10,6), last_cash_add_time timestamp, passive_time integer, stats_date date)
-returns(pk_stat integer)
-as
-begin
- pk_stat = gen_id(gn_pk_stat, 1);
- insert into tb_stats (pk_stat, fk_user, cash, free_mb, last_activity_time, last_cash_add, last_cash_add_time, passive_time, stats_date) values (:pk_stat, (select pk_user from tb_users where name = :name), :cash, :free_mb, :last_activity_time, :last_cash_add, :last_cash_add_time, :passive_time, :stats_date);
-end !!
-set term ; !!
-
-/*
- *****************************************************************************
- * -= Создание администратора =-
- *****************************************************************************
- */
-
-insert into tb_admins values(0, 'admin', 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk', 1, 1, 1, 1, 1, 1, 1, 1, 1);
-
-/* EOF */
+++ /dev/null
-/*
- * DB migration from v00 to v01 (mysql)
- */
-
-ALTER TABLE users ADD DisabledDetailStat INT(3) DEFAULT 0;
+++ /dev/null
-/*
- * DB migration from v01 to v02 (mysql)
- */
-
-ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month';
-
-CREATE TABLE info
-(
- version INTEGER NOT NULL
-);
-
-INSERT INTO info VALUES (1);
+++ /dev/null
-/*
- * DB migration from v01 to v02 (postgres)
- */
-BEGIN;
-
-CREATE DOMAIN DM_TARIFF_PERIOD AS TEXT NOT NULL
- CONSTRAINT valid_value CHECK (VALUE = 'month' OR VALUE = 'day');
-
-ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
-
-UPDATE tb_info SET version = 7;
-
-COMMIT;
+++ /dev/null
-/*
- * DB migration from v01 to v02 (firebird)
- */
-
-CREATE DOMAIN DM_TARIFF_PERIOD AS VARCHAR(32) NOT NULL
- CHECK (VALUE = 'month' OR VALUE = 'day');
-
-ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
-
-CREATE TABLE tb_info
-(
- version INTEGER NOT NULL
-);
-
-INSERT INTO tb_info VALUES (1);
+++ /dev/null
-/*
- * DB migration from v02 to v03 (postgres)
- */
-BEGIN;
-
-CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL
- CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
-
-ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
-ALTER TABLE tb_tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
-
-UPDATE tb_info SET version = 8;
-
-COMMIT;
+++ /dev/null
-/*
- * DB migration from v02 to v03 (firebird)
- */
-
-CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS VARCHAR(32) NOT NULL
- CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
-
-ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
-ALTER TABLE tb_tariffs ADD change_policy_timeout DM_MOMENT DEFAULT '1970-01-01 00:00:00';
-
-UPDATE tb_tariffs SET change_policy = 'allow', change_policy_timeout = '1970-01-01 00:00:00';
-
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
-
-UPDATE tb_info SET version = 2;
+++ /dev/null
-password=geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa
-ChgConf=1
-ChgPassword=1
-ChgStat=1
-ChgCash=1
-UsrAddDel=1
-ChgTariff=1
-ChgAdmin=1
+++ /dev/null
-Fee=10.000000
-Free=0
-NoDiscount0=1
-NoDiscount1=1
-NoDiscount2=1
-NoDiscount3=1
-NoDiscount4=1
-NoDiscount5=1
-NoDiscount6=1
-NoDiscount7=1
-NoDiscount8=1
-NoDiscount9=1
-PassiveCost=0.000000
-PriceDayA0=0.000000
-PriceDayA1=0.750000
-PriceDayA2=0.000000
-PriceDayA3=0.000000
-PriceDayA4=0.000000
-PriceDayA5=0.000000
-PriceDayA6=0.000000
-PriceDayA7=0.000000
-PriceDayA8=0.000000
-PriceDayA9=0.000000
-PriceDayB0=0.000000
-PriceDayB1=0.750000
-PriceDayB2=0.000000
-PriceDayB3=0.000000
-PriceDayB4=0.000000
-PriceDayB5=0.000000
-PriceDayB6=0.000000
-PriceDayB7=0.000000
-PriceDayB8=0.000000
-PriceDayB9=0.000000
-PriceNightA0=1.000000
-PriceNightA1=0.000000
-PriceNightA2=0.000000
-PriceNightA3=0.000000
-PriceNightA4=0.000000
-PriceNightA5=0.000000
-PriceNightA6=0.000000
-PriceNightA7=0.000000
-PriceNightA8=0.000000
-PriceNightA9=0.000000
-PriceNightB0=1.000000
-PriceNightB1=0.000000
-PriceNightB2=0.000000
-PriceNightB3=0.000000
-PriceNightB4=0.000000
-PriceNightB5=0.000000
-PriceNightB6=0.000000
-PriceNightB7=0.000000
-PriceNightB8=0.000000
-PriceNightB9=0.000000
-SinglePrice0=1
-SinglePrice1=1
-SinglePrice2=0
-SinglePrice3=0
-SinglePrice4=0
-SinglePrice5=0
-SinglePrice6=0
-SinglePrice7=0
-SinglePrice8=0
-SinglePrice9=0
-Threshold0=0
-Threshold1=0
-Threshold2=0
-Threshold3=0
-Threshold4=0
-Threshold5=0
-Threshold6=0
-Threshold7=0
-Threshold8=0
-Threshold9=0
-Time0=0:0-0:0
-Time1=0:0-0:0
-Time2=0:0-0:0
-Time3=0:0-0:0
-Time4=0:0-0:0
-Time5=0:0-0:0
-Time6=0:0-0:0
-Time7=0:0-0:0
-Time8=0:0-0:0
-Time9=0:0-0:0
-TraffType=up+down
+++ /dev/null
-Address=
-AlwaysOnline=0
-CreationTime=1123487395
-Credit=0.000000
-CreditExpire=0
-Down=0
-Email=
-Group=
-Iface=eth1
-IP=192.168.1.1
-Note=
-Passive=0
-Password=123456
-Phone=
-RealName=
-Tariff=tariff
-TariffChange=
-Userdata0=
-Userdata1=
+++ /dev/null
-Cash=10.000000
-D0=0
-D1=0
-D2=0
-D3=0
-D4=0
-D5=0
-D6=0
-D7=0
-D8=0
-D9=0
-FreeMb=0.000000
-LastActivityTime=0
-LastCashAdd=0
-LastCashAddTime=0
-PassiveTime=0
-U0=0
-U1=0
-U2=0
-U3=0
-U4=0
-U5=0
-U6=0
-U7=0
-U8=0
-U9=0
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#include "store_loader.h"
-#include "plugin_mgr.h"
-#include "plugin_runner.h"
-#include "users_impl.h"
-#include "admins_impl.h"
-#include "tariffs_impl.h"
-#include "services_impl.h"
-#include "corps_impl.h"
-#include "traffcounter_impl.h"
-#include "settings_impl.h"
-#include "pidfile.h"
-#include "eventloop.h"
-#include "stg_timer.h"
-
-#include "stg/user.h"
-#include "stg/common.h"
-#include "stg/plugin.h"
-#include "stg/logger.h"
-#include "stg/scriptexecuter.h"
-#include "stg/version.h"
-
-#include <fstream>
-#include <vector>
-#include <set>
-#include <csignal>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib> // srandom, exit
-
-#include <unistd.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h> // S_IRUSR
-#include <fcntl.h> // create
-
-#ifdef DEBUG
- #define NO_DAEMON (1)
-#endif
-
-#define START_FILE "/._ST_ART_ED_"
-
-namespace
-{
-std::set<pid_t> executers;
-
-void StartTimer();
-int StartScriptExecuter(char * procName, int msgKey, int * msgID);
-int ForkAndWait(const std::string & confDir);
-void KillExecuters();
-
-//-----------------------------------------------------------------------------
-void StartTimer()
-{
-STG_LOGGER & WriteServLog = GetStgLogger();
-
-if (RunStgTimer())
- {
- WriteServLog("Cannot start timer. Fatal.");
- //printfd(__FILE__, "Cannot start timer. Fatal.\n");
- exit(1);
- }
-else
- {
- WriteServLog("Timer thread started successfully.");
- //printfd(__FILE__, "Timer thread started successfully.\n");
- }
-}
-//-----------------------------------------------------------------------------
-#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 pid = fork();
-
-switch (pid)
- {
- case -1:
- WriteServLog("Fork error!");
- return -1;
-
- case 0:
-#if defined(LINUX) || defined(DARWIN)
- Executer(*msgID, pid, procName);
-#else
- Executer(*msgID, pid);
-#endif
- return 1;
-
- default:
- if (executers.empty()) {
-#if defined(LINUX) || defined(DARWIN)
- Executer(*msgID, pid, NULL);
-#else
- Executer(*msgID, pid);
-#endif
- }
- executers.insert(pid);
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-#ifndef NO_DAEMON
-int ForkAndWait(const std::string & confDir)
-#else
-int ForkAndWait(const std::string &)
-#endif
-{
-#ifndef NO_DAEMON
-pid_t pid = fork();
-std::string startFile = confDir + START_FILE;
-unlink(startFile.c_str());
-
-switch (pid)
- {
- case -1:
- return -1;
- break;
-
- case 0:
- close(1);
- close(2);
- setsid();
- break;
-
- default:
- struct timespec ts = {0, 200000000};
- for (int i = 0; i < 120 * 5; i++)
- {
- if (access(startFile.c_str(), F_OK) == 0)
- {
- unlink(startFile.c_str());
- exit(0);
- }
-
- nanosleep(&ts, NULL);
- }
- unlink(startFile.c_str());
- exit(1);
- break;
- }
-#endif
-return 0;
-}
-//-----------------------------------------------------------------------------
-void KillExecuters()
-{
-std::set<pid_t>::iterator pid(executers.begin());
-while (pid != executers.end())
- {
- printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
- kill(*pid, SIGUSR1);
- ++pid;
- }
-}
-//-----------------------------------------------------------------------------
-} // namespace anonymous
-//-----------------------------------------------------------------------------
-int main(int argc, char * argv[])
-{
-int msgID = -11;
-
-GetStgLogger().SetLogFileName("/var/log/stargazer.log");
-
-if (getuid())
- {
- printf("You must be root. Exit.\n");
- return 1;
- }
-
-SETTINGS_IMPL settings(argc == 2 ? argv[1] : "");
-
-if (settings.ReadSettings())
- {
- STG_LOGGER & WriteServLog = GetStgLogger();
-
- if (settings.GetLogFileName() != "")
- WriteServLog.SetLogFileName(settings.GetLogFileName());
-
- WriteServLog("ReadSettings error. %s", settings.GetStrError().c_str());
- return -1;
- }
-
-#ifndef NO_DAEMON
-std::string startFile(settings.GetConfDir() + START_FILE);
-#endif
-
-if (ForkAndWait(settings.GetConfDir()) < 0)
- {
- STG_LOGGER & WriteServLog = GetStgLogger();
- WriteServLog("Fork error!");
- return -1;
- }
-
-STG_LOGGER & WriteServLog = GetStgLogger();
-WriteServLog.SetLogFileName(settings.GetLogFileName());
-WriteServLog("Stg v. %s", SERVER_VERSION);
-
-for (size_t i = 0; i < settings.GetExecutersNum(); i++)
- {
- int ret = StartScriptExecuter(argv[0], settings.GetExecMsgKey(), &msgID);
- if (ret < 0)
- {
- STG_LOGGER & WriteServLog = GetStgLogger();
- WriteServLog("Start Script Executer error!");
- return -1;
- }
- if (ret == 1)
- {
- // Stopping child
- return 0;
- }
- }
-
-PIDFile pidFile(settings.GetPIDFileName());
-
-struct sigaction sa;
-memset(&sa, 0, sizeof(sa));
-sa.sa_handler = SIG_DFL;
-sigaction(SIGHUP, &sa, NULL); // Apparently FreeBSD ignores SIGHUP by default when launched from rc.d at bot time.
-
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-StartTimer();
-WaitTimer();
-if (!IsStgTimerRunning())
- {
- printfd(__FILE__, "Timer thread not started in 1 sec!\n");
- WriteServLog("Timer thread not started in 1 sec!");
- return -1;
- }
-
-EVENT_LOOP & loop(EVENT_LOOP_SINGLETON::GetInstance());
-
-STORE_LOADER storeLoader(settings);
-if (storeLoader.Load())
- {
- printfd(__FILE__, "Storage plugin: '%s'\n", storeLoader.GetStrError().c_str());
- WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
- return -1;
- }
-
-if (loop.Start())
- {
- printfd(__FILE__, "Event loop not started.\n");
- WriteServLog("Event loop not started.");
- return -1;
- }
-
-STORE & store(storeLoader.GetStore());
-WriteServLog("Storage plugin: %s. Loading successfull.", store.GetVersion().c_str());
-
-ADMINS_IMPL admins(&store);
-TARIFFS_IMPL tariffs(&store);
-SERVICES_IMPL services(&store);
-CORPORATIONS_IMPL corps(&store);
-USERS_IMPL users(&settings, &store, &tariffs, services, admins.GetSysAdmin());
-TRAFFCOUNTER_IMPL traffCnt(&users, settings.GetRulesFileName());
-traffCnt.SetMonitorDir(settings.GetMonitorDir());
-
-if (users.Start())
- return -1;
-
-WriteServLog("Users started successfully.");
-
-if (traffCnt.Start())
- return -1;
-
-WriteServLog("Traffcounter started successfully.");
-
-STG::PluginManager manager(settings, store, admins, tariffs, services, corps, users, traffCnt);
-
-srandom(static_cast<unsigned int>(stgTime));
-
-WriteServLog("Stg started successfully.");
-WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-#ifndef NO_DAEMON
-creat(startFile.c_str(), S_IRUSR);
-#endif
-
-bool running = true;
-while (running)
- {
- sigfillset(&signalSet);
- int sig = 0;
- sigwait(&signalSet, &sig);
- int status;
- switch (sig)
- {
- case SIGHUP:
- {
- SETTINGS_IMPL newSettings(settings);
- if (newSettings.ReadSettings())
- WriteServLog("ReadSettings error. %s", newSettings.GetStrError().c_str());
- else
- settings = newSettings;
- WriteServLog.SetLogFileName(settings.GetLogFileName());
- traffCnt.Reload();
- manager.reload(settings);
- }
- break;
- case SIGTERM:
- running = false;
- break;
- case SIGINT:
- running = false;
- break;
- case SIGPIPE:
- WriteServLog("Broken pipe!");
- break;
- case SIGCHLD:
- executers.erase(waitpid(-1, &status, WNOHANG));
- if (executers.empty())
- running = false;
- break;
- default:
- WriteServLog("Ignore signal %d", sig);
- break;
- }
- }
-
-WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-manager.stop();
-
-if (loop.Stop())
- WriteServLog("Event loop not stopped.");
-
-if (!traffCnt.Stop())
- WriteServLog("Traffcounter: Stop successfull.");
-
-if (!users.Stop())
- WriteServLog("Users: Stop successfull.");
-
-sleep(1);
-int res = msgctl(msgID, IPC_RMID, NULL);
-if (res)
- WriteServLog("Queue was not removed. id=%d", msgID);
-else
- WriteServLog("Queue removed successfully.");
-
-KillExecuters();
-
-StopStgTimer();
-WriteServLog("StgTimer: Stop successfull.");
-
-WriteServLog("Stg stopped successfully.");
-WriteServLog("---------------------------------------------");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2009/06/09 09:07:32 $
- $Author: faust $
- */
-
-/*
- * An implementation of RAII pid-file writer
- */
-
-#include <fstream>
-#include <unistd.h>
-
-#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());
- }
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Header file for RAII pid-file writer
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2009/06/09 09:07:32 $
- $Author: faust $
- */
-
-#ifndef __PID_FILE_H__
-#define __PID_FILE_H__
-
-#include <string>
-
-class PIDFile {
-public:
- explicit PIDFile(const std::string & fn);
- ~PIDFile();
-private:
- std::string fileName;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "plugin_mgr.h"
-
-#include "plugin_runner.h"
-
-#include "admins_impl.h"
-#include "tariffs_impl.h"
-#include "services_impl.h"
-#include "corps_impl.h"
-#include "users_impl.h"
-#include "traffcounter_impl.h"
-#include "settings_impl.h"
-
-#include "stg/logger.h"
-
-using STG::PluginManager;
-
-namespace
-{
-
-bool StartModCmp(const PLUGIN_RUNNER * lhs, const PLUGIN_RUNNER * rhs)
-{
- return lhs->GetStartPosition() < rhs->GetStartPosition();
-}
-
-bool StopModCmp(const PLUGIN_RUNNER * lhs, const PLUGIN_RUNNER * rhs)
-{
- return lhs->GetStopPosition() > rhs->GetStopPosition();
-}
-
-} // namespace anonymous
-
-PluginManager::PluginManager(const SETTINGS_IMPL& settings,
- STORE& store, ADMINS_IMPL& admins, TARIFFS_IMPL& tariffs,
- SERVICES_IMPL& services, CORPORATIONS_IMPL& corporations,
- USERS_IMPL& users, TRAFFCOUNTER_IMPL& traffcounter)
- : m_log(GetStgLogger())
-{
- std::string basePath = settings.GetModulesPath();
- const std::vector<MODULE_SETTINGS> & modSettings(settings.GetModulesSettings());
- for (size_t i = 0; i < modSettings.size(); i++)
- {
- std::string moduleName = modSettings[i].moduleName;
- std::string modulePath = basePath + "/mod_" + moduleName + ".so";
- printfd(__FILE__, "Module: %s\n", modulePath.c_str());
- try
- {
- m_modules.push_back(
- new PLUGIN_RUNNER(modulePath, moduleName, modSettings[i], admins, tariffs,
- users, services, corporations, traffcounter,
- store, settings)
- );
- }
- catch (const PLUGIN_RUNNER::Error & ex)
- {
- m_log(ex.what());
- printfd(__FILE__, "%s\n", ex.what());
- // TODO: React
- }
- }
- std::sort(m_modules.begin(), m_modules.end(), StartModCmp);
- for (size_t i = 0; i < m_modules.size(); ++i)
- {
- PLUGIN & plugin = m_modules[i]->GetPlugin();
- if (m_modules[i]->Start())
- {
- m_log("Failed to start module '%s': '%s'", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- printfd(__FILE__, "Failed to start module '%s': '%s'\n", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- }
- else
- {
- m_log("Module '%s' started successfully.", plugin.GetVersion().c_str());
- printfd(__FILE__, "Module '%s' started successfully.\n", plugin.GetVersion().c_str());
- }
- }
-}
-
-PluginManager::~PluginManager()
-{
- stop();
- for (size_t i = 0; i < m_modules.size(); ++i)
- delete m_modules[i];
-}
-
-void PluginManager::reload(const SETTINGS_IMPL& settings)
-{
- const std::vector<MODULE_SETTINGS> & modSettings(settings.GetModulesSettings());
- for (size_t i = 0; i < m_modules.size(); ++i)
- {
- for (size_t j = 0; j < modSettings.size(); j++)
- {
- if (modSettings[j].moduleName == m_modules[i]->GetName())
- {
- PLUGIN & plugin = m_modules[i]->GetPlugin();
- if (m_modules[i]->Reload(modSettings[j]))
- {
- m_log("Error reloading module '%s': '%s'", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- printfd(__FILE__, "Error reloading module '%s': '%s'\n", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- }
- break;
- }
- }
- }
-}
-
-void PluginManager::stop()
-{
- std::sort(m_modules.begin(), m_modules.end(), StopModCmp);
- for (size_t i = 0; i < m_modules.size(); ++i)
- {
- if (!m_modules[i]->IsRunning())
- continue;
- PLUGIN & plugin = m_modules[i]->GetPlugin();
- if (m_modules[i]->Stop())
- {
- m_log("Failed to stop module '%s': '%s'", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- printfd(__FILE__, "Failed to stop module '%s': '%s'\n", plugin.GetVersion().c_str(),
- plugin.GetStrError().c_str());
- }
- else
- {
- m_log("Module '%s' stopped successfully.", plugin.GetVersion().c_str());
- printfd(__FILE__, "Module '%s' stopped successfully.\n", plugin.GetVersion().c_str());
- }
- }
-}
+++ /dev/null
-#ifndef __STG_PLUGIN_MGR_H__
-#define __STG_PLUGIN_MGR_H__
-
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "stg/module_settings.h"
-
-#include <vector>
-
-class SETTINGS_IMPL;
-class PLUGIN_RUNNER;
-class STORE;
-class ADMINS_IMPL;
-class TARIFFS_IMPL;
-class SERVICES_IMPL;
-class CORPORATIONS_IMPL;
-class USERS_IMPL;
-class TRAFFCOUNTER_IMPL;
-class STG_LOGGER;
-
-namespace STG
-{
-
-class PluginManager
-{
- public:
- PluginManager(const SETTINGS_IMPL& settings,
- STORE& store, ADMINS_IMPL& admins, TARIFFS_IMPL& tariffs,
- SERVICES_IMPL& services, CORPORATIONS_IMPL& corporations,
- USERS_IMPL& users, TRAFFCOUNTER_IMPL& traffcounter);
- ~PluginManager();
-
- void reload(const SETTINGS_IMPL& settings);
- void stop();
-
- private:
- std::vector<PLUGIN_RUNNER*> m_modules;
- STG_LOGGER & m_log;
-};
-
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "plugin_runner.h"
-
-#include "stg/common.h"
-
-#include <dlfcn.h>
-#include <unistd.h>
-
-//-----------------------------------------------------------------------------
-PLUGIN_RUNNER::PLUGIN_RUNNER(const std::string & fileName,
- const std::string & name,
- const MODULE_SETTINGS & ms,
- ADMINS & admins,
- TARIFFS & tariffs,
- USERS & users,
- SERVICES & services,
- CORPORATIONS & corporations,
- TRAFFCOUNTER & traffcounter,
- STORE & store,
- const SETTINGS & settings)
- : pluginFileName(fileName),
- pluginName(name),
- libHandle(NULL),
- m_plugin(Load(ms, admins, tariffs, users, services, corporations,
- traffcounter, store, settings))
-{
-}
-//-----------------------------------------------------------------------------
-PLUGIN_RUNNER::~PLUGIN_RUNNER()
-{
-delete &m_plugin;
-if (dlclose(libHandle))
- {
- errorStr = "Failed to unload plugin '" + pluginFileName + "': " + dlerror();
- printfd(__FILE__, "PLUGIN_RUNNER::Unload() - %s", errorStr.c_str());
- }
-}
-//-----------------------------------------------------------------------------
-int PLUGIN_RUNNER::Start()
-{
-int res = m_plugin.Start();
-errorStr = m_plugin.GetStrError();
-return res;
-}
-//-----------------------------------------------------------------------------
-int PLUGIN_RUNNER::Stop()
-{
-int res = m_plugin.Stop();
-errorStr = m_plugin.GetStrError();
-return res;
-}
-//-----------------------------------------------------------------------------
-int PLUGIN_RUNNER::Reload(const MODULE_SETTINGS & ms)
-{
-int res = m_plugin.Reload(ms);
-errorStr = m_plugin.GetStrError();
-return res;
-}
-//-----------------------------------------------------------------------------
-PLUGIN & PLUGIN_RUNNER::Load(const MODULE_SETTINGS & ms,
- ADMINS & admins,
- TARIFFS & tariffs,
- USERS & users,
- SERVICES & services,
- CORPORATIONS & corporations,
- TRAFFCOUNTER & traffcounter,
- STORE & store,
- const SETTINGS & settings)
-{
-if (pluginFileName.empty())
- {
- const std::string msg = "Empty plugin file name.";
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-
-if (access(pluginFileName.c_str(), R_OK))
- {
- const std::string msg = "Plugin file '" + pluginFileName + "' is missing or inaccessible.";
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-
-libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
-
-if (!libHandle)
- {
- std::string msg = "Error loading plugin '" + pluginFileName + "'";
- const char* error = dlerror();
- if (error)
- msg = msg + ": '" + error + "'";
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-
-PLUGIN * (*GetPlugin)();
-GetPlugin = (PLUGIN * (*)())dlsym(libHandle, "GetPlugin");
-if (!GetPlugin)
- {
- const std::string msg = "Plugin '" + pluginFileName + "' does not have GetPlugin() function. ";
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-PLUGIN * plugin = GetPlugin();
-
-if (!plugin)
- {
- const std::string msg = "Failed to create an instance of plugin '" + pluginFileName + "'.";
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-
-plugin->SetSettings(ms);
-plugin->SetTariffs(&tariffs);
-plugin->SetAdmins(&admins);
-plugin->SetUsers(&users);
-plugin->SetServices(&services);
-plugin->SetCorporations(&corporations);
-plugin->SetTraffcounter(&traffcounter);
-plugin->SetStore(&store);
-plugin->SetStgSettings(&settings);
-
-if (plugin->ParseSettings())
- {
- const std::string msg = "Plugin '" + pluginFileName + "' is unable to parse settings. " + plugin->GetStrError();
- printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
- throw Error(msg);
- }
-
-return *plugin;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef PLUGIN_RUNNER_H
-#define PLUGIN_RUNNER_H
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/os_int.h"
-
-#include <string>
-#include <stdexcept>
-
-class SETTINGS;
-class ADMINS;
-class TARIFFS;
-class USERS;
-class SERVICES;
-class CORPORATIONS;
-class TRAFFCOUNTER;
-class STORE;
-
-//-----------------------------------------------------------------------------
-class PLUGIN_RUNNER {
-public:
- struct Error : public std::runtime_error {
- explicit Error(const std::string & msg) : runtime_error(msg) {}
- };
-
- PLUGIN_RUNNER(const std::string & pluginFileName,
- const std::string & pluginName,
- const MODULE_SETTINGS & ms,
- ADMINS & admins,
- TARIFFS & tariffs,
- USERS & users,
- SERVICES & services,
- CORPORATIONS & corporations,
- TRAFFCOUNTER & traffcounter,
- STORE & store,
- const SETTINGS & settings);
- ~PLUGIN_RUNNER();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & ms);
- int Restart();
- bool IsRunning() { return m_plugin.IsRunning(); }
-
- const std::string & GetStrError() const { return errorStr; }
- PLUGIN & GetPlugin() { return m_plugin; }
- const std::string & GetFileName() const { return pluginFileName; }
- const std::string & GetName() const { return pluginName; }
-
- uint16_t GetStartPosition() const { return m_plugin.GetStartPosition(); }
- uint16_t GetStopPosition() const { return m_plugin.GetStopPosition(); }
-
-private:
- PLUGIN_RUNNER(const PLUGIN_RUNNER & rvalue);
- PLUGIN_RUNNER & operator=(const PLUGIN_RUNNER & rvalue);
-
- PLUGIN & Load(const MODULE_SETTINGS & ms,
- ADMINS & admins,
- TARIFFS & tariffs,
- USERS & users,
- SERVICES & services,
- CORPORATIONS & corporations,
- TRAFFCOUNTER & traffcounter,
- STORE & store,
- const SETTINGS & settings);
-
- std::string pluginFileName;
- std::string pluginName;
- void * libHandle;
-
- PLUGIN & m_plugin;
- std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-#endif //PLUGIN_RUNNER_H
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.1 2007/09/26 13:55:45 faust Exp $
-###############################################################################
-
-include ../../../Makefile.conf
-
-.PHONY: clean install uninstall
-.PHONY: all $(PLUGINS)
-
-all: $(PLUGINS)
-
-$(PLUGINS):
- $(MAKE) $(MAKECMDGOALS) -C $@
-
-clean: all
-
-install: all
-
-uninstall: all
-
+++ /dev/null
-###############################################################################
-# $Id: Makefile.in,v 1.11 2009/03/03 15:49:35 faust Exp $
-###############################################################################
-
-SEARCH_DIRS = -I $(DIR_INCLUDE)
-
-OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
-
-LN = ln
-
-STGLIBS_INCS = $(addprefix -I ../../../../../stglibs/,$(addsuffix .lib/include,$(STGLIBS)))
-STGLIBS_PATHS = $(addprefix -L ../../../../../stglibs/,$(addsuffix .lib,$(STGLIBS)))
-
-STGLIBS_LIBS = $(addprefix -lstg,$(STGLIBS))
-
-CXXFLAGS += -fPIC $(DEFS) $(SEARCH_DIRS) $(STGLIBS_INCS)
-CFLAGS += -fPIC $(DEFS) $(SEARCH_DIRS) $(STGLIBS_INCS)
-
-ifneq ($(OS),darwin)
-LDFLAGS += -shared -Wl,-rpath,$(PREFIX)/usr/lib/stg
-else
-LDFLAGS += -dynamiclib -undefined suppress -flat_namespace -Wl,-rpath,$(PREFIX)/usr/lib/stg
-endif
-
-all: $(PROG)
-
-$(PROG): $(OBJS)
- $(CXX) $^ $(LDFLAGS) $(STGLIBS_PATHS) $(STGLIBS_LIBS) $(LIBS) -o $(PROG)
- $(LN) -fs "`pwd`/$(PROG)" $(DIR_MOD)/$(PROG)
-
-clean:
- rm -f deps $(PROG) *.o tags *.*~
-
-install: $(PROG)
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/stg
-ifeq ($(DEBUG), yes)
- install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
-else
- install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
-endif
-
-uninstall:
- rm -f $(PREFIX)/usr/lib/stg/$(PROG)
-
-ifneq ($(MAKECMDGOALS),clean)
-ifneq ($(MAKECMDGOALS),uninstall)
--include deps
-endif
-endif
-
-deps: $(SRCS) ../../../../../Makefile.conf
- @>deps ;\
- for file in $(SRCS); do\
- echo "$$file" | grep ".c$$" > /dev/null;\
- if [ $$? -eq 0 ];\
- then\
- echo "`$(CC) $(CFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile ../../../../../Makefile.conf" >> deps ;\
- printf '%b\n' '\t$$(CC) -c $$< $(CFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
- else\
- echo "`$(CXX) $(CXXFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile ../../../../../Makefile.conf" >> deps ;\
- printf '%b\n' '\t$$(CXX) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
- fi;\
- done
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.10 2008/12/04 15:41:03 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_auth_ao.so
-
-SRCS = ./ao.cpp
-
-STGLIBS = scriptexecuter \
- logger \
- common
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
-$Revision: 1.30 $
-$Date: 2010/03/04 12:29:06 $
-$Author: faust $
-*/
-
-#include <unistd.h>
-
-#include <csignal>
-#include <cassert>
-#include <algorithm> // for_each
-#include <functional> // mem_fun_ref
-
-#include "stg/user.h"
-#include "stg/users.h"
-#include "stg/user_property.h"
-#include "stg/common.h"
-#include "stg/plugin_creator.h"
-#include "ao.h"
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-static PLUGIN_CREATOR<AUTH_AO> aoc;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return aoc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-template <typename varType>
-class IS_CONTAINS_USER: public std::binary_function<varType, USER_PTR, bool>
-{
-public:
- bool operator()(const varType& notifier, USER_PTR user) const
- {
- return notifier.GetUser() == user;
- }
-};
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string AUTH_AO::GetVersion() const
-{
-return "Always Online authorizator v.1.0";
-}
-//-----------------------------------------------------------------------------
-AUTH_AO::AUTH_AO()
- : users(NULL),
- isRunning(false),
- onAddUserNotifier(*this),
- onDelUserNotifier(*this),
- logger(GetPluginLogger(GetStgLogger(), "auth_ao"))
-{
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::Start()
-{
-printfd(__FILE__, "AUTH_AO::Start()\n");
-GetUsers();
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-std::for_each(usersList.begin(), usersList.end(), std::bind1st(std::mem_fun(&AUTH_AO::UpdateUserAuthorization), this));
-
-isRunning = true;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::Stop()
-{
-printfd(__FILE__, "AUTH_AO::Stop()\n");
-if (!isRunning)
- return 0;
-
-users->DelNotifierUserAdd(&onAddUserNotifier);
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-std::list<USER_PTR>::iterator users_iter;
-users_iter = usersList.begin();
-while (users_iter != usersList.end())
- {
- if ((*users_iter)->IsAuthorizedBy(this))
- users->Unauthorize((*users_iter)->GetLogin(), this);
- UnSetUserNotifiers(*users_iter);
- ++users_iter;
- }
-isRunning = false;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::SetUserNotifiers(USER_PTR u)
-{
-// ---------- AlwaysOnline -------------------
-CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier(*this, u);
-CHG_AFTER_NOTIFIER<int> AfterChgAONotifier(*this, u);
-
-BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
-AfterChgAONotifierList.push_front(AfterChgAONotifier);
-
-u->GetProperty().alwaysOnline.AddBeforeNotifier(&BeforeChgAONotifierList.front());
-u->GetProperty().alwaysOnline.AddAfterNotifier(&AfterChgAONotifierList.front());
-// ---------- AlwaysOnline end ---------------
-
-// ---------- IP -------------------
-CHG_BEFORE_NOTIFIER<USER_IPS> BeforeChgIPNotifier(*this, u);
-CHG_AFTER_NOTIFIER<USER_IPS> AfterChgIPNotifier(*this, u);
-
-BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
-AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
-
-u->GetProperty().ips.AddBeforeNotifier(&BeforeChgIPNotifierList.front());
-u->GetProperty().ips.AddAfterNotifier(&AfterChgIPNotifierList.front());
-// ---------- IP end ---------------
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::UnSetUserNotifiers(USER_PTR u)
-{
-// --- AlwaysOnline ---
-IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<int> > IsContainsUserAOB;
-IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<int> > IsContainsUserAOA;
-
-std::list<CHG_BEFORE_NOTIFIER<int> >::iterator aoBIter;
-std::list<CHG_AFTER_NOTIFIER<int> >::iterator aoAIter;
-
-aoBIter = find_if(BeforeChgAONotifierList.begin(),
- BeforeChgAONotifierList.end(),
- bind2nd(IsContainsUserAOB, u));
-
-if (aoBIter != BeforeChgAONotifierList.end())
- {
- aoBIter->GetUser()->GetProperty().alwaysOnline.DelBeforeNotifier(&(*aoBIter));
- BeforeChgAONotifierList.erase(aoBIter);
- }
-
-aoAIter = find_if(AfterChgAONotifierList.begin(),
- AfterChgAONotifierList.end(),
- bind2nd(IsContainsUserAOA, u));
-
-if (aoAIter != AfterChgAONotifierList.end())
- {
- aoAIter->GetUser()->GetProperty().alwaysOnline.DelAfterNotifier(&(*aoAIter));
- AfterChgAONotifierList.erase(aoAIter);
- }
-// --- AlwaysOnline end ---
-
-// --- IP ---
-IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<USER_IPS> > IsContainsUserIPB;
-IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<USER_IPS> > IsContainsUserIPA;
-
-std::list<CHG_BEFORE_NOTIFIER<USER_IPS> >::iterator ipBIter;
-std::list<CHG_AFTER_NOTIFIER<USER_IPS> >::iterator ipAIter;
-
-ipBIter = std::find_if(BeforeChgIPNotifierList.begin(),
- BeforeChgIPNotifierList.end(),
- bind2nd(IsContainsUserIPB, u));
-
-if (ipBIter != BeforeChgIPNotifierList.end())
- {
- ipBIter->GetUser()->GetProperty().ips.DelBeforeNotifier(&(*ipBIter));
- BeforeChgIPNotifierList.erase(ipBIter);
- }
-
-ipAIter = find_if(AfterChgIPNotifierList.begin(),
- AfterChgIPNotifierList.end(),
- bind2nd(IsContainsUserIPA, u));
-
-if (ipAIter != AfterChgIPNotifierList.end())
- {
- ipAIter->GetUser()->GetProperty().ips.DelAfterNotifier(&(*ipAIter));
- AfterChgIPNotifierList.erase(ipAIter);
- }
-// --- IP end ---
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::GetUsers()
-{
-USER_PTR u;
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (!users->SearchNext(h, &u))
- {
- usersList.push_back(u);
- SetUserNotifiers(u);
- }
-
-users->CloseSearch(h);
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::UpdateUserAuthorization(CONST_USER_PTR u) const
-{
-if (u->GetProperty().alwaysOnline)
- {
- USER_IPS ips = u->GetProperty().ips;
- if (ips.OnlyOneIP())
- {
- users->Authorize(u->GetLogin(), ips[0].ip, 0xFFffFFff, this);
- }
- }
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::AddUser(USER_PTR u)
-{
-SetUserNotifiers(u);
-usersList.push_back(u);
-UpdateUserAuthorization(u);
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::DelUser(USER_PTR u)
-{
-if (u->IsAuthorizedBy(this))
- users->Unauthorize(u->GetLogin(), this);
-UnSetUserNotifiers(u);
-usersList.remove(u);
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::SendMessage(const STG_MSG &, uint32_t) const
-{
-errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
-return -1;
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::Unauthorize, user);
-if (user->IsAuthorizedBy(&auth))
- auth.users->Unauthorize(user->GetLogin(), &auth);
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::UpdateUserAuthorization, user);
-auth.UpdateUserAuthorization(user);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.21 $
- $Date: 2010/09/10 06:38:26 $
- $Author: faust $
-*/
-
-#ifndef AO_H
-#define AO_H
-
-#include <pthread.h>
-
-#include <string>
-#include <list>
-
-#include "stg/auth.h"
-#include "stg/store.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/user.h"
-#include "stg/logger.h"
-
-extern "C" PLUGIN * GetPlugin();
-
-class AUTH_AO;
-class USERS;
-//-----------------------------------------------------------------------------
-template <typename T>
-class CHG_BEFORE_NOTIFIER : public PROPERTY_NOTIFIER_BASE<T> {
-public:
- CHG_BEFORE_NOTIFIER(AUTH_AO & a, USER_PTR u)
- : PROPERTY_NOTIFIER_BASE<T>(), user(u), auth(a) {}
- CHG_BEFORE_NOTIFIER(const CHG_BEFORE_NOTIFIER<T> & rvalue)
- : PROPERTY_NOTIFIER_BASE<T>(),
- user(rvalue.user), auth(rvalue.auth) {}
- void Notify(const T & oldValue, const T & newValue);
- USER_PTR GetUser() const { return user; }
-
-private:
- CHG_BEFORE_NOTIFIER<T> & operator=(const CHG_BEFORE_NOTIFIER<T> & rvalue);
-
- USER_PTR user;
- const AUTH_AO & auth;
-};
-//-----------------------------------------------------------------------------
-template <typename T>
-class CHG_AFTER_NOTIFIER : public PROPERTY_NOTIFIER_BASE<T> {
-public:
- CHG_AFTER_NOTIFIER(AUTH_AO & a, USER_PTR u)
- : PROPERTY_NOTIFIER_BASE<T>(), user(u), auth(a) {}
- CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER<T> & rvalue)
- : PROPERTY_NOTIFIER_BASE<T>(),
- user(rvalue.user), auth(rvalue.auth) {}
- void Notify(const T & oldValue, const T & newValue);
- USER_PTR GetUser() const { return user; }
-
-private:
- CHG_AFTER_NOTIFIER<T> & operator=(const CHG_AFTER_NOTIFIER<T> & rvalue);
-
- USER_PTR user;
- const AUTH_AO & auth;
-};
-//-----------------------------------------------------------------------------
-class AUTH_AO : public AUTH {
-public:
- AUTH_AO();
- virtual ~AUTH_AO(){}
-
- void SetUsers(USERS * u) { users = u; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
- void SetSettings(const MODULE_SETTINGS &) {}
- int ParseSettings() { return 0; }
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 30; }
- uint16_t GetStopPosition() const { return 30; }
-
- void AddUser(USER_PTR u);
- void DelUser(USER_PTR u);
-
- int SendMessage(const STG_MSG & msg, uint32_t ip) const;
-
-private:
- AUTH_AO(const AUTH_AO & rvalue);
- AUTH_AO & operator=(const AUTH_AO & rvalue);
-
- void GetUsers();
- void SetUserNotifiers(USER_PTR u);
- void UnSetUserNotifiers(USER_PTR u);
- void UpdateUserAuthorization(CONST_USER_PTR u) const;
-
- mutable std::string errorStr;
- USERS * users;
- std::list<USER_PTR> usersList;
- bool isRunning;
- MODULE_SETTINGS settings;
-
- std::list<CHG_BEFORE_NOTIFIER<int> > BeforeChgAONotifierList;
- std::list<CHG_AFTER_NOTIFIER<int> > AfterChgAONotifierList;
-
- std::list<CHG_BEFORE_NOTIFIER<USER_IPS> > BeforeChgIPNotifierList;
- std::list<CHG_AFTER_NOTIFIER<USER_IPS> > AfterChgIPNotifierList;
-
- class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
- public:
- explicit ADD_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
- virtual ~ADD_USER_NONIFIER() {}
- void Notify(const USER_PTR & user) { auth.AddUser(user); }
-
- private:
- ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
- ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
-
- AUTH_AO & auth;
- } onAddUserNotifier;
-
- class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
- public:
- explicit DEL_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
- virtual ~DEL_USER_NONIFIER() {}
- void Notify(const USER_PTR & user) { auth.DelUser(user); }
-
- private:
- DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
- DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
-
- AUTH_AO & auth;
- } onDelUserNotifier;
- PLUGIN_LOGGER logger;
-
- friend class CHG_BEFORE_NOTIFIER<int>;
- friend class CHG_AFTER_NOTIFIER<int>;
- friend class CHG_BEFORE_NOTIFIER<USER_IPS>;
- friend class CHG_AFTER_NOTIFIER<USER_IPS>;
-
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.10 2010/02/16 11:41:00 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-LIBS += $(LIB_THREAD)
-
-PROG = mod_auth_ia.so
-
-SRCS = ./inetaccess.cpp
-
-STGLIBS = common \
- crypto \
- logger \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.79 $
- $Date: 2010/03/25 15:18:48 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h> // close
-
-#include <csignal>
-#include <cstdlib>
-#include <cstdio> // snprintf
-#include <cerrno>
-#include <cmath>
-#include <algorithm>
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/tariff.h"
-#include "stg/user_property.h"
-#include "stg/settings.h"
-#include "stg/plugin_creator.h"
-#include "inetaccess.h"
-
-extern volatile time_t stgTime;
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<AUTH_IA> iac;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return iac.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-AUTH_IA_SETTINGS::AUTH_IA_SETTINGS()
- : userDelay(0),
- userTimeout(0),
- port(0),
- errorStr(),
- freeMbShowType(freeMbCash),
- logProtocolErrors(false)
-{
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-int p;
-PARAM_VALUE pv;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-///////////////////////////
-pv.param = "Port";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Port\' not found.";
- printfd(__FILE__, "Parameter 'Port' not found\n");
- return -1;
- }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
- {
- errorStr = "Cannot parse parameter \'Port\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'Port'\n");
- return -1;
- }
-port = static_cast<uint16_t>(p);
-///////////////////////////
-pv.param = "UserDelay";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'UserDelay\' not found.";
- printfd(__FILE__, "Parameter 'UserDelay' not found\n");
- return -1;
- }
-
-if (ParseIntInRange(pvi->value[0], 5, 600, &userDelay))
- {
- errorStr = "Cannot parse parameter \'UserDelay\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'UserDelay'\n");
- return -1;
- }
-///////////////////////////
-pv.param = "UserTimeout";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'UserTimeout\' not found.";
- printfd(__FILE__, "Parameter 'UserTimeout' not found\n");
- return -1;
- }
-
-if (ParseIntInRange(pvi->value[0], 15, 1200, &userTimeout))
- {
- errorStr = "Cannot parse parameter \'UserTimeout\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'UserTimeout'\n");
- return -1;
- }
-///////////////////////////
-pv.param = "LogProtocolErrors";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- logProtocolErrors = false;
-else if (ParseYesNo(pvi->value[0], &logProtocolErrors))
- {
- errorStr = "Cannot parse parameter \'LogProtocolErrors\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'LogProtocolErrors'\n");
- return -1;
- }
-/////////////////////////////////////////////////////////////
-std::string freeMbType;
-int n = 0;
-pv.param = "FreeMb";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'FreeMb\' not found.";
- printfd(__FILE__, "Parameter 'FreeMb' not found\n");
- return -1;
- }
-freeMbType = pvi->value[0];
-
-if (strcasecmp(freeMbType.c_str(), "cash") == 0)
- {
- freeMbShowType = freeMbCash;
- }
-else if (strcasecmp(freeMbType.c_str(), "none") == 0)
- {
- freeMbShowType = freeMbNone;
- }
-else if (!str2x(freeMbType.c_str(), n))
- {
- if (n < 0 || n >= DIR_NUM)
- {
- errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
- freeMbShowType = (FREEMB)(freeMb0 + n);
- }
-else
- {
- errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-/////////////////////////////////////////////////////////////
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-#ifdef IA_PHASE_DEBUG
-IA_PHASE::IA_PHASE()
- : phase(1),
- flog(NULL)
-{
-gettimeofday(&phaseTime, NULL);
-}
-#else
-IA_PHASE::IA_PHASE()
- : phase(1)
-{
-gettimeofday(&phaseTime, NULL);
-}
-#endif
-//-----------------------------------------------------------------------------
-IA_PHASE::~IA_PHASE()
-{
-#ifdef IA_PHASE_DEBUG
-flog = fopen(log.c_str(), "at");
-if (flog)
- {
- fprintf(flog, "IA %s D\n", login.c_str());
- fclose(flog);
- }
-#endif
-}
-//-----------------------------------------------------------------------------
-#ifdef IA_PHASE_DEBUG
-void IA_PHASE::SetLogFileName(const string & logFileName)
-{
-log = logFileName + ".ia.log";
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetUserLogin(const string & login)
-{
-IA_PHASE::login = login;
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::WritePhaseChange(int newPhase)
-{
-UTIME newPhaseTime;
-gettimeofday(&newPhaseTime, NULL);
-flog = fopen(log.c_str(), "at");
-if (flog)
- {
- string action = newPhase == phase ? "U" : "C";
- double delta = newPhaseTime.GetSec() - phaseTime.GetSec();
- delta += (newPhaseTime.GetUSec() - phaseTime.GetUSec()) * 1.0e-6;
- fprintf(flog, "IA %s %s oldPhase = %d, newPhase = %d. dt = %.6f\n",
- login.c_str(),
- action.c_str(),
- phase,
- newPhase,
- delta);
- fclose(flog);
- }
-}
-#endif
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase1()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(1);
-#endif
-phase = 1;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase2()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(2);
-#endif
-phase = 2;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase3()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(3);
-#endif
-phase = 3;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase4()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(4);
-#endif
-phase = 4;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-int IA_PHASE::GetPhase() const
-{
-return phase;
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::UpdateTime()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(phase);
-#endif
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-const UTIME & IA_PHASE::GetTime() const
-{
-return phaseTime;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-AUTH_IA::AUTH_IA()
- : ctxS(),
- errorStr(),
- iaSettings(),
- settings(),
- nonstop(false),
- isRunningRun(false),
- isRunningRunTimeouter(false),
- users(NULL),
- stgSettings(NULL),
- ip2user(),
- recvThread(),
- timeouterThread(),
- mutex(),
- listenSocket(-1),
- connSynAck6(),
- connSynAck8(),
- disconnSynAck6(),
- disconnSynAck8(),
- aliveSyn6(),
- aliveSyn8(),
- fin6(),
- fin8(),
- packetTypes(),
- enabledDirs(0xFFffFFff),
- onDelUserNotifier(*this),
- logger(GetPluginLogger(GetStgLogger(), "auth_ia"))
-{
-InitContext("pr7Hhen", 7, &ctxS);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-
-memset(&connSynAck6, 0, sizeof(CONN_SYN_ACK_6));
-memset(&connSynAck8, 0, sizeof(CONN_SYN_ACK_8));
-memset(&disconnSynAck6, 0, sizeof(DISCONN_SYN_ACK_6));
-memset(&disconnSynAck8, 0, sizeof(DISCONN_SYN_ACK_8));
-memset(&aliveSyn6, 0, sizeof(ALIVE_SYN_6));
-memset(&aliveSyn8, 0, sizeof(ALIVE_SYN_8));
-memset(&fin6, 0, sizeof(FIN_6));
-memset(&fin8, 0, sizeof(FIN_8));
-
-printfd(__FILE__, "sizeof(CONN_SYN_6) = %d %d\n", sizeof(CONN_SYN_6), Min8(sizeof(CONN_SYN_6)));
-printfd(__FILE__, "sizeof(CONN_SYN_8) = %d %d\n", sizeof(CONN_SYN_8), Min8(sizeof(CONN_SYN_8)));
-printfd(__FILE__, "sizeof(CONN_SYN_ACK_6) = %d %d\n", sizeof(CONN_SYN_ACK_6), Min8(sizeof(CONN_SYN_ACK_6)));
-printfd(__FILE__, "sizeof(CONN_SYN_ACK_8) = %d %d\n", sizeof(CONN_SYN_ACK_8), Min8(sizeof(CONN_SYN_ACK_8)));
-printfd(__FILE__, "sizeof(CONN_ACK_6) = %d %d\n", sizeof(CONN_ACK_6), Min8(sizeof(CONN_ACK_6)));
-printfd(__FILE__, "sizeof(ALIVE_SYN_6) = %d %d\n", sizeof(ALIVE_SYN_6), Min8(sizeof(ALIVE_SYN_6)));
-printfd(__FILE__, "sizeof(ALIVE_SYN_8) = %d %d\n", sizeof(ALIVE_SYN_8), Min8(sizeof(ALIVE_SYN_8)));
-printfd(__FILE__, "sizeof(ALIVE_ACK_6) = %d %d\n", sizeof(ALIVE_ACK_6), Min8(sizeof(ALIVE_ACK_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_6) = %d %d\n", sizeof(DISCONN_SYN_6), Min8(sizeof(DISCONN_SYN_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_6) = %d %d\n", sizeof(DISCONN_SYN_ACK_6), Min8(sizeof(DISCONN_SYN_ACK_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_8) = %d %d\n", sizeof(DISCONN_SYN_ACK_8), Min8(sizeof(DISCONN_SYN_ACK_8)));
-printfd(__FILE__, "sizeof(DISCONN_ACK_6) = %d %d\n", sizeof(DISCONN_ACK_6), Min8(sizeof(DISCONN_ACK_6)));
-printfd(__FILE__, "sizeof(FIN_6) = %d %d\n", sizeof(FIN_6), Min8(sizeof(FIN_6)));
-printfd(__FILE__, "sizeof(FIN_8) = %d %d\n", sizeof(FIN_8), Min8(sizeof(FIN_8)));
-printfd(__FILE__, "sizeof(ERR) = %d %d\n", sizeof(ERR), Min8(sizeof(ERR)));
-printfd(__FILE__, "sizeof(INFO_6) = %d %d\n", sizeof(INFO_6), Min8(sizeof(INFO_6)));
-printfd(__FILE__, "sizeof(INFO_7) = %d %d\n", sizeof(INFO_7), Min8(sizeof(INFO_7)));
-printfd(__FILE__, "sizeof(INFO_8) = %d %d\n", sizeof(INFO_8), Min8(sizeof(INFO_8)));
-
-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;
-}
-//-----------------------------------------------------------------------------
-AUTH_IA::~AUTH_IA()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Start()
-{
-users->AddNotifierUserDel(&onDelUserNotifier);
-nonstop = true;
-
-if (PrepareNet())
- {
- return -1;
- }
-
-if (!isRunningRun)
- {
- if (pthread_create(&recvThread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- printfd(__FILE__, "Cannot create recv thread\n");
- logger("Cannot create recv thread.");
- return -1;
- }
- }
-
-if (!isRunningRunTimeouter)
- {
- if (pthread_create(&timeouterThread, NULL, RunTimeouter, this))
- {
- errorStr = "Cannot create thread.";
- printfd(__FILE__, "Cannot create timeouter thread\n");
- logger("Cannot create timeouter thread.");
- return -1;
- }
- }
-errorStr = "";
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Stop()
-{
-if (!IsRunning())
- return 0;
-
-nonstop = false;
-
-std::for_each(
- ip2user.begin(),
- ip2user.end(),
- UnauthorizeUser(this)
- );
-
-if (isRunningRun)
- {
- //5 seconds to thread stops itself
- for (int i = 0; i < 25 && isRunningRun; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- }
-
-FinalizeNet();
-
-if (isRunningRunTimeouter)
- {
- //5 seconds to thread stops itself
- for (int i = 0; i < 25 && isRunningRunTimeouter; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- }
-
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-if (isRunningRun || isRunningRunTimeouter)
- return -1;
-
-printfd(__FILE__, "AUTH_IA::Stoped successfully.\n");
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * AUTH_IA::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-AUTH_IA * ia = static_cast<AUTH_IA *>(d);
-
-ia->isRunningRun = true;
-
-char buffer[512];
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-
-while (ia->nonstop)
- {
- ia->RecvData(buffer, sizeof(buffer));
- if ((touchTime + MONITOR_TIME_DELAY_SEC <= stgTime) && ia->stgSettings->GetMonitoring())
- {
- touchTime = stgTime;
- std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_r";
- TouchFile(monFile);
- }
- }
-
-ia->isRunningRun = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void * AUTH_IA::RunTimeouter(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-AUTH_IA * ia = static_cast<AUTH_IA *>(d);
-
-ia->isRunningRunTimeouter = true;
-
-int a = -1;
-std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_t";
-while (ia->nonstop)
- {
- struct timespec ts = {0, 20000000};
- nanosleep(&ts, NULL);
- ia->Timeouter();
- // TODO change counter to timer and MONITOR_TIME_DELAY_SEC
- if (++a % (50 * 60) == 0 && ia->stgSettings->GetMonitoring())
- {
- TouchFile(monFile);
- }
- }
-
-ia->isRunningRunTimeouter = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::ParseSettings()
-{
-int ret = iaSettings.ParseSettings(settings);
-if (ret)
- errorStr = iaSettings.GetStrError();
-return ret;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Reload(const MODULE_SETTINGS & ms)
-{
-AUTH_IA_SETTINGS newIaSettings;
-if (newIaSettings.ParseSettings(ms))
- {
- printfd(__FILE__, "AUTH_IA::Reload() - Failed to reload InetAccess.\n");
- logger("AUTH_IA: Cannot reload InetAccess. Errors found.");
- return -1;
- }
-
-printfd(__FILE__, "AUTH_IA::Reload() - Reloaded InetAccess successfully.\n");
-logger("AUTH_IA: Reloaded InetAccess successfully.");
-iaSettings = newIaSettings;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::PrepareNet()
-{
-struct sockaddr_in listenAddr;
-
-listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
-
-if (listenSocket < 0)
- {
- errorStr = "Cannot create socket.";
- logger("Cannot create a socket: %s", strerror(errno));
- return -1;
- }
-
-listenAddr.sin_family = AF_INET;
-listenAddr.sin_port = htons(static_cast<uint16_t>(iaSettings.GetUserPort()));
-listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
-
-if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
- {
- errorStr = "AUTH_IA: Bind failed.";
- logger("Cannot bind the socket: %s", strerror(errno));
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::FinalizeNet()
-{
-close(listenSocket);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RecvData(char * buffer, int bufferSize)
-{
-if (!WaitPackets(listenSocket)) // Timeout
- {
- return 0;
- }
-
-struct sockaddr_in outerAddr;
-socklen_t outerAddrLen(sizeof(outerAddr));
-ssize_t dataLen = recvfrom(listenSocket, buffer, bufferSize, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
-
-if (!dataLen) // EOF
- {
- return 0;
- }
-
-if (dataLen <= 0) // Error
- {
- if (errno != EINTR)
- {
- printfd(__FILE__, "recvfrom res=%d, error: '%s'\n", dataLen, strerror(errno));
- logger("recvfrom error: %s", strerror(errno));
- return -1;
- }
- return 0;
- }
-
-if (dataLen > 256)
- return -1;
-
-uint32_t sip = outerAddr.sin_addr.s_addr;
-uint16_t sport = htons(outerAddr.sin_port);
-
-int protoVer;
-if (CheckHeader(buffer, sip, &protoVer))
- return -1;
-
-char login[PASSWD_LEN]; //TODO why PASSWD_LEN ?
-memset(login, 0, PASSWD_LEN);
-
-DecryptString(login, buffer + 8, PASSWD_LEN, &ctxS);
-
-USER_PTR user;
-if (users->FindByName(login, &user))
- {
- logger("User's connect failed: user '%s' not found. IP %s",
- login,
- inet_ntostring(sip).c_str());
- printfd(__FILE__, "User '%s' NOT found!\n", login);
- SendError(sip, sport, protoVer, IconvString("Неправильный логин.", "utf8", "koi8-ru"));
- return -1;
- }
-
-printfd(__FILE__, "User '%s' FOUND!\n", user->GetLogin().c_str());
-
-if (user->GetProperty().disabled.Get())
- {
- logger("Cannont authorize '%s', user is disabled.", login);
- SendError(sip, sport, protoVer, IconvString("Учетная запись заблокирована.", "utf8", "koi8-ru"));
- return 0;
- }
-
-if (user->GetProperty().passive.Get())
- {
- logger("Cannont authorize '%s', user is passive.", login);
- SendError(sip, sport, protoVer, IconvString("Учетная запись заморожена.", "utf8", "koi8-ru"));
- return 0;
- }
-
-if (!user->GetProperty().ips.Get().IsIPInIPS(sip))
- {
- printfd(__FILE__, "User %s. IP address is incorrect. IP %s\n",
- user->GetLogin().c_str(), inet_ntostring(sip).c_str());
- logger("User %s. IP address is incorrect. IP %s",
- user->GetLogin().c_str(), inet_ntostring(sip).c_str());
- SendError(sip, sport, protoVer, IconvString("Пользователь не опознан. Проверьте IP-адрес.", "utf8", "koi8-ru"));
- return 0;
- }
-
-return PacketProcessor(buffer, dataLen, sip, sport, protoVer, user);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::CheckHeader(const char * buffer, uint32_t sip, int * protoVer)
-{
-if (strncmp(IA_ID, buffer, strlen(IA_ID)) != 0)
- {
- printfd(__FILE__, "update needed - IA_ID\n");
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. Header: invalid packed signature.", inet_ntostring(sip).c_str());
- return -1;
- }
-
-if (buffer[6] != 0) //proto[0] shoud be 0
- {
- printfd(__FILE__, "update needed - PROTO major: %d\n", buffer[6]);
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. Header: invalid protocol major version: %d.", inet_ntostring(sip).c_str(), buffer[6]);
- return -1;
- }
-
-if (buffer[7] < 6)
- {
- // need update
- printfd(__FILE__, "update needed - PROTO minor: %d\n", buffer[7]);
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. Header: invalid protocol minor version: %d.", inet_ntostring(sip).c_str(), buffer[7]);
- return -1;
- }
-else
- {
- *protoVer = buffer[7];
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Timeouter()
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, IA_USER>::iterator it;
-it = ip2user.begin();
-
-while (it != ip2user.end())
- {
- uint32_t sip = it->first;
-
- static UTIME currTime;
- gettimeofday(&currTime, NULL);
-
- if ((it->second.phase.GetPhase() == 2)
- && (currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay())
- {
- if (iaSettings.LogProtocolErrors())
- logger("User '%s'. Protocol version: %d. Phase 2: connect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
- it->second.phase.SetPhase1();
- printfd(__FILE__, "Phase changed from 2 to 1. Reason: timeout\n");
- ip2user.erase(it++);
- continue;
- }
-
- if (it->second.phase.GetPhase() == 3)
- {
- if (!it->second.messagesToSend.empty())
- {
- if (it->second.protoVer == 6)
- RealSendMessage6(*it->second.messagesToSend.begin(), sip, it->second);
-
- if (it->second.protoVer == 7)
- RealSendMessage7(*it->second.messagesToSend.begin(), sip, it->second);
-
- if (it->second.protoVer == 8)
- RealSendMessage8(*it->second.messagesToSend.begin(), sip, it->second);
-
- it->second.messagesToSend.erase(it->second.messagesToSend.begin());
- }
-
- if((currTime - it->second.lastSendAlive) > iaSettings.GetUserDelay())
- {
- switch (it->second.protoVer)
- {
- case 6:
- Send_ALIVE_SYN_6(&(it->second), sip);
- break;
- case 7:
- Send_ALIVE_SYN_7(&(it->second), sip);
- break;
- case 8:
- Send_ALIVE_SYN_8(&(it->second), sip);
- break;
- }
-
- gettimeofday(&it->second.lastSendAlive, NULL);
- }
-
- if ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserTimeout())
- {
- if (iaSettings.LogProtocolErrors())
- logger("User '%s'. Protocol version: %d. Phase 3: alive timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserTimeout().GetSec());
- users->Unauthorize(it->second.user->GetLogin(), this);
- ip2user.erase(it++);
- continue;
- }
- }
-
- if ((it->second.phase.GetPhase() == 4)
- && ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay()))
- {
- if (iaSettings.LogProtocolErrors())
- logger("User '%s'. Protocol version: %d. Phase 4: disconnect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
- it->second.phase.SetPhase3();
- printfd(__FILE__, "Phase changed from 4 to 3. Reason: timeout\n");
- }
-
- ++it;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, USER_PTR user)
-{
-std::string login(user->GetLogin());
-const size_t offset = LOGIN_LEN + 2 + 6; // LOGIN_LEN + sizeOfMagic + sizeOfVer;
-
-STG_LOCKER lock(&mutex);
-std::map<uint32_t, IA_USER>::iterator it(ip2user.find(sip));
-
-if (it == ip2user.end())
- {
- USER_PTR userPtr;
- if (!users->FindByIPIdx(sip, &userPtr))
- {
- if (userPtr->GetID() != user->GetID())
- {
- printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
- userPtr->GetLogin().c_str(),
- inet_ntostring(sip).c_str(),
- login.c_str());
- logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
- userPtr->GetLogin().c_str(),
- inet_ntostring(sip).c_str(),
- login.c_str());
- SendError(sip, sport, protoVer, IconvString("IP-адрес уже сипользуется.", "utf8", "koi8-ru"));
- return 0;
- }
- }
-
- printfd(__FILE__, "Add new user '%s' from ip %s\n",
- login.c_str(), inet_ntostring(sip).c_str());
- std::pair<std::map<uint32_t, IA_USER>::iterator, bool> res;
- res = ip2user.insert(std::make_pair(sip, IA_USER(login, user, sport, protoVer)));
- it = res.first;
- #ifdef IA_PHASE_DEBUG
- it->second.phase.SetLogFileName(stgSettings->GetLogFileName());
- it->second.phase.SetUserLogin(login);
- #endif
- }
-else if (user->GetID() != it->second.user->GetID())
- {
- printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
- it->second.user->GetLogin().c_str(),
- inet_ntostring(sip).c_str(),
- user->GetLogin().c_str());
- logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
- it->second.user->GetLogin().c_str(),
- inet_ntostring(sip).c_str(),
- user->GetLogin().c_str());
- SendError(sip, sport, protoVer, IconvString("IP-адрес уже используется.", "utf8", "koi8-ru"));
- return 0;
- }
-
-IA_USER * iaUser = &(it->second);
-
-if (iaUser->password != user->GetProperty().password.Get())
- {
- const std::string & password = user->GetProperty().password.Get();
- InitContext(password.c_str(), password.length(), &iaUser->ctx);
- iaUser->password = user->GetProperty().password.Get();
- }
-
-DecryptString(static_cast<char *>(buff) + offset, static_cast<char *>(buff) + offset, (dataLen - offset), &iaUser->ctx);
-
-char packetName[IA_MAX_TYPE_LEN];
-strncpy(packetName, static_cast<char *>(buff) + offset + 4, IA_MAX_TYPE_LEN);
-packetName[IA_MAX_TYPE_LEN - 1] = 0;
-
-std::map<std::string, int>::iterator pi(packetTypes.find(packetName));
-if (pi == packetTypes.end())
- {
- SendError(sip, sport, protoVer, IconvString("Неправильный логин или пароль.", "utf8", "koi8-ru"));
- printfd(__FILE__, "Login or password is wrong!\n");
- logger("User's connect failed. User: '%s', ip %s. Wrong login or password",
- login.c_str(),
- inet_ntostring(sip).c_str());
- ip2user.erase(it);
- return 0;
- }
-
-if (user->IsAuthorizedBy(this) && user->GetCurrIP() != sip)
- {
- printfd(__FILE__, "Login %s already in use from ip %s. IP %s\n",
- login.c_str(), inet_ntostring(user->GetCurrIP()).c_str(),
- inet_ntostring(sip).c_str());
- logger("Login '%s' is already in use from ip %s. IP %s",
- login.c_str(),
- inet_ntostring(user->GetCurrIP()).c_str(),
- inet_ntostring(sip).c_str());
- SendError(sip, sport, protoVer, IconvString("Логин уже используется.", "utf8", "koi8-ru"));
- ip2user.erase(it);
- return 0;
- }
-
-switch (pi->second)
- {
- case CONN_SYN_N:
- switch (protoVer)
- {
- case 6:
- if (Process_CONN_SYN_6(static_cast<CONN_SYN_6 *>(buff), &(it->second), sip))
- return -1;
- return Send_CONN_SYN_ACK_6(iaUser, sip);
- case 7:
- if (Process_CONN_SYN_7(static_cast<CONN_SYN_7 *>(buff), &(it->second), sip))
- return -1;
- return Send_CONN_SYN_ACK_7(iaUser, sip);
- case 8:
- if (Process_CONN_SYN_8(static_cast<CONN_SYN_8 *>(buff), &(it->second), sip))
- return -1;
- return Send_CONN_SYN_ACK_8(iaUser, sip);
- }
- break;
-
- case CONN_ACK_N:
- switch (protoVer)
- {
- case 6:
- if (Process_CONN_ACK_6(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
- return -1;
- return Send_ALIVE_SYN_6(iaUser, sip);
- case 7:
- if (Process_CONN_ACK_7(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
- return -1;
- return Send_ALIVE_SYN_7(iaUser, sip);
- case 8:
- if (Process_CONN_ACK_8(static_cast<CONN_ACK_8 *>(buff), iaUser, sip))
- return -1;
- return Send_ALIVE_SYN_8(iaUser, sip);
- }
- break;
-
- case ALIVE_ACK_N:
- switch (protoVer)
- {
- case 6:
- return Process_ALIVE_ACK_6(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
- case 7:
- return Process_ALIVE_ACK_7(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
- case 8:
- return Process_ALIVE_ACK_8(static_cast<ALIVE_ACK_8 *>(buff), iaUser, sip);
- }
- break;
-
- case DISCONN_SYN_N:
- switch (protoVer)
- {
- case 6:
- if (Process_DISCONN_SYN_6(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
- return -1;
- return Send_DISCONN_SYN_ACK_6(iaUser, sip);
- case 7:
- if (Process_DISCONN_SYN_7(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
- return -1;
- return Send_DISCONN_SYN_ACK_7(iaUser, sip);
- case 8:
- if (Process_DISCONN_SYN_8(static_cast<DISCONN_SYN_8 *>(buff), iaUser, sip))
- return -1;
- return Send_DISCONN_SYN_ACK_8(iaUser, sip);
- }
- break;
-
- case DISCONN_ACK_N:
- switch (protoVer)
- {
- case 6:
- if (Process_DISCONN_ACK_6(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
- return -1;
- return Send_FIN_6(iaUser, sip, it);
- case 7:
- if (Process_DISCONN_ACK_7(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
- return -1;
- return Send_FIN_7(iaUser, sip, it);
- case 8:
- if (Process_DISCONN_ACK_8(static_cast<DISCONN_ACK_8 *>(buff), iaUser, sip, it))
- return -1;
- return Send_FIN_8(iaUser, sip, it);
- }
- break;
- }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-void AUTH_IA::DelUser(USER_PTR u)
-{
-
-uint32_t ip = u->GetCurrIP();
-
-if (!ip)
- return;
-
-std::map<uint32_t, IA_USER>::iterator it;
-
-STG_LOCKER lock(&mutex);
-it = ip2user.find(ip);
-if (it == ip2user.end())
- {
- //Nothing to delete
- printfd(__FILE__, "Nothing to delete\n");
- return;
- }
-
-if (it->second.user == u)
- {
- printfd(__FILE__, "User removed!\n");
- users->Unauthorize(u->GetLogin(), this);
- ip2user.erase(it);
- }
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text)
-{
-struct sockaddr_in sendAddr;
-ssize_t res;
-switch (protoVer)
- {
- case 6:
- case 7:
- ERR err;
- memset(&err, 0, sizeof(ERR));
-
- sendAddr.sin_family = AF_INET;
- sendAddr.sin_port = htons(port);
- sendAddr.sin_addr.s_addr = ip;
-
- err.len = 1;
- strncpy((char*)err.type, "ERR", 16);
- strncpy((char*)err.text, text.c_str(), MAX_MSG_LEN);
-
- #ifdef ARCH_BE
- SwapBytes(err.len);
- #endif
-
- res = sendto(listenSocket, &err, sizeof(err), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
- printfd(__FILE__, "SendError %d bytes sent\n", res);
- break;
-
- case 8:
- ERR_8 err8;
- memset(&err8, 0, sizeof(ERR_8));
-
- sendAddr.sin_family = AF_INET;
- sendAddr.sin_port = htons(port);
- sendAddr.sin_addr.s_addr = ip;
-
- err8.len = 256;
- strncpy((char*)err8.type, "ERR", 16);
- strncpy((char*)err8.text, text.c_str(), MAX_MSG_LEN);
-
- #ifdef ARCH_BE
- SwapBytes(err8.len);
- #endif
-
- res = sendto(listenSocket, &err8, sizeof(err8), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
- printfd(__FILE__, "SendError_8 %d bytes sent\n", res);
- break;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send(uint32_t ip, uint16_t port, const char * buffer, size_t len)
-{
-struct sockaddr_in sendAddr;
-
-sendAddr.sin_family = AF_INET;
-sendAddr.sin_port = htons(port);
-sendAddr.sin_addr.s_addr = ip;
-
-if (sendto(listenSocket, buffer, len, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr)) == static_cast<ssize_t>(len))
- return 0;
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::SendMessage(const STG_MSG & msg, uint32_t ip) const
-{
-printfd(__FILE__, "SendMessage userIP=%s\n", inet_ntostring(ip).c_str());
-
-std::map<uint32_t, IA_USER>::iterator it;
-
-STG_LOCKER lock(&mutex);
-it = ip2user.find(ip);
-if (it == ip2user.end())
- {
- errorStr = "Unknown user.";
- return -1;
- }
-it->second.messagesToSend.push_back(msg);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 6 user=%s\n", user.login.c_str());
-
-INFO_6 info;
-memset(&info, 0, sizeof(INFO_6));
-
-info.len = 256;
-strncpy((char*)info.type, "INFO", 16);
-info.infoType = 'I';
-strncpy((char*)info.text, msg.text.c_str(), 235);
-info.text[234] = 0;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-#endif
-
-char buffer[256];
-memcpy(buffer, &info, sizeof(INFO_6));
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, iaSettings.GetUserPort(), buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 7 user=%s\n", user.login.c_str());
-
-INFO_7 info;
-memset(&info, 0, sizeof(INFO_7));
-
-info.len = 264;
-strncpy((char*)info.type, "INFO_7", 16);
-info.infoType = static_cast<int8_t>(msg.header.type);
-info.showTime = static_cast<int8_t>(msg.header.showTime);
-info.sendTime = msg.header.creationTime;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-SwapBytes(info.sendTime);
-#endif
-
-strncpy((char*)info.text, msg.text.c_str(), MAX_MSG_LEN - 1);
-info.text[MAX_MSG_LEN - 1] = 0;
-
-char buffer[300];
-memcpy(buffer, &info, sizeof(INFO_7));
-
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, iaSettings.GetUserPort(), buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 8 user=%s\n", user.login.c_str());
-
-INFO_8 info;
-memset(&info, 0, sizeof(INFO_8));
-
-info.len = 1056;
-strncpy((char*)info.type, "INFO_8", 16);
-info.infoType = static_cast<int8_t>(msg.header.type);
-info.showTime = static_cast<int8_t>(msg.header.showTime);
-info.sendTime = msg.header.creationTime;
-
-strncpy((char*)info.text, msg.text.c_str(), IA_MAX_MSG_LEN_8 - 1);
-info.text[IA_MAX_MSG_LEN_8 - 1] = 0;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-SwapBytes(info.sendTime);
-#endif
-
-char buffer[1500];
-memcpy(buffer, &info, sizeof(INFO_8));
-
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, user.port, buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_6(CONN_SYN_6 *, IA_USER * iaUser, uint32_t)
-{
-if (!(iaUser->phase.GetPhase() == 1 || iaUser->phase.GetPhase() == 3))
- return -1;
-
-enabledDirs = 0xFFffFFff;
-
-iaUser->phase.SetPhase2();
-printfd(__FILE__, "Phase changed from %d to 2. Reason: CONN_SYN_6\n", iaUser->phase.GetPhase());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip)
-{
-return Process_CONN_SYN_6(connSyn, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connSyn->dirs);
-#endif
-int ret = Process_CONN_SYN_6(reinterpret_cast<CONN_SYN_6 *>(connSyn), iaUser, sip);
-enabledDirs = connSyn->dirs;
-return ret;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connAck->len);
-SwapBytes(connAck->rnd);
-#endif
-printfd( __FILE__, "CONN_ACK_6 %s\n", connAck->type);
-
-if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
- {
- iaUser->phase.UpdateTime();
-
- iaUser->lastSendAlive = iaUser->phase.GetTime();
- if (users->Authorize(iaUser->login, sip, enabledDirs, this))
- {
- iaUser->phase.SetPhase3();
- printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_6\n");
- return 0;
- }
- else
- {
- errorStr = iaUser->user->GetStrError();
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
- iaUser->phase.SetPhase1();
- ip2user.erase(sip);
- printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
- return -1;
- }
- }
-printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
-if (iaSettings.LogProtocolErrors())
- {
- if (iaUser->phase.GetPhase() != 2)
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- if (connAck->rnd != iaUser->rnd + 1)
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
- }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-return Process_CONN_ACK_6(connAck, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connAck->len);
-SwapBytes(connAck->rnd);
-#endif
-printfd( __FILE__, "CONN_ACK_8 %s\n", connAck->type);
-
-if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
- {
- iaUser->phase.UpdateTime();
- iaUser->lastSendAlive = iaUser->phase.GetTime();
- if (users->Authorize(iaUser->login, sip, enabledDirs, this))
- {
- iaUser->phase.SetPhase3();
- printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_8\n");
- return 0;
- }
- else
- {
- errorStr = iaUser->user->GetStrError();
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
- iaUser->phase.SetPhase1();
- ip2user.erase(sip);
- printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
- return -1;
- }
- }
-printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
-if (iaSettings.LogProtocolErrors())
- {
- if (iaUser->phase.GetPhase() != 2)
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- if (connAck->rnd != iaUser->rnd + 1)
- logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
- }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t)
-{
-#ifdef ARCH_BE
-SwapBytes(aliveAck->len);
-SwapBytes(aliveAck->rnd);
-#endif
-printfd(__FILE__, "ALIVE_ACK_6\n");
-if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
- {
- iaUser->phase.UpdateTime();
- #ifdef IA_DEBUG
- iaUser->aliveSent = false;
- #endif
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip)
-{
-return Process_ALIVE_ACK_6(aliveAck, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t)
-{
-#ifdef ARCH_BE
-SwapBytes(aliveAck->len);
-SwapBytes(aliveAck->rnd);
-#endif
-printfd(__FILE__, "ALIVE_ACK_8\n");
-if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
- {
- iaUser->phase.UpdateTime();
- #ifdef IA_DEBUG
- iaUser->aliveSent = false;
- #endif
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_6(DISCONN_SYN_6 *, IA_USER * iaUser, uint32_t sip)
-{
-printfd(__FILE__, "DISCONN_SYN_6\n");
-if (iaUser->phase.GetPhase() != 3)
- {
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
- errorStr = "Incorrect request DISCONN_SYN";
- return -1;
- }
-
-iaUser->phase.SetPhase4();
-printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip)
-{
-return Process_DISCONN_SYN_6(disconnSyn, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_8(DISCONN_SYN_8 *, IA_USER * iaUser, uint32_t sip)
-{
-if (iaUser->phase.GetPhase() != 3)
- {
- if (iaSettings.LogProtocolErrors())
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- errorStr = "Incorrect request DISCONN_SYN";
- printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
- return -1;
- }
-
-iaUser->phase.SetPhase4();
-printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnAck,
- IA_USER * iaUser,
- uint32_t sip,
- std::map<uint32_t, IA_USER>::iterator)
-{
-#ifdef ARCH_BE
-SwapBytes(disconnAck->len);
-SwapBytes(disconnAck->rnd);
-#endif
-printfd(__FILE__, "DISCONN_ACK_6\n");
-if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
- {
- if (iaSettings.LogProtocolErrors())
- {
- if (iaUser->phase.GetPhase() != 4)
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- if (disconnAck->rnd != iaUser->rnd + 1)
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
- }
- printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-return Process_DISCONN_ACK_6(disconnAck, iaUser, sip, it);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator)
-{
-#ifdef ARCH_BE
-SwapBytes(disconnAck->len);
-SwapBytes(disconnAck->rnd);
-#endif
-printfd(__FILE__, "DISCONN_ACK_8\n");
-if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
- {
- if (iaSettings.LogProtocolErrors())
- {
- if (iaUser->phase.GetPhase() != 4)
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
- if (disconnAck->rnd != iaUser->rnd + 1)
- logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
- }
- printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
-{
-//+++ Fill static data in connSynAck +++
-// TODO Move this code. It must be executed only once
-connSynAck6.len = Min8(sizeof(CONN_SYN_ACK_6));
-strcpy((char*)connSynAck6.type, "CONN_SYN_ACK");
-for (int j = 0; j < DIR_NUM; j++)
- {
- strncpy((char*)connSynAck6.dirName[j],
- stgSettings->GetDirName(j).c_str(),
- sizeof(string16));
-
- connSynAck6.dirName[j][sizeof(string16) - 1] = 0;
- }
-//--- Fill static data in connSynAck ---
-
-iaUser->rnd = static_cast<uint32_t>(random());
-connSynAck6.rnd = iaUser->rnd;
-
-printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
-
-connSynAck6.userTimeOut = iaSettings.GetUserTimeout().GetSec();
-connSynAck6.aliveDelay = iaSettings.GetUserDelay().GetSec();
-
-#ifdef ARCH_BE
-SwapBytes(connSynAck6.len);
-SwapBytes(connSynAck6.rnd);
-SwapBytes(connSynAck6.userTimeOut);
-SwapBytes(connSynAck6.aliveDelay);
-#endif
-
-EncryptString((char*)&connSynAck6, (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)));;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_CONN_SYN_ACK_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)connSynAck8.hdr.magic, IA_ID);
-connSynAck8.hdr.protoVer[0] = 0;
-connSynAck8.hdr.protoVer[1] = 8;
-
-//+++ Fill static data in connSynAck +++
-// TODO Move this code. It must be executed only once
-connSynAck8.len = Min8(sizeof(CONN_SYN_ACK_8));
-strcpy((char*)connSynAck8.type, "CONN_SYN_ACK");
-for (int j = 0; j < DIR_NUM; j++)
- {
- strncpy((char*)connSynAck8.dirName[j],
- stgSettings->GetDirName(j).c_str(),
- sizeof(string16));
-
- connSynAck8.dirName[j][sizeof(string16) - 1] = 0;
- }
-//--- Fill static data in connSynAck ---
-
-iaUser->rnd = static_cast<uint32_t>(random());
-connSynAck8.rnd = iaUser->rnd;
-
-printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
-
-connSynAck8.userTimeOut = iaSettings.GetUserTimeout().GetSec();
-connSynAck8.aliveDelay = iaSettings.GetUserDelay().GetSec();
-
-#ifdef ARCH_BE
-SwapBytes(connSynAck8.len);
-SwapBytes(connSynAck8.rnd);
-SwapBytes(connSynAck8.userTimeOut);
-SwapBytes(connSynAck8.aliveDelay);
-#endif
-
-EncryptString((char*)&connSynAck8, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip)
-{
-aliveSyn6.len = Min8(sizeof(ALIVE_SYN_6));
-aliveSyn6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-strcpy((char*)aliveSyn6.type, "ALIVE_SYN");
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- aliveSyn6.md[i] = iaUser->user->GetProperty().down.Get()[i];
- aliveSyn6.mu[i] = iaUser->user->GetProperty().up.Get()[i];
-
- aliveSyn6.sd[i] = iaUser->user->GetSessionDownload()[i];
- aliveSyn6.su[i] = iaUser->user->GetSessionUpload()[i];
- }
-
-//TODO
-int dn = iaSettings.GetFreeMbShowType();
-const TARIFF * tf = iaUser->user->GetTariff();
-
-if (dn < DIR_NUM)
- {
- double p = tf->GetPriceWithTraffType(aliveSyn6.mu[dn],
- aliveSyn6.md[dn],
- dn,
- stgTime);
- p *= 1024 * 1024;
- if (std::fabs(p) < 1.0e-3)
- {
- snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "---");
- }
- else
- {
- double fmb = iaUser->user->GetProperty().freeMb;
- fmb = fmb < 0 ? 0 : fmb;
- snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
- }
- }
-else
- {
- if (freeMbNone == iaSettings.GetFreeMbShowType())
- {
- aliveSyn6.freeMb[0] = 0;
- }
- else
- {
- double fmb = iaUser->user->GetProperty().freeMb;
- fmb = fmb < 0 ? 0 : fmb;
- snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
- }
- }
-
-#ifdef IA_DEBUG
-if (iaUser->aliveSent)
- {
- printfd(__FILE__, "========= ALIVE_ACK_6(7) TIMEOUT !!! %s =========\n", iaUser->login.c_str());
- }
-iaUser->aliveSent = true;
-#endif
-
-aliveSyn6.cash =(int64_t) (iaUser->user->GetProperty().cash.Get() * 1000.0);
-if (!stgSettings->GetShowFeeInCash())
- aliveSyn6.cash -= (int64_t)(tf->GetFee() * 1000.0);
-
-#ifdef ARCH_BE
-SwapBytes(aliveSyn6.len);
-SwapBytes(aliveSyn6.rnd);
-SwapBytes(aliveSyn6.cash);
-for (int i = 0; i < DIR_NUM; ++i)
- {
- SwapBytes(aliveSyn6.mu[i]);
- SwapBytes(aliveSyn6.md[i]);
- SwapBytes(aliveSyn6.su[i]);
- SwapBytes(aliveSyn6.sd[i]);
- }
-#endif
-
-EncryptString((char*)&aliveSyn6, (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_ALIVE_SYN_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)aliveSyn8.hdr.magic, IA_ID);
-aliveSyn8.hdr.protoVer[0] = 0;
-aliveSyn8.hdr.protoVer[1] = 8;
-
-aliveSyn8.len = Min8(sizeof(ALIVE_SYN_8));
-aliveSyn8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-strcpy((char*)aliveSyn8.type, "ALIVE_SYN");
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- aliveSyn8.md[i] = iaUser->user->GetProperty().down.Get()[i];
- aliveSyn8.mu[i] = iaUser->user->GetProperty().up.Get()[i];
-
- aliveSyn8.sd[i] = iaUser->user->GetSessionDownload()[i];
- aliveSyn8.su[i] = iaUser->user->GetSessionUpload()[i];
- }
-
-//TODO
-int dn = iaSettings.GetFreeMbShowType();
-
-if (dn < DIR_NUM)
- {
- const TARIFF * tf = iaUser->user->GetTariff();
- double p = tf->GetPriceWithTraffType(aliveSyn8.mu[dn],
- aliveSyn8.md[dn],
- dn,
- stgTime);
- p *= 1024 * 1024;
- if (std::fabs(p) < 1.0e-3)
- {
- snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "---");
- }
- else
- {
- double fmb = iaUser->user->GetProperty().freeMb;
- fmb = fmb < 0 ? 0 : fmb;
- snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
- }
- }
-else
- {
- if (freeMbNone == iaSettings.GetFreeMbShowType())
- {
- aliveSyn8.freeMb[0] = 0;
- }
- else
- {
- double fmb = iaUser->user->GetProperty().freeMb;
- fmb = fmb < 0 ? 0 : fmb;
- snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
- }
- }
-
-#ifdef IA_DEBUG
-if (iaUser->aliveSent)
- {
- printfd(__FILE__, "========= ALIVE_ACK_8 TIMEOUT !!! =========\n");
- }
-iaUser->aliveSent = true;
-#endif
-
-const TARIFF * tf = iaUser->user->GetTariff();
-
-aliveSyn8.cash =(int64_t) (iaUser->user->GetProperty().cash.Get() * 1000.0);
-if (!stgSettings->GetShowFeeInCash())
- aliveSyn8.cash -= (int64_t)(tf->GetFee() * 1000.0);
-
-#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
-
-EncryptString((char*)&aliveSyn8, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
-{
-disconnSynAck6.len = Min8(sizeof(DISCONN_SYN_ACK_6));
-strcpy((char*)disconnSynAck6.type, "DISCONN_SYN_ACK");
-disconnSynAck6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-#ifdef ARCH_BE
-SwapBytes(disconnSynAck6.len);
-SwapBytes(disconnSynAck6.rnd);
-#endif
-
-EncryptString((char*)&disconnSynAck6, (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_DISCONN_SYN_ACK_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)disconnSynAck8.hdr.magic, IA_ID);
-disconnSynAck8.hdr.protoVer[0] = 0;
-disconnSynAck8.hdr.protoVer[1] = 8;
-
-disconnSynAck8.len = Min8(sizeof(DISCONN_SYN_ACK_8));
-strcpy((char*)disconnSynAck8.type, "DISCONN_SYN_ACK");
-disconnSynAck8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-#ifdef ARCH_BE
-SwapBytes(disconnSynAck8.len);
-SwapBytes(disconnSynAck8.rnd);
-#endif
-
-EncryptString((char*)&disconnSynAck8, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-fin6.len = Min8(sizeof(FIN_6));
-strcpy((char*)fin6.type, "FIN");
-strcpy((char*)fin6.ok, "OK");
-
-#ifdef ARCH_BE
-SwapBytes(fin6.len);
-#endif
-
-EncryptString((char*)&fin6, (char*)&fin6, Min8(sizeof(fin6)), &iaUser->ctx);
-
-users->Unauthorize(iaUser->login, this);
-
-int res = Send(sip, iaSettings.GetUserPort(), (char*)&fin6, Min8(sizeof(fin6)));
-
-ip2user.erase(it);
-
-return res;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-return Send_FIN_6(iaUser, sip, it);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-strcpy((char*)fin8.hdr.magic, IA_ID);
-fin8.hdr.protoVer[0] = 0;
-fin8.hdr.protoVer[1] = 8;
-
-fin8.len = Min8(sizeof(FIN_8));
-strcpy((char*)fin8.type, "FIN");
-strcpy((char*)fin8.ok, "OK");
-
-#ifdef ARCH_BE
-SwapBytes(fin8.len);
-#endif
-
-EncryptString((char*)&fin8, (char*)&fin8, Min8(sizeof(fin8)), &iaUser->ctx);
-
-users->Unauthorize(iaUser->login, this);
-
-int res = Send(sip, iaUser->port, (char*)&fin8, Min8(sizeof(fin8)));
-
-ip2user.erase(it);
-
-return res;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.34 $
- $Date: 2010/09/10 06:39:19 $
- $Author: faust $
- */
-
-#ifndef INETACCESS_H
-#define INETACCESS_H
-
-#include "stg/os_int.h"
-#include "stg/auth.h"
-#include "stg/store.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/user.h"
-#include "stg/users.h"
-#include "stg/ia_packets.h"
-#include "stg/blowfish.h"
-#include "stg/logger.h"
-#include "stg/utime.h"
-#include "stg/logger.h"
-
-#include <cstring>
-#include <ctime>
-#include <string>
-#include <map>
-#include <list>
-#include <functional>
-#include <utility>
-
-#include <sys/time.h>
-#include <pthread.h>
-
-#define IA_PROTO_VER (6)
-
-//#define IA_DEBUG (1)
-//#define IA_PHASE_DEBUG (1)
-
-class AUTH_IA;
-//-----------------------------------------------------------------------------
-enum FREEMB {
- freeMb0 = 0,
- freeMb1,
- freeMb2,
- freeMb3,
- freeMb4,
- freeMb5,
- freeMb6,
- freeMb7,
- freeMb8,
- freeMb9,
- freeMb10,
- freeMb11,
- freeMb12,
- freeMb13,
- freeMb14,
- freeMb15,
- freeMb16,
- freeMb17,
- freeMb18,
- freeMb19,
- freeMbCash = 100,
- freeMbNone = 101
-};
-//-----------------------------------------------------------------------------
-class IA_PHASE {
-public:
- IA_PHASE();
- ~IA_PHASE();
-
- void SetPhase1();
- void SetPhase2();
- void SetPhase3();
- void SetPhase4();
- int GetPhase() const;
-
- void UpdateTime();
- const UTIME & GetTime() const;
-
- #ifdef IA_PHASE_DEBUG
- void SetUserLogin(const std::string & login);
- void SetLogFileName(const std::string & logFileName);
- #endif
-
-private:
- int phase;
- UTIME phaseTime;
-
- #ifdef IA_PHASE_DEBUG
- void WritePhaseChange(int newPhase);
- std::string log;
- std::string login;
- FILE * flog;
- #endif
-};
-//-----------------------------------------------------------------------------
-struct IA_USER {
- IA_USER()
- : login(),
- user(NULL),
- phase(),
- lastSendAlive(0),
- rnd(static_cast<uint32_t>(random())),
- port(0),
- ctx(),
- messagesToSend(),
- protoVer(0),
- password("NO 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);
-
- #ifdef IA_DEBUG
- aliveSent = false;
- #endif
- }
-
- IA_USER(const IA_USER & u)
- : login(u.login),
- user(u.user),
- phase(u.phase),
- lastSendAlive(u.lastSendAlive),
- rnd(u.rnd),
- port(u.port),
- ctx(),
- messagesToSend(u.messagesToSend),
- protoVer(u.protoVer),
- password(u.password)
- {
- #ifdef IA_DEBUG
- aliveSent = u.aliveSent;
- #endif
- memcpy(&ctx, &u.ctx, sizeof(BLOWFISH_CTX));
- }
-
- IA_USER(const std::string & l,
- CONST_USER_PTR u,
- uint16_t p,
- int ver)
- : login(l),
- user(u),
- phase(),
- lastSendAlive(0),
- rnd(static_cast<uint32_t>(random())),
- port(p),
- ctx(),
- messagesToSend(),
- protoVer(ver),
- password(user->GetProperty().password.Get())
- {
- unsigned char keyL[PASSWD_LEN];
- memset(keyL, 0, PASSWD_LEN);
- strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
- Blowfish_Init(&ctx, keyL, PASSWD_LEN);
-
- #ifdef IA_DEBUG
- aliveSent = false;
- #endif
- }
-
- std::string login;
- CONST_USER_PTR user;
- IA_PHASE phase;
- UTIME lastSendAlive;
- uint32_t rnd;
- uint16_t port;
- BLOWFISH_CTX ctx;
- std::list<STG_MSG> messagesToSend;
- int protoVer;
- std::string password;
- #ifdef IA_DEBUG
- bool aliveSent;
- #endif
-
-private:
- IA_USER & operator=(const IA_USER & rvalue);
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA_SETTINGS {
-public:
- AUTH_IA_SETTINGS();
- virtual ~AUTH_IA_SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- UTIME GetUserDelay() const { return UTIME(userDelay); }
- UTIME GetUserTimeout() const { return UTIME(userTimeout); }
- uint16_t GetUserPort() const { return port; }
- FREEMB GetFreeMbShowType() const { return freeMbShowType; }
- bool LogProtocolErrors() const { return logProtocolErrors; }
-
-private:
- int userDelay;
- int userTimeout;
- uint16_t port;
- std::string errorStr;
- FREEMB freeMbShowType;
- bool logProtocolErrors;
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA;
-//-----------------------------------------------------------------------------
-class DEL_USER_NOTIFIER: public NOTIFIER_BASE<USER_PTR> {
-public:
- explicit DEL_USER_NOTIFIER(AUTH_IA & a) : auth(a) {}
- virtual ~DEL_USER_NOTIFIER() {}
-
- void Notify(const USER_PTR & user);
-private:
- DEL_USER_NOTIFIER(const DEL_USER_NOTIFIER & rvalue);
- DEL_USER_NOTIFIER & operator=(const DEL_USER_NOTIFIER & rvalue);
-
- AUTH_IA & auth;
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA :public AUTH {
-friend class DEL_USER_NOTIFIER;
-public:
- AUTH_IA();
- virtual ~AUTH_IA();
-
- void SetUsers(USERS * u) { users = u; }
- void SetStgSettings(const SETTINGS * s) { stgSettings = s; }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & ms);
- bool IsRunning() { return isRunningRunTimeouter || isRunningRun; }
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return "InetAccess authorization plugin v.1.4"; }
- uint16_t GetStartPosition() const { return 30; }
- uint16_t GetStopPosition() const { return 30; }
-
- int SendMessage(const STG_MSG & msg, uint32_t ip) const;
-
-private:
- AUTH_IA(const AUTH_IA & rvalue);
- AUTH_IA & operator=(const AUTH_IA & rvalue);
-
- static void * Run(void *);
- static void * RunTimeouter(void * d);
- int PrepareNet();
- int FinalizeNet();
- void DelUser(USER_PTR u);
- int RecvData(char * buffer, int bufferSize);
- int CheckHeader(const char * buffer, uint32_t sip, int * protoVer);
- int PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, USER_PTR user);
-
- int Process_CONN_SYN_6(CONN_SYN_6 * connSyn, IA_USER * iaUser, uint32_t sip);
- int Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip);
- int Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip);
-
- int Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip);
- int Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip);
- int Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip);
-
- int Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t sip);
- int Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip);
- int Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t sip);
-
- int Process_DISCONN_SYN_6(DISCONN_SYN_6 * disconnSyn, IA_USER * iaUser, uint32_t sip);
- int Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip);
- int Process_DISCONN_SYN_8(DISCONN_SYN_8 * disconnSyn, IA_USER * iaUser, uint32_t sip);
-
- int Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnSyn,
- IA_USER * iaUser,
- uint32_t sip,
- std::map<uint32_t, IA_USER>::iterator it);
- int Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnSyn,
- IA_USER * iaUser,
- uint32_t sip,
- std::map<uint32_t, IA_USER>::iterator it);
- int Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnSyn,
- IA_USER * iaUser,
- uint32_t sip,
- std::map<uint32_t, IA_USER>::iterator it);
-
- int Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
- int Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
- int Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
-
- int Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip);
- int Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip);
- int Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip);
-
- int Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
- int Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
- int Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
-
- int Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
- int Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
- int Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
-
- int Timeouter();
-
- int SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text);
- int Send(uint32_t ip, uint16_t port, const char * buffer, size_t len);
- int RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user);
- int RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user);
- int RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user);
-
- BLOWFISH_CTX ctxS; //for loginS
-
- mutable std::string errorStr;
- AUTH_IA_SETTINGS iaSettings;
- MODULE_SETTINGS settings;
-
- bool nonstop;
-
- bool isRunningRun;
- bool isRunningRunTimeouter;
-
- USERS * users;
- const SETTINGS * stgSettings;
-
- mutable std::map<uint32_t, IA_USER> ip2user;
-
- pthread_t recvThread;
- pthread_t timeouterThread;
- mutable pthread_mutex_t mutex;
-
- int listenSocket;
-
- CONN_SYN_ACK_6 connSynAck6;
- CONN_SYN_ACK_8 connSynAck8;
-
- DISCONN_SYN_ACK_6 disconnSynAck6;
- DISCONN_SYN_ACK_8 disconnSynAck8;
-
- ALIVE_SYN_6 aliveSyn6;
- ALIVE_SYN_8 aliveSyn8;
- FIN_6 fin6;
- FIN_8 fin8;
-
- std::map<std::string, int> packetTypes;
-
- uint32_t enabledDirs;
-
- DEL_USER_NOTIFIER onDelUserNotifier;
-
- PLUGIN_LOGGER logger;
-
- friend class UnauthorizeUser;
-};
-//-----------------------------------------------------------------------------
-class UnauthorizeUser : std::unary_function<const std::pair<uint32_t, IA_USER> &, void> {
- public:
- explicit UnauthorizeUser(AUTH_IA * a) : auth(a) {}
- UnauthorizeUser(const UnauthorizeUser & rvalue) : auth(rvalue.auth) {}
- void operator()(const std::pair<uint32_t, IA_USER> & p)
- {
- auth->users->Unauthorize(p.second.user->GetLogin(), auth);
- }
- private:
- UnauthorizeUser & operator=(const UnauthorizeUser & rvalue);
-
- AUTH_IA * auth;
-};
-//-----------------------------------------------------------------------------
-inline
-void DEL_USER_NOTIFIER::Notify(const USER_PTR & user)
-{
- auth.DelUser(user);
-}
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.4 2008/12/04 17:01:28 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_auth_stress.so
-
-SRCS = ./stress.cpp
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.5 $
- $Date: 2009/06/19 12:50:32 $
- $Author: faust $
- */
-
-#include <stdio.h>
-#include <unistd.h>
-
-#include <csignal>
-#include <algorithm>
-
-#include "stg/user.h"
-#include "stg/common.h"
-#include "stg/user_property.h"
-#include "stg/plugin_creator.h"
-
-#include "stress.h"
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN_CREATOR<AUTH_STRESS> stressc;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// ëÌÁÓÓ ÄÌÑ ÐÏÉÓËÁ ÀÚÅÒÁ × ÓÐÉÓËÅ ÎÏÔÉÆÉËÁÔÏÒÏ×
-template <typename varType>
-class IS_CONTAINS_USER: public binary_function<varType, USER_PTR, bool>
-{
-public:
- bool operator()(varType notifier, USER_PTR user) const
- {
- return notifier.GetUser() == user;
- };
-};
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-//printf("BASE_CAPTURER * GetCapturer()\n");
-return stressc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-AUTH_STRESS_SETTINGS::AUTH_STRESS_SETTINGS()
- : averageOnlineTime(0)
-{
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-PARAM_VALUE pv;
-vector<PARAM_VALUE>::const_iterator pvi;
-
-pv.param = "AverageOnlineTime";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end())
- {
- errorStr = "Parameter \'" + pv.param + "\' not found.";
- return -1;
- }
-
-if (ParseIntInRange(pvi->value[0], 5, 10*3600, &averageOnlineTime))
- {
- errorStr = "Cannot parse parameter \'" + pv.param + "\': " + errorStr;
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS_SETTINGS::GetAverageOnlineTime() const
-{
-return averageOnlineTime;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-const string AUTH_STRESS::GetVersion() const
-{
-return "Stress authorizator v.0.1";
-}
-//-----------------------------------------------------------------------------
-AUTH_STRESS::AUTH_STRESS()
-{
-pthread_mutex_init(&mutex, NULL);
-isRunning = false;
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::SetUsers(USERS * u)
-{
-users = u;
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::SetSettings(const MODULE_SETTINGS & s)
-{
-settings = s;
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS::ParseSettings()
-{
-int ret = stressSettings.ParseSettings(settings);
-if (ret)
- errorStr = stressSettings.GetStrError();
-return ret;
-}
-//-----------------------------------------------------------------------------
-const string & AUTH_STRESS::GetStrError() const
-{
-return errorStr;
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS::Start()
-{
-GetUsers();
-nonstop = true;
-
-list<USER_PTR>::iterator users_iter;
-
-onAddUserNotifier.SetAuthorizator(this);
-onDelUserNotifier.SetAuthorizator(this);
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-if (!isRunning)
- {
- if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- return -1;
- }
- }
-
-users_iter = usersList.begin();
-while (users_iter != usersList.end())
- {
- Authorize(*users_iter);
- ++users_iter;
- }
-
-//isRunning = true;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS::Stop()
-{
-nonstop = false;
-if (isRunning)
- {
- //5 seconds to thread stops itself
- int i;
- for (i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
- //after 5 seconds waiting thread still running. now killing it
- if (isRunning)
- {
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- return -1;
- }
- printfd(__FILE__, "AUTH_STRESS killed Run\n");
- }
- }
-
-users->DelNotifierUserAdd(&onAddUserNotifier);
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool AUTH_STRESS::IsRunning()
-{
-return isRunning;
-}
-//-----------------------------------------------------------------------------
-uint16_t AUTH_STRESS::GetStartPosition() const
-{
-return 30;
-}
-//-----------------------------------------------------------------------------
-uint16_t AUTH_STRESS::GetStopPosition() const
-{
-return 30;
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::SetUserNotifiers(USER_PTR u)
-{
-// ---------- IP -------------------
-CHG_BEFORE_NOTIFIER<USER_IPS> BeforeChgIPNotifier;
-CHG_AFTER_NOTIFIER<USER_IPS> AfterChgIPNotifier;
-
-BeforeChgIPNotifier.SetAuthorizator(this);
-BeforeChgIPNotifier.SetUser(u);
-BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
-
-AfterChgIPNotifier.SetAuthorizator(this);
-AfterChgIPNotifier.SetUser(u);
-AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
-
-u->GetProperty().ips.AddBeforeNotifier(&(*BeforeChgIPNotifierList.begin()));
-u->GetProperty().ips.AddAfterNotifier(&(*AfterChgIPNotifierList.begin()));
-// ---------- IP end ---------------
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::UnSetUserNotifiers(USER_PTR u)
-{
-// --- IP ---
-IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<USER_IPS> > IsContainsUserIPB;
-IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<USER_IPS> > IsContainsUserIPA;
-
-list<CHG_BEFORE_NOTIFIER<USER_IPS> >::iterator ipBIter;
-list<CHG_AFTER_NOTIFIER<USER_IPS> >::iterator ipAIter;
-
-ipBIter = find_if(BeforeChgIPNotifierList.begin(),
- BeforeChgIPNotifierList.end(),
- bind2nd(IsContainsUserIPB, u));
-
-if (ipBIter != BeforeChgIPNotifierList.end())
- {
- ipBIter->GetUser()->GetProperty().ips.DelBeforeNotifier(&(*ipBIter));
- BeforeChgIPNotifierList.erase(ipBIter);
- }
-
-ipAIter = find_if(AfterChgIPNotifierList.begin(),
- AfterChgIPNotifierList.end(),
- bind2nd(IsContainsUserIPA, u));
-
-if (ipAIter != AfterChgIPNotifierList.end())
- {
- ipAIter->GetUser()->GetProperty().ips.DelAfterNotifier(&(*ipAIter));
- AfterChgIPNotifierList.erase(ipAIter);
- }
-// --- IP end ---
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::GetUsers()
-{
-USER_PTR u;
-printfd(__FILE__, "users->OpenSearch() usernum=%d\n", users->GetUserNum());
-int h = users->OpenSearch();
-if (!h)
- {
- printfd(__FILE__, "users->OpenSearch() error\n");
- return;
- }
-
-while (1)
- {
- if (users->SearchNext(h, &u))
- {
- break;
- }
- usersList.push_back(u);
- SetUserNotifiers(u);
- }
-
-users->CloseSearch(h);
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::Unauthorize(USER_PTR u) const
-{
-if (!u->IsAuthorizedBy(this))
- return;
-
-printfd(__FILE__, "Unauthorized user %s\n", u->GetLogin().c_str());
-u->Unauthorize(this);
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::Authorize(USER_PTR u) const
-{
-USER_IPS ips = u->GetProperty().ips;
-if (ips.OnlyOneIP() && !u->IsAuthorizedBy(this))
- {
- if (u->Authorize(ips[0].ip, 0xFFffFFff, this) == 0)
- {
- printfd(__FILE__, "Authorized user %s\n", u->GetLogin().c_str());
- }
- }
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::AddUser(USER_PTR u)
-{
-//printfd(__FILE__, "User added to list %s\n", u->GetLogin().c_str());
-SetUserNotifiers(u);
-usersList.push_back(u);
-}
-//-----------------------------------------------------------------------------
-void AUTH_STRESS::DelUser(USER_PTR u)
-{
-Unauthorize(u);
-UnSetUserNotifiers(u);
-
-list<USER_PTR>::iterator users_iter;
-users_iter = usersList.begin();
-
-while (users_iter != usersList.end())
- {
- if (u == *users_iter)
- {
- usersList.erase(users_iter);
- printfd(__FILE__, "User removed from list %s\n", u->GetLogin().c_str());
- break;
- }
- ++users_iter;
- }
-}
-//-----------------------------------------------------------------------------
-int AUTH_STRESS::SendMessage(const STG_MSG &, uint32_t) const
-{
-errorStr = "Authorization modele \'AUTH_STRESS\' does not support sending messages";
-return -1;
-}
-//-----------------------------------------------------------------------------
-void * AUTH_STRESS::Run(void * d)
-{
-AUTH_STRESS * ia = static_cast<AUTH_STRESS *>(d);
-
-ia->isRunning = true;
-
-while (ia->nonstop)
- {
- printfd(__FILE__, "AUTH_STRESS::Run - averageTime: %d\n", random() % (2*ia->stressSettings.GetAverageOnlineTime()));
-
- list<USER_PTR>::iterator users_iter;
- users_iter = ia->usersList.begin();
- while (users_iter != ia->usersList.end())
- {
- if (random() % (2*ia->stressSettings.GetAverageOnlineTime()) == 1)
- {
- ia->Authorize(*users_iter);
- printfd(__FILE__, "AUTH_STRESS::Authorize - user: '%s'\n", (*users_iter)->GetLogin().c_str());
- }
- if (random() % (2*ia->stressSettings.GetAverageOnlineTime()) == 2)
- {
- ia->Unauthorize(*users_iter);
- printfd(__FILE__, "AUTH_STRESS::Unauthorize - user: '%s'\n", (*users_iter)->GetLogin().c_str());
- }
-
- ++users_iter;
- }
-
- sleep(1);
- }
-
-ia->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-auth->Unauthorize(user);
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-auth->Authorize(user);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.3 $
- $Date: 2009/06/19 12:50:32 $
- $Author: faust $
- */
-
-
-#ifndef STRESS_H
-#define STRESS_H
-
-#include <pthread.h>
-
-#include <string>
-#include <list>
-
-#include "stg/auth.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/users.h"
-#include "stg/module_settings.h"
-
-extern "C" PLUGIN * GetPlugin();
-
-class AUTH_STRESS;
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-class CHG_BEFORE_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType> {
-public:
- CHG_BEFORE_NOTIFIER() : auth(NULL) {}
- void Notify(const varParamType & oldValue, const varParamType & newValue);
- void SetUser(USER_PTR u) { user = u; }
- USER_PTR GetUser() {return user; }
- void SetAuthorizator(const AUTH_STRESS * a) { auth = a; }
-
-private:
- USER_PTR user;
- const AUTH_STRESS * auth;
-};
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-class CHG_AFTER_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType> {
-public:
- CHG_AFTER_NOTIFIER() : auth(NULL) {}
- void Notify(const varParamType & oldValue, const varParamType & newValue);
- void SetUser(USER_PTR u) { user = u; }
- USER_PTR GetUser() {return user; }
- void SetAuthorizator(const AUTH_STRESS * a) { auth = a; }
-
-private:
- USER_PTR user;
- const AUTH_STRESS * auth;
-};
-//-----------------------------------------------------------------------------
-class AUTH_STRESS_SETTINGS {
-public:
- AUTH_STRESS_SETTINGS();
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- int GetAverageOnlineTime() const;
-private:
- int averageOnlineTime;
- std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-class AUTH_STRESS :public AUTH {
-friend class CHG_BEFORE_NOTIFIER<USER_IPS>;
-friend class CHG_AFTER_NOTIFIER<USER_IPS>;
-public:
- AUTH_STRESS();
- virtual ~AUTH_STRESS() {}
-
- void SetUsers(USERS * u);
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning();
- void SetSettings(const MODULE_SETTINGS & s);
- int ParseSettings();
- const std::string & GetStrError() const;
- const std::string GetVersion() const;
- uint16_t GetStartPosition() const;
- uint16_t GetStopPosition() const;
-
- int SendMessage(const STG_MSG & msg, uint32_t ip) const;
-
-private:
- void GetUsers();
- void SetUserNotifiers(USER_PTR u);
- void UnSetUserNotifiers(USER_PTR u);
-
- void AddUser(USER_PTR u);
- void DelUser(USER_PTR u);
-
- void Authorize(USER_PTR u) const;
- void Unauthorize(USER_PTR u) const;
-
- static void * Run(void *);
-
- bool nonstop;
-
- mutable std::string errorStr;
- AUTH_STRESS_SETTINGS stressSettings;
- USERS * users;
- std::list<USER_PTR> usersList;
- bool isRunning;
- MODULE_SETTINGS settings;
-
- pthread_t thread;
- pthread_mutex_t mutex;
-
- std::list<CHG_BEFORE_NOTIFIER<USER_IPS> > BeforeChgIPNotifierList;
- std::list<CHG_AFTER_NOTIFIER<USER_IPS> > AfterChgIPNotifierList;
-
- class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
- public:
- ADD_USER_NONIFIER() : auth(NULL) {}
- virtual ~ADD_USER_NONIFIER() {}
-
- void SetAuthorizator(AUTH_STRESS * a) { auth = a; }
- void Notify(const USER_PTR & user)
- {
- auth->AddUser(user);
- }
-
- private:
- AUTH_STRESS * auth;
- } onAddUserNotifier;
-
- class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
- public:
- DEL_USER_NONIFIER() : auth(NULL) {}
- virtual ~DEL_USER_NONIFIER() {}
-
- void SetAuthorizator(AUTH_STRESS * a) { auth = a; }
- void Notify(const USER_PTR & user)
- {
- auth->DelUser(user);
- }
-
- private:
- AUTH_STRESS * auth;
- } onDelUserNotifier;
-
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.10 2008/12/04 17:03:25 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_debug.so
-
-SRCS = ./debug_cap.cpp \
- ./checksum.c \
- ./ip.c \
- ./packet.c \
- ./tcp.c
-
-STGLIBS = common
-
-LIBS += $(LIB_THREAD)
-
-include ../../Makefile.in
-
+++ /dev/null
-/*$Id: checksum.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-unsigned short
-in_cksum(unsigned short *addr, int len)
-{
- int nleft = len;
- int sum = 0;
- unsigned short *w = addr;
- unsigned short answer = 0;
-
- /*
- * Our algorithm is simple, using a 32 bit accumulator (sum), we add
- * sequential 16 bit words to it, and at the end, fold back all the
- * carry bits from the top 16 bits into the lower 16 bits.
- */
- while (nleft > 1) {
- sum += *w++;
- nleft -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nleft == 1) {
- *(unsigned char *)(&answer) = *(unsigned char *)w ;
- sum += answer;
- }
-
- /* add back carry outs from top 16 bits to low 16 bits */
- sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
- sum += (sum >> 16); /* add carry */
- answer = ~sum; /* truncate to 16 bits */
- return(answer);
-}
+++ /dev/null
-/* $Id: checksum.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-unsigned short in_cksum(unsigned short *addr, int len);
+++ /dev/null
-/* $Id: constants.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
-* socket types
-*/
-#define PKT_RAW SOCK_RAW
-#define PKT_STREAM SOCK_STREAM
-#define PKT_DGRAM SOCK_DGRAM
-
-/*
-* Link Layer
-*/
-#define PKT_LINK_ARP 0x01
-#define PKT_LINK_RARP 0x02
-
-/*
-* Network Layer
-*/
-#define PKT_NET_IP 0x01
-#define PKT_NET_ICMP 0x02
-#define PKT_NET_IGMP 0x04
-
-/*
-* Transport layer
-*/
-#define PKT_TRANS_TCP 0x01
-#define PKT_TRANS_UDP 0x02
-
-/* --- [ IP ] ------------------------ */
-/* IP options */
-#define PKT_IP_OPT_EOL 0 /* end of option list */
-#define PKT_IP_OPT_END PKT_IP_OPT_EOL
-#define PKT_IP_OPT_NOP 1 /* no operation */
-#define PKT_IP_OPT_NOOP PKT_IP_OPT_NOP
-
-#define PKT_IP_OPT_RR 7 /* record packet route */
-#define PKT_IP_OPT_TS 68 /* timestamp */
-#define PKT_IP_OPT_TIMESTAMP PKT_IP_OPT_TS
-#define PKT_IP_OPT_SECURITY 130 /* provide s,c,h,tcc */
-#define PKT_IP_OPT_SEC PKT_IP_OPT_SECURITY
-#define PKT_IP_OPT_LSRR 131 /* loose source route */
-#define PKT_IP_OPT_SATID 136 /* satnet id */
-#define PKT_IP_OPT_SID PKT_IP_OPT_SATID
-#define PKT_IP_OPT_SSRR 137 /* strict source route */
-#define PKT_IP_OPT_RA 148 /* router alert */
-
-/* flag bits for ipt_flg */
-#define PKT_IP_OPT_TS_TSONLY 0 /* timestamps only */
-#define PKT_IP_OPT_TS_TSANDADDR 1 /* timestamps and addresses */
-#define PKT_IP_OPT_TS_PRESPEC 3 /* specified modules only */
-
-/* --- [ TCP ] ------------------------ */
-/* tcp flags */
-#ifndef __FAVOUR_BSD
-#define TH_FIN 0x01
-#define TH_SYN 0x02
-#define TH_RST 0x04
-#define TH_PUSH 0x08
-#define TH_ACK 0x10
-#define TH_URG 0x20
-#endif
-/* additional flags */
-#define TH_XMAS 0x40
-#define TH_YMAS 0x80
-
-/* tcp options */
-#define PKT_TCP_OPT_END 0x00
-#define PKT_TCP_OPT_NOP 0x01
-#define PKT_TCP_OPT_MSS 0x02
-#define PKT_TCP_OPT_WSF 0x03 /*window scale factor*/
-#define PKT_TCP_OPT_SACK_PERM 0x04
-#define PKT_TCP_OPT_SACK 0x05
-#define PKT_TCP_OPT_TIME 0x08 /* timestamp option */
-
-/* tcp option lenghts */
-#define PKT_TCP_OPT_END_LEN 0x01
-#define PKT_TCP_OPT_NOP_LEN 0x01
-#define PKT_TCP_OPT_MSS_LEN 0x04
-#define PKT_TCP_OPT_WSF_LEN 0x03 /*window scale factor*/
-#define PKT_TCP_OPT_SACK_PERM_LEN 0x02
-#define PKT_TCP_OPT_SACK_LEN 0x01
-#define PKT_TCP_OPT_TIME_LEN 0x0a /* timestamp option */
-
-/* return values and errors */
-#define PKTOK 0
-#define EPKTRANGE -64
-#define EERRNO -63 /* errno has been set */
-#define EPKTINVALPTR -62
-#define EPKTUNKNOWNTYPE -61
+++ /dev/null
-/*
- * 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: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.21 $
-$Date: 2009/03/19 20:03:35 $
-$Author: faust $
-*/
-
-#include "debug_cap.h"
-
-#include "libpal.h"
-
-#include "stg/plugin_creator.h"
-#include "stg/traffcounter.h"
-#include "stg/common.h"
-
-#include <cstdio>
-#include <csignal>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-extern volatile time_t stgTime;
-
-//-----------------------------------------------------------------------------
-void WriteStat(uint32_t u, uint32_t d)
-{
-FILE * f;
-f = fopen("/tmp/cap.stat", "at");
-fprintf(f, "up %5.2f Mbit, down %5.2f Mbit, sum %5.2f Mbit\n",
- u / (1000000*8.0),
- d / (1000000*8.0),
- (u + d) / (1000000*8.0));
-fclose(f);
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<DEBUG_CAP> cdc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return cdc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-RAW_PACKET MakeTCPPacket(const char * src,
- const char * dst,
- uint16_t sport,
- uint16_t dport,
- uint16_t len);
-std::string DEBUG_CAP::GetVersion() const
-{
-return "cap_debug v.0.01a";
-}
-//-----------------------------------------------------------------------------
-DEBUG_CAP::DEBUG_CAP()
- : nonstop(false),
- isRunning(false),
- traffCnt(NULL)
-{
-}
-//-----------------------------------------------------------------------------
-void DEBUG_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
-{
-traffCnt = tc;
-}
-//-----------------------------------------------------------------------------
-const std::string & DEBUG_CAP::GetStrError() const
-{
-return errorStr;
-}
-//-----------------------------------------------------------------------------
-int DEBUG_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-printfd(__FILE__, "DEBUG_CAP::Start()\n");
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run1, this) == 0)
- {
- return 0;
- }
-
-errorStr = "Cannot create thread.";
-return -1;
-}
-//-----------------------------------------------------------------------------
-int DEBUG_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
-
- usleep(200000);
- //printf(".");
- }
-
-/*if (i)
- printf("\n");*/
-
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- //TODO pthread_cancel()
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- return -1;
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool DEBUG_CAP::IsRunning()
-{
-return nonstop;
-}
-//-----------------------------------------------------------------------------
-void * DEBUG_CAP::Run1(void * data)
-{
-printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-
-DEBUG_CAP * dc = static_cast<DEBUG_CAP *>(data);
-dc->isRunning = true;
-
-RAW_PACKET rp;
-rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
-int a = 0;
-sleep(3);
-
-struct tm * tm;
-time_t t;
-uint32_t u = 0;
-uint32_t d = 0;
-
-//2 upload : 3 download
-
-int usize;
-int dsize;
-
-t = stgTime;
-tm = localtime(&t);
-int min = tm->tm_min;
-
-char cliIP[20];
-char srvIP[20];
-
-while (dc->nonstop)
- {
- for (int i = 8; i <= 252; i++)
- {
- usize = random()%100 + 100;
- dsize = random()%500 + 900;
-
- for (int j = 2; j < 11; j++)
- {
- sprintf(cliIP, "192.168.%d.%d", j, i);
- sprintf(srvIP, "10.1.%d.%d", random()%8, 1);
-
- rp = MakeTCPPacket(srvIP, cliIP, 80, random()%2 + 2000, dsize);
- d += dsize;
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(cliIP, srvIP, random()%2 + 2000, 80, usize);
- u += usize;
- dc->traffCnt->Process(rp);
- }
- }
-
- usleep(100000);
- t = stgTime;
-
- if (min != localtime(&t)->tm_min)
- {
- min = localtime(&t)->tm_min;
- WriteStat(u, d);
- u = d = 0;
- }
-
- a++;
-
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void * DEBUG_CAP::Run2(void * data)
-{
-printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-
-DEBUG_CAP * dc = static_cast<DEBUG_CAP *>(data);
-dc->isRunning = true;
-
-RAW_PACKET rp;
-rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
-int a = 0;
-sleep(3);
-
-struct tm * tm;
-time_t t;
-uint32_t u = 0;
-uint32_t d = 0;
-
-//2 upload : 3 download
-
-int usize = 200;
-int dsize = 1500;
-
-t = stgTime;
-tm = localtime(&t);
-int min = tm->tm_min;
-
-char cliIP[20];
-char srvIP[20];
-
-while (dc->nonstop)
- {
- for (int i = 101; i <= 150; i++)
- {
- sprintf(cliIP, "192.168.1.%d", i);
- for (int dp = 0; dp < 1; dp++)
- {
- //sprintf(srvIP, "10.1.%d.%d", i, 10 + dp);
- sprintf(srvIP, "10.1.%d.%d", i, 10 + dp);
-
- rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
- d += dsize;
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
- d += dsize;
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
- dc->traffCnt->Process(rp);
- d += dsize;
-
-
- rp = MakeTCPPacket(cliIP, srvIP, 10000 + i + dp, 80, usize);
- u += usize;
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(cliIP, srvIP, 10000 + i + dp, 80, usize);
- u += usize;
- dc->traffCnt->Process(rp);
- }
- }
-
- //usleep(20000);
- t = stgTime;
-
- if (min != localtime(&t)->tm_min)
- {
- min = localtime(&t)->tm_min;
- WriteStat(u, d);
- u = d = 0;
- }
-
- a++;
-
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void * DEBUG_CAP::Run3(void * data)
-{
-printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-
-DEBUG_CAP * dc = static_cast<DEBUG_CAP *>(data);
-dc->isRunning = true;
-
-RAW_PACKET rp;
-rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
-int a = 0;
-sleep(3);
-
-time_t t;
-uint32_t u = 0;
-uint32_t d = 0;
-
-//2 upload : 3 download
-
-int usize = 200;
-int dsize = 1500;
-
-t = stgTime;
-
-char cliIP[20];
-char srvIP1[20];
-char srvIP2[20];
-char srvIP3[20];
-
-int firstTime = true;
-
-while (dc->nonstop)
- {
- if (firstTime)
- {
- sprintf(srvIP1, "10.1.%d.%d", random() % 14 + 153, random() % 11 + 35);
-
- sprintf(srvIP2, "%d.%d.%d.%d",
- random() % 20 + 81,
- random() % 28 + 153,
- random() % 28 + 37,
- random() % 28 + 13);
-
- sprintf(srvIP3, "%d.%d.%d.%d",
- random() % 20 + 81,
- random() % 28 + 153,
- random() % 28 + 37,
- random() % 28 + 13);
-
- printfd(__FILE__, "firstTime=false\n");
- firstTime = false;
- }
-
- int rnd = random() % 400;
- if (rnd < 5)
- {
- sprintf(srvIP1, "10.1.%d.%d", random() % 14 + 153, random() % 11 + 35);
- printfd(__FILE__, "srvIP1=%s\n", srvIP1);
- }
- if (rnd == 9)
- {
- sprintf(srvIP2, "%d.%d.%d.%d",
- random() % 20 + 81,
- random() % 28 + 153,
- random() % 28 + 37,
- random() % 28 + 13);
- printfd(__FILE__, "srvIP2=%s\n", srvIP2);
- }
- if (rnd == 5)
- {
- sprintf(srvIP2, "%d.%d.%d.%d",
- random() % 20 + 81,
- random() % 28 + 153,
- random() % 28 + 37,
- random() % 28 + 13);
- printfd(__FILE__, "srvIP3=%s\n", srvIP3);
- }
-
- for (int i = 2; i < 52; i++)
- {
- sprintf(cliIP, "192.168.1.%d", i);
- for (int dp = 0; dp < 1; dp++)
- {
- usize = 50 + random() % 100;
- dsize = 1000 + random() % 400;
-
- rp = MakeTCPPacket(srvIP1, cliIP, 80, 10000 + i + dp, dsize);
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(srvIP2, cliIP, 80, 10000 + i + dp, dsize);
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(srvIP3, cliIP, 80, 10000 + i + dp, dsize);
- dc->traffCnt->Process(rp);
-
-
- rp = MakeTCPPacket(cliIP, srvIP1, 10000 + i + dp, 80, usize);
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(cliIP, srvIP2, 10000 + i + dp, 80, usize);
- dc->traffCnt->Process(rp);
-
- rp = MakeTCPPacket(cliIP, srvIP3, 10000 + i + dp, 80, usize);
- dc->traffCnt->Process(rp);
- }
- }
-
- usleep(300000);
- /*t = stgTime;
-
- if (min != localtime(&t)->tm_min)
- {
- min = localtime(&t)->tm_min;
- WriteStat(u, d);
- u = d = 0;
- }*/
-
- a++;
-
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-uint16_t DEBUG_CAP::GetStartPosition() const
-{
-return 40;
-}
-//-----------------------------------------------------------------------------
-uint16_t DEBUG_CAP::GetStopPosition() const
-{
-return 40;
-}
-//-----------------------------------------------------------------------------
-RAW_PACKET MakeTCPPacket(const char * src,
- const char * dst,
- uint16_t sport,
- uint16_t dport,
- uint16_t len)
-{
-struct packet pkt;
-if (pkt_init(&pkt, 0, 100))
- {
- printfd(__FILE__, "pkt_init error!\n");
- }
-
-in_addr_t sip = inet_addr(src);
-in_addr_t dip = inet_addr(dst);
-
-pkt_ip_header(&pkt,
- 5, //header len
- 4,
- 0,
- len, //total len
- 0,
- 0,
- 64, //ttl
- 6, //TCP
- 0,
- *(uint32_t*)&sip,
- *(uint32_t*)&dip);
-
-pkt_move_actptr(&pkt, 20);
-
-pkt_tcp_header(&pkt,
- sport,
- dport,
- 1, // seq,
- 1, // ackseq,
- 5, // headerlen,
- 0, // reserved,
- 0, // flags,
- 0, // window,
- 0, // checksum,
- 0); // urgent
-
-RAW_PACKET rp;
-memcpy(&rp, pkt.pkt, sizeof(rp));
-
-if (pkt_free(&pkt))
- {
- printfd(__FILE__, "pkt_free error!\n");
- }
-rp.dataLen = -1;
-return rp;
-}
-//-----------------------------------------------------------------------------
-
-
+++ /dev/null
-/*
- * 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: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.12 $
-$Date: 2009/06/23 11:32:27 $
-$Author: faust $
-*/
-
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-
-//-----------------------------------------------------------------------------
-struct iphdr_eth {
- 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;
- int32_t len;
- char iface[10];
-};
-//-----------------------------------------------------------------------------
-class CAP_SETTINGS {
-public:
- const std::string & GetStrError() const { static std::string s; return s; }
- int ParseSettings(const MODULE_SETTINGS & s) { return 0; }
-};
-//-----------------------------------------------------------------------------
-class DEBUG_CAP :public PLUGIN
-{
-public:
- DEBUG_CAP();
- virtual ~DEBUG_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc);
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- int ParseSettings() { return 0; }
- bool IsRunning();
- const std::string & GetStrError() const;
- std::string GetVersion() const;
- uint16_t GetStartPosition() const;
- uint16_t GetStopPosition() const;
-private:
- static void * Run1(void *);
- static void * Run2(void *);
- static void * Run3(void *);
- mutable std::string errorStr;
- CAP_SETTINGS capSettings;
- pthread_t thread;
- bool nonstop;
- bool isRunning;
-
- TRAFFCOUNTER * traffCnt;
-};
-//-----------------------------------------------------------------------------
+++ /dev/null
-/* $Id: ip.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "libpal.h"
-
-int
-pkt_ip_header(struct packet *pkt,
- unsigned int iphdr_len,
- unsigned int version,
- unsigned char tos,
- unsigned short int total_len,
- unsigned short int id,
- unsigned short int frag_off,
- unsigned char ttl,
- unsigned char protocol,
- unsigned short int cksum,
- unsigned int saddr,
- unsigned int daddr)
-{
- struct ip *ip;
-
- if (!pkt)
- return EPKTINVALPTR;
-
- ip = (struct ip *) pkt->pkt_ptr;
-
- ip->ip_hl = iphdr_len;
- ip->ip_v = version;
- ip->ip_tos = tos;
- ip->ip_len = htons(total_len);
- ip->ip_id = htons(id);
- ip->ip_off = htons(frag_off);
- ip->ip_ttl = ttl;
- ip->ip_p = protocol;
- ip->ip_src.s_addr = saddr;
- ip->ip_dst.s_addr = daddr;
-
- return 0;
-}
+++ /dev/null
-/* $Id: libpal.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef _LIBPAL_H_
-#define _LIBPAL_H_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "checksum.h"
-#include "constants.h"
-
-/*
-* generic packet structure
-*
-* we maintain a so called "active ptr" inside the packet. Most operations
-* on the packet will take place at the position the pointer points at.
-* The pointer should never be moved directly, instead the functions
-* pkt_set_actpr() and pkt_move_actptr() are provided.
-* Using this approach we can perform bounds checking and make sure our
-* library functions won't segfault.
-* pkt_type is not really being used at the moment. I don't know if it
-* ever will be. It might just be left out one day, so keep your fingers
-* off. Use pkt_init() to set it. And dont even think of messing with the
-* packet payload pointer pkt. You do NOT want to do that. Use the provided
-* library functions.
-* To be clear: don't do _anything_ with this struct. Just pass it as a
-* parameter, be happy and your programs will (hopefully) work.
-*/
-struct packet {
- unsigned long pkt_type;
- unsigned char *pkt;
- unsigned int pkt_size;
- unsigned char *pkt_ptr; /* active ptr inside packet */
- unsigned int pkt_pos; /* pkt_ptr position, starting at 0 */
-};
-
-/*
-* our socket structure
-*
-* same as above. Use the provided library fuctions to change its values.
-* Do not do it on your own. Live and let die. You have been warned.
-*/
-struct pkt_socket {
- int rawfd;
- struct sockaddr_in *sckad;
- /*struct sockaddr_ll *sckll;*/
- socklen_t sckad_len;
-};
-
-/* memory management */
-int pkt_init(struct packet *pkt, unsigned long type, unsigned int size);
-int pkt_free(struct packet *pkt);
-
-/* pointer movement */
-int pkt_move_actptr(struct packet *pkt, int relmov);
-
-/* IP */
-int pkt_ip_header(struct packet *pkt, unsigned int iphdr_len, unsigned int version, unsigned char tos, unsigned short int total_len, unsigned short int id, unsigned short int frag_off /* 3bit flag, 13bit offset */, unsigned char ttl, unsigned char protocol, unsigned short int cksum, unsigned int saddr, unsigned int daddr);
-
-/* TCP */
-int pkt_tcp_header(struct packet *pkt, unsigned short int sport, unsigned short int dport, unsigned int seq, unsigned int ackseq, unsigned char headerlen, unsigned char reserved, unsigned char flags, unsigned short window, unsigned short int checksum, unsigned short int urgent);
-int pkt_tcp_cksum(struct packet *pkt, char *saddr, char *daddr, unsigned int tcp_pkt_size);
-int pkt_tcp_option(struct packet *pkt, unsigned char kind, unsigned char len, void *optval, size_t optlen);
-
-/* functions that might be useful and might be added some day ...
-int pkt_shift_data(struct packet *pkt, unsigned int from, unsigned int to, unsigned int len);
-int pkt_tcp_change_seqno(int rel_seq, int rel_ackseq);
-int pkt_tcp_set_seqno(unsigned int seq, unsigned int ackseq);
-int pkt_ip_option(struct packet *pkt, unsigned char code, unsigned char len, unsigned char ptr);
-int pkt_ip_option_addval(struct *pkt, unsigned char posptr, unsigned int optval);
-*/
-
-#endif
+++ /dev/null
-/* $Id: packet.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "libpal.h"
-
-/*
-<++doc++>
-@name int pkt_init(struct packet *pkt, unsigned long type, unsigned int size)
-@desc Allocates memory for a new packet and initializes its internal variables
-@param pkt pointer to the new packet
-@param type type of the packet. Its setting is currently ignored, but this is likely to change. Possible values are e.g. PKT_NET_IP|PKT_TRANS_TCP. See packet.h for other values
-@param size overall size if the packet not including ethernet headers or trailers.
-<--doc-->
-*/
-int
-pkt_init(struct packet *pkt, unsigned long type, unsigned int size)
-{
- if ((pkt->pkt = (unsigned char *) malloc(size)) == NULL) {
- /* no mem, we assume errno will be set */
- return -1;
- } else {
- /* clear mem out */
- memset(pkt->pkt, 0, size);
- /* init vars */
- pkt->pkt_type = type;
- pkt->pkt_size = size;
- /* set active ptr to beginning of mem */
- pkt->pkt_ptr = pkt->pkt;
- pkt->pkt_pos = 0;
- return 0;
- }
-}
-
-/*
-<++doc++>
-@name int pkt_free(struct packet *pkt)
-@desc Used to destroy a packet and to free used memory
-@param pkt the packet to destroy
-<--doc-->
-*/
-int
-pkt_free(struct packet *pkt)
-{
- if (pkt) {
- free(pkt->pkt);
- pkt->pkt=NULL;
- return 0;
- }
- return EPKTINVALPTR;
-}
-
-/*
-<++doc++>
-@name int pkt_move_actptr(struct packet *pkt, int relmov)
-@desc This function moves the active pointer inside the packet.
-@param pkt the packet whose active ptr is to be moved
-@param relmov number of bytes the active ptr shall be moved. To move it backward, negative values may be used.
-<--doc-->
-*/
-int
-pkt_move_actptr(struct packet *pkt, int relmov)
-{
- if (!pkt)
- return EPKTINVALPTR;
- if ((pkt->pkt_pos + relmov > pkt->pkt_size) ||
- (pkt->pkt_pos + relmov < 0)) {
- return EPKTRANGE;
- } else {
- pkt->pkt_ptr += relmov;
- return PKTOK;
- }
-}
+++ /dev/null
-/* $Id: tcp.c,v 1.2 2009/06/19 12:50:47 faust Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "libpal.h"
-#include "types.h" /* internal types */
-
-int
-pkt_tcp_header(struct packet *pkt,
- unsigned short int sport,
- unsigned short int dport,
- unsigned int seq,
- unsigned int ackseq,
- unsigned char headerlen,
- unsigned char reserved,
- unsigned char flags,
- unsigned short window,
- unsigned short int checksum,
- unsigned short int urgent)
-{
- struct tcphdr *tcp;
-
- if (!pkt)
- return EPKTINVALPTR;
-
- tcp = (struct tcphdr *) pkt->pkt_ptr;
- tcp->source = htons(sport);
- tcp->dest = htons(dport);
- tcp->seq = htonl(seq);
- tcp->ack_seq = htonl(ackseq);
- tcp->window = htons(window);
- tcp->urg_ptr = htons(urgent);
-
- tcp->doff = headerlen;
- tcp->res1 = reserved;
- if (flags) {
- tcp->fin = ((flags & TH_FIN) != 0);
- tcp->syn = ((flags & TH_SYN) != 0);
- tcp->rst = ((flags & TH_RST) != 0);
- tcp->psh = ((flags & TH_RST) != 0);
- tcp->ack = ((flags & TH_ACK) != 0);
- tcp->urg = ((flags & TH_URG) != 0);
-# if __BYTE_ORDER == __LITTLE_ENDIAN
- tcp->res2 = (flags & (TH_XMAS | TH_YMAS)) >> 6;
-# elif __BYTE_ORDER == __BIG_ENDIAN
- tcp->res2 = (flags & (TH_XMAS | TH_YMAS));
-# else
-# error "Adjust your <bits/endian.h> defines"
-# endif
- } else {
- tcp->fin = 0;
- tcp->syn = 0;
- tcp->rst = 0;
- tcp->psh = 0;
- tcp->ack = 0;
- tcp->urg = 0;
- tcp->res2 = 0;
- }
- tcp->check = htons(checksum);
- return 0;
-}
-
-int
-pkt_tcp_cksum(struct packet *pkt, char *saddr, char *daddr,
- unsigned int tcp_pkt_size)
-{
- char *tosum;
- struct pseudohdr *psh;
- struct tcphdr *tcp;
- struct in_addr addr;
-
- if (!pkt || !saddr || !daddr)
- return EPKTINVALPTR;
-
- if ((tcp_pkt_size + pkt->pkt_pos) > pkt->pkt_size -1)
- return EPKTRANGE;
-
- if ((tosum = (char *) malloc(tcp_pkt_size+sizeof(struct pseudohdr))) != NULL) {
- memset(tosum, 0, tcp_pkt_size+sizeof(struct pseudohdr));
- psh = (struct pseudohdr *) tosum;
- tcp = (struct tcphdr *) pkt->pkt_ptr;
-
- tcp->check = 0;
-
- if (inet_pton(AF_INET, saddr, &addr) < 0)
- return EERRNO;
- psh->saddr = addr.s_addr;
- if (inet_pton(AF_INET, daddr, &addr) < 0)
- return EERRNO;
- psh->daddr = addr.s_addr;
- psh->zero = 0x00;
- psh->protocol = IPPROTO_TCP;
- psh->length = htons(tcp_pkt_size);
-
- memcpy(tosum + sizeof(struct pseudohdr), tcp, tcp_pkt_size);
- tcp->check = in_cksum((unsigned short *)tosum, tcp_pkt_size + sizeof(struct pseudohdr));
- free(tosum);
- return 0;
- } else
- return EERRNO;
-}
-
-int
-pkt_tcp_option(struct packet *pkt, unsigned char kind,
- unsigned char len, void *optval, size_t optlen)
-{
- void *vp;
- unsigned short int mss;
-
- if (!pkt)
- return EPKTINVALPTR;
-
- if ((pkt->pkt_size) < (pkt->pkt_pos+2+optlen))
- return EPKTRANGE;
-
- vp = (void *)pkt->pkt_ptr;
-
- memcpy(vp, &kind, 1);
- char * p;
- p = (char*)vp;
- p++;
- vp = p;
- //vp++;
- memcpy(vp, &len, 1);
- //vp++;
- p = (char*)vp;
- p++;
- vp = p;
- if (kind == PKT_TCP_OPT_MSS) {
- mss = htons(*(unsigned short int *)optval);
- memcpy(vp, &mss, optlen);
- } else if (kind == PKT_TCP_OPT_TIME) {
- unsigned int time = htonl(*(unsigned int *)optval);
- memcpy(vp, &time, optlen);
- } else {
- memcpy(vp, optval, optlen);
- }
- return 0;
-}
+++ /dev/null
-/* $Id: types.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
-
-Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef _LIBPAL_TYPES_H_
-#define _LIBPAL_TYPES_H_
-
-/*
-* these are types users wont need
-*/
-
-/* Stevens' pseudo header */
-struct pseudohdr {
- u_int32_t saddr;
- u_int32_t daddr;
- u_int8_t zero;
- u_int8_t protocol;
- u_int16_t length;
-};
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.2 2008/12/04 17:04:41 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_nf.so
-
-SRCS = ./cap_nf.cpp
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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: 16.05.2008
-*/
-
-/*
-* Author : Maxim Mamontov <faust@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.11 $
-$Date: 2010/09/10 06:41:06 $
-$Author: faust $
-*/
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include <vector>
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-#include "cap_nf.h"
-
-namespace
-{
-PLUGIN_CREATOR<NF_CAP> cnc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-
-PLUGIN * GetPlugin()
-{
-return cnc.GetPlugin();
-}
-
-NF_CAP::NF_CAP()
- : traffCnt(NULL),
- runningTCP(false),
- runningUDP(false),
- stoppedTCP(true),
- stoppedUDP(true),
- portT(0),
- portU(0),
- sockTCP(-1),
- sockUDP(-1),
- logger(GetPluginLogger(GetStgLogger(), "cap_nf"))
-{
-}
-
-NF_CAP::~NF_CAP()
-{
-}
-
-int NF_CAP::ParseSettings()
-{
-std::vector<PARAM_VALUE>::iterator it;
-for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
- {
- if (it->param == "TCPPort" && !it->value.empty())
- {
- if (str2x(it->value[0], portT))
- {
- errorStr = "Invalid TCPPort value";
- printfd(__FILE__, "Error: Invalid TCPPort value\n");
- return -1;
- }
- continue;
- }
- if (it->param == "UDPPort" && !it->value.empty())
- {
- if (str2x(it->value[0], portU))
- {
- errorStr = "Invalid UDPPort value";
- printfd(__FILE__, "Error: Invalid UDPPort value\n");
- return -1;
- }
- continue;
- }
- printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
- }
-return 0;
-}
-
-int NF_CAP::Start()
-{
-if (portU > 0)
- {
- if (OpenUDP())
- {
- return -1;
- }
- runningUDP = true;
- if (pthread_create(&tidUDP, NULL, RunUDP, this))
- {
- runningUDP = false;
- CloseUDP();
- errorStr = "Cannot create UDP thread";
- logger("Cannot create UDP thread.");
- printfd(__FILE__, "Error: Cannot create UDP thread\n");
- return -1;
- }
- }
-if (portT > 0)
- {
- if (OpenTCP())
- {
- return -1;
- }
- runningTCP = true;
- if (pthread_create(&tidTCP, NULL, RunTCP, this))
- {
- runningTCP = false;
- CloseTCP();
- logger("Cannot create TCP thread.");
- errorStr = "Cannot create TCP thread";
- printfd(__FILE__, "Error: Cannot create TCP thread\n");
- return -1;
- }
- }
-return 0;
-}
-
-int NF_CAP::Stop()
-{
-runningTCP = runningUDP = false;
-if (portU && !stoppedUDP)
- {
- CloseUDP();
- for (int i = 0; i < 25 && !stoppedUDP; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (stoppedUDP)
- {
- pthread_join(tidUDP, NULL);
- }
- else
- {
- if (pthread_kill(tidUDP, SIGUSR1))
- {
- errorStr = "Error sending signal to UDP thread";
- logger("Error sending sugnal to UDP thread.");
- printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
- return -1;
- }
- printfd(__FILE__, "UDP thread NOT stopped\n");
- logger("Cannot stop UDP thread.");
- }
- }
-if (portT && !stoppedTCP)
- {
- CloseTCP();
- for (int i = 0; i < 25 && !stoppedTCP; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (stoppedTCP)
- {
- pthread_join(tidTCP, NULL);
- }
- else
- {
- if (pthread_kill(tidTCP, SIGUSR1))
- {
- errorStr = "Error sending signal to TCP thread";
- logger("Error sending signal to TCP thread.");
- printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
- return -1;
- }
- printfd(__FILE__, "TCP thread NOT stopped\n");
- logger("Cannot stop TCP thread.");
- }
- }
-return 0;
-}
-
-bool NF_CAP::OpenUDP()
-{
-struct sockaddr_in sin;
-sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
-if (sockUDP <= 0)
- {
- errorStr = "Error opening UDP socket";
- logger("Cannot create UDP socket: %s", strerror(errno));
- printfd(__FILE__, "Error: Error opening UDP socket\n");
- return true;
- }
-sin.sin_family = AF_INET;
-sin.sin_port = htons(portU);
-sin.sin_addr.s_addr = inet_addr("0.0.0.0");
-if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
- {
- errorStr = "Error binding UDP socket";
- logger("Cannot bind UDP socket: %s", strerror(errno));
- printfd(__FILE__, "Error: Error binding UDP socket\n");
- return true;
- }
-return false;
-}
-
-bool NF_CAP::OpenTCP()
-{
-struct sockaddr_in sin;
-sockTCP = socket(PF_INET, SOCK_STREAM, 0);
-if (sockTCP <= 0)
- {
- errorStr = "Error opening TCP socket";
- logger("Cannot create TCP socket: %s", strerror(errno));
- printfd(__FILE__, "Error: Error opening TCP socket\n");
- return true;
- }
-sin.sin_family = AF_INET;
-sin.sin_port = htons(portT);
-sin.sin_addr.s_addr = inet_addr("0.0.0.0");
-if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
- {
- errorStr = "Error binding TCP socket";
- logger("Cannot bind TCP socket: %s", strerror(errno));
- printfd(__FILE__, "Error: Error binding TCP socket\n");
- return true;
- }
-if (listen(sockTCP, 1))
- {
- errorStr = "Error listening on TCP socket";
- logger("Cannot listen on TCP socket: %s", strerror(errno));
- printfd(__FILE__, "Error: Error listening TCP socket\n");
- return true;
- }
-return false;
-}
-
-void * NF_CAP::RunUDP(void * c)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedUDP = false;
-while (cap->runningUDP)
- {
- if (!WaitPackets(cap->sockUDP))
- {
- continue;
- }
-
- // Data
- struct sockaddr_in sin;
- socklen_t slen = sizeof(sin);
- uint8_t buf[BUF_SIZE];
- ssize_t res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
- if (!cap->runningUDP)
- break;
-
- if (res < 0)
- {
- cap->logger("recvfrom error: %s", strerror(errno));
- continue;
- }
-
- if (res == 0) // EOF
- {
- continue;
- }
-
- if (res < 24)
- {
- if (errno != EINTR)
- {
- cap->errorStr = "Invalid data received";
- printfd(__FILE__, "Error: Invalid data received through UDP\n");
- }
- continue;
- }
-
- cap->ParseBuffer(buf, res);
- }
-cap->stoppedUDP = true;
-return NULL;
-}
-
-void * NF_CAP::RunTCP(void * c)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedTCP = false;
-while (cap->runningTCP)
- {
- if (!WaitPackets(cap->sockTCP))
- {
- continue;
- }
-
- // Data
- struct sockaddr_in sin;
- socklen_t slen = sizeof(sin);
- int sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
- if (!cap->runningTCP)
- break;
-
- if (sd <= 0)
- {
- if (sd < 0)
- cap->logger("accept error: %s", strerror(errno));
- continue;
- }
-
- if (!WaitPackets(sd))
- {
- close(sd);
- continue;
- }
-
- uint8_t buf[BUF_SIZE];
- ssize_t res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
-
- if (res < 0)
- cap->logger("recv error: %s", strerror(errno));
-
- close(sd);
-
- if (!cap->runningTCP)
- break;
-
- if (res == 0) // EOF
- {
- continue;
- }
-
- // Wrong logic!
- // Need to check actual data length and wait all data to receive
- if (res < 24)
- {
- continue;
- }
-
- cap->ParseBuffer(buf, res);
- }
-cap->stoppedTCP = true;
-return NULL;
-}
-
-void NF_CAP::ParseBuffer(uint8_t * buf, ssize_t size)
-{
-RAW_PACKET ip;
-NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
-if (htons(hdr->version) != 5)
- {
- return;
- }
-
-int packets = htons(hdr->count);
-
-if (packets < 0 || packets > 30)
- {
- return;
- }
-
-if (24 + 48 * packets != size)
- {
- // See 'wrong logic' upper
- return;
- }
-
-for (int i = 0; i < packets; ++i)
- {
- NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
-
- ip.rawPacket.header.ipHeader.ip_v = 4;
- ip.rawPacket.header.ipHeader.ip_hl = 5;
- ip.rawPacket.header.ipHeader.ip_p = data->proto;
- ip.dataLen = ntohl(data->octets);
- ip.rawPacket.header.ipHeader.ip_src.s_addr = data->srcAddr;
- ip.rawPacket.header.ipHeader.ip_dst.s_addr = data->dstAddr;
- ip.rawPacket.header.sPort = data->srcPort;
- ip.rawPacket.header.dPort = data->dstPort;
-
- traffCnt->Process(ip);
- }
-}
+++ /dev/null
-/*
- * 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: 16.05.2008
-*/
-
-/*
-* Author : Maxim Mamontov <faust@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.5 $
-$Date: 2009/12/13 12:56:07 $
-$Author: faust $
-*/
-#ifndef __CAP_NF_H__
-#define __CAP_NF_H__
-
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#define VERSION "cap_nf v. 0.4"
-#define START_POS 40
-#define STOP_POS 40
-
-class USERS;
-class USER;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class STORE;
-class SETTINGS;
-
-struct NF_HEADER {
- uint16_t version; // Protocol version
- uint16_t count; // Flows count
- uint32_t uptime; // System uptime
- uint32_t timestamp; // UNIX timestamp
- uint32_t nsecs; // Residual nanoseconds
- uint32_t flowSeq; // Sequence counter
- uint8_t eType; // Engine type
- uint8_t eID; // Engine ID
- uint16_t sInterval; // Sampling mode and interval
-};
-
-struct NF_DATA {
- uint32_t srcAddr; // Flow source address
- uint32_t dstAddr; // Flow destination address
- uint32_t nextHop; // IP addres on next hop router
- uint16_t inSNMP; // SNMP index of input iface
- uint16_t outSNMP; // SNMP index of output iface
- uint32_t packets; // Packets in flow
- uint32_t octets; // Total number of bytes in flow
- uint32_t timeStart; // Uptime on first packet in flow
- uint32_t timeFinish;// Uptime on last packet in flow
- uint16_t srcPort; // Flow source port
- uint16_t dstPort; // Flow destination port
- uint8_t pad1; // 1-byte padding
- uint8_t TCPFlags; // Cumulative OR of TCP flags
- uint8_t proto; // IP protocol type (tcp, udp, etc.)
- uint8_t tos; // IP Type of Service (ToS)
- uint16_t srcAS; // Source BGP autonomous system number
- uint16_t dstAS; // Destination BGP autonomus system number
- uint8_t srcMask; // Source address mask in "slash" notation
- uint8_t dstMask; // Destination address mask in "slash" notation
- uint16_t pad2; // 2-byte padding
-};
-
-#define BUF_SIZE (sizeof(NF_HEADER) + 30 * sizeof(NF_DATA))
-
-class NF_CAP : public PLUGIN {
-public:
- NF_CAP();
- ~NF_CAP();
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return runningTCP || runningUDP; }
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return VERSION; }
- uint16_t GetStartPosition() const { return START_POS; }
- uint16_t GetStopPosition() const { return STOP_POS; }
-
-private:
- NF_CAP(const NF_CAP & rvalue);
- NF_CAP & operator=(const NF_CAP & rvalue);
-
- TRAFFCOUNTER * traffCnt;
- MODULE_SETTINGS settings;
- pthread_t tidTCP;
- pthread_t tidUDP;
- bool runningTCP;
- bool runningUDP;
- bool stoppedTCP;
- bool stoppedUDP;
- uint16_t portT;
- uint16_t portU;
- int sockTCP;
- int sockUDP;
- mutable std::string errorStr;
- PLUGIN_LOGGER logger;
-
- static void * RunUDP(void *);
- static void * RunTCP(void *);
- void ParseBuffer(uint8_t * buf, ssize_t size);
-
- bool OpenTCP();
- bool OpenUDP();
- void CloseTCP() { close(sockTCP); }
- void CloseUDP() { close(sockUDP); }
-};
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.4 2008/12/04 17:05:21 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_divert.so
-
-SRCS = ./divert_cap.cpp
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.13 $
-$Date: 2010/09/10 06:43:03 $
-*/
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstring>
-#include <cerrno>
-#include <cstdlib>
-#include <csignal>
-
-#include <algorithm>
-#include <vector>
-
-#include "stg/common.h"
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-#include "divert_cap.h"
-
-#define BUFF_LEN (16384) /* max mtu -> lo=16436 TODO why?*/
-
-//-----------------------------------------------------------------------------
-struct DIVERT_DATA {
-int sock;
-short int port;
-char iface[10];
-};
-//-----------------------------------------------------------------------------
-pollfd pollddiv;
-DIVERT_DATA cddiv; //capture data
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<DIVERT_CAP> dcc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return dcc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string DIVERT_CAP::GetVersion() const
-{
-return "cap_divert v.1.0";
-}
-//-----------------------------------------------------------------------------
-DIVERT_CAP::DIVERT_CAP()
- : port(0),
- disableForwarding(false),
- nonstop(false),
- isRunning(false),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_divert"))
-{
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-if (DivertCapOpen() < 0)
- {
- errorStr = "Cannot open socket!";
- printfd(__FILE__, "Cannot open socket\n");
- return -1;
- }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-DivertCapClose();
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
-
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- printfd(__FILE__, "Cannot kill thread\n");
- return -1;
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * DIVERT_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
-dc->isRunning = true;
-
-char buffer[pcktSize + 14];
-while (dc->nonstop)
- {
- RAW_PACKET rp;
- dc->DivertCapRead(buffer, sizeof(buffer), NULL);
-
- if (buffer[12] != 0x8)
- continue;
-
- memcpy(rp.rawPacket.pckt, &buffer[14], pcktSize);
-
- dc->traffCnt->Process(rp);
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapOpen()
-{
-memset(&pollddiv, 0, sizeof(pollddiv));
-memset(&cddiv, 0, sizeof(DIVERT_DATA));
-
-strcpy(cddiv.iface, "foo");
-cddiv.port = port;
-
-DivertCapOpen(0);
-pollddiv.events = POLLIN;
-pollddiv.fd = cddiv.sock;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapOpen(int)
-{
-int ret;
-cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
-if (cddiv.sock < 0)
- {
- errorStr = "Create divert socket error.";
- logger("Cannot create a socket: %s", strerror(errno));
- printfd(__FILE__, "Cannot create divert socket\n");
- return -1;
- }
-
-struct sockaddr_in divAddr;
-
-memset(&divAddr, 0, sizeof(divAddr));
-
-divAddr.sin_family = AF_INET;
-divAddr.sin_port = htons(cddiv.port);
-divAddr.sin_addr.s_addr = INADDR_ANY;
-
-ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
-
-if (ret < 0)
- {
- errorStr = "Bind divert socket error.";
- logger("Cannot bind the scoket: %s", strerror(errno));
- printfd(__FILE__, "Cannot bind divert socket\n");
- return -1;
- }
-
-return cddiv.sock;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
-{
-poll(&pollddiv, 1, -1);
-
-if (pollddiv.revents & POLLIN)
- {
- DivertCapRead(b, blen, iface, 0);
- pollddiv.revents = 0;
- return 0;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
-{
-static char buf[BUFF_LEN];
-static struct sockaddr_in divertaddr;
-static int bytes;
-static socklen_t divertaddrSize = sizeof(divertaddr);
-
-if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
- 0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
- {
- memcpy(b + 14, buf, blen - 14);
- b[12] = 0x8;
-
- if (iface)
- *iface = cddiv.iface;
-
- if (!disableForwarding)
- {
- if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
- logger("sendto error: %s", strerror(errno));
- }
- }
-else
- {
- if (bytes < 0)
- logger("recvfrom error: %s", strerror(errno));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapClose()
-{
-close(cddiv.sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::ParseSettings()
-{
-int p;
-PARAM_VALUE pv;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-
-pv.param = "Port";
-pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
-if (pvi == settings.moduleParams.end() || pvi->value.empty())
- {
- p = 15701;
- }
-else if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
- {
- errorStr = "Cannot parse parameter \'Port\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'Port'\n");
- return -1;
- }
-
-port = p;
-
-bool d = false;
-pv.param = "DisableForwarding";
-pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
-if (pvi == settings.moduleParams.end() || pvi->value.empty())
- {
- disableForwarding = false;
- }
-else if (ParseYesNo(pvi->value[0], &d))
- {
- errorStr = "Cannot parse parameter \'DisableForwarding\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'DisableForwarding'\n");
- return -1;
- }
-
-disableForwarding = d;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.6 $
-$Date: 2009/06/23 11:32:27 $
-*/
-
-#ifndef DIVERT_CAP_H
-#define DIVERT_CAP_H
-
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-class USERS;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class SETTINGS;
-
-//-----------------------------------------------------------------------------
-class DIVERT_CAP : public PLUGIN {
-public:
- DIVERT_CAP();
- virtual ~DIVERT_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
-private:
- DIVERT_CAP(const DIVERT_CAP & rvalue);
- DIVERT_CAP & operator=(const DIVERT_CAP & rvalue);
-
- static void * Run(void *);
-
- int DivertCapOpen();
- int DivertCapOpen(int n);
- int DivertCapRead(char * buffer, int blen, char ** iface);
- int DivertCapRead(char * buffer, int blen, char ** iface, int n);
- int DivertCapClose();
-
- MODULE_SETTINGS settings;
-
- int port;
- bool disableForwarding;
-
- mutable std::string errorStr;
-
- pthread_t thread;
-
- bool nonstop;
- bool isRunning;
-
- TRAFFCOUNTER * traffCnt;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.7 2008/12/04 17:06:56 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_bpf.so
-
-SRCS = ./ether_cap.cpp
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.19 $
-$Date: 2009/03/24 11:20:15 $
-$Author: faust $
-*/
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-
-#include <net/bpf.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <cstdlib>
-#include <csignal>
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-
-#include "ether_cap.h"
-
-//#define CAP_DEBUG 1
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<BPF_CAP> bcc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return bcc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-int BPF_CAP_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-iface.erase(iface.begin(), iface.end());
-
-if (s.moduleParams.empty())
- {
- errorStr = "Parameter \'iface\' not found.";
- printfd(__FILE__, "Parameter 'iface' not found\n");
- return -1;
- }
-
-for (unsigned i = 0; i < s.moduleParams.size(); i++)
- {
- if (s.moduleParams[i].param != "iface")
- {
- errorStr = "Parameter \'" + s.moduleParams[i].param + "\' unrecognized.";
- printfd(__FILE__, "Invalid parameter: '%s'\n", s.moduleParams[i].param.c_str());
- return -1;
- }
- for (unsigned j = 0; j < s.moduleParams[i].value.size(); j++)
- {
- iface.push_back(s.moduleParams[i].value[j]);
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-std::string BPF_CAP_SETTINGS::GetIface(unsigned int num)
-{
-if (num >= iface.size())
- {
- return "";
- }
-return iface[num];
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string BPF_CAP::GetVersion() const
-{
-return "cap_bpf v.1.0";
-}
-//-----------------------------------------------------------------------------
-BPF_CAP::BPF_CAP()
- : nonstop(false),
- isRunning(false),
- capSock(-1),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_bpf"))
-{
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::ParseSettings()
-{
-int ret = capSettings.ParseSettings(settings);
-if (ret)
- {
- errorStr = capSettings.GetStrError();
- return ret;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-if (BPFCapOpen() < 0)
- {
- //errorStr = "Cannot open bpf device!";
- return -1;
- }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-BPFCapClose();
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
-
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- //TODO pthread_cancel()
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- printfd(__FILE__, "Cannot kill thread\n");
- return -1;
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * BPF_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-BPF_CAP * dc = static_cast<BPF_CAP *>(d);
-dc->isRunning = true;
-
-uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96
-
-RAW_PACKET * rpp = (RAW_PACKET *)&hdr[14];
-memset(hdr, 0, sizeof(hdr));
-
-rpp->dataLen = -1;
-char * iface;
-
-while (dc->nonstop)
- {
- if (dc->BPFCapRead((char*)&hdr, 68 + 14, &iface))
- continue;
-
- if (!(hdr[12] == 0x8 && hdr[13] == 0x0))
- continue;
-
- dc->traffCnt->Process(*rpp);
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapOpen()
-{
-int i = 0;
-BPF_DATA bd;
-pollfd pd;
-
-while ((bd.iface = capSettings.GetIface(i)) != "")
- {
- bpfData.push_back(bd);
- if (BPFCapOpen(&bpfData[i]) < 0)
- {
- return -1;
- }
-
- pd.events = POLLIN;
- pd.fd = bpfData[i].fd;
- polld.push_back(pd);
- i++;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapOpen(BPF_DATA * bd)
-{
-char devbpf[20];
-int i = 0;
-int l = BUFF_LEN;
-int im = 1;
-struct ifreq ifr;
-
-do
- {
- sprintf(devbpf, "/dev/bpf%d", i);
- i++;
- bd->fd = open(devbpf, O_RDONLY);
- } while(bd->fd < 0 && errno == EBUSY);
-
-if (bd->fd < 0)
- {
- errorStr = "Can't capture packets. Open bpf device for " + bd->iface + " error.";
- logger("Cannot open device for interface '%s': %s", bd->iface.c_str(), strerror(errno));
- printfd(__FILE__, "Cannot open BPF device\n");
- return -1;
- }
-
-strncpy(ifr.ifr_name, bd->iface.c_str(), sizeof(ifr.ifr_name));
-
-if (ioctl(bd->fd, BIOCSBLEN, (caddr_t)&l) < 0)
- {
- errorStr = bd->iface + " BIOCSBLEN " + std::string(strerror(errno));
- logger("ioctl (BIOCSBLEN) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
- printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
- return -1;
- }
-
-if (ioctl(bd->fd, BIOCSETIF, (caddr_t)&ifr) < 0)
- {
- errorStr = bd->iface + " BIOCSETIF " + std::string(strerror(errno));
- logger("ioctl (BIOCSETIF) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
- printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
- return -1;
- }
-
-if (ioctl(bd->fd, BIOCIMMEDIATE, &im) < 0)
- {
- errorStr = bd->iface + " BIOCIMMEDIATE " + std::string(strerror(errno));
- logger("ioctl (BIOCIMMEDIATE) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
- printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
- return -1;
- }
-
-return bd->fd;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapClose()
-{
-for (unsigned int i = 0; i < bpfData.size(); i++)
- close(bpfData[i].fd);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapRead(char * buffer, int blen, char ** capIface)
-{
-poll(&polld[0], polld.size(), -1);
-
-for (unsigned int i = 0; i < polld.size(); i++)
- {
- if (polld[i].revents & POLLIN)
- {
- if (BPFCapRead(buffer, blen, capIface, &bpfData[i]))
- {
- polld[i].revents = 0;
- continue;
- }
- polld[i].revents = 0;
- return 0;
- }
- }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapRead(char * buffer, int blen, char **, BPF_DATA * bd)
-{
-if (bd->canRead)
- {
- bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
- if (bd->r < 0)
- {
- logger("read error: %s", strerror(errno));
- struct timespec ts = {0, 20000000};
- nanosleep(&ts, NULL);
- return -1;
- }
-
- bd->p = bd->buffer;
- bd->bh = (struct bpf_hdr*)bd->p;
- bd->canRead = 0;
- }
-
-if(bd->r > bd->sum)
- {
- memcpy(buffer, (char*)(bd->p) + bd->bh->bh_hdrlen, blen);
-
- bd->sum += BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
- bd->p = bd->p + BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
- bd->bh = (struct bpf_hdr*)bd->p;
- }
-
-if(bd->r <= bd->sum)
- {
- bd->canRead = 1;
- bd->sum = 0;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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
- */
-
- /*
- $Revision: 1.11 $
- $Date: 2009/06/23 11:32:27 $
- $Author: faust $
- */
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-#ifndef ETHER_CAP_H
-#define ETHER_CAP_H
-
-#include <pthread.h>
-
-#include <string>
-#include <vector>
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#define BUFF_LEN (128)
-
-class TRAFFCOUNTER;
-
-//-----------------------------------------------------------------------------
-struct BPF_DATA {
- BPF_DATA()
- {
- fd = 0;
- p = NULL;
- r = 0;
- sum = 0;
- memset(buffer, 0, BUFF_LEN);
- bh = NULL;
- canRead = 1;
- iface = "";
- };
-
- BPF_DATA(const BPF_DATA & bd)
- {
- fd = bd.fd;
- p = bd.p;
- r = bd.r;
- sum = bd.sum;
- memcpy(buffer, bd.buffer, BUFF_LEN);
- bh = bd.bh;
- canRead = bd.canRead;
- iface = bd.iface;
- };
-
-int fd;
-uint8_t * p;
-int r;
-int sum;
-uint8_t buffer[BUFF_LEN];
-struct bpf_hdr * bh;
-int canRead;
-std::string iface;
-};
-//-----------------------------------------------------------------------------
-class BPF_CAP_SETTINGS {
-public:
- virtual ~BPF_CAP_SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- std::string GetIface(unsigned int num);
-
-private:
- std::vector<std::string> iface;
- mutable std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-class BPF_CAP : public PLUGIN {
-public:
- BPF_CAP();
- virtual ~BPF_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
-private:
- BPF_CAP(const BPF_CAP & rvalue);
- BPF_CAP & operator=(const BPF_CAP & rvalue);
-
- static void * Run(void *);
- int BPFCapOpen();
- int BPFCapOpen(BPF_DATA * bd);
- int BPFCapClose();
- int BPFCapRead(char * buffer, int blen, char ** iface);
- int BPFCapRead(char * buffer, int blen, char ** iface, BPF_DATA * bd);
-
- BPF_CAP_SETTINGS capSettings;
-
- mutable std::string errorStr;
-
- std::vector<BPF_DATA> bpfData;
- std::vector<pollfd> polld;
-
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- int capSock;
- MODULE_SETTINGS settings;
-
- TRAFFCOUNTER * traffCnt;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.9 2008/12/04 17:07:37 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_ether.so
-
-SRCS = ./ether_cap.cpp
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-/*
-$Revision: 1.23 $
-$Date: 2009/12/13 13:45:13 $
-*/
-
-
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <csignal>
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-
-#include "ether_cap.h"
-
-//#define CAP_DEBUG 1
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<ETHER_CAP> ecc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return ecc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string ETHER_CAP::GetVersion() const
-{
-return "cap_ether v.1.2";
-}
-//-----------------------------------------------------------------------------
-ETHER_CAP::ETHER_CAP()
- : nonstop(false),
- isRunning(false),
- capSock(-1),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_ether"))
-{
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-if (EthCapOpen() < 0)
- {
- errorStr = "Cannot open socket!";
- printfd(__FILE__, "Cannot open socket\n");
- return -1;
- }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- if (pthread_kill(thread, SIGUSR1))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- return -1;
- }
- for (int i = 0; i < 25 && isRunning; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (isRunning)
- {
- errorStr = "ETHER_CAP not stopped.";
- logger("Cannot stop thread.");
- printfd(__FILE__, "Cannot stop thread\n");
- return -1;
- }
- else
- {
- pthread_join(thread, NULL);
- }
- }
-
-EthCapClose();
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * ETHER_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-ETHER_CAP * dc = static_cast<ETHER_CAP *>(d);
-dc->isRunning = true;
-
-struct ETH_IP
-{
-uint16_t ethHdr[8];
-RAW_PACKET rp;
-char padding[4];
-char padding1[8];
-};
-
-char ethip[sizeof(ETH_IP)];
-
-memset(ðip, 0, sizeof(ETH_IP));
-
-ETH_IP * ethIP = static_cast<ETH_IP *>(static_cast<void *>(ðip));
-ethIP->rp.dataLen = -1;
-
-char * iface = NULL;
-
-while (dc->nonstop)
- {
- if (dc->EthCapRead(ðip, 68 + 14, &iface))
- {
- continue;
- }
-
- if (ethIP->ethHdr[7] != 0x8)
- continue;
-
- dc->traffCnt->Process(ethIP->rp);
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapOpen()
-{
-capSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-if (capSock < 0)
- logger("Cannot create socket: %s", strerror(errno));
-return capSock;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapClose()
-{
-close(capSock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapRead(void * buffer, int blen, char **)
-{
-struct sockaddr_ll addr;
-int addrLen;
-
-if (!WaitPackets(capSock))
- {
- return ENODATA;
- }
-
-addrLen = sizeof(addr);
-
-if (recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen) < 0)
- {
- logger("recvfrom error: %s", strerror(errno));
- return ENODATA;
- }
-
-return 0;
-}
+++ /dev/null
-/*
- * 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
- */
-
- /*
- $Revision: 1.12 $
- $Date: 2009/12/13 13:45:13 $
- */
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-#ifndef ETHER_CAP_H
-#define ETHER_CAP_H
-
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-class USERS;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class SETTINGS;
-
-class TRAFFCOUNTER;
-
-//-----------------------------------------------------------------------------
-class ETHER_CAP : public PLUGIN {
-public:
- ETHER_CAP();
- virtual ~ETHER_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- int ParseSettings() { return 0; }
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
-private:
- ETHER_CAP(const ETHER_CAP & rvalue);
- ETHER_CAP & operator=(const ETHER_CAP & rvalue);
-
- static void * Run(void *);
- int EthCapOpen();
- int EthCapClose();
- int EthCapRead(void * buffer, int blen, char ** iface);
-
- mutable std::string errorStr;
-
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- int capSock;
-
- TRAFFCOUNTER * traffCnt;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.6 2008/12/04 17:08:56 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_ipq.so
-
-SRCS = ./ipq_cap.cpp \
- ./libipq.c
-
-LIBS += $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
-*/
-
-#include <netinet/in.h>
-#include <linux/netfilter.h>
-
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-#include "stg/common.h"
-
-#include "ipq_cap.h"
-
-extern "C"
-{
-#include "libipq.h"
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<IPQ_CAP> icc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return icc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string IPQ_CAP::GetVersion() const
-{
-return "cap_ipq v.1.2";
-}
-//-----------------------------------------------------------------------------
-IPQ_CAP::IPQ_CAP()
- : ipq_h(NULL),
- nonstop(false),
- isRunning(false),
- capSock(-1),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_ipq"))
-{
-memset(buf, 0, BUFSIZE);
-}
-//-----------------------------------------------------------------------------
-int IPQ_CAP::Start()
-{
-if (isRunning)
- return 0;
-if (IPQCapOpen() < 0)
- {
- errorStr = "Cannot open socket!";
- printfd(__FILE__, "Cannot open socket\n");
- return -1;
- }
-nonstop = true;
-if (pthread_create(&thread, NULL, Run, this) == 0)
- {
- return 0;
- }
-errorStr = "Cannot create thread.";
-printfd(__FILE__, "Cannot create thread\n");
-return -1;
-}
-//-----------------------------------------------------------------------------
-int IPQ_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-nonstop = false;
-//5 seconds to thread stops itself
-for (int i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- return -1;
- }
- for (int i = 0; i < 25 && isRunning; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (isRunning)
- {
- printfd(__FILE__, "Thread not stopped\n");
- }
- else
- {
- pthread_join(thread, NULL);
- }
- }
-IPQCapClose();
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * IPQ_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-RAW_PACKET raw_packet;
-
-IPQ_CAP * dc = static_cast<IPQ_CAP *>(d);
-dc->isRunning = true;
-memset(&raw_packet, 0, sizeof(raw_packet));
-raw_packet.dataLen = -1;
-while (dc->nonstop)
- {
- int status = dc->IPQCapRead(&raw_packet, 68);
- if (status == -1 ||
- status == -2 ||
- status == -3 ||
- status == -4)
- continue;
- dc->traffCnt->Process(raw_packet);
- }
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int IPQ_CAP::IPQCapOpen()
-{
-ipq_h = ipq_create_handle(0, PF_INET);
-if (ipq_h == NULL)
- {
- ipq_destroy_handle(ipq_h);
- logger("Cannot create IPQ handle. Error: '%s', '%s'", ipq_errstr(), strerror(errno));
- errorStr = "Cannot create ipq handle!";
- return -1;
- }
-int status = ipq_set_mode(ipq_h, IPQ_COPY_PACKET, PAYLOAD_LEN);
-if (status < 0)
- {
- ipq_destroy_handle(ipq_h);
- logger("Cannot set IPQ_COPY_PACKET mode.");
- errorStr = "Cannot set IPQ_COPY_PACKET mode!";
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int IPQ_CAP::IPQCapClose()
-{
-ipq_destroy_handle(ipq_h);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int IPQ_CAP::IPQCapRead(void * buffer, int blen)
-{
-memset(buf, 0, BUFSIZE);
-int status = ipq_read(ipq_h, buf, BUFSIZE, 1);
-if (status == 0)
- return -4;
-if (errno == EINTR)
- return -3;
-if (status < 0)
- return -1;
-if (ipq_message_type(buf) != IPQM_PACKET)
- return -2;
-static ipq_packet_msg_t * m = ipq_get_packet(buf);
-memcpy(buffer, m->payload, blen);
-ipq_set_verdict(ipq_h, m->packet_id, NF_ACCEPT, 0, NULL);
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
-*/
-
-#ifndef IPQ_CAP_H
-#define IPQ_CAP_H
-
-#include <string>
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/os_int.h"
-#include "stg/logger.h"
-
-#define BUFSIZE (256)
-#define PAYLOAD_LEN (96)
-
-class USERS;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class SETTINGS;
-
-//-----------------------------------------------------------------------------
-class IPQ_CAP :public PLUGIN {
-public:
- IPQ_CAP();
- virtual ~IPQ_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- int ParseSettings() { return 0; }
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
-private:
- IPQ_CAP(const IPQ_CAP & rvalue);
- IPQ_CAP & operator=(const IPQ_CAP & rvalue);
-
- static void * Run(void *);
- int IPQCapOpen();
- int IPQCapClose();
- int IPQCapRead(void * buffer, int blen);
-
- struct ipq_handle * ipq_h;
- mutable std::string errorStr;
-
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- int capSock;
-
- TRAFFCOUNTER * traffCnt;
- unsigned char buf[BUFSIZE];
-
- PLUGIN_LOGGER logger;
-};
-
-#endif
+++ /dev/null
-/*
- * libipq.c
- *
- * IPQ userspace library.
- *
- * Please note that this library is still developmental, and there may
- * be some API changes.
- *
- * Author: James Morris <jmorris@intercode.com.au>
- *
- * 07-11-2001 Modified by Fernando Anton to add support for IPv6.
- *
- * Copyright (c) 2000-2001 Netfilter Core Team
- *
- * 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.
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include "libipq.h"
-
-/****************************************************************************
- *
- * Private interface
- *
- ****************************************************************************/
-
-enum
- {
- IPQ_ERR_NONE = 0,
- IPQ_ERR_IMPL,
- IPQ_ERR_HANDLE,
- IPQ_ERR_SOCKET,
- IPQ_ERR_BIND,
- IPQ_ERR_BUFFER,
- IPQ_ERR_RECV,
- IPQ_ERR_NLEOF,
- IPQ_ERR_ADDRLEN,
- IPQ_ERR_STRUNC,
- IPQ_ERR_RTRUNC,
- IPQ_ERR_NLRECV,
- IPQ_ERR_SEND,
- IPQ_ERR_SUPP,
- IPQ_ERR_RECVBUF,
- IPQ_ERR_TIMEOUT,
- IPQ_ERR_PROTOCOL
- };
-#define IPQ_MAXERR IPQ_ERR_PROTOCOL
-
-struct ipq_errmap_t
- {
- int errcode;
- char *message;
- } ipq_errmap[] = {
- { IPQ_ERR_NONE, "Unknown error"},
- { IPQ_ERR_IMPL, "Implementation error"},
- { IPQ_ERR_HANDLE, "Unable to create netlink handle"},
- { IPQ_ERR_SOCKET, "Unable to create netlink socket"},
- { IPQ_ERR_BIND, "Unable to bind netlink socket"},
- { IPQ_ERR_BUFFER, "Unable to allocate buffer"},
- { IPQ_ERR_RECV, "Failed to receive netlink message"},
- { IPQ_ERR_NLEOF, "Received EOF on netlink socket"},
- { IPQ_ERR_ADDRLEN, "Invalid peer address length"},
- { IPQ_ERR_STRUNC, "Sent message truncated"},
- { IPQ_ERR_RTRUNC, "Received message truncated"},
- { IPQ_ERR_NLRECV, "Received error from netlink"},
- { IPQ_ERR_SEND, "Failed to send netlink message"},
- { IPQ_ERR_SUPP, "Operation not supported"},
- { IPQ_ERR_RECVBUF, "Receive buffer size invalid"},
- { IPQ_ERR_TIMEOUT, "Timeout"},
- { IPQ_ERR_PROTOCOL, "Invalid protocol specified"}
-};
-
-static int ipq_errno = IPQ_ERR_NONE;
-
-static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
- const void *msg, size_t len);
-
-static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
- unsigned char *buf, size_t len,
- int timeout);
-
-static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
- const struct msghdr *msg,
- unsigned int flags);
-
-//static char *ipq_strerror(int errcode);
-//-----------------------------------------------------------------------------
-static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
- const void *msg, size_t len)
-{
- int status = sendto(h->fd, msg, len, 0,
- (struct sockaddr *)&h->peer, sizeof(h->peer));
- if (status < 0)
- ipq_errno = IPQ_ERR_SEND;
- return status;
-}
-//-----------------------------------------------------------------------------
-static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
- const struct msghdr *msg,
- unsigned int flags)
-{
- int status = sendmsg(h->fd, msg, flags);
- if (status < 0)
- ipq_errno = IPQ_ERR_SEND;
- return status;
-}
-//-----------------------------------------------------------------------------
-static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
- unsigned char *buf, size_t len,
- int timeout)
-{
- socklen_t addrlen;
- int status;
- struct nlmsghdr *nlh;
-
- if (len < sizeof(struct nlmsgerr))
- {
- ipq_errno = IPQ_ERR_RECVBUF;
- return -1;
- }
- addrlen = sizeof(h->peer);
-
- if (timeout != 0)
- {
- int ret;
- struct timeval tv;
- fd_set read_fds;
-
- if (timeout < 0)
- {
- /* non-block non-timeout */
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- }
- else
- {
- tv.tv_sec = timeout / 1000000;
- tv.tv_usec = timeout % 1000000;
- }
-
- FD_ZERO(&read_fds);
- FD_SET(h->fd, &read_fds);
- ret = select(h->fd+1, &read_fds, NULL, NULL, &tv);
- if (ret < 0)
- {
- if (errno == EINTR)
- {
- return 0;
- }
- else
- {
- ipq_errno = IPQ_ERR_RECV;
- return -1;
- }
- }
- if (!FD_ISSET(h->fd, &read_fds))
- {
- ipq_errno = IPQ_ERR_TIMEOUT;
- return 0;
- }
- }
- status = recvfrom(h->fd, buf, len, 0,
- (struct sockaddr *)&h->peer, &addrlen);
- if (status < 0)
- {
- ipq_errno = IPQ_ERR_RECV;
- return status;
- }
- if (addrlen != sizeof(h->peer))
- {
- ipq_errno = IPQ_ERR_RECV;
- return -1;
- }
- if (h->peer.nl_pid != 0)
- {
- ipq_errno = IPQ_ERR_RECV;
- return -1;
- }
- if (status == 0)
- {
- ipq_errno = IPQ_ERR_NLEOF;
- return -1;
- }
- nlh = (struct nlmsghdr *)buf;
- if (nlh->nlmsg_flags & MSG_TRUNC || (int)nlh->nlmsg_len > status)
- {
- ipq_errno = IPQ_ERR_RTRUNC;
- return -1;
- }
- return status;
-}
-//-----------------------------------------------------------------------------
-static char *ipq_strerror(int errcode)
-{
- if (errcode < 0 || errcode > IPQ_MAXERR)
- errcode = IPQ_ERR_IMPL;
- return ipq_errmap[errcode].message;
-}
-
-/****************************************************************************
- *
- * Public interface
- *
- ****************************************************************************/
-
-/*
- * Create and initialise an ipq handle.
- */
-struct ipq_handle *ipq_create_handle(u_int32_t __attribute__((unused)) flags, u_int32_t protocol)
- {
- int status;
- struct ipq_handle *h;
-
- h = (struct ipq_handle *)malloc(sizeof(struct ipq_handle));
- if (h == NULL)
- {
- ipq_errno = IPQ_ERR_HANDLE;
- return NULL;
- }
-
- memset(h, 0, sizeof(struct ipq_handle));
-
- if (protocol == PF_INET)
- h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
- else if (protocol == PF_INET6)
- h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);
- else
- {
- ipq_errno = IPQ_ERR_PROTOCOL;
- free(h);
- return NULL;
- }
-
- if (h->fd == -1)
- {
- ipq_errno = IPQ_ERR_SOCKET;
- close(h->fd);
- free(h);
- return NULL;
- }
- memset(&h->local, 0, sizeof(struct sockaddr_nl));
- h->local.nl_family = AF_NETLINK;
- h->local.nl_pid = getpid();
- h->local.nl_groups = 0;
- status = bind(h->fd, (struct sockaddr *)&h->local, sizeof(h->local));
- if (status == -1)
- {
- ipq_errno = IPQ_ERR_BIND;
- close(h->fd);
- free(h);
- return NULL;
- }
- memset(&h->peer, 0, sizeof(struct sockaddr_nl));
- h->peer.nl_family = AF_NETLINK;
- h->peer.nl_pid = 0;
- h->peer.nl_groups = 0;
- return h;
- }
-//-----------------------------------------------------------------------------
-/*
- * No error condition is checked here at this stage, but it may happen
- * if/when reliable messaging is implemented.
- */
-int ipq_destroy_handle(struct ipq_handle *h)
-{
- if (h)
- {
- close(h->fd);
- free(h);
- }
- return 0;
-}
-//-----------------------------------------------------------------------------
-int ipq_set_mode(const struct ipq_handle *h,
- u_int8_t mode, size_t range)
-{
- #define FAKE_ARRAY_SIZE 16
- struct
- {
- struct nlmsghdr nlh;
- ipq_peer_msg_t pm;
- char s[FAKE_ARRAY_SIZE];
- } req;
-
- memset(&req, 0, sizeof(req));
- req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req)-FAKE_ARRAY_SIZE);
- req.nlh.nlmsg_flags = NLM_F_REQUEST;
- req.nlh.nlmsg_type = IPQM_MODE;
- req.nlh.nlmsg_pid = h->local.nl_pid;
- req.pm.msg.mode.value = mode;
- req.pm.msg.mode.range = range;
- return ipq_netlink_sendto(h, (void *)&req, req.nlh.nlmsg_len);
- //return ipq_netlink_sendto(h, (void *)&req, sizeof(req));
-}
-//-----------------------------------------------------------------------------
-/*
- * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
- *
- */
-ssize_t ipq_read(const struct ipq_handle *h,
- unsigned char *buf, size_t len, int timeout)
-{
- return ipq_netlink_recvfrom(h, buf, len, timeout);
-}
-//-----------------------------------------------------------------------------
-int ipq_message_type(const unsigned char *buf)
-{
- return((struct nlmsghdr*)buf)->nlmsg_type;
-}
-//-----------------------------------------------------------------------------
-ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf)
-{
- return(ipq_packet_msg_t *)(NLMSG_DATA((struct nlmsghdr *)(buf)));
-}
-//-----------------------------------------------------------------------------
-int ipq_set_verdict(const struct ipq_handle *h,
- ipq_id_t id,
- unsigned int verdict,
- size_t data_len,
- unsigned char *buf)
-{
- unsigned char nvecs;
- size_t tlen;
- struct nlmsghdr nlh;
- ipq_peer_msg_t pm;
- struct iovec iov[3];
- struct msghdr msg;
-
- memset(&nlh, 0, sizeof(nlh));
- nlh.nlmsg_flags = NLM_F_REQUEST;
- nlh.nlmsg_type = IPQM_VERDICT;
- nlh.nlmsg_pid = h->local.nl_pid;
- memset(&pm, 0, sizeof(pm));
- pm.msg.verdict.value = verdict;
- pm.msg.verdict.id = id;
- pm.msg.verdict.data_len = data_len;
- iov[0].iov_base = &nlh;
- iov[0].iov_len = sizeof(nlh);
- iov[1].iov_base = ±
- iov[1].iov_len = sizeof(pm);
- tlen = sizeof(nlh) + sizeof(pm);
- nvecs = 2;
- if (data_len && buf)
- {
- iov[2].iov_base = buf;
- iov[2].iov_len = data_len;
- tlen += data_len;
- nvecs++;
- }
- msg.msg_name = (void *)&h->peer;
- msg.msg_namelen = sizeof(h->peer);
- msg.msg_iov = iov;
- msg.msg_iovlen = nvecs;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
- nlh.nlmsg_len = tlen;
- return ipq_netlink_sendmsg(h, &msg, 0);
-}
-//-----------------------------------------------------------------------------
-char *ipq_errstr(void)
-{
- return ipq_strerror(ipq_errno);
-}
-//-----------------------------------------------------------------------------
-/*void ipq_perror(const char *s)
-{
- if (s)
- fputs(s, stderr);
- else
- fputs("ERROR", stderr);
- if (ipq_errno)
- fprintf(stderr, ": %s", ipq_errstr());
- if (errno)
- fprintf(stderr, ": %s", strerror(errno));
- fputc('\n', stderr);
-}*/
-//-----------------------------------------------------------------------------
-
-
+++ /dev/null
-/*
- * libipq.h
- *
- * IPQ library for userspace.
- *
- * Author: James Morris <jmorris@intercode.com.au>
- *
- * Copyright (c) 2000-2001 Netfilter Core Team
- *
- * 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.
- *
- */
-
-#ifndef _LIBIPQ_H
-#define _LIBIPQ_H
-
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <asm/types.h>
-#include <linux/netlink.h>
-
-#include <linux/netfilter_ipv4/ip_queue.h>
-#ifdef KERNEL_64_USERSPACE_32
-typedef u_int64_t ipq_id_t;
-#else
-typedef unsigned long ipq_id_t;
-#endif
-
-#ifdef DEBUG_LIBIPQ
-#include <stdio.h>
-#define LDEBUG(x...) fprintf(stderr, ## x)
-#else
-#define LDEBUG(x...)
-#endif /* DEBUG_LIBIPQ */
-
-/* FIXME: glibc sucks */
-#ifndef MSG_TRUNC
-#define MSG_TRUNC 0x20
-#endif
-
-struct ipq_handle
-{
- int fd;
- u_int8_t blocking;
- struct sockaddr_nl local;
- struct sockaddr_nl peer;
-};
-
-struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol);
-
-int ipq_destroy_handle(struct ipq_handle *h);
-
-ssize_t ipq_read(const struct ipq_handle *h,
- unsigned char *buf, size_t len, int timeout);
-
-int ipq_set_mode(const struct ipq_handle *h, u_int8_t mode, size_t len);
-
-ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf);
-
-int ipq_message_type(const unsigned char *buf);
-
-int ipq_set_verdict(const struct ipq_handle *h,
- ipq_id_t id,
- unsigned int verdict,
- size_t data_len,
- unsigned char *buf);
-
-char *ipq_errstr(void);
-//void ipq_perror(const char *s);
-
-#endif /* _LIBIPQ_H */
-
+++ /dev/null
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_nfqueue.so
-
-SRCS = ./nfqueue.cpp
-
-LIBS += $(NFQ_LDFLAGS) $(NETLINK_LDFLAGS) $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
-*/
-
-#include "nfqueue.h"
-
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-
-extern "C" {
-
-#include <linux/netfilter.h> /* Defines verdicts (NF_ACCEPT, etc) */
-#include <libnetfilter_queue/libnetfilter_queue.h>
-
-}
-
-#include <cerrno>
-#include <csignal>
-
-#include <arpa/inet.h> // ntohl
-
-#include <unistd.h> // read
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-
-PLUGIN_CREATOR<NFQ_CAP> ncc;
-
-int Callback(struct nfq_q_handle * queueHandle, struct nfgenmsg * /*msg*/,
- struct nfq_data * nfqData, void *data)
-{
-int id = 0;
-
-struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
-if (packetHeader == NULL)
- return 0;
-
-id = ntohl(packetHeader->packet_id);
-
-unsigned char * payload = NULL;
-
-if (nfq_get_payload(nfqData, &payload) < 0 || payload == NULL)
- return id;
-
-RAW_PACKET packet;
-
-memcpy(&packet.rawPacket, payload, sizeof(packet.rawPacket));
-
-NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
-
-cap->Process(packet);
-
-return nfq_set_verdict(queueHandle, id, NF_ACCEPT, 0, NULL);
-}
-
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return ncc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string NFQ_CAP::GetVersion() const
-{
-return "cap_nfqueue v.1.0";
-}
-//-----------------------------------------------------------------------------
-NFQ_CAP::NFQ_CAP()
- : nonstop(false),
- isRunning(false),
- queueNumber(0),
- nfqHandle(NULL),
- queueHandle(NULL),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_nfqueue"))
-{
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::ParseSettings()
-{
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
- if (settings.moduleParams[i].param == "queueNumber" && !settings.moduleParams[i].value.empty())
- if (str2x(settings.moduleParams[i].value[0], queueNumber) < 0)
- {
- errorStr = "Queue number should be a number. Got: '" + settings.moduleParams[i].param + "'";
- logger(errorStr);
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-nfqHandle = nfq_open();
-if (nfqHandle == NULL)
- {
- errorStr = "Failed to initialize netfilter queue.";
- logger(errorStr);
- return -1;
- }
-
-if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
- {
- errorStr = "Failed to unbind netfilter queue from IP handling.";
- logger(errorStr);
- return -1;
- }
-
-if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
- {
- errorStr = "Failed to bind netfilter queue to IP handling.";
- logger(errorStr);
- return -1;
- }
-
-queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
-if (queueHandle == NULL)
- {
- errorStr = "Failed to create queue " + x2str(queueNumber) + ".";
- logger(errorStr);
- return -1;
- }
-
-if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
- {
- errorStr = "Failed to set queue " + x2str(queueNumber) + " mode.";
- logger(errorStr);
- return -1;
- }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- if (pthread_kill(thread, SIGUSR1))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- return -1;
- }
- for (int i = 0; i < 25 && isRunning; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (isRunning)
- {
- errorStr = "NFQ_CAP not stopped.";
- logger("Cannot stop thread.");
- printfd(__FILE__, "Cannot stop thread\n");
- return -1;
- }
- }
-
-pthread_join(thread, NULL);
-
-nfq_destroy_queue(queueHandle);
-nfq_close(nfqHandle);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * NFQ_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
-dc->isRunning = true;
-
-int fd = nfq_fd(dc->nfqHandle);
-char buf[4096];
-
-while (dc->nonstop)
- {
- if (!WaitPackets(fd))
- continue;
-
- int rv = read(fd, buf, sizeof(buf));
- if (rv < 0)
- {
- dc->errorStr = std::string("Read error: ") + strerror(errno);
- dc->logger(dc->errorStr);
- break;
- }
- nfq_handle_packet(dc->nfqHandle, buf, rv);
- }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void NFQ_CAP::Process(const RAW_PACKET & packet)
-{
-traffCnt->Process(packet);
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
-*/
-
-#ifndef NFQ_CAP_H
-#define NFQ_CAP_H
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-
-#include <pthread.h>
-
-class USERS;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class SETTINGS;
-struct RAW_PACKET;
-
-class TRAFFCOUNTER;
-
-struct nfq_handle;
-struct nfq_q_handle;
-
-class NFQ_CAP : public PLUGIN {
-public:
- NFQ_CAP();
- virtual ~NFQ_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
- void Process(const RAW_PACKET & packet);
-
-private:
- NFQ_CAP(const NFQ_CAP & rvalue);
- NFQ_CAP & operator=(const NFQ_CAP & rvalue);
-
- static void * Run(void *);
-
- mutable std::string errorStr;
-
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- MODULE_SETTINGS settings;
-
- size_t queueNumber;
-
- struct nfq_handle * nfqHandle;
- struct nfq_q_handle * queueHandle;
-
- TRAFFCOUNTER * traffCnt;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-include ../../../../../Makefile.conf
-
-PROG = mod_cap_pcap.so
-
-SRCS = ./pcap_cap.cpp
-
-LIBS += -lpcap $(LIB_THREAD)
-
-STGLIBS = common \
- logger
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
-*/
-
-#include "pcap_cap.h"
-
-#include "stg/traffcounter.h"
-#include "stg/plugin_creator.h"
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-
-#include <signal.h>
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<PCAP_CAP> pcc;
-
-const size_t SNAP_LEN = 1518;
-const size_t ETHER_ADDR_LEN = 6;
-
-struct ETH
-{
-u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
-u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
-u_short ether_type; /* IP? ARP? RARP? etc */
-};
-
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return pcc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string PCAP_CAP::GetVersion() const
-{
-return "pcap_cap v.1.0";
-}
-//-----------------------------------------------------------------------------
-PCAP_CAP::PCAP_CAP()
- : nonstop(false),
- isRunning(false),
- traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "pcap_cap"))
-{
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::ParseSettings()
-{
-devices.erase(devices.begin(), devices.end());
-
-if (settings.moduleParams.empty())
- {
- devices.push_back(DEV());
- logger("Defaulting to pseudo-device 'any'.");
- return 0;
- }
-
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
- if (settings.moduleParams[i].param == "interfaces")
- for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
- devices.push_back(DEV(settings.moduleParams[i].value[j]));
-
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
- if (settings.moduleParams[i].param == "filters")
- for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
- if (j < devices.size())
- devices[j].filterExpression = settings.moduleParams[i].value[j];
-
-if (devices.empty())
- {
- devices.push_back(DEV());
- logger("Defaulting to pseudo-device 'all'.");
- return 0;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::Start()
-{
-if (isRunning)
- return 0;
-
-DEV_MAP::iterator it(devices.begin());
-while (it != devices.end())
- {
- bpf_u_int32 mask;
- bpf_u_int32 net;
- char errbuf[PCAP_ERRBUF_SIZE];
-
- /* get network number and mask associated with capture device */
- if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1)
- {
- errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf;
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- /* open capture device */
- it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf);
- if (it->handle == NULL)
- {
- errorStr = "Couldn't open device " + it->device + ": " + errbuf;
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- if (pcap_setnonblock(it->handle, true, errbuf) == -1)
- {
- errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf;
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- /* make sure we're capturing on an Ethernet device [2] */
- if (pcap_datalink(it->handle) != DLT_EN10MB)
- {
- errorStr = it->device + " is not an Ethernet";
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- /* compile the filter expression */
- if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1)
- {
- errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- /* apply the compiled filter */
- if (pcap_setfilter(it->handle, &it->filter) == -1)
- {
- errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- it->fd = pcap_get_selectable_fd(it->handle);
- if (it->fd == -1)
- {
- errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle);
- logger(errorStr);
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
- ++it;
- }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::Stop()
-{
-if (!isRunning)
- return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
- {
- if (pthread_kill(thread, SIGUSR1))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- return -1;
- }
- for (int i = 0; i < 25 && isRunning; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- if (isRunning)
- {
- errorStr = "PCAP_CAP not stopped.";
- logger("Cannot stop thread.");
- printfd(__FILE__, "Cannot stop thread\n");
- return -1;
- }
- }
-
-pthread_join(thread, NULL);
-
-for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it)
- {
- pcap_freecode(&it->filter);
- pcap_close(it->handle);
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * PCAP_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-PCAP_CAP * dc = static_cast<PCAP_CAP *>(d);
-dc->isRunning = true;
-
-fd_set fds;
-FD_ZERO(&fds);
-int maxFd = 0;
-for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it)
- {
- FD_SET(it->fd, &fds);
- maxFd = std::max(maxFd, it->fd);
- }
-
-while (dc->nonstop)
- {
- fd_set rfds = fds;
- struct timeval tv = {0, 500000};
-
- if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0)
- dc->TryRead(rfds);
- }
-
-dc->isRunning = false;
-return NULL;
-}
-
-void PCAP_CAP::TryRead(const fd_set & set)
-{
-for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it)
- if (FD_ISSET(it->fd, &set))
- TryReadDev(*it);
-}
-
-void PCAP_CAP::TryReadDev(const DEV & dev)
-{
-struct pcap_pkthdr * header;
-const u_char * packet;
-if (pcap_next_ex(dev.handle, &header, &packet) == -1)
- {
- printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle));
- return;
- }
-
-const ETH * eth = reinterpret_cast<const ETH *>(packet);
-if (eth->ether_type != 0x8)
- return;
-
-RAW_PACKET ip;
-memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket));
-traffCnt->Process(ip);
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
-*/
-
-#ifndef PCAP_CAP_H
-#define PCAP_CAP_H
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-
-#include <pcap.h>
-#include <pthread.h>
-#include <sys/select.h>
-
-class USERS;
-class TARIFFS;
-class ADMINS;
-class TRAFFCOUNTER;
-class SETTINGS;
-
-class TRAFFCOUNTER;
-
-struct DEV
-{
- DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {}
- DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {}
- DEV(const std::string & d, const std::string & f)
- : device(d), filterExpression(f), handle(NULL), fd(-1) {}
-
- std::string device;
- std::string filterExpression;
- pcap_t * handle;
- struct bpf_program filter;
- int fd;
-};
-
-typedef std::vector<DEV> DEV_MAP;
-
-class PCAP_CAP : public PLUGIN {
-public:
- PCAP_CAP();
- virtual ~PCAP_CAP() {}
-
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const;
- uint16_t GetStartPosition() const { return 40; }
- uint16_t GetStopPosition() const { return 40; }
-
-private:
- PCAP_CAP(const PCAP_CAP & rvalue);
- PCAP_CAP & operator=(const PCAP_CAP & rvalue);
-
- void TryRead(const fd_set & set);
- void TryReadDev(const DEV & dev);
-
- static void * Run(void *);
-
- mutable std::string errorStr;
-
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- MODULE_SETTINGS settings;
- DEV_MAP devices;
-
- TRAFFCOUNTER * traffCnt;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.10 2009/08/03 10:25:40 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_conf_rpc.so
-
-SRCS = ./rpcconfig.cpp \
- ./user_helper.cpp \
- ./tariff_helper.cpp \
- ./info_methods.cpp \
- ./users_methods.cpp \
- ./tariffs_methods.cpp \
- ./admins_methods.cpp \
- ./messages_methods.cpp
-
-LIBS += $(XMLRPC_LDFLAGS) \
- $(LIB_THREAD) \
- $(LIBICONV)
-
-STGLIBS = common \
- logger \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "stg/common.h"
-#include "admins_methods.h"
-#include "rpcconfig.h"
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(login, &admin))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["login"] = xmlrpc_c::value_string(admin->GetLogin());
-structVal["password"] = xmlrpc_c::value_string(admin->GetPassword());
-
-const PRIV * priv = admin->GetPriv();
-
-structVal["user_stat"] = xmlrpc_c::value_boolean(priv->userStat);
-structVal["user_conf"] = xmlrpc_c::value_boolean(priv->userConf);
-structVal["user_cash"] = xmlrpc_c::value_boolean(priv->userCash);
-structVal["user_passwd"] = xmlrpc_c::value_boolean(priv->userPasswd);
-structVal["user_add_del"] = xmlrpc_c::value_boolean(priv->userAddDel);
-structVal["admin_chg"] = xmlrpc_c::value_boolean(priv->adminChg);
-structVal["tariff_chg"] = xmlrpc_c::value_boolean(priv->tariffChg);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_ADD::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Not logged or cookie timeout'\n");
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Invalid admin (logged)'\n");
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (admins->Add(login, admin))
- {
- printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Failed to add admin'\n");
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_DEL::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (admins->Del(login, admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_CHG::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * loggedAdmin;
-
-if (admins->Find(adminInfo.admin, &loggedAdmin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(login, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN_CONF conf;
-
-conf.priv = *admin->GetPriv();
-conf.password = admin->GetPassword();
-conf.login = login;
-
-std::map<std::string, xmlrpc_c::value> structVal(
- static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
- );
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = structVal.find("password")) != structVal.end())
- {
- conf.password = xmlrpc_c::value_string(it->second);
- }
-
-if ((it = structVal.find("user_stat")) != structVal.end())
- {
- conf.priv.userStat = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("user_conf")) != structVal.end())
- {
- conf.priv.userConf = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("user_cash")) != structVal.end())
- {
- conf.priv.userCash = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("user_passwd")) != structVal.end())
- {
- conf.priv.userPasswd = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("user_add_del")) != structVal.end())
- {
- conf.priv.userAddDel = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("admin_chg")) != structVal.end())
- {
- conf.priv.adminChg = xmlrpc_c::value_boolean(it->second);
- }
-
-if ((it = structVal.find("tariff_chg")) != structVal.end())
- {
- conf.priv.tariffChg = xmlrpc_c::value_boolean(it->second);
- }
-
-if (admins->Change(conf, loggedAdmin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMINS_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> mainStructVal;
-std::vector<xmlrpc_c::value> retval;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- mainStructVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(mainStructVal);
- return;
- }
-
-ADMIN_CONF ac;
-int h = admins->OpenSearch();
-
-while (admins->SearchNext(h, &ac) == 0)
- {
- std::map<std::string, xmlrpc_c::value> structVal;
- structVal["result"] = xmlrpc_c::value_boolean(true);
- structVal["login"] = xmlrpc_c::value_string(ac.login);
- structVal["password"] = xmlrpc_c::value_string(ac.password);
- structVal["user_stat"] = xmlrpc_c::value_boolean(ac.priv.userStat);
- structVal["user_conf"] = xmlrpc_c::value_boolean(ac.priv.userConf);
- structVal["user_cash"] = xmlrpc_c::value_boolean(ac.priv.userCash);
- structVal["user_passwd"] = xmlrpc_c::value_boolean(ac.priv.userPasswd);
- structVal["user_add_del"] = xmlrpc_c::value_boolean(ac.priv.userAddDel);
- structVal["admin_chg"] = xmlrpc_c::value_boolean(ac.priv.adminChg);
- structVal["tariff_chg"] = xmlrpc_c::value_boolean(ac.priv.tariffChg);
-
- retval.push_back(xmlrpc_c::value_struct(structVal));
- }
-
-*retvalPtr = xmlrpc_c::value_array(retval);
-}
+++ /dev/null
-#ifndef __ADMINS_METHODS_H__
-#define __ADMINS_METHODS_H__
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-
-class RPC_CONFIG;
-
-class METHOD_ADMIN_GET : public xmlrpc_c::method {
-public:
- METHOD_ADMIN_GET(RPC_CONFIG * c,
- ADMINS * a)
- : config(c),
- admins(a)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_ADMIN_GET(const METHOD_ADMIN_GET & rvalue);
- METHOD_ADMIN_GET & operator=(const METHOD_ADMIN_GET & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
-};
-
-class METHOD_ADMIN_ADD : public xmlrpc_c::method {
-public:
- METHOD_ADMIN_ADD(RPC_CONFIG * c,
- ADMINS * a)
- : config(c),
- admins(a)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_ADMIN_ADD(const METHOD_ADMIN_ADD & rvalue);
- METHOD_ADMIN_ADD & operator=(const METHOD_ADMIN_ADD & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
-};
-
-class METHOD_ADMIN_DEL : public xmlrpc_c::method {
-public:
- METHOD_ADMIN_DEL(RPC_CONFIG * c,
- ADMINS * a)
- : config(c),
- admins(a)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_ADMIN_DEL(const METHOD_ADMIN_DEL & rvalue);
- METHOD_ADMIN_DEL & operator=(const METHOD_ADMIN_DEL & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
-};
-
-class METHOD_ADMIN_CHG : public xmlrpc_c::method {
-public:
- METHOD_ADMIN_CHG(RPC_CONFIG * c,
- ADMINS * a)
- : config(c),
- admins(a)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_ADMIN_CHG(const METHOD_ADMIN_CHG & rvalue);
- METHOD_ADMIN_CHG & operator=(const METHOD_ADMIN_CHG & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
-};
-
-class METHOD_ADMINS_GET : public xmlrpc_c::method {
-public:
- METHOD_ADMINS_GET(RPC_CONFIG * c,
- ADMINS * a)
- : config(c),
- admins(a)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_ADMINS_GET(const METHOD_ADMINS_GET & rvalue);
- METHOD_ADMINS_GET & operator=(const METHOD_ADMINS_GET & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
-};
-
-#endif
+++ /dev/null
-#include <sys/utsname.h>
-
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "stg/version.h"
-#include "stg/common.h"
-#include "info_methods.h"
-#include "rpcconfig.h"
-
-void METHOD_INFO::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-paramList.verifyEnd(0);
-std::map<std::string, xmlrpc_c::value> structVal;
-
-std::string un;
-struct utsname utsn;
-
-uname(&utsn);
-un[0] = 0;
-
-un += utsn.sysname;
-un += " ";
-un += utsn.release;
-un += " ";
-un += utsn.machine;
-un += " ";
-un += utsn.nodename;
-
-structVal["version"] = xmlrpc_c::value_string(SERVER_VERSION);
-structVal["tariff_num"] = xmlrpc_c::value_int(static_cast<int>(tariffs->Count()));
-structVal["tariff"] = xmlrpc_c::value_int(2);
-structVal["users_num"] = xmlrpc_c::value_int(static_cast<int>(users->Count()));
-structVal["uname"] = xmlrpc_c::value_string(un);
-structVal["dir_num"] = xmlrpc_c::value_int(DIR_NUM);
-structVal["day_fee"] = xmlrpc_c::value_int(static_cast<int>(dayFee));
-
-std::vector<xmlrpc_c::value> dirnameVal;
-
-for (int i = 0; i< DIR_NUM; i++)
- {
- dirnameVal.push_back(xmlrpc_c::value_string(IconvString(dirNames[i], "KOI8-RU", "UTF-8")));
- }
-
-structVal["dir_names"] = xmlrpc_c::value_array(dirnameVal);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-void METHOD_LOGIN::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string login = paramList.getString(0);
-std::string password = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-
-std::string cookie;
-if (config->CheckAdmin(login, password, &cookie))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- structVal["cookie"] = xmlrpc_c::value_string("");
- }
-else
- {
- structVal["result"] = xmlrpc_c::value_boolean(true);
- structVal["cookie"] = xmlrpc_c::value_string(cookie);
- }
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-void METHOD_LOGOUT::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-if (config->LogoutAdmin(cookie))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- }
-else
- {
- *retvalPtr = xmlrpc_c::value_boolean(true);
- }
-}
+++ /dev/null
-#ifndef __INFO_METHODS_H__
-#define __INFO_METHODS_H__
-
-#include <string>
-#include <vector>
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-#include "stg/users.h"
-#include "stg/tariffs.h"
-
-// Forward declaration
-class RPC_CONFIG;
-class SETTINGS;
-
-class METHOD_INFO : public xmlrpc_c::method
-{
-public:
- METHOD_INFO(TARIFFS * t,
- USERS * u,
- size_t df,
- const std::vector<std::string> & dn)
- : tariffs(t),
- users(u),
- dayFee(df),
- dirNames(dn)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_INFO(const METHOD_INFO & rvalue);
- METHOD_INFO & operator=(const METHOD_INFO & rvalue);
-
- TARIFFS * tariffs;
- USERS * users;
- size_t dayFee;
- const std::vector<std::string> & dirNames;
-};
-
-class METHOD_LOGIN : public xmlrpc_c::method
-{
-public:
- explicit METHOD_LOGIN(RPC_CONFIG * c)
- : config(c)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_LOGIN(const METHOD_LOGIN & rvalue);
- METHOD_LOGIN & operator=(const METHOD_LOGIN & rvalue);
-
- RPC_CONFIG * config;
-};
-
-class METHOD_LOGOUT : public xmlrpc_c::method
-{
-public:
- explicit METHOD_LOGOUT(RPC_CONFIG * c)
- : config(c)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_LOGOUT(const METHOD_LOGOUT & rvalue);
- METHOD_LOGOUT & operator=(const METHOD_LOGOUT & rvalue);
-
- RPC_CONFIG * config;
-};
-
-#endif
+++ /dev/null
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "stg/message.h"
-#include "stg/common.h"
-#include "messages_methods.h"
-#include "rpcconfig.h"
-
-extern volatile time_t stgTime;
-
-//------------------------------------------------------------------------------
-
-void METHOD_MESSAGE_SEND::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::vector<xmlrpc_c::value> logins(paramList.getArray(1));
-std::map<std::string, xmlrpc_c::value> msgInfo(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-STG_MSG message;
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = msgInfo.find("version")) == msgInfo.end())
- {
- message.header.ver = 1; // Default value
- }
-else
- {
- message.header.ver = xmlrpc_c::value_int(it->second);
- }
-
-if ((it = msgInfo.find("type")) == msgInfo.end())
- {
- message.header.type = 1; // default value
- }
-else
- {
- message.header.type = xmlrpc_c::value_int(it->second);
- }
-
-if ((it = msgInfo.find("repeat")) == msgInfo.end())
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-message.header.repeat = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("repeat_period")) == msgInfo.end())
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-message.header.repeatPeriod = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("show_time")) == msgInfo.end())
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-message.header.showTime = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("text")) == msgInfo.end())
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-message.text = IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "CP1251");
-
-message.header.creationTime = static_cast<int>(stgTime);
-message.header.lastSendTime = 0;
-
-std::vector<xmlrpc_c::value>::iterator lit;
-for (lit = logins.begin(); lit != logins.end(); ++lit)
- {
- USER_PTR ui;
- if (users->FindByName(xmlrpc_c::value_string(*lit), &ui))
- {
- printfd(__FILE__, "METHOD_MESSAGE_SEND::execute(): 'User '%s' not found'\n", std::string(xmlrpc_c::value_string(*lit)).c_str());
- }
- else
- {
- ui->AddMessage(&message);
- }
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
+++ /dev/null
-#ifndef __MESSAGES_METHODS_H__
-#define __MESSAGES_METHODS_H__
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-#include "stg/users.h"
-
-class RPC_CONFIG;
-
-class METHOD_MESSAGE_SEND : public xmlrpc_c::method {
-public:
- METHOD_MESSAGE_SEND(RPC_CONFIG * c,
- USERS * u)
- : config(c),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_MESSAGE_SEND(const METHOD_MESSAGE_SEND & rvalue);
- METHOD_MESSAGE_SEND & operator=(const METHOD_MESSAGE_SEND & rvalue);
-
- RPC_CONFIG * config;
- USERS * users;
-};
-
-#endif
+++ /dev/null
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-#include <cstdlib>
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-#include <vector>
-#include <algorithm>
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "stg/common.h"
-#include "stg/admin.h"
-#include "stg/module_settings.h"
-#include "stg/settings.h"
-#include "stg/plugin_creator.h"
-
-#include "rpcconfig.h"
-#include "info_methods.h"
-#include "users_methods.h"
-#include "tariffs_methods.h"
-#include "admins_methods.h"
-#include "messages_methods.h"
-
-namespace
-{
-PLUGIN_CREATOR<RPC_CONFIG> rpcc;
-}
-
-extern "C" PLUGIN * GetPlugin();
-
-RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
- : port(0),
- cookieTimeout(0)
-{
-}
-
-int RPC_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-PARAM_VALUE pv;
-pv.param = "Port";
-std::vector<PARAM_VALUE>::const_iterator pvi;
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Port\' not found.";
- printfd(__FILE__, "Parameter 'Port' not found\n");
- return -1;
- }
-int p;
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
- {
- errorStr = "Cannot parse parameter \'Port\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'Port'\n");
- return -1;
- }
-port = static_cast<uint16_t>(p);
-
-pv.param = "CookieTimeout";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- cookieTimeout = 1800; // 30 * 60
- }
-else
- {
- if (str2x(pvi->value[0], cookieTimeout))
- {
- errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
- printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
- return -1;
- }
- }
-
-return 0;
-}
-
-PLUGIN * GetPlugin()
-{
-return rpcc.GetPlugin();
-}
-
-RPC_CONFIG::RPC_CONFIG()
- : users(NULL),
- admins(NULL),
- tariffs(NULL),
- store(NULL),
- fd(-1),
- rpcServer(NULL),
- running(false),
- stopped(true),
- dayFee(0),
- logger(GetPluginLogger(GetStgLogger(), "conf_rpc"))
-{
-}
-
-RPC_CONFIG::~RPC_CONFIG()
-{
-// delete server
-delete rpcServer;
-}
-
-int RPC_CONFIG::ParseSettings()
-{
-int ret = rpcConfigSettings.ParseSettings(settings);
-
-if (ret)
- errorStr = rpcConfigSettings.GetStrError();
-
-return ret;
-}
-
-void RPC_CONFIG::SetStgSettings(const SETTINGS * s)
-{
- dayFee = s->GetDayFee();
- dirNames.erase(dirNames.begin(), dirNames.end());
- for (size_t i = 0; i < DIR_NUM; ++i) {
- dirNames.push_back(s->GetDirName(i));
- }
-}
-
-int RPC_CONFIG::Start()
-{
-InitiateRegistry();
-running = true;
-
-fd = socket(AF_INET, SOCK_STREAM, 0);
-if (fd < 0)
- {
- errorStr = "Failed to create socket";
- logger("Cannot create a socket: %s", strerror(errno));
- printfd(__FILE__, "Failed to create listening socket: %s\n", strerror(errno));
- return -1;
- }
-
-int flag = 1;
-
-if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))
- {
- errorStr = "Setsockopt failed.";
- logger("setsockopt error: %s", strerror(errno));
- printfd(__FILE__, "Setsockopt failed: %s\n", strerror(errno));
- return -1;
- }
-
-struct sockaddr_in addr;
-addr.sin_family = AF_INET;
-addr.sin_port = htons(rpcConfigSettings.GetPort());
-addr.sin_addr.s_addr = inet_addr("0.0.0.0");
-
-if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
- {
- logger("Cannot bind the socket: %s", strerror(errno));
- errorStr = "Failed to bind socket";
- printfd(__FILE__, "Failed to bind listening socket: %s\n", strerror(errno));
- return -1;
- }
-
-if (listen(fd, 10))
- {
- logger("Cannot listen the socket: %s", strerror(errno));
- errorStr = "Failed to listen socket";
- printfd(__FILE__, "Failed to listen listening socket: %s\n", strerror(errno));
- return -1;
- }
-
-rpcServer = new xmlrpc_c::serverAbyss(
- xmlrpc_c::serverAbyss::constrOpt()
- .registryP(&rpcRegistry)
- .logFileName("/var/log/stargazer_rpc.log")
- .socketFd(fd)
- );
-
-if (pthread_create(&tid, NULL, Run, this))
- {
- errorStr = "Failed to create RPC thread";
- logger("Cannot create RPC thread.");
- printfd(__FILE__, "Failed to crate RPC thread\n");
- return -1;
- }
-
-return 0;
-}
-
-int RPC_CONFIG::Stop()
-{
-running = false;
-for (int i = 0; i < 5 && !stopped; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
-if (!stopped)
- {
- running = true;
- logger("Cannot stop RPC thread.");
- printfd(__FILE__, "Failed to stop RPC thread\n");
- errorStr = "Failed to stop RPC thread";
- return -1;
- }
-else
- {
- pthread_join(tid, NULL);
- }
-
-close(fd);
-
-return 0;
-}
-
-void * RPC_CONFIG::Run(void * rc)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
-
-config->stopped = false;
-while (config->running)
- {
- if (WaitPackets(config->fd))
- config->rpcServer->runOnce();
- }
-config->stopped = true;
-
-return NULL;
-}
-
-bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
- ADMIN_INFO * info)
-{
-std::map<std::string,
- ADMIN_INFO>::iterator it;
-
-it = cookies.find(cookie);
-
-if (it == cookies.end())
- {
- return true;
- }
-
-if (difftime(it->second.accessTime, time(NULL)) >
- rpcConfigSettings.GetCookieTimeout())
- {
- cookies.erase(it);
- return true;
- }
-
-// Update access time
-time(&it->second.accessTime);
-*info = it->second;
-return false;
-}
-
-bool RPC_CONFIG::CheckAdmin(const std::string & login,
- const std::string & password,
- std::string * cookie)
-{
-ADMIN * admin = NULL;
-
-if (!admins->Correct(login, password, &admin))
- {
- logger("Attempt to connect with invalid credentials. Login: %s", login.c_str());
- return true;
- }
-
-ADMIN_INFO info;
-time(&info.accessTime);
-info.admin = login;
-info.priviledges = *admin->GetPriv();
-*cookie = GetCookie();
-cookies[*cookie] = info;
-
-return false;
-}
-
-bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
-{
-std::map<std::string,
- ADMIN_INFO>::iterator it;
-
-it = cookies.find(cookie);
-
-if (it == cookies.end())
- {
- return true;
- }
-
-cookies.erase(it);
-
-return false;
-}
-
-std::string RPC_CONFIG::GetCookie() const
-{
-std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
-std::string cookie;
-
-for (int i = 0; i < 64; ++i)
- {
- cookie += charset[rand() % charset.length()];
- };
-
-return cookie;
-}
-
-void RPC_CONFIG::InitiateRegistry()
-{
-// manage registry
-xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
- tariffs,
- users,
- dayFee,
- dirNames
- ));
-rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
-
-xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
- this
- ));
-rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
-
-xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
- this
- ));
-rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
-
-xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
- this,
- users
- ));
-rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
-
-xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
- this,
- admins,
- users
- ));
-rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
-
-xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
- this,
- admins,
- users
- ));
-rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
-
-xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
- this,
- users
- ));
-rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
-
-xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
- this,
- admins,
- tariffs,
- store,
- users
- ));
-rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
-
-xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
- this,
- admins,
- store,
- users
- ));
-rpcRegistry.addMethod("stargazer.add_user_cash", methodAddCashPtr);
-
-xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
- this,
- admins,
- store,
- users
- ));
-rpcRegistry.addMethod("stargazer.set_user_cash", methodSetCashPtr);
-
-xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
- this,
- admins,
- tariffs,
- store,
- users
- ));
-rpcRegistry.addMethod("stargazer.chg_user_tariff", methodTariffChangePtr);
-
-xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
- this,
- tariffs
- ));
-rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
-
-xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
- this,
- admins,
- tariffs
- ));
-rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
-
-xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
- this,
- tariffs
- ));
-rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
-
-xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
- this,
- admins,
- tariffs
- ));
-rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
-
-xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
- this,
- admins,
- tariffs,
- users
- ));
-rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
-
-xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
- this,
- admins
- ));
-rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
-
-xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
- this,
- admins
- ));
-rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
-
-xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
- this,
- admins
- ));
-rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
-
-xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
- this,
- admins
- ));
-rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
-
-xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
- this,
- admins
- ));
-rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
-
-xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
- this,
- users
- ));
-rpcRegistry.addMethod("stargazer.send_user_message", methodSendMessagePtr);
-
-xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
- this,
- users
- ));
-rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
-
-xmlrpc_c::methodPtr const methodGetUserAuthByPtr(new METHOD_GET_USER_AUTH_BY(
- this,
- users
- ));
-rpcRegistry.addMethod("stargazer.get_user_auth_by", methodGetUserAuthByPtr);
-}
-
+++ /dev/null
-#ifndef __RPC_CONFIG_H__
-#define __RPC_CONFIG_H__
-
-#include <pthread.h>
-
-#include <ctime>
-#include <string>
-#include <map>
-#include <vector>
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-#include <xmlrpc-c/server_abyss.hpp>
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/admin_conf.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#define RPC_CONFIG_VERSION "Stargazer RPC v. 0.2"
-
-class ADMINS;
-class TARIFFS;
-class USERS;
-class STORE;
-
-class RPC_CONFIG_SETTINGS
-{
-public:
- RPC_CONFIG_SETTINGS();
- virtual ~RPC_CONFIG_SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- uint16_t GetPort() const { return port; }
- double GetCookieTimeout() const { return cookieTimeout; }
-
-private:
- std::string errorStr;
- uint16_t port;
- double cookieTimeout;
-};
-
-struct ADMIN_INFO
-{
- ADMIN_INFO()
- : admin(),
- accessTime(0),
- priviledges()
- {}
-
- std::string admin;
- time_t accessTime;
- PRIV priviledges;
-};
-
-class RPC_CONFIG : public PLUGIN
-{
-public:
- RPC_CONFIG();
- virtual ~RPC_CONFIG();
-
- void SetUsers(USERS * u) { users = u; }
- void SetTariffs(TARIFFS * t) { tariffs = t; }
- void SetAdmins(ADMINS * a) { admins = a; }
- void SetStore(STORE * s) { store = s; }
- void SetStgSettings(const SETTINGS * s);
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return running && !stopped; }
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return RPC_CONFIG_VERSION; }
- uint16_t GetStartPosition() const { return 20; }
- uint16_t GetStopPosition() const { return 20; }
-
- bool GetAdminInfo(const std::string & cookie,
- ADMIN_INFO * info);
- bool CheckAdmin(const std::string & login,
- const std::string & password,
- std::string * cookie);
- bool LogoutAdmin(const std::string & cookie);
-
-private:
- RPC_CONFIG(const RPC_CONFIG & rvalue);
- RPC_CONFIG & operator=(const RPC_CONFIG & rvalue);
-
- static void * Run(void *);
- std::string GetCookie() const;
- void InitiateRegistry();
-
- mutable std::string errorStr;
- RPC_CONFIG_SETTINGS rpcConfigSettings;
- USERS * users;
- ADMINS * admins;
- TARIFFS * tariffs;
- STORE * store;
- MODULE_SETTINGS settings;
- int fd;
- xmlrpc_c::registry rpcRegistry;
- xmlrpc_c::serverAbyss * rpcServer;
- bool running;
- bool stopped;
- pthread_t tid;
- std::map<std::string,
- ADMIN_INFO> cookies;
- size_t dayFee;
- std::vector<std::string> dirNames;
- PLUGIN_LOGGER logger;
-};
-
-#endif
+++ /dev/null
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "tariff_helper.h"
-#include "stg/common.h"
-
-void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const
-{
-std::map<std::string, xmlrpc_c::value> structVal;
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["name"] = xmlrpc_c::value_string(data.tariffConf.name);
-structVal["fee"] = xmlrpc_c::value_double(data.tariffConf.fee);
-structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free);
-structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
-structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
-structVal["period"] = xmlrpc_c::value_string(TARIFF::PeriodToString(data.tariffConf.period));
-structVal["changePolicy"] = xmlrpc_c::value_string(TARIFF::ChangePolicyToString(data.tariffConf.changePolicy));
-structVal["changePolicyTimeout"] = xmlrpc_c::value_string(formatTime(data.tariffConf.changePolicyTimeout));
-
-std::vector<xmlrpc_c::value> prices(DIR_NUM);
-
-for (unsigned i = 0; i < DIR_NUM; ++i)
- {
- std::map<std::string, xmlrpc_c::value> dirPrice;
- dirPrice["hday"] = xmlrpc_c::value_int(data.dirPrice[i].hDay);
- dirPrice["mday"] = xmlrpc_c::value_int(data.dirPrice[i].mDay);
- dirPrice["hnight"] = xmlrpc_c::value_int(data.dirPrice[i].hNight);
- dirPrice["mnight"] = xmlrpc_c::value_int(data.dirPrice[i].mNight);
- dirPrice["pricedaya"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayA * 1024 * 1024);
- dirPrice["pricedayb"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayB * 1024 * 1024);
- dirPrice["pricenighta"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightA * 1024 * 1024);
- dirPrice["pricenightb"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightB * 1024 * 1024);
- dirPrice["threshold"] = xmlrpc_c::value_int(data.dirPrice[i].threshold);
- dirPrice["singleprice"] = xmlrpc_c::value_boolean(data.dirPrice[i].singlePrice);
- dirPrice["nodiscount"] = xmlrpc_c::value_boolean(data.dirPrice[i].noDiscount);
- prices[i] = xmlrpc_c::value_struct(dirPrice);
- }
-
-structVal["dirprices"] = xmlrpc_c::value_array(prices);
-
-*info = xmlrpc_c::value_struct(structVal);
-}
-
-bool TARIFF_HELPER::SetTariffInfo(const xmlrpc_c::value & info)
-{
-std::map<std::string, xmlrpc_c::value> structVal(
- static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
- );
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = structVal.find("fee")) != structVal.end())
- {
- data.tariffConf.fee = xmlrpc_c::value_double(it->second);
- }
-
-if ((it = structVal.find("freemb")) != structVal.end())
- {
- data.tariffConf.free = xmlrpc_c::value_double(it->second);
- }
-
-if ((it = structVal.find("passivecost")) != structVal.end())
- {
- data.tariffConf.passiveCost = xmlrpc_c::value_double(it->second);
- }
-
-if ((it = structVal.find("traffType")) != structVal.end())
- {
- data.tariffConf.traffType = static_cast<TARIFF::TRAFF_TYPE>(xmlrpc_c::value_int(it->second).cvalue());
- }
-
-if ((it = structVal.find("period")) != structVal.end())
- {
- data.tariffConf.period = TARIFF::StringToPeriod(xmlrpc_c::value_string(it->second));
- }
-
-if ((it = structVal.find("changePolicy")) != structVal.end())
- {
- data.tariffConf.changePolicy = TARIFF::StringToChangePolicy(xmlrpc_c::value_string(it->second));
- }
-
-if ((it = structVal.find("changePolicyTimeout")) != structVal.end())
- {
- data.tariffConf.changePolicyTimeout = readTime(xmlrpc_c::value_string(it->second));
- }
-
-if ((it = structVal.find("dirprices")) != structVal.end())
- {
- std::vector<xmlrpc_c::value> prices(
- xmlrpc_c::value_array(it->second).vectorValueValue()
- );
-
- for (unsigned i = 0; i < DIR_NUM; ++i)
- {
- std::map<std::string, xmlrpc_c::value> dirPrice(
- static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(prices[i]))
- );
- data.dirPrice[i].mDay = xmlrpc_c::value_int(dirPrice["mday"]);
- data.dirPrice[i].hDay = xmlrpc_c::value_int(dirPrice["hday"]);
- data.dirPrice[i].mNight = xmlrpc_c::value_int(dirPrice["mnight"]);
- data.dirPrice[i].hNight = xmlrpc_c::value_int(dirPrice["hnight"]);
- data.dirPrice[i].priceDayA = xmlrpc_c::value_double(dirPrice["pricedaya"]) / 1024 / 1024;
- data.dirPrice[i].priceDayB = xmlrpc_c::value_double(dirPrice["pricedayb"]) / 1024 / 1024;
- data.dirPrice[i].priceNightA = xmlrpc_c::value_double(dirPrice["pricenighta"]) / 1024 / 1024;
- data.dirPrice[i].priceNightB = xmlrpc_c::value_double(dirPrice["pricenightb"]) / 1024 / 1024;
- data.dirPrice[i].threshold = xmlrpc_c::value_int(dirPrice["threshold"]);
- data.dirPrice[i].singlePrice = xmlrpc_c::value_boolean(dirPrice["singleprice"]);
- data.dirPrice[i].noDiscount = xmlrpc_c::value_boolean(dirPrice["nodiscount"]);
- }
- }
-
-return false;
-}
+++ /dev/null
-#ifndef __TARIFF_HELPER_H__
-#define __TARIFF_HELPER_H__
-
-#include <xmlrpc-c/base.hpp>
-#include "stg/tariff_conf.h"
-
-class TARIFF_HELPER
-{
-public:
- explicit TARIFF_HELPER(TARIFF_DATA & td)
- : data(td)
- {}
-
- void GetTariffInfo(xmlrpc_c::value * info) const;
- bool SetTariffInfo(const xmlrpc_c::value & info);
-private:
- TARIFF_DATA & data;
-};
-
-#endif
-
-
+++ /dev/null
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "tariffs_methods.h"
-#include "rpcconfig.h"
-#include "tariff_helper.h"
-#include "stg/tariffs.h"
-#include "stg/users.h"
-#include "stg/admins.h"
-#include "stg/admin.h"
-
-void METHOD_TARIFF_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string name = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-const TARIFF * tariff = tariffs->FindByName(name);
-
-if (!tariff)
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-TARIFF_DATA td(tariff->GetTariffData());
-
-TARIFF_HELPER helper(td);
-
-helper.GetTariffInfo(retvalPtr);
-}
-
-void METHOD_TARIFF_CHG::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string name = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-const TARIFF * tariff = tariffs->FindByName(name);
-
-if (!tariff)
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-TARIFF_DATA td(tariff->GetTariffData());
-
-TARIFF_HELPER helper(td);
-
-helper.SetTariffInfo(info);
-
-if (tariffs->Chg(td, admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-void METHOD_TARIFFS_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-std::vector<xmlrpc_c::value> tariffsInfo;
-
-
-std::list<TARIFF_DATA> dataList;
-tariffs->GetTariffsData(&dataList);
-std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
-for (; it != dataList.end(); ++it)
- {
- xmlrpc_c::value info;
- TARIFF_DATA td(*it); // 'cause TARIFF_HELPER work in both ways and take not const referense
- TARIFF_HELPER helper(td);
- helper.GetTariffInfo(&info);
- tariffsInfo.push_back(info);
- }
-
-*retvalPtr = xmlrpc_c::value_array(tariffsInfo);
-}
-
-void METHOD_TARIFF_ADD::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string tariff = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (tariffs->Add(tariff, admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-void METHOD_TARIFF_DEL::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string tariff = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (users->TariffInUse(tariff))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (tariffs->Del(tariff, admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
+++ /dev/null
-#ifndef __TARIFFS_METHODS_H__
-#define __TARIFFS_METHODS_H__
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-class RPC_CONFIG;
-class TARIFFS;
-class USERS;
-class ADMINS;
-
-class METHOD_TARIFF_GET : public xmlrpc_c::method {
-public:
- METHOD_TARIFF_GET(RPC_CONFIG * c,
- TARIFFS * t)
- : config(c),
- tariffs(t)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_TARIFF_GET(const METHOD_TARIFF_GET & rvalue);
- METHOD_TARIFF_GET & operator=(const METHOD_TARIFF_GET & rvalue);
-
- RPC_CONFIG * config;
- TARIFFS * tariffs;
-};
-
-class METHOD_TARIFF_CHG : public xmlrpc_c::method {
-public:
- METHOD_TARIFF_CHG(RPC_CONFIG * c,
- ADMINS * a,
- TARIFFS * t)
- : config(c),
- admins(a),
- tariffs(t)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_TARIFF_CHG(const METHOD_TARIFF_CHG & rvalue);
- METHOD_TARIFF_CHG & operator=(const METHOD_TARIFF_CHG & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- TARIFFS * tariffs;
-};
-
-class METHOD_TARIFFS_GET : public xmlrpc_c::method {
-public:
- METHOD_TARIFFS_GET(RPC_CONFIG * c,
- TARIFFS * t)
- : config(c),
- tariffs(t)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr);
-
-private:
- METHOD_TARIFFS_GET(const METHOD_TARIFFS_GET & rvalue);
- METHOD_TARIFFS_GET & operator=(const METHOD_TARIFFS_GET & rvalue);
-
- RPC_CONFIG * config;
- TARIFFS * tariffs;
-};
-
-class METHOD_TARIFF_ADD : public xmlrpc_c::method {
-public:
- METHOD_TARIFF_ADD(RPC_CONFIG * c,
- ADMINS * a,
- TARIFFS * t)
- : config(c),
- admins(a),
- tariffs(t)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_TARIFF_ADD(const METHOD_TARIFF_ADD & rvalue);
- METHOD_TARIFF_ADD & operator=(const METHOD_TARIFF_ADD & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- TARIFFS * tariffs;
-};
-
-class METHOD_TARIFF_DEL : public xmlrpc_c::method {
-public:
- METHOD_TARIFF_DEL(RPC_CONFIG * c,
- ADMINS * a,
- TARIFFS * t,
- USERS * u)
- : config(c),
- admins(a),
- tariffs(t),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_TARIFF_DEL(const METHOD_TARIFF_DEL & rvalue);
- METHOD_TARIFF_DEL & operator=(const METHOD_TARIFF_DEL & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- TARIFFS * tariffs;
- USERS * users;
-};
-
-#endif
+++ /dev/null
-#include <cmath>
-
-#include "stg/tariffs.h"
-#include "stg/admin.h"
-#include "stg/store.h"
-#include "stg/user_ips.h"
-#include "stg/common.h"
-#include "stg/user_property.h"
-#include "user_helper.h"
-
-//------------------------------------------------------------------------------
-
-void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
- bool hidePassword)
-{
-std::map<std::string, xmlrpc_c::value> structVal;
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["login"] = xmlrpc_c::value_string(ptr->GetLogin());
-
-if (!hidePassword)
- {
- structVal["password"] = xmlrpc_c::value_string(ptr->GetProperty().password.Get());
- }
-else
- {
- structVal["password"] = xmlrpc_c::value_string("++++++++");
- }
-
-structVal["cash"] = xmlrpc_c::value_double(ptr->GetProperty().cash.Get());
-structVal["freemb"] = xmlrpc_c::value_double(ptr->GetProperty().freeMb.Get());
-structVal["credit"] = xmlrpc_c::value_double(ptr->GetProperty().credit.Get());
-
-if (ptr->GetProperty().nextTariff.Get() != "")
- {
- structVal["tariff"] = xmlrpc_c::value_string(
- ptr->GetProperty().tariffName.Get() +
- "/" +
- ptr->GetProperty().nextTariff.Get()
- );
- }
-else
- {
- structVal["tariff"] = xmlrpc_c::value_string(ptr->GetProperty().tariffName.Get());
- }
-
-structVal["note"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().note, "KOI8-RU", "UTF-8"));
-
-structVal["phone"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().phone, "KOI8-RU", "UTF-8"));
-
-structVal["address"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().address, "KOI8-RU", "UTF-8"));
-
-structVal["email"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().email, "KOI8-RU", "UTF-8"));
-
-std::vector<xmlrpc_c::value> userdata;
-
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata0.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata1.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata2.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata3.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata4.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata5.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata6.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata7.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata8.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata9.Get(), "KOI8-RU", "UTF-8")));
-
-structVal["userdata"] = xmlrpc_c::value_array(userdata);
-
-structVal["name"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().realName, "KOI8-RU", "UTF-8"));
-
-structVal["group"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().group, "KOI8-RU", "UTF-8"));
-
-structVal["status"] = xmlrpc_c::value_boolean(ptr->GetConnected());
-structVal["aonline"] = xmlrpc_c::value_boolean(ptr->GetProperty().alwaysOnline.Get());
-structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(ptr->GetCurrIP()));
-structVal["pingtime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetPingTime()));
-structVal["ips"] = xmlrpc_c::value_string(ptr->GetProperty().ips.Get().GetIpStr());
-
-std::map<std::string, xmlrpc_c::value> traffInfo;
-std::vector<xmlrpc_c::value> mu(DIR_NUM);
-std::vector<xmlrpc_c::value> md(DIR_NUM);
-std::vector<xmlrpc_c::value> su(DIR_NUM);
-std::vector<xmlrpc_c::value> sd(DIR_NUM);
-
-DIR_TRAFF upload;
-DIR_TRAFF download;
-DIR_TRAFF supload;
-DIR_TRAFF sdownload;
-download = ptr->GetProperty().down.Get();
-upload = ptr->GetProperty().up.Get();
-sdownload = ptr->GetSessionUpload();
-supload = ptr->GetSessionDownload();
-
-for (int j = 0; j < DIR_NUM; j++)
- {
- std::string value;
- x2str(upload[j], value);
- mu[j] = xmlrpc_c::value_string(value);
- x2str(download[j], value);
- md[j] = xmlrpc_c::value_string(value);
- x2str(supload[j], value);
- su[j] = xmlrpc_c::value_string(value);
- x2str(sdownload[j], value);
- sd[j] = xmlrpc_c::value_string(value);
- }
-
-traffInfo["mu"] = xmlrpc_c::value_array(mu);
-traffInfo["md"] = xmlrpc_c::value_array(md);
-traffInfo["su"] = xmlrpc_c::value_array(su);
-traffInfo["sd"] = xmlrpc_c::value_array(sd);
-
-structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
-
-structVal["down"] = xmlrpc_c::value_boolean(ptr->GetProperty().disabled.Get());
-structVal["disableddetailstat"] = xmlrpc_c::value_boolean(ptr->GetProperty().disabledDetailStat.Get());
-structVal["passive"] = xmlrpc_c::value_boolean(ptr->GetProperty().passive.Get());
-structVal["lastcash"] = xmlrpc_c::value_double(ptr->GetProperty().lastCashAdd.Get());
-structVal["lasttimecash"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().lastCashAddTime.Get()));
-structVal["lastactivitytime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().lastActivityTime.Get()));
-structVal["creditexpire"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().creditExpire.Get()));
-
-*info = xmlrpc_c::value_struct(structVal);
-}
-
-//------------------------------------------------------------------------------
-
-bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
- const ADMIN * admin,
- const std::string & login,
- const STORE & store,
- TARIFFS * tariffs)
-{
-std::map<std::string, xmlrpc_c::value> structVal(
- static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
- );
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-bool check = false;
-bool alwaysOnline = ptr->GetProperty().alwaysOnline;
-if ((it = structVal.find("aonline")) != structVal.end())
- {
- check = true;
- alwaysOnline = xmlrpc_c::value_boolean(it->second);
- }
-bool onlyOneIP = ptr->GetProperty().ips.ConstData().OnlyOneIP();
-if ((it = structVal.find("ips")) != structVal.end())
- {
- check = true;
- onlyOneIP = StrToIPS(xmlrpc_c::value_string(it->second)).OnlyOneIP();
- }
-
-if (check && alwaysOnline && !onlyOneIP)
- {
- printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
- return true;
- }
-
-if ((it = structVal.find("ips")) != structVal.end())
- {
- USER_IPS ips;
- ips = StrToIPS(xmlrpc_c::value_string(it->second));
-
- for (size_t i = 0; i < ips.Count(); ++i)
- {
- CONST_USER_PTR user;
- uint32_t ip = ips[i].ip;
- if (users.IsIPInUse(ip, login, &user))
- {
- printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), login.c_str(), user->GetLogin().c_str());
- return true;
- }
- }
-
- if (!ptr->GetProperty().ips.Set(ips,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("aonline")) != structVal.end())
- {
- bool value(xmlrpc_c::value_boolean(it->second));
- if (ptr->GetProperty().alwaysOnline.Get() != value)
- if (!ptr->GetProperty().alwaysOnline.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("password")) != structVal.end())
- {
- std::string value(xmlrpc_c::value_string(it->second));
- if (ptr->GetProperty().password.Get() != value)
- if (!ptr->GetProperty().password.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("address")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().address.Get() != value)
- if (!ptr->GetProperty().address.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("phone")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().phone.Get() != value)
- if (!ptr->GetProperty().phone.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("email")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().email.Get() != value)
- if (!ptr->GetProperty().email.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("cash")) != structVal.end())
- {
- double value(xmlrpc_c::value_double(it->second));
- if (std::fabs(ptr->GetProperty().cash.Get() - value) > 1.0e-3)
- if (!ptr->GetProperty().cash.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("creditexpire")) != structVal.end())
- {
- time_t value(xmlrpc_c::value_int(it->second));
- if (ptr->GetProperty().creditExpire.Get() != value)
- if (!ptr->GetProperty().creditExpire.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("credit")) != structVal.end())
- {
- double value(xmlrpc_c::value_double(it->second));
- if (std::fabs(ptr->GetProperty().credit.Get() - value) > 1.0e-3)
- if (!ptr->GetProperty().credit.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("freemb")) != structVal.end())
- {
- double value(xmlrpc_c::value_double(it->second));
- if (std::fabs(ptr->GetProperty().freeMb.Get() - value) > 1.0e-3)
- if (!ptr->GetProperty().freeMb.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("down")) != structVal.end())
- {
- bool value(xmlrpc_c::value_boolean(it->second));
- if (ptr->GetProperty().disabled.Get() != value)
- if (!ptr->GetProperty().disabled.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("passive")) != structVal.end())
- {
- bool value(xmlrpc_c::value_boolean(it->second));
- if (ptr->GetProperty().passive.Get() != value)
- if (!ptr->GetProperty().passive.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("disableddetailstat")) != structVal.end())
- {
- bool value(xmlrpc_c::value_boolean(it->second));
- if (ptr->GetProperty().disabledDetailStat.Get() != value)
- if (!ptr->GetProperty().disabledDetailStat.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("name")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().realName.Get() != value)
- if (!ptr->GetProperty().realName.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("group")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().group.Get() != value)
- if (!ptr->GetProperty().group.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("note")) != structVal.end())
- {
- std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
- if (ptr->GetProperty().note.Get() != value)
- if (!ptr->GetProperty().note.Set(value,
- admin,
- login,
- &store))
- return true;
- }
-
-if ((it = structVal.find("userdata")) != structVal.end())
- {
- std::vector<USER_PROPERTY_LOGGED<std::string> *> userdata;
- userdata.push_back(ptr->GetProperty().userdata0.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata1.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata2.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata3.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata4.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata5.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata6.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata7.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata8.GetPointer());
- userdata.push_back(ptr->GetProperty().userdata9.GetPointer());
-
- std::vector<xmlrpc_c::value> udata(
- xmlrpc_c::value_array(it->second).vectorValueValue()
- );
-
- for (unsigned i = 0; i < userdata.size(); ++i)
- {
- std::string value(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-RU"));
- if (userdata[i]->Get() != value)
- if (!userdata[i]->Set(value,
- admin,
- login,
- &store))
- return true;
- }
- }
-
-if ((it = structVal.find("traff")) != structVal.end())
- {
- std::map<std::string, xmlrpc_c::value> traff(
- static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
- );
-
- DIR_TRAFF dtData;
- dtData = ptr->GetProperty().up.Get();
- if ((it = traff.find("mu")) != traff.end())
- {
- std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
-
- for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
- {
- int64_t value;
- if (str2x(xmlrpc_c::value_string(data[i]), value))
- printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
- else
- dtData[i] = value;
- }
- if (!ptr->GetProperty().up.Set(dtData,
- admin,
- login,
- &store))
- return true;
- }
- dtData = ptr->GetProperty().down.Get();
- if ((it = traff.find("md")) != traff.end())
- {
- std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
-
- for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
- {
- int64_t value;
- if (str2x(xmlrpc_c::value_string(data[i]), value))
- printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
- else
- dtData[i] = value;
- }
- if (!ptr->GetProperty().down.Set(dtData,
- admin,
- login,
- &store))
- return true;
- }
- }
-
-if ((it = structVal.find("tariff")) != structVal.end())
- {
- std::string tariff(xmlrpc_c::value_string(it->second));
- size_t pos = tariff.find('/');
- std::string nextTariff;
- if (pos != std::string::npos)
- {
- nextTariff = tariff.substr(pos + 1);
- tariff = tariff.substr(0, pos);
- }
-
- const TARIFF * newTariff = tariffs->FindByName(tariff);
- if (newTariff)
- {
- const TARIFF * currentTariff = ptr->GetTariff();
- std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
- if (message.empty())
- {
- if (ptr->GetProperty().tariffName.Get() != tariff)
- {
- if (!ptr->GetProperty().tariffName.Set(tariff,
- admin,
- login,
- &store))
- return true;
- }
- }
- else
- {
- GetStgLogger()("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str());
- }
- }
-
- if (nextTariff != "" &&
- tariffs->FindByName(nextTariff))
- if (ptr->GetProperty().nextTariff.Get() != nextTariff)
- if (!ptr->GetProperty().nextTariff.Set(tariff,
- admin,
- login,
- &store))
- return true;
- }
-
-return false;
-}
+++ /dev/null
-#ifndef __USER_HELPER_H__
-#define __USER_HELPER_H__
-
-#include <string>
-
-#include <xmlrpc-c/base.hpp>
-
-#include "stg/users.h"
-
-class ADMIN;
-class STORE;
-class TARIFFS;
-
-class USER_HELPER
-{
-public:
- USER_HELPER(USER_PTR & p, USERS & us)
- : ptr(p),
- users(us)
- {
- }
-
- void GetUserInfo(xmlrpc_c::value * info,
- bool hidePassword = false);
- bool SetUserInfo(const xmlrpc_c::value & info,
- const ADMIN * admin,
- const std::string & login,
- const STORE & store,
- TARIFFS * tariffs);
-private:
- USER_PTR & ptr;
- USERS & users;
-};
-
-#endif
+++ /dev/null
-#include <cerrno>
-
-#include "stg/users.h"
-#include "stg/admins.h"
-#include "stg/tariffs.h"
-#include "stg/user_ips.h"
-#include "stg/common.h"
-#include "stg/user_property.h"
-
-#include "users_methods.h"
-#include "rpcconfig.h"
-#include "user_helper.h"
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-USER_HELPER uhelper(u, *users);
-
-if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
- {
- uhelper.GetUserInfo(retvalPtr, true);
- return;
- }
-
-uhelper.GetUserInfo(retvalPtr);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_ADD::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin = NULL;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- if (users->Add(login, admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
- *retvalPtr = xmlrpc_c::value_boolean(true);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-return;
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_DEL::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (!users->FindByName(login, &u))
- {
- users->Del(login, admin);
- *retvalPtr = xmlrpc_c::value_boolean(true);
- return;
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-return;
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USERS_GET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-std::vector<xmlrpc_c::value> retval;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-bool hidePassword = !adminInfo.priviledges.userConf ||
- !adminInfo.priviledges.userPasswd;
-
-USER_PTR u;
-
-int h = users->OpenSearch();
-if (!h)
- {
- printfd(__FILE__, "users->OpenSearch() error\n");
- users->CloseSearch(h);
- return;
- }
-
-while (1)
- {
- if (users->SearchNext(h, &u))
- {
- break;
- }
-
- xmlrpc_c::value info;
-
- USER_HELPER uhelper(u, *users);
-
- uhelper.GetUserInfo(&info, hidePassword);
-
- retval.push_back(info);
- }
-
-*retvalPtr = xmlrpc_c::value_array(retval);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CHG::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_HELPER uhelper(u, *users);
-
-if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
- {
- uhelper.SetUserInfo(info, admin, login, *store, tariffs);
- }
-else
- {
- uhelper.SetUserInfo(info, admin, login, *store, tariffs);
- }
-
-u->WriteConf();
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CASH_ADD::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-double amount = paramList.getDouble(2);
-std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
-paramList.verifyEnd(4);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-double cash = u->GetProperty().cash.Get();
-cash += amount;
-
-if (!u->GetProperty().cash.Set(cash, admin, login, store, comment))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CASH_SET::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-double cash = paramList.getDouble(2);
-std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
-paramList.verifyEnd(4);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (!u->GetProperty().cash.Set(cash, admin, login, store, comment))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_TARIFF_CHANGE::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-std::string tariff = paramList.getString(2);
-bool delayed = paramList.getBoolean(3);
-std::string comment = IconvString(paramList.getString(4), "UTF-8", "KOI8-R");
-paramList.verifyEnd(5);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-ADMIN * admin;
-
-if (admins->Find(adminInfo.admin, &admin))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- *retvalPtr = xmlrpc_c::value_boolean(false);
- return;
- }
-
-if (tariffs->FindByName(tariff))
- {
- if (delayed)
- {
- if (u->GetProperty().nextTariff.Set(tariff,
- admin,
- login,
- store,
- comment))
- {
- u->WriteConf();
- *retvalPtr = xmlrpc_c::value_boolean(true);
- return;
- }
- }
- else
- {
- const TARIFF * newTariff = tariffs->FindByName(tariff);
- if (newTariff)
- {
- const TARIFF * currentTariff = u->GetTariff();
- std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
- if (message.empty())
- {
- if (u->GetProperty().tariffName.Set(tariff,
- admin,
- login,
- store,
- comment))
- {
- u->ResetNextTariff();
- u->WriteConf();
- *retvalPtr = xmlrpc_c::value_boolean(true);
- return;
- }
- }
- else
- {
- GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
- }
- }
- }
- }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_GET_ONLINE_IPS::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-typedef std::vector<xmlrpc_c::value> ValueVector;
-ValueVector subnetsStr = paramList.getArray(1);
-paramList.verifyEnd(2);
-
-std::vector<IP_MASK> subnets;
-
-for (ValueVector::const_iterator it(subnetsStr.begin()); it != subnetsStr.end(); ++it)
- {
- IP_MASK ipm;
- if (ParseNet(xmlrpc_c::value_string(*it), ipm))
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::execute(): Failed to parse subnet ('%s')\n", std::string(xmlrpc_c::value_string(*it)).c_str());
- }
- else
- {
- subnets.push_back(ipm);
- }
- }
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-ValueVector ips;
-
-USER_PTR u;
-
-int handle = users->OpenSearch();
-if (!handle)
- {
- printfd(__FILE__, "users->OpenSearch() error\n");
- users->CloseSearch(handle);
- return;
- }
-
-while (1)
- {
- if (users->SearchNext(handle, &u))
- {
- break;
- }
-
- if (u->GetAuthorized())
- {
- uint32_t ip = u->GetCurrIP();
-
- for (std::vector<IP_MASK>::const_iterator it(subnets.begin()); it != subnets.end(); ++it)
- {
- if ((it->ip & it->mask) == (ip & it->mask))
- {
- ips.push_back(xmlrpc_c::value_string(inet_ntostring(u->GetCurrIP())));
- break;
- }
- }
- }
- }
-
-structVal["ips"] = xmlrpc_c::value_array(ips);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-bool METHOD_GET_ONLINE_IPS::ParseNet(const std::string & net, IP_MASK & ipm) const
-{
-size_t pos = net.find_first_of('/');
-
-if (pos == std::string::npos)
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network address is not in CIDR-notation\n");
- return true;
- }
-
-int res = inet_pton(AF_INET, net.substr(0, pos).c_str(), &ipm.ip);
-
-if (res < 0)
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): '%s'\n", strerror(errno));
- return true;
- }
-else if (res == 0)
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network address\n", strerror(errno));
- return true;
- }
-
-if (str2x(net.substr(pos + 1, net.length() - pos - 1), ipm.mask))
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network mask\n");
- return true;
- }
-if (ipm.mask > 32)
- {
- printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network mask is out of range\n");
- return true;
- }
-ipm.mask = htonl(0xffFFffFF << (32 - ipm.mask));
-
-return false;
-}
-
-void METHOD_GET_USER_AUTH_BY::execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-USER_PTR u;
-
-if (users->FindByName(login, &u))
- {
- structVal["result"] = xmlrpc_c::value_boolean(false);
- *retvalPtr = xmlrpc_c::value_struct(structVal);
- return;
- }
-
-std::vector<std::string> list(u->GetAuthorizers());
-std::vector<xmlrpc_c::value> authList;
-for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
- authList.push_back(xmlrpc_c::value_string(*it));
-*retvalPtr = xmlrpc_c::value_array(authList);
-}
+++ /dev/null
-#ifndef __USERS_METHODS_H__
-#define __USERS_METHODS_H__
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-class RPC_CONFIG;
-class ADMINS;
-class TARIFFS;
-class USERS;
-class STORE;
-struct IP_MASK;
-
-class METHOD_USER_GET : public xmlrpc_c::method {
-public:
- METHOD_USER_GET(RPC_CONFIG * c,
- USERS * u)
- : config(c),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_GET(const METHOD_USER_GET & rvalue);
- METHOD_USER_GET & operator=(const METHOD_USER_GET & rvalue);
-
- RPC_CONFIG * config;
- USERS * users;
-};
-
-class METHOD_USER_ADD : public xmlrpc_c::method {
-public:
- METHOD_USER_ADD(RPC_CONFIG * c,
- ADMINS * a,
- USERS * u)
- : config(c),
- admins(a),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_ADD(const METHOD_USER_ADD & rvalue);
- METHOD_USER_ADD & operator=(const METHOD_USER_ADD & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- USERS * users;
-};
-
-class METHOD_USER_DEL : public xmlrpc_c::method {
-public:
- METHOD_USER_DEL(RPC_CONFIG * c,
- ADMINS * a,
- USERS * u)
- : config(c),
- admins(a),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_DEL(const METHOD_USER_DEL & rvalue);
- METHOD_USER_DEL & operator=(const METHOD_USER_DEL & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- USERS * users;
-};
-
-class METHOD_USERS_GET : public xmlrpc_c::method {
-public:
- METHOD_USERS_GET(RPC_CONFIG * c,
- USERS * u)
- : config(c),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USERS_GET(const METHOD_USERS_GET & rvalue);
- METHOD_USERS_GET & operator=(const METHOD_USERS_GET & rvalue);
-
- RPC_CONFIG * config;
- USERS * users;
-};
-
-class METHOD_USER_CHG : public xmlrpc_c::method {
-public:
- METHOD_USER_CHG(RPC_CONFIG * c,
- ADMINS * a,
- TARIFFS * t,
- STORE * s,
- USERS * u)
- : config(c),
- admins(a),
- tariffs(t),
- store(s),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_CHG(const METHOD_USER_CHG & rvalue);
- METHOD_USER_CHG & operator=(const METHOD_USER_CHG & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- TARIFFS * tariffs;
- STORE * store;
- USERS * users;
-};
-
-class METHOD_USER_CASH_ADD : public xmlrpc_c::method {
-public:
- METHOD_USER_CASH_ADD(RPC_CONFIG * c,
- ADMINS * a,
- STORE * s,
- USERS * u)
- : config(c),
- admins(a),
- store(s),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_CASH_ADD(const METHOD_USER_CASH_ADD & rvalue);
- METHOD_USER_CASH_ADD & operator=(const METHOD_USER_CASH_ADD & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- STORE * store;
- USERS * users;
-};
-
-class METHOD_USER_CASH_SET : public xmlrpc_c::method {
-public:
- METHOD_USER_CASH_SET(RPC_CONFIG * c,
- ADMINS * a,
- STORE * s,
- USERS * u)
- : config(c),
- admins(a),
- store(s),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_CASH_SET(const METHOD_USER_CASH_SET & rvalue);
- METHOD_USER_CASH_SET & operator=(const METHOD_USER_CASH_SET & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- STORE * store;
- USERS * users;
-};
-
-class METHOD_USER_TARIFF_CHANGE : public xmlrpc_c::method {
-public:
- METHOD_USER_TARIFF_CHANGE(RPC_CONFIG * c,
- ADMINS * a,
- TARIFFS * t,
- STORE * s,
- USERS * u)
- : config(c),
- admins(a),
- tariffs(t),
- store(s),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_USER_TARIFF_CHANGE(const METHOD_USER_TARIFF_CHANGE & rvalue);
- METHOD_USER_TARIFF_CHANGE & operator=(const METHOD_USER_TARIFF_CHANGE & rvalue);
-
- RPC_CONFIG * config;
- ADMINS * admins;
- TARIFFS * tariffs;
- STORE * store;
- USERS * users;
-};
-
-class METHOD_GET_ONLINE_IPS : public xmlrpc_c::method {
-public:
- METHOD_GET_ONLINE_IPS(RPC_CONFIG * c,
- USERS * u)
- : config(c),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_GET_ONLINE_IPS(const METHOD_GET_ONLINE_IPS & rvalue);
- METHOD_GET_ONLINE_IPS & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
-
- RPC_CONFIG * config;
- USERS * users;
-
- bool ParseNet(const std::string & net, IP_MASK & ipm) const;
-};
-
-class METHOD_GET_USER_AUTH_BY : public xmlrpc_c::method {
-public:
- METHOD_GET_USER_AUTH_BY(RPC_CONFIG * c,
- USERS * u)
- : config(c),
- users(u)
- {
- }
-
- void execute(xmlrpc_c::paramList const & paramList,
- xmlrpc_c::value * const retvalP);
-
-private:
- METHOD_GET_USER_AUTH_BY(const METHOD_GET_ONLINE_IPS & rvalue);
- METHOD_GET_USER_AUTH_BY & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
-
- RPC_CONFIG * config;
- USERS * users;
-};
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.11 2010/03/04 10:47:45 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_conf_sg.so
-
-SRCS = ./stgconfig.cpp \
- ./conn.cpp \
- ./configproto.cpp \
- ./parser.cpp \
- ./parser_tariffs.cpp \
- ./parser_admins.cpp \
- ./parser_users.cpp \
- ./parser_services.cpp \
- ./parser_message.cpp \
- ./parser_auth_by.cpp \
- ./parser_user_info.cpp \
- ./parser_server_info.cpp
-
-LIBS += -lexpat \
- $(LIB_THREAD)
-
-STGLIBS = common \
- logger \
- crypto \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "configproto.h"
-
-#include "conn.h"
-
-#include "parser_server_info.h"
-#include "parser_admins.h"
-#include "parser_tariffs.h"
-#include "parser_users.h"
-#include "parser_services.h"
-#include "parser_message.h"
-#include "parser_user_info.h"
-#include "parser_auth_by.h"
-
-#include "stg/common.h"
-#include "stg/logger.h"
-
-#include <algorithm>
-#include <functional>
-#include <vector>
-#include <csignal>
-#include <cstring>
-#include <cerrno>
-#include <cassert>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-namespace SP = STG::PARSER;
-
-CONFIGPROTO::CONFIGPROTO(PLUGIN_LOGGER & l)
- : m_settings(NULL),
- m_admins(NULL),
- m_tariffs(NULL),
- m_users(NULL),
- m_services(NULL),
- m_corporations(NULL),
- m_store(NULL),
- m_port(0),
- m_bindAddress("0.0.0.0"),
- m_running(false),
- m_stopped(true),
- m_logger(l),
- m_listenSocket(-1)
-{
-}
-
-CONFIGPROTO::~CONFIGPROTO()
-{
- {
- std::deque<STG::Conn *>::iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- delete *it;
- }
- {
- BASE_PARSER::REGISTRY::iterator it;
- for (it = m_registry.begin(); it != m_registry.end(); ++it)
- delete it->second;
- }
-}
-
-int CONFIGPROTO::Prepare()
-{
- sigset_t sigmask, oldmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGINT);
- sigaddset(&sigmask, SIGTERM);
- sigaddset(&sigmask, SIGUSR1);
- sigaddset(&sigmask, SIGHUP);
- pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
- m_listenSocket = socket(PF_INET, SOCK_STREAM, 0);
-
- if (m_listenSocket < 0)
- {
- m_errorStr = std::string("Cannot create listen socket: '") + strerror(errno) + "'.";
- m_logger(m_errorStr);
- return -1;
- }
-
- int dummy = 1;
-
- if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &dummy, 4) != 0)
- {
- m_errorStr = std::string("Failed to set SO_REUSEADDR to the listen socket: '") + strerror(errno) + "'.";
- m_logger(m_errorStr);
- return -1;
- }
-
- if (!Bind())
- return -1;
-
- if (listen(m_listenSocket, 64) == -1) // TODO: backlog length
- {
- m_errorStr = std::string("Failed to start listening for connections: '") + strerror(errno) + "'.";
- m_logger(m_errorStr);
- return -1;
- }
-
- RegisterParsers();
-
- m_running = true;
- m_stopped = false;
- return 0;
-}
-
-int CONFIGPROTO::Stop()
-{
- m_running = false;
- for (int i = 0; i < 5 && !m_stopped; ++i)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
- if (!m_stopped)
- {
- m_errorStr = "Cannot stop listenign thread.";
- m_logger(m_errorStr);
- return -1;
- }
-
- shutdown(m_listenSocket, SHUT_RDWR);
- close(m_listenSocket);
- return 0;
-}
-
-void CONFIGPROTO::Run()
-{
- while (m_running)
- {
- fd_set fds;
-
- BuildFDSet(fds);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 500000;
-
- int res = select(MaxFD() + 1, &fds, NULL, NULL, &tv);
- if (res < 0)
- {
- m_errorStr = std::string("'select' is failed: '") + strerror(errno) + "'.";
- printfd(__FILE__, "%s\n", m_errorStr.c_str());
- m_logger(m_errorStr);
- break;
- }
- if (!m_running)
- break;
- if (res > 0)
- HandleEvents(fds);
-
- CleanupConns();
- }
- m_stopped = true;
-}
-
-bool CONFIGPROTO::Bind()
-{
- const hostent * he = gethostbyname(m_bindAddress.c_str());
- if (he == NULL)
- {
- m_errorStr = "Failed to resolve name '" + m_bindAddress + "': '" + hstrerror(h_errno) + "'.";
- printfd(__FILE__, "%s\n", m_errorStr.c_str());
- m_logger(m_errorStr);
- return false;
- }
-
- char ** ptr = he->h_addr_list;
- while (*ptr != NULL)
- {
- struct sockaddr_in listenAddr;
- listenAddr.sin_family = PF_INET;
- listenAddr.sin_port = htons(m_port);
- listenAddr.sin_addr.s_addr = *reinterpret_cast<in_addr_t *>(*ptr);
-
- printfd(__FILE__, "Trying to bind to %s:%d\n", inet_ntostring(listenAddr.sin_addr.s_addr).c_str(), m_port);
-
- if (bind(m_listenSocket, reinterpret_cast<sockaddr *>(&listenAddr), sizeof(listenAddr)) == 0)
- return true;
-
- m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'.";
- printfd(__FILE__, "%s\n", m_errorStr.c_str());
- m_logger(m_errorStr);
-
- ++ptr;
- }
-
- return false;
-}
-
-void CONFIGPROTO::RegisterParsers()
-{
- assert(m_settings != NULL);
- assert(m_store != NULL);
- assert(m_admins != NULL);
- assert(m_users != NULL);
- assert(m_tariffs != NULL);
- assert(m_services != NULL);
- assert(m_corporations != NULL);
-
- SP::GET_SERVER_INFO::FACTORY::Register(m_registry, *m_settings, *m_users, *m_tariffs);
-
- SP::GET_ADMINS::FACTORY::Register(m_registry, *m_admins);
- SP::ADD_ADMIN::FACTORY::Register(m_registry, *m_admins);
- SP::DEL_ADMIN::FACTORY::Register(m_registry, *m_admins);
- SP::CHG_ADMIN::FACTORY::Register(m_registry, *m_admins);
-
- SP::GET_TARIFFS::FACTORY::Register(m_registry, *m_tariffs);
- SP::ADD_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
- SP::DEL_TARIFF::FACTORY::Register(m_registry, *m_tariffs, *m_users);
- SP::CHG_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
-
- SP::GET_USERS::FACTORY::Register(m_registry, *m_users);
- SP::GET_USER::FACTORY::Register(m_registry, *m_users);
- SP::ADD_USER::FACTORY::Register(m_registry, *m_users);
- SP::DEL_USER::FACTORY::Register(m_registry, *m_users);
- SP::CHG_USER::FACTORY::Register(m_registry, *m_users, *m_store, *m_tariffs);
- SP::CHECK_USER::FACTORY::Register(m_registry, *m_users);
-
- SP::GET_SERVICES::FACTORY::Register(m_registry, *m_services);
- SP::GET_SERVICE::FACTORY::Register(m_registry, *m_services);
- SP::ADD_SERVICE::FACTORY::Register(m_registry, *m_services);
- SP::DEL_SERVICE::FACTORY::Register(m_registry, *m_services);
- SP::CHG_SERVICE::FACTORY::Register(m_registry, *m_services);
-
- SP::SEND_MESSAGE::FACTORY::Register(m_registry, *m_users);
-
- SP::AUTH_BY::FACTORY::Register(m_registry, *m_users);
-
- SP::USER_INFO::FACTORY::Register(m_registry, *m_users);
-}
-
-int CONFIGPROTO::MaxFD() const
-{
- int maxFD = m_listenSocket;
- std::deque<STG::Conn *>::const_iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- if (maxFD < (*it)->Sock())
- maxFD = (*it)->Sock();
- return maxFD;
-}
-
-void CONFIGPROTO::BuildFDSet(fd_set & fds) const
-{
- FD_ZERO(&fds);
- FD_SET(m_listenSocket, &fds);
- std::deque<STG::Conn *>::const_iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- FD_SET((*it)->Sock(), &fds);
-}
-
-void CONFIGPROTO::CleanupConns()
-{
- std::deque<STG::Conn *>::iterator pos;
- for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
- if (((*pos)->IsDone() && !(*pos)->IsKeepAlive()) || !(*pos)->IsOk())
- {
- delete *pos;
- *pos = NULL;
- }
-
- pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
- m_conns.erase(pos, m_conns.end());
-}
-
-void CONFIGPROTO::HandleEvents(const fd_set & fds)
-{
- if (FD_ISSET(m_listenSocket, &fds))
- AcceptConnection();
- else
- {
- std::deque<STG::Conn *>::iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- if (FD_ISSET((*it)->Sock(), &fds))
- (*it)->Read();
- }
-}
-
-void CONFIGPROTO::AcceptConnection()
-{
- struct sockaddr_in outerAddr;
- socklen_t outerAddrLen(sizeof(outerAddr));
- int sock = accept(m_listenSocket, reinterpret_cast<sockaddr *>(&outerAddr), &outerAddrLen);
-
- if (sock < 0)
- {
- m_errorStr = std::string("Failed to accept connection: '") + strerror(errno) + "'.";
- printfd(__FILE__, "%s\n", m_errorStr.c_str());
- m_logger(m_errorStr);
- return;
- }
-
- assert(m_admins != NULL);
-
- try
- {
- m_conns.push_back(new STG::Conn(m_registry, *m_admins, sock, outerAddr, m_logger));
- printfd(__FILE__, "New connection from %s:%d. Total connections: %d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port(), m_conns.size());
- }
- catch (const STG::Conn::Error & error)
- {
- // Unlikely.
- m_logger(std::string("Failed to create new client connection: '") + error.what() + "'.");
- }
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef CONFIGPROTO_H
-#define CONFIGPROTO_H
-
-#include "parser.h"
-
-#include "stg/module_settings.h"
-#include "stg/os_int.h"
-
-#include <string>
-#include <deque>
-
-#include <sys/select.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-class SETTINGS;
-class ADMINS;
-class TARIFFS;
-class USERS;
-class SERVICES;
-class CORPORATIONS;
-class STORE;
-class PLUGIN_LOGGER;
-
-namespace STG
-{
-
-class Conn;
-
-}
-
-class CONFIGPROTO {
-public:
- explicit CONFIGPROTO(PLUGIN_LOGGER & l);
- ~CONFIGPROTO();
-
- void SetPort(uint16_t port) { m_port = port; }
- void SetBindAddress(const std::string & address) { m_bindAddress = address; }
- void SetSettings(const SETTINGS * settings) { m_settings = settings; }
- void SetAdmins(ADMINS * admins) { m_admins = admins; }
- void SetTariffs(TARIFFS * tariffs) { m_tariffs = tariffs; }
- void SetUsers(USERS * users) { m_users = users; }
- void SetStore(STORE * store) { m_store = store; }
- void SetServices(SERVICES * services) { m_services = services; }
- void SetCorporations(CORPORATIONS * corporations) { m_corporations = corporations; }
-
- int Prepare();
- int Stop();
- const std::string & GetStrError() const { return m_errorStr; }
- void Run();
-
-private:
- CONFIGPROTO(const CONFIGPROTO & rvalue);
- CONFIGPROTO & operator=(const CONFIGPROTO & rvalue);
-
- const SETTINGS * m_settings;
- ADMINS * m_admins;
- TARIFFS * m_tariffs;
- USERS * m_users;
- SERVICES * m_services;
- CORPORATIONS * m_corporations;
- STORE * m_store;
-
- uint16_t m_port;
- std::string m_bindAddress;
- bool m_running;
- bool m_stopped;
- PLUGIN_LOGGER & m_logger;
- int m_listenSocket;
-
- std::string m_errorStr;
-
- BASE_PARSER::REGISTRY m_registry;
- std::deque<STG::Conn *> m_conns;
-
- bool Bind();
-
- void RegisterParsers();
-
- int MaxFD() const;
- void BuildFDSet(fd_set & fds) const;
- void CleanupConns();
- void HandleEvents(const fd_set & fds);
- void AcceptConnection();
-};
-
-#endif //CONFIGPROTO_H
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "conn.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/logger.h"
-#include "stg/blowfish.h"
-#include "stg/bfstream.h"
-#include "stg/common.h"
-
-#include <cassert>
-#include <cstring>
-#include <cerrno>
-
-#include <unistd.h>
-#include <sys/socket.h>
-
-using STG::Conn;
-
-const char Conn::STG_HEADER[] = "SG04";
-const char Conn::OK_HEADER[] = "OKHD";
-const char Conn::ERR_HEADER[] = "ERHD";
-const char Conn::OK_LOGIN[] = "OKLG";
-const char Conn::ERR_LOGIN[] = "ERLG";
-const char Conn::OK_LOGINS[] = "OKLS";
-const char Conn::ERR_LOGINS[] = "ERLS";
-
-Conn::Conn(const BASE_PARSER::REGISTRY & registry,
- ADMINS & admins, int sock, const sockaddr_in& addr,
- PLUGIN_LOGGER & logger)
- : m_registry(registry),
- m_admins(admins),
- m_admin(NULL),
- m_sock(sock),
- m_addr(addr),
- m_keepAlive(false),
- m_parser(NULL),
- m_xmlParser(XML_ParserCreate(NULL)),
- m_state(HEADER),
- m_buffer(m_header),
- m_bufferSize(sizeof(m_header)),
- m_stream(NULL),
- m_logger(logger),
-#ifdef DUMPCRYPTO
- m_dataState(false, *this),
- m_dumper(endpoint())
-#else
- m_dataState(false, *this)
-#endif
-{
- if (m_xmlParser == NULL)
- throw Error("Failed to create XML parser.");
-
- XML_ParserReset(m_xmlParser, NULL);
- XML_SetElementHandler(m_xmlParser, ParseXMLStart, ParseXMLEnd);
- XML_SetUserData(m_xmlParser, this);
-}
-
-Conn::~Conn()
-{
- shutdown(m_sock, SHUT_RDWR);
- close(m_sock);
-
- XML_ParserFree(m_xmlParser);
-
- delete m_stream;
- delete m_parser;
-}
-
-bool Conn::Read()
-{
- ssize_t res = read(m_sock, m_buffer, m_bufferSize);
- if (res < 0)
- {
- m_state = ERROR;
- Log(__FILE__, "Failed to read data from " + endpoint() + ". Reason: '" + strerror(errno) + "'");
- return false;
- }
- if (res == 0 && m_state != DATA) // EOF is ok for data.
- {
- m_state = ERROR;
- Log(__FILE__, "Failed to read data from " + endpoint() + ". Unexpected EOF.");
- return false;
- }
-#ifdef DUMPCRYPTO
- m_dumper.write(m_buffer, res);
-#endif
- m_bufferSize -= res;
- m_buffer = static_cast<char*>(m_buffer) + res;
- return HandleBuffer(res);
-}
-
-bool Conn::WriteAnswer(const void* buffer, size_t size)
-{
- ssize_t res = write(m_sock, buffer, size);
- if (res < 0)
- {
- m_state = ERROR;
- Log(__FILE__, "Failed to write data to " + endpoint() + ". Reason: '" + strerror(errno) + "'.");
- return false;
- }
- return true;
-}
-
-BASE_PARSER * Conn::GetParser(const std::string & tag) const
-{
- BASE_PARSER::REGISTRY::const_iterator it = m_registry.find(ToLower(tag));
- if (it == m_registry.end())
- return NULL;
- return it->second->create(*m_admin);
-}
-
-bool Conn::HandleBuffer(size_t size)
-{
- if (m_state == DATA)
- return HandleData(size);
-
- if (m_bufferSize > 0)
- return true;
-
- switch (m_state)
- {
- case HEADER: return HandleHeader();
- case LOGIN: return HandleLogin();
- case CRYPTO_LOGIN: return HandleCryptoLogin();
- default: return true;
- }
-
- return true;
-}
-
-bool Conn::HandleHeader()
-{
- if (strncmp(m_header, STG_HEADER, sizeof(m_header)) != 0)
- {
- Log(__FILE__, "Received invalid header from " + endpoint() + ".");
- WriteAnswer(ERR_HEADER, sizeof(ERR_HEADER) - 1); // Without \0
- m_state = ERROR;
- return false;
- }
- m_state = LOGIN;
- m_buffer = m_login;
- m_bufferSize = sizeof(m_login);
- return WriteAnswer(OK_HEADER, sizeof(OK_HEADER) - 1); // Without \0
-}
-
-bool Conn::HandleLogin()
-{
- if (m_admins.Find(m_login, &m_admin)) // ADMINS::Find returns true on error.
- {
- std::string login(m_login, strnlen(m_login, sizeof(m_login)));
- Log(__FILE__, "Received invalid login '" + ToPrintable(login) + "' from " + endpoint() + ".");
- WriteAnswer(ERR_LOGIN, sizeof(ERR_LOGIN) - 1); // Without \0
- m_state = ERROR;
- return false;
- }
- m_admin->SetIP(IP());
- m_state = CRYPTO_LOGIN;
- m_buffer = m_cryptoLogin;
- m_bufferSize = sizeof(m_cryptoLogin);
- return WriteAnswer(OK_LOGIN, sizeof(OK_LOGIN) - 1); // Without \0
-}
-
-bool Conn::HandleCryptoLogin()
-{
- char login[ADM_LOGIN_LEN + 1];
- BLOWFISH_CTX ctx;
- InitContext(m_admin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
- DecryptString(login, m_cryptoLogin, ADM_LOGIN_LEN, &ctx);
-
- if (strncmp(m_login, login, sizeof(login)) != 0)
- {
- Log(__FILE__, "Attempt to connect with wrong password from " + m_admin->GetLogin() + "@" + endpoint() + ".");
- WriteAnswer(ERR_LOGINS, sizeof(ERR_LOGINS) - 1); // Without \0
- m_state = ERROR;
- return false;
- }
-
- m_state = DATA;
- m_buffer = m_data;
- m_bufferSize = sizeof(m_data);
- m_stream = new STG::DECRYPT_STREAM(m_admin->GetPassword(), DataCallback, &m_dataState);
- return WriteAnswer(OK_LOGINS, sizeof(OK_LOGINS) - 1); // Without \0
-}
-
-bool Conn::HandleData(size_t size)
-{
- m_stream->Put(m_data, size, size == 0 || memchr(m_data, 0, size) != NULL);
- m_buffer = m_data;
- return m_stream->IsOk();
-}
-
-bool Conn::DataCallback(const void * block, size_t size, void * data)
-{
- assert(data != NULL);
- DataState& state = *static_cast<DataState *>(data);
-
- const char * xml = static_cast<const char *>(block);
- size_t length = strnlen(xml, size);
-
- state.final = state.final || length < size || size == 0;
-
- if (XML_Parse(state.conn.m_xmlParser, xml, length, state.final) == XML_STATUS_ERROR)
- {
- state.conn.Log(__FILE__, "Received invalid XML from " + state.conn.m_admin->GetLogin() + "@" + state.conn.endpoint() + ".");
- printfd(__FILE__, "XML parse error at line %d, %d: %s. Is final: %d\n",
- static_cast<int>(XML_GetCurrentLineNumber(state.conn.m_xmlParser)),
- static_cast<int>(XML_GetCurrentColumnNumber(state.conn.m_xmlParser)),
- XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), (int)state.final);
- printfd(__FILE__, "Data block: '%s' of size %d\n", xml, length);
- state.conn.m_state = ERROR;
- return false;
- }
-
- if (state.final)
- {
- if (!state.conn.WriteResponse())
- {
- state.conn.Log(__FILE__, "Failed to write response to " + state.conn.m_admin->GetLogin() + "@" + state.conn.endpoint() + ".");
- state.conn.m_state = ERROR;
- return false;
- }
- state.conn.m_state = DONE;
- }
-
- return true;
-}
-
-void Conn::ParseXMLStart(void * data, const char * el, const char ** attr)
-{
- assert(data != NULL);
- Conn & conn = *static_cast<Conn *>(data);
-
- if (conn.m_parser == NULL)
- conn.m_parser = conn.GetParser(el);
-
- if (conn.m_parser == NULL)
- {
- conn.Log(__FILE__, "Received unknown command '" + std::string(el) + "' from " + conn.m_admin->GetLogin() + "@" + conn.endpoint() + ".");
- conn.m_state = ERROR;
- return;
- }
-
- conn.m_parser->Start(data, el, attr);
-}
-
-void Conn::ParseXMLEnd(void * data, const char * el)
-{
- assert(data != NULL);
- Conn & conn = *static_cast<Conn *>(data);
-
- if (conn.m_parser == NULL)
- {
- // No need to log it.
- conn.m_state = ERROR;
- return;
- }
-
- conn.m_parser->End(data, el);
-}
-
-bool Conn::WriteResponse()
-{
- STG::ENCRYPT_STREAM stream(m_admin->GetPassword(), WriteCallback, this);
- std::string answer;
- if (m_parser != NULL)
- answer = m_parser->GetAnswer();
- else
- answer = "<Error result=\"Unknown command.\"/>";
- delete m_parser;
- m_parser = NULL;
- printfd(__FILE__, "Writing %d bytes of answer.\n", answer.length());
- stream.Put(answer.c_str(), answer.length() + 1 /* including \0 */, true /* final */);
- return stream.IsOk();
-}
-
-bool Conn::WriteCallback(const void * block, size_t size, void * data)
-{
- assert(data != NULL);
- Conn & conn = *static_cast<Conn *>(data);
- return WriteAll(conn.m_sock, block, size);;
-}
-
-void Conn::Log(const char * file, const std::string & message)
-{
- printfd(file, "%s\n", message.c_str());
- m_logger(message);
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_CONN_H__
-#define __STG_SGCONFIG_CONN_H__
-
-#include "parser.h"
-
-#include "dumphelpers.h"
-
-#include "stg/os_int.h"
-#include "stg/const.h"
-
-#include <stdexcept>
-#include <string>
-
-#include <expat.h>
-
-#include <netinet/in.h>
-
-class SETTINGS;
-class ADMINS;
-class USERS;
-class TARIFFS;
-class ADMIN;
-class BASE_PARSER;
-class PLUGIN_LOGGER;
-
-namespace STG
-{
-
-class DECRYPT_STREAM;
-
-class Conn
-{
- public:
- struct Error : public std::runtime_error
- {
- explicit Error(const std::string& message) : runtime_error(message.c_str()) {}
- };
-
- Conn(const BASE_PARSER::REGISTRY & registry,
- ADMINS & admins, int sock, const sockaddr_in& addr,
- PLUGIN_LOGGER & logger);
- ~Conn();
-
- int Sock() const { return m_sock; }
- uint32_t IP() const { return *(uint32_t *)(&m_addr.sin_addr); }
- uint16_t Port() const { return ntohs(m_addr.sin_port); }
-
- std::string endpoint() const { return inet_ntostring(IP()) + ":" + x2str(Port()); }
-
- bool Read();
-
- bool IsOk() const { return m_state != ERROR; }
- bool IsDone() const { return m_state == DONE; }
- bool IsKeepAlive() const { return m_keepAlive; }
-
- void SetKeepAlive() { m_keepAlive = true; }
-
- private:
-
- static const char STG_HEADER[5];
- static const char OK_HEADER[5];
- static const char ERR_HEADER[5];
- static const char OK_LOGIN[5];
- static const char ERR_LOGIN[5];
- static const char OK_LOGINS[5];
- static const char ERR_LOGINS[5];
-
- const BASE_PARSER::REGISTRY & m_registry;
-
- ADMINS & m_admins;
-
- ADMIN * m_admin;
-
- int m_sock;
- sockaddr_in m_addr;
- bool m_keepAlive;
-
- BASE_PARSER * m_parser;
-
- XML_Parser m_xmlParser;
-
- enum { HEADER, LOGIN, CRYPTO_LOGIN, DATA, DONE, ERROR } m_state;
-
- void * m_buffer;
- size_t m_bufferSize;
- char m_header[sizeof(STG_HEADER) - 1]; // Without \0
- char m_login[ADM_LOGIN_LEN]; // Without \0
- char m_cryptoLogin[ADM_LOGIN_LEN]; // Without \0
- char m_data[1024];
- STG::DECRYPT_STREAM * m_stream;
- PLUGIN_LOGGER & m_logger;
-
- BASE_PARSER * GetParser(const std::string & tag) const;
-
- bool HandleBuffer(size_t size);
-
- bool HandleHeader();
- bool HandleLogin();
- bool HandleCryptoLogin();
- bool HandleData(size_t size);
-
- bool WriteAnswer(const void* buffer, size_t size);
- bool WriteResponse();
-
- void Log(const char * file, const std::string & message);
-
- struct DataState
- {
- DataState(bool f, Conn & c) : final(f), conn(c) {}
- bool final;
- Conn & conn;
- } m_dataState;
-
-#ifdef DUMPCRYPTO
- Dumper m_dumper;
-#endif
-
- static bool DataCallback(const void * block, size_t size, void * data);
- static void ParseXMLStart(void * data, const char * el, const char ** attr);
- static void ParseXMLEnd(void * data, const char * el);
- static bool WriteCallback(const void * block, size_t size, void * data);
-};
-
-}
-
-#endif
+++ /dev/null
-#ifndef __STG_DUMP_HELPERS_H__
-#define __STG_DUMP_HELPERS_H__
-
-#include "stg/common.h"
-
-#include <string>
-#include <fstream>
-#include <sstream>
-#include <iomanip>
-
-#include <cstddef>
-#include <ctime>
-
-namespace STG
-{
-
-class Dumper
-{
- public:
- explicit Dumper(const std::string& tag)
- : m_stream(getName(tag).c_str())
- {
- }
- ~Dumper() {}
-
- void write(const void* data, size_t size)
- {
- writePrefix();
- m_stream << " ";
- writeHEX(data, size);
- }
-
- private:
- std::ofstream m_stream;
-
- tm getTime() const
- {
- time_t now = time(NULL);
- tm localTime;
- localtime_r(&now, &localTime);
- return localTime;
- }
-
- std::string getName(const std::string& tag) const
- {
- tm localTime = getTime();
-
- std::ostringstream res;
- res << tag
- << "-" << (localTime.tm_year + 1900) << twoDigit(localTime.tm_mon + 1) << twoDigit(localTime.tm_mday)
- << "-" << twoDigit(localTime.tm_hour) << twoDigit(localTime.tm_min) << twoDigit(localTime.tm_sec)
- << ".data";
-
- return res.str();
- }
-
- void writePrefix()
- {
- tm localTime = getTime();
- m_stream << "[" << (localTime.tm_year + 1900) << "-" << twoDigit(localTime.tm_mon + 1) << "-" << twoDigit(localTime.tm_mday)
- << " " << twoDigit(localTime.tm_hour) << ":" << twoDigit(localTime.tm_min) << ":" << twoDigit(localTime.tm_sec)
- << "]";
- }
-
- void writeHEX(const void* data, size_t size)
- {
- m_stream << "(" << std::setw(4) << std::setfill(' ') << size << ") ";
- const unsigned char* pos = static_cast<const unsigned char*>(data);
- for (size_t i = 0; i < size; ++i)
- m_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*pos++);
- m_stream << std::dec << "\n";
- }
-
- std::string twoDigit(int value) const
- {
- std::string res = x2str(value);
- if (res.length() < 2)
- res = "0" + res;
- return res;
- }
-};
-
-} // namespace Caster
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#include "parser.h"
-
-#include <cstring>
-
-//-----------------------------------------------------------------------------
-// BASE PARSER
-//-----------------------------------------------------------------------------
-int BASE_PARSER::Start(void *, const char * el, const char **)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- return 0;
-
- return -1;
-}
-//-----------------------------------------------------------------------------
-int BASE_PARSER::End(void *, const char * el)
-{
- if (m_depth < 2)
- {
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
- CreateAnswer();
- }
-
- --m_depth;
- return 0;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#ifndef PARSER_H
-#define PARSER_H
-
-#include <string>
-#include <map>
-
-class ADMIN;
-
-class BASE_PARSER
-{
- public:
- struct FACTORY
- {
- virtual ~FACTORY() {}
- virtual BASE_PARSER * create(const ADMIN & admin) = 0;
- };
- typedef std::map<std::string, FACTORY *> REGISTRY;
-
- BASE_PARSER(const ADMIN & admin, const std::string & t)
- : m_currAdmin(admin),
- m_depth(0),
- m_tag(t)
- {}
- virtual ~BASE_PARSER() {}
- virtual int Start(void * data, const char * el, const char ** attr);
- virtual int End(void * data, const char * el);
-
- const std::string & GetAnswer() const { return m_answer; }
- const std::string & GetTag() const { return m_tag; }
- std::string GetOpenTag() const { return "<" + m_tag + ">"; }
- std::string GetCloseTag() const { return "</" + m_tag + ">"; }
-
- protected:
- BASE_PARSER(const BASE_PARSER & rvalue);
- BASE_PARSER & operator=(const BASE_PARSER & rvalue);
-
- const ADMIN & m_currAdmin;
- size_t m_depth;
- std::string m_answer;
- std::string m_tag;
-
- private:
- virtual void CreateAnswer() = 0;
-};
-
-#endif //PARSER_H
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_admins.h"
-
-#include "stg/admins.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::GET_ADMINS;
-using STG::PARSER::ADD_ADMIN;
-using STG::PARSER::DEL_ADMIN;
-using STG::PARSER::CHG_ADMIN;
-
-const char * GET_ADMINS::tag = "GetAdmins";
-const char * ADD_ADMIN::tag = "AddAdmin";
-const char * DEL_ADMIN::tag = "DelAdmin";
-const char * CHG_ADMIN::tag = "ChgAdmin";
-
-void GET_ADMINS::CreateAnswer()
-{
- const PRIV * priv = m_currAdmin.GetPriv();
- if (!priv->adminChg)
- {
- m_answer = "<Error Result=\"Error. Access denied.\"/>";
- return;
- }
-
- m_answer = "<Admins>";
- ADMIN_CONF ac;
- int h = m_admins.OpenSearch();
-
- while (m_admins.SearchNext(h, &ac) == 0)
- {
- unsigned int p = (ac.priv.userStat << 0) +
- (ac.priv.userConf << 2) +
- (ac.priv.userCash << 4) +
- (ac.priv.userPasswd << 6) +
- (ac.priv.userAddDel << 8) +
- (ac.priv.adminChg << 10) +
- (ac.priv.tariffChg << 12);
- m_answer += "<admin login=\"" + ac.login + "\" priv=\"" + x2str(p) + "\"/>";
- }
- m_admins.CloseSearch(h);
- m_answer += "</Admins>";
-}
-
-int DEL_ADMIN::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- m_admin = attr[1];
- return 0;
- }
- return -1;
-}
-
-void DEL_ADMIN::CreateAnswer()
-{
- if (m_admins.Del(m_admin, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " Result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.GetStrError() + "\"/>";
-}
-
-int ADD_ADMIN::Start(void *, const char *el, const char **attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- m_admin = attr[1];
- return 0;
- }
- return -1;
-}
-
-void ADD_ADMIN::CreateAnswer()
-{
- if (m_admins.Add(m_admin, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " Result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.GetStrError() + "\"/>";
-}
-
-int CHG_ADMIN::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- for (size_t i = 0; i < 6; i += 2)
- {
- printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
- if (attr[i] == NULL)
- break;
-
- if (strcasecmp(attr[i], "Login") == 0)
- {
- login = attr[i + 1];
- continue;
- }
-
- if (strcasecmp(attr[i], "Priv") == 0)
- {
- privAsString = attr[i + 1];
- continue;
- }
-
- if (strcasecmp(attr[i], "Password") == 0)
- {
- password = attr[i + 1];
- continue;
- }
- }
-
- return 0;
- }
- return -1;
-}
-
-void CHG_ADMIN::CreateAnswer()
-{
- if (!login.empty())
- {
- ADMIN * origAdmin = NULL;
-
- if (m_admins.Find(login, &origAdmin))
- {
- m_answer = "<" + m_tag + " Result = \"Admin '" + login + "' is not found.\"/>";
- return;
- }
-
- ADMIN_CONF conf(origAdmin->GetConf());
-
- if (!password.empty())
- conf.password = password.data();
-
- if (!privAsString.empty())
- {
- int p = 0;
- if (str2x(privAsString.data().c_str(), p) < 0)
- {
- m_answer = "<" + m_tag + " Result = \"Incorrect parameter Priv.\"/>";
- return;
- }
-
- conf.priv.FromInt(p);
- }
-
- if (m_admins.Change(conf, &m_currAdmin) != 0)
- m_answer = "<" + m_tag + " Result = \"" + m_admins.GetStrError() + "\"/>";
- else
- m_answer = "<" + m_tag + " Result = \"Ok\"/>";
- }
- else
- m_answer = "<" + m_tag + " Result = \"Incorrect parameter login.\"/>";
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_ADMINS_H__
-#define __STG_SGCONFIG_PARSER_ADMINS_H__
-
-#include "parser.h"
-
-#include "stg/common.h"
-#include "stg/resetable.h"
-
-#include <string>
-
-class ADMINS;
-class ADMIN;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class GET_ADMINS: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(const ADMINS & admins) : m_admins(admins) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_ADMINS(admin, m_admins); }
- static void Register(REGISTRY & registry, const ADMINS & admins)
- { registry[ToLower(tag)] = new FACTORY(admins); }
- private:
- const ADMINS & m_admins;
- };
-
- static const char * tag;
-
- GET_ADMINS(const ADMIN & admin, const ADMINS & admins)
- : BASE_PARSER(admin, tag), m_admins(admins) {}
-
- private:
- const ADMINS & m_admins;
-
- void CreateAnswer();
-};
-
-class ADD_ADMIN: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_ADMIN(admin, m_admins); }
- static void Register(REGISTRY & registry, ADMINS & admins)
- { registry[ToLower(tag)] = new FACTORY(admins); }
- private:
- ADMINS & m_admins;
- };
-
- static const char * tag;
-
- ADD_ADMIN(const ADMIN & admin, ADMINS & admins)
- : BASE_PARSER(admin, tag), m_admins(admins) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string m_admin;
- ADMINS & m_admins;
-
- void CreateAnswer();
-};
-
-class DEL_ADMIN: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_ADMIN(admin, m_admins); }
- static void Register(REGISTRY & registry, ADMINS & admins)
- { registry[ToLower(tag)] = new FACTORY(admins); }
- private:
- ADMINS & m_admins;
- };
-
- static const char * tag;
-
- DEL_ADMIN(const ADMIN & admin, ADMINS & admins)
- : BASE_PARSER(admin, tag), m_admins(admins) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string m_admin;
- ADMINS & m_admins;
-
- void CreateAnswer();
-};
-
-class CHG_ADMIN: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_ADMIN(admin, m_admins); }
- static void Register(REGISTRY & registry, ADMINS & admins)
- { registry[ToLower(tag)] = new FACTORY(admins); }
- private:
- ADMINS & m_admins;
- };
-
- static const char * tag;
-
- CHG_ADMIN(const ADMIN & admin, ADMINS & admins)
- : BASE_PARSER(admin, tag), m_admins(admins) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string login;
- RESETABLE<std::string> password;
- RESETABLE<std::string> privAsString;
- ADMINS & m_admins;
-
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "parser_auth_by.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-
-using STG::PARSER::AUTH_BY;
-
-const char * AUTH_BY::tag = "GetUserAuthBy";
-
-int AUTH_BY::Start(void * /*data*/, const char *el, const char **attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- if (!attr[1])
- return -1;
-
- m_login = attr[1];
- return 0;
-}
-
-void AUTH_BY::CreateAnswer()
-{
- CONST_USER_PTR u;
- if (m_users.FindByName(m_login, &u))
- {
- m_answer = "<AuthorizedBy result=\"error\" reason=\"User not found.\"/>";
- return;
- }
-
- m_answer = "<AuthorizedBy result=\"ok\">";
- std::vector<std::string> list(u->GetAuthorizers());
- for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
- m_answer += "<Auth name=\"" + *it + "\"/>";
- m_answer += "</AuthorizedBy>";
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_PARSER_AUTH_BY_H__
-#define __STG_PARSER_AUTH_BY_H__
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-class ADMIN;
-class USERS;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class AUTH_BY : public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(const USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new AUTH_BY(admin, m_users); }
- static void Register(REGISTRY & registry, const USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- const USERS & m_users;
- };
-
- static const char * tag;
-
- AUTH_BY(const ADMIN & admin, const USERS & users)
- : BASE_PARSER(admin, tag), m_users(users) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- const USERS & m_users;
- std::string m_login;
-
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_message.h"
-
-#include "stg/users.h"
-
-extern volatile time_t stgTime; // So sad...
-
-using STG::PARSER::SEND_MESSAGE;
-
-const char * SEND_MESSAGE::tag = "Message";
-
-int SEND_MESSAGE::Start(void *, const char *el, const char **attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- for (size_t i = 0; i < 14; i++)
- if (attr[i] == NULL)
- {
- m_result = res_params_error;
- CreateAnswer();
- printfd(__FILE__, "To few parameters\n");
- return 0;
- }
-
- for (size_t i = 0; i < 14; i += 2)
- {
- if (strcasecmp(attr[i], "login") == 0)
- ParseLogins(attr[i + 1]);
-
- if (strcasecmp(attr[i], "MsgVer") == 0)
- {
- str2x(attr[i + 1], m_msg.header.ver);
- if (m_msg.header.ver != 1)
- m_result = res_params_error;
- }
-
- if (strcasecmp(attr[i], "MsgType") == 0)
- {
- str2x(attr[i + 1], m_msg.header.type);
- if (m_msg.header.type != 1)
- m_result = res_params_error;
- }
-
- if (strcasecmp(attr[i], "Repeat") == 0)
- {
- str2x(attr[i + 1], m_msg.header.repeat);
- if (m_msg.header.repeat < 0)
- m_result = res_params_error;
- }
-
- if (strcasecmp(attr[i], "RepeatPeriod") == 0)
- str2x(attr[i + 1], m_msg.header.repeatPeriod);
-
- if (strcasecmp(attr[i], "ShowTime") == 0)
- str2x(attr[i + 1], m_msg.header.showTime);
-
- if (strcasecmp(attr[i], "Text") == 0)
- {
- Decode21str(m_msg.text, attr[i + 1]);
- m_result = res_ok;
- }
- }
- return 0;
-}
-
-int SEND_MESSAGE::End(void *, const char *el)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- m_result = res_unknown;
- for (unsigned i = 0; i < m_logins.size(); i++)
- {
- if (m_users.FindByName(m_logins[i], &m_user))
- {
- printfd(__FILE__, "User not found. %s\n", m_logins[i].c_str());
- continue;
- }
- m_msg.header.creationTime = static_cast<unsigned int>(stgTime);
- m_user->AddMessage(&m_msg);
- m_result = res_ok;
- }
- CreateAnswer();
- return 0;
-}
-
-int SEND_MESSAGE::ParseLogins(const char * login)
-{
- char * p;
- char * l = new char[strlen(login) + 1];
- strcpy(l, login);
- p = strtok(l, ":");
- m_logins.clear();
- while (p)
- {
- m_logins.push_back(p);
- p = strtok(NULL, ":");
- }
-
- delete[] l;
- return 0;
-}
-
-void SEND_MESSAGE::CreateAnswer()
-{
- switch (m_result)
- {
- case res_ok:
- m_answer = "<SendMessageResult value=\"ok\"/>";
- break;
- case res_params_error:
- m_answer = "<SendMessageResult value=\"Parameters error.\"/>";
- break;
- case res_unknown:
- m_answer = "<SendMessageResult value=\"Unknown user.\"/>";
- break;
- }
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_SEND_MESSAGE_H__
-#define __STG_SGCONFIG_PARSER_SEND_MESSAGE_H__
-
-#include "parser.h"
-
-#include "stg/message.h"
-#include "stg/common.h"
-
-#include <vector>
-#include <string>
-
-class USERS;
-class USER;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class SEND_MESSAGE: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new SEND_MESSAGE(admin, m_users); }
- static void Register(REGISTRY & registry, USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- USERS & m_users;
- };
-
- static const char * tag;
-
- SEND_MESSAGE(const ADMIN & admin, USERS & users)
- : BASE_PARSER(admin, tag), m_users(users), m_result(res_ok), m_user(NULL) {}
- int Start(void *data, const char *el, const char **attr);
- int End(void *data, const char *el);
-
- private:
- USERS & m_users;
- std::vector<std::string> m_logins;
- enum { res_ok, res_params_error, res_unknown } m_result;
- STG_MSG m_msg;
- USER * m_user;
-
- int ParseLogins(const char * logins);
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_server_info.h"
-
-#include "stg/settings.h"
-#include "stg/users.h"
-#include "stg/tariffs.h"
-#include "stg/version.h"
-#include "stg/const.h"
-
-#include <string>
-#include <cstring>
-
-#include <sys/utsname.h>
-
-using STG::PARSER::GET_SERVER_INFO;
-
-const char * GET_SERVER_INFO::tag = "GetServerInfo";
-
-void GET_SERVER_INFO::CreateAnswer()
-{
- struct utsname utsn;
- uname(&utsn);
-
- std::string name = std::string(utsn.sysname) + " " +
- utsn.release + " " +
- utsn.machine + " " +
- utsn.nodename;
-
- m_answer = std::string("<ServerInfo><version value=\"") + SERVER_VERSION + "\"/>" +
- "<tariff_num value=\"" + x2str(m_tariffs.Count()) + "\"/>" +
- "<tariff value=\"2\"/>" +
- "<user_num value=\"" + x2str(m_users.Count()) + "\"/>" +
- "<uname value=\"" + name + "\"/>" +
- "<dir_num value=\"" + x2str(DIR_NUM) + "\"/>" +
- "<day_fee value=\"" + x2str(m_settings.GetDayFee()) + "\"/>";
-
- for (size_t i = 0; i< DIR_NUM; i++)
- m_answer += "<dir_name_" + x2str(i) + " value=\"" + Encode12str(m_settings.GetDirName(i)) + "\"/>";
-
- m_answer += "</ServerInfo>";
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_SERVER_INFO_H__
-#define __STG_SGCONFIG_PARSER_SERVER_INFO_H__
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-class ADMIN;
-class SETTINGS;
-class USERS;
-class TARIFFS;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class GET_SERVER_INFO: public BASE_PARSER {
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(const SETTINGS & settings, const USERS & users, const TARIFFS & tariffs)
- : m_settings(settings), m_users(users), m_tariffs(tariffs) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
- static void Register(REGISTRY & registry, const SETTINGS & settings, const USERS & users, const TARIFFS & tariffs)
- { registry[ToLower(tag)] = new FACTORY(settings, users, tariffs); }
- private:
- const SETTINGS & m_settings;
- const USERS & m_users;
- const TARIFFS & m_tariffs;
- };
-
- static const char * tag;
-
- GET_SERVER_INFO(const ADMIN & admin,
- const SETTINGS & settings,
- const USERS & users,
- const TARIFFS & tariffs)
- : BASE_PARSER(admin, tag),
- m_settings(settings),
- m_users(users),
- m_tariffs(tariffs)
- {}
-
- private:
- const SETTINGS & m_settings;
- const USERS & m_users;
- const TARIFFS & m_tariffs;
-
- void CreateAnswer();
-};
-
-}
-}
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "parser_services.h"
-
-#include "stg/services.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::GET_SERVICES;
-using STG::PARSER::GET_SERVICE;
-using STG::PARSER::ADD_SERVICE;
-using STG::PARSER::DEL_SERVICE;
-using STG::PARSER::CHG_SERVICE;
-
-const char * GET_SERVICES::tag = "GetServices";
-const char * GET_SERVICE::tag = "AddService";
-const char * ADD_SERVICE::tag = "AddService";
-const char * DEL_SERVICE::tag = "DelService";
-const char * CHG_SERVICE::tag = "SetService";
-
-void GET_SERVICES::CreateAnswer()
-{
- // TODO: no priviledges implemented yet
- /*const PRIV * priv = m_currAdmin.GetPriv();
- if (!priv->serviceChg)
- {
- m_answer = "<Error Result=\"Error. Access denied.\"/>";
- return;
- }*/
-
- m_answer = "<Services>";
- SERVICE_CONF conf;
- int h = m_services.OpenSearch();
- while (m_services.SearchNext(h, &conf) == 0)
- {
- m_answer += "<Service name=\"" + conf.name +
- "\" comment=\"" + Encode12str(conf.comment) +
- "\" cost=\"" + x2str(conf.cost) +
- "\" payDay=\"" + x2str(conf.payDay) + "\"/>";
- }
- m_services.CloseSearch(h);
- m_answer += "</Services>";
-}
-
-int GET_SERVICE::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- m_name = attr[1];
- return 0;
- }
- return -1;
-}
-
-void GET_SERVICE::CreateAnswer()
-{
- // TODO: no priviledges implemented yet
- /*const PRIV * priv = m_currAdmin.GetPriv();
- if (!priv->serviceChg)
- {
- m_answer = "<Error Result=\"Error. Access denied.\"/>";
- return;
- }*/
-
- SERVICE_CONF conf;
- if (!m_services.Find(m_name, &conf))
- m_answer = "<Error result=\"Service '" + m_name + "' does not exist.\"/>";
- else
- m_answer += "<" + m_tag + " name=\"" + conf.name +
- "\" comment=\"" + Encode12str(conf.comment) +
- "\" cost=\"" + x2str(conf.cost) +
- "\" payDay=\"" + x2str(conf.payDay) + "\"/>";
-}
-
-int ADD_SERVICE::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- m_name = attr[1];
- return 0;
- }
- return -1;
-}
-
-void ADD_SERVICE::CreateAnswer()
-{
- SERVICE_CONF conf(m_name);
- if (m_services.Add(conf, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
-}
-
-int DEL_SERVICE::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- m_name = attr[1];
- return 0;
- }
- return -1;
-}
-
-void DEL_SERVICE::CreateAnswer()
-{
- if (m_services.Del(m_name, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
-}
-
-int CHG_SERVICE::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- for (size_t i = 0; i < 8; i += 2)
- {
- if (attr[i] == NULL)
- break;
-
- if (strcasecmp(attr[i], "name") == 0)
- {
- m_service.name = attr[i + 1];
- continue;
- }
-
- if (strcasecmp(attr[i], "comment") == 0)
- {
- m_service.comment = Decode21str(attr[i + 1]);
- continue;
- }
-
- if (strcasecmp(attr[i], "cost") == 0)
- {
- double cost = 0;
- if (str2x(attr[i + 1], cost) == 0)
- m_service.cost = cost;
- else
- printfd(__FILE__, "Bad cast from '%s' to double\n", attr[i + 1]);
- // TODO: log it
- continue;
- }
-
- if (strcasecmp(attr[i], "payDay") == 0)
- {
- unsigned payDay;
- if (str2x(attr[i + 1], payDay) == 0)
- m_service.payDay = payDay;
- else
- printfd(__FILE__, "Bad cast from '%s' to unsigned\n", attr[i + 1]);
- // TODO: log it
- continue;
- }
- }
-
- return 0;
- }
- return -1;
-}
-
-void CHG_SERVICE::CreateAnswer()
-{
- if (m_service.name.empty())
- {
- m_answer = "<" + m_tag + " result=\"Empty service name.\"/>";
- return;
- }
-
- if (!m_services.Exists(m_service.name.const_data()))
- {
- m_answer = "<" + m_tag + " result = \"Service '" + m_service.name.const_data() + "' does not exist.\"/>";
- return;
- }
-
- SERVICE_CONF orig;
- m_services.Find(m_service.name.const_data(), &orig);
-
- SERVICE_CONF_RES conf(orig);
- conf.Splice(m_service);
-
- if (m_services.Change(conf.GetData(), &m_currAdmin) != 0)
- m_answer = "<" + m_tag + " result = \"" + m_services.GetStrError() + "\"/>";
- else
- m_answer = "<" + m_tag + " result = \"Ok\"/>";
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_SERVICES_H__
-#define __STG_SGCONFIG_PARSER_SERVICES_H__
-
-#include "parser.h"
-
-#include "stg/service_conf.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-class SERVICES;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class GET_SERVICES: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(const SERVICES & services) : m_services(services) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVICES(admin, m_services); }
- static void Register(REGISTRY & registry, const SERVICES & services)
- { registry[ToLower(tag)] = new FACTORY(services); }
- private:
- const SERVICES & m_services;
- };
-
- static const char * tag;
-
- GET_SERVICES(const ADMIN & admin, const SERVICES & services)
- : BASE_PARSER(admin, tag), m_services(services) {}
-
- private:
- const SERVICES & m_services;
-
- void CreateAnswer();
-};
-
-class GET_SERVICE: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(const SERVICES & services) : m_services(services) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVICE(admin, m_services); }
- static void Register(REGISTRY & registry, SERVICES & services)
- { registry[ToLower(tag)] = new FACTORY(services); }
- private:
- const SERVICES & m_services;
- };
-
- static const char * tag;
-
- GET_SERVICE(const ADMIN & admin, const SERVICES & services)
- : BASE_PARSER(admin, tag), m_services(services) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string m_name;
- const SERVICES & m_services;
-
- void CreateAnswer();
-};
-
-class ADD_SERVICE: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(SERVICES & services) : m_services(services) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_SERVICE(admin, m_services); }
- static void Register(REGISTRY & registry, SERVICES & services)
- { registry[ToLower(tag)] = new FACTORY(services); }
- private:
- SERVICES & m_services;
- };
-
- static const char * tag;
-
- ADD_SERVICE(const ADMIN & admin, SERVICES & services)
- : BASE_PARSER(admin, tag), m_services(services) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string m_name;
- SERVICES & m_services;
-
- void CreateAnswer();
-};
-
-class DEL_SERVICE: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(SERVICES & services) : m_services(services) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_SERVICE(admin, m_services); }
- static void Register(REGISTRY & registry, SERVICES & services)
- { registry[ToLower(tag)] = new FACTORY(services); }
- private:
- SERVICES & m_services;
- };
-
- static const char * tag;
-
- DEL_SERVICE(const ADMIN & admin, SERVICES & services)
- : BASE_PARSER(admin, tag), m_services(services) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string m_name;
- SERVICES & m_services;
-
- void CreateAnswer();
-};
-
-class CHG_SERVICE: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(SERVICES & services) : m_services(services) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_SERVICE(admin, m_services); }
- static void Register(REGISTRY & registry, SERVICES & services)
- { registry[ToLower(tag)] = new FACTORY(services); }
- private:
- SERVICES & m_services;
- };
-
- static const char * tag;
-
- CHG_SERVICE(const ADMIN & admin, SERVICES & services)
- : BASE_PARSER(admin, tag), m_services(services) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- SERVICE_CONF_RES m_service;
- SERVICES & m_services;
-
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_tariffs.h"
-
-#include "stg/tariffs.h"
-#include "stg/users.h"
-#include "stg/resetable.h"
-
-#include <cstdio> // snprintf
-#include <cstring>
-
-using STG::PARSER::GET_TARIFFS;
-using STG::PARSER::ADD_TARIFF;
-using STG::PARSER::DEL_TARIFF;
-using STG::PARSER::CHG_TARIFF;
-
-const char * GET_TARIFFS::tag = "GetTariffs";
-const char * ADD_TARIFF::tag = "AddTariff";
-const char * DEL_TARIFF::tag = "DelTariff";
-const char * CHG_TARIFF::tag = "SetTariff";
-
-namespace
-{
-
-const double pt_mega = 1024 * 1024;
-
-template <typename A, typename C, typename F>
-std::string AOS2String(const A & array, size_t size, const F C::* field, F multiplier)
-{
- std::string res;
- for (size_t i = 0; i < size; ++i)
- {
- if (!res.empty())
- res += "/";
- res += x2str((array[i].*field) * multiplier);
- }
- return res;
-}
-
-template <typename T>
-bool str2res(const std::string& source, RESETABLE<T>& dest, T divisor)
-{
- T value = 0;
- if (str2x(source, value))
- return false;
- dest = value / divisor;
- return true;
-}
-
-template <typename A, typename C, typename F>
-bool String2AOS(const std::string & source, A & array, size_t size, RESETABLE<F> C::* field, F divisor)
-{
- size_t index = 0;
- std::string::size_type from = 0;
- std::string::size_type pos = 0;
- while (index < size && (pos = source.find('/', from)) != std::string::npos)
- {
- if (!str2res(source.substr(from, pos - from), array[index].*field, divisor))
- return false;
- from = pos + 1;
- ++index;
- }
- if (str2res(source.substr(from), array[index].*field, divisor))
- return false;
- return true;
-}
-
-}
-
-void GET_TARIFFS::CreateAnswer()
-{
- m_answer = "<Tariffs>";
-
- std::list<TARIFF_DATA> dataList;
- m_tariffs.GetTariffsData(&dataList);
- std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
- for (; it != dataList.end(); ++it)
- {
- m_answer += "<tariff name=\"" + it->tariffConf.name + "\">";
-
- for (size_t i = 0; i < DIR_NUM; i++)
- m_answer += "<Time" + x2str(i) + " value=\"" +
- x2str(it->dirPrice[i].hDay) + ":" + x2str(it->dirPrice[i].mDay) + "-" +
- x2str(it->dirPrice[i].hNight) + ":" + x2str(it->dirPrice[i].mNight) + "\"/>";
-
- m_answer += "<PriceDayA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceDayA, pt_mega) + "\"/>" +
- "<PriceDayB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceDayB, pt_mega) + "\"/>" +
- "<PriceNightA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceNightA, pt_mega) + "\"/>" +
- "<PriceNightB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceNightB, pt_mega) + "\"/>" +
- "<Threshold value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::threshold, 1) + "\"/>" +
- "<SinglePrice value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::singlePrice, 1) + "\"/>" +
- "<NoDiscount value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::noDiscount, 1) + "\"/>" +
- "<Fee value=\"" + x2str(it->tariffConf.fee) + "\"/>" +
- "<PassiveCost value=\"" + x2str(it->tariffConf.passiveCost) + "\"/>" +
- "<Free value=\"" + x2str(it->tariffConf.free) + "\"/>" +
- "<TraffType value=\"" + TARIFF::TraffTypeToString(it->tariffConf.traffType) + "\"/>" +
- "<Period value=\"" + TARIFF::PeriodToString(it->tariffConf.period) + "\"/>" +
- "<ChangePolicy value=\"" + TARIFF::ChangePolicyToString(it->tariffConf.changePolicy) + "\"/>" +
- "<ChangePolicyTimeout value=\"" + x2str(it->tariffConf.changePolicyTimeout) + "\"/>" +
- "</tariff>";
- }
-
- m_answer += "</Tariffs>";
-}
-
-int ADD_TARIFF::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- if (attr[1] == NULL)
- return -1;
-
- tariff = attr[1];
- return 0;
-}
-
-void ADD_TARIFF::CreateAnswer()
-{
- if (m_tariffs.Add(tariff, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " Result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
-}
-
-int DEL_TARIFF::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- if (attr[1] == NULL)
- return -1;
-
- tariff = attr[1];
- return 0;
-}
-
-void DEL_TARIFF::CreateAnswer()
-{
- if (m_users.TariffInUse(tariff))
- m_answer = "<" + m_tag + " Result=\"Error. Tariff \'" + tariff + "\' cannot be deleted, it is in use.\"/>";
- else if (m_tariffs.Del(tariff, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " Result=\"Ok\"/>";
- else
- m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
-}
-
-int CHG_TARIFF::Start(void *, const char * el, const char ** attr)
-{
- m_depth++;
-
- if (m_depth == 1)
- {
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- const TARIFF * tariff = m_tariffs.FindByName(attr[1]);
- if (tariff != NULL)
- td = tariff->GetTariffData();
- else
- return -1;
- return 0;
- }
- }
- else
- {
- if (strcasecmp(el, "PriceDayA") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceDayA, pt_mega))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "PriceDayB") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceDayB, pt_mega))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "PriceNightA") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceNightA, pt_mega))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "PriceNightB") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceNightB, pt_mega))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "Threshold") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::threshold, 1))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "SinglePrice") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::singlePrice, 1))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- if (strcasecmp(el, "NoDiscount") == 0)
- {
- if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::noDiscount, 1))
- return -1; // TODO: log it
- else
- return 0;
- }
-
- for (int j = 0; j < DIR_NUM; j++)
- {
- char st[50];
- snprintf(st, 50, "Time%d", j);
- if (strcasecmp(el, st) == 0)
- {
- int h1 = 0;
- int m1 = 0;
- int h2 = 0;
- int m2 = 0;
- if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
- {
- td.dirPrice[j].hDay = h1;
- td.dirPrice[j].mDay = m1;
- td.dirPrice[j].hNight = h2;
- td.dirPrice[j].mNight = m2;
- }
- return 0;
- }
- }
-
- if (strcasecmp(el, "Fee") == 0)
- {
- double fee;
- if (strtodouble2(attr[1], fee) == 0)
- td.tariffConf.fee = fee;
- return 0;
- }
-
- if (strcasecmp(el, "PassiveCost") == 0)
- {
- double pc;
- if (strtodouble2(attr[1], pc) == 0)
- td.tariffConf.passiveCost = pc;
- return 0;
- }
-
- if (strcasecmp(el, "Free") == 0)
- {
- double free;
- if (strtodouble2(attr[1], free) == 0)
- td.tariffConf.free = free;
- return 0;
- }
-
- if (strcasecmp(el, "TraffType") == 0)
- {
- td.tariffConf.traffType = TARIFF::StringToTraffType(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "Period") == 0)
- {
- td.tariffConf.period = TARIFF::StringToPeriod(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "ChangePolicy") == 0)
- {
- td.tariffConf.changePolicy = TARIFF::StringToChangePolicy(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "ChangePolicyTimeout") == 0)
- {
- int64_t policyTime = 0;
- if (str2x(attr[1], policyTime) == 0)
- td.tariffConf.changePolicyTimeout = (time_t)policyTime;
- return 0;
- }
- }
- return -1;
-}
-
-void CHG_TARIFF::CreateAnswer()
-{
- if (!td.tariffConf.name.data().empty())
- {
- TARIFF_DATA tariffData = td.GetData();
- if (m_tariffs.Chg(tariffData, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " Result=\"ok\"/>";
- else
- m_answer = "<" + m_tag + " Result=\"Change tariff error! " + m_tariffs.GetStrError() + "\"/>";
- }
- else
- m_answer = "<" + m_tag + " Result=\"Change tariff error!\"/>";
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_TARIFFS_H__
-#define __STG_SGCONFIG_PARSER_TARIFFS_H__
-
-#include "parser.h"
-
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-
-#include <string>
-
-class TARIFFS;
-class USERS;
-class ADMIN;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class GET_TARIFFS: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(const TARIFFS & tariffs) : m_tariffs(tariffs) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_TARIFFS(admin, m_tariffs); }
- static void Register(REGISTRY & registry, const TARIFFS & tariffs)
- { registry[ToLower(tag)] = new FACTORY(tariffs); }
- private:
- const TARIFFS & m_tariffs;
- };
-
- static const char * tag;
-
- GET_TARIFFS(const ADMIN & admin, const TARIFFS & tariffs)
- : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-
- private:
- const TARIFFS & m_tariffs;
-
- void CreateAnswer();
-};
-
-class ADD_TARIFF: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(TARIFFS & tariffs) : m_tariffs(tariffs) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_TARIFF(admin, m_tariffs); }
- static void Register(REGISTRY & registry, TARIFFS & tariffs)
- { registry[ToLower(tag)] = new FACTORY(tariffs); }
- private:
- TARIFFS & m_tariffs;
- };
-
- static const char * tag;
-
- ADD_TARIFF(const ADMIN & admin, TARIFFS & tariffs)
- : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string tariff;
- TARIFFS & m_tariffs;
-
- void CreateAnswer();
-};
-
-class DEL_TARIFF: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(TARIFFS & tariffs, const USERS & users) : m_tariffs(tariffs), m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_TARIFF(admin, m_users, m_tariffs); }
- static void Register(REGISTRY & registry, TARIFFS & tariffs, const USERS & users)
- { registry[ToLower(tag)] = new FACTORY(tariffs, users); }
- private:
- TARIFFS & m_tariffs;
- const USERS & m_users;
- };
-
- static const char * tag;
-
- DEL_TARIFF(const ADMIN & admin, const USERS & users, TARIFFS & tariffs)
- : BASE_PARSER(admin, tag), m_users(users), m_tariffs(tariffs) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- std::string tariff;
- const USERS & m_users;
- TARIFFS & m_tariffs;
-
- void CreateAnswer();
-};
-
-class CHG_TARIFF: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(TARIFFS & tariffs) : m_tariffs(tariffs) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_TARIFF(admin, m_tariffs); }
- static void Register(REGISTRY & registry, TARIFFS & tariffs)
- { registry[ToLower(tag)] = new FACTORY(tariffs); }
- private:
- TARIFFS & m_tariffs;
- };
-
- static const char * tag;
-
- CHG_TARIFF(const ADMIN & admin, TARIFFS & tariffs)
- : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- TARIFF_DATA_RES td;
- TARIFFS & m_tariffs;
-
- int CheckTariffData();
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "parser_user_info.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::USER_INFO;
-
-const char * USER_INFO::tag = "GetUserInfo";
-
-int USER_INFO::Start(void * /*data*/, const char *el, const char **attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- if (!attr[1])
- return -1;
-
- m_login = attr[1];
- return 0;
-}
-
-void USER_INFO::CreateAnswer()
-{
- CONST_USER_PTR u;
- if (m_users.FindByName(m_login, &u))
- {
- m_answer = "<UserInfo result=\"error\"/>";
- return;
- }
-
- m_answer = "<UserInfo lastAuthTime=\"" + x2str(u->GetAuthorizedModificationTime()) + "\"" +
- " lastDisconnectTime=\"" + x2str(u->GetConnectedModificationTime()) + "\"" +
- " connected=\"" + (u->GetConnected() ? "true" : "false") + "\"" +
- " lastDisconnectReason=\"" + u->GetLastDisconnectReason() + "\">";
- std::vector<std::string> list(u->GetAuthorizers());
- for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
- m_answer += "<Auth name=\"" + *it + "\"/>";
- m_answer += "</UserInfo>";
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_PARSER_USER_INFO_H__
-#define __STG_PARSER_USER_INFO_H__
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-class USERS;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class USER_INFO : public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(const USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new USER_INFO(admin, m_users); }
- static void Register(REGISTRY & registry, const USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- const USERS & m_users;
- };
-
- static const char * tag;
-
- USER_INFO(const ADMIN & admin, const USERS & users)
- : BASE_PARSER(admin, tag), m_users(users) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- const USERS & m_users;
- std::string m_login;
-
- void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_users.h"
-
-#include "stg/users.h"
-#include "stg/tariffs.h"
-#include "stg/user_property.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-
-#include <cstdio>
-#include <cassert>
-
-using STG::PARSER::GET_USERS;
-using STG::PARSER::GET_USER;
-using STG::PARSER::ADD_USER;
-using STG::PARSER::DEL_USER;
-using STG::PARSER::CHG_USER;
-using STG::PARSER::CHECK_USER;
-
-const char * GET_USERS::tag = "GetUsers";
-const char * GET_USER::tag = "GetUser";
-const char * ADD_USER::tag = "AddUser";
-const char * CHG_USER::tag = "SetUser";
-const char * DEL_USER::tag = "DelUser";
-const char * CHECK_USER::tag = "CheckUser";
-
-namespace
-{
-
-std::string UserToXML(const USER & user, bool loginInStart, bool showPass, time_t lastTime = 0)
-{
- std::string answer;
-
- if (loginInStart)
- answer += "<User login=\"" + user.GetLogin() + "\" result=\"ok\">";
- else
- answer += "<User result=\"ok\">";
-
- answer += "<Login value=\"" + user.GetLogin() + "\"/>";
-
- if (user.GetProperty().password.ModificationTime() > lastTime)
- {
- if (showPass)
- answer += "<Password value=\"" + user.GetProperty().password.Get() + "\" />";
- else
- answer += "<Password value=\"++++++\"/>";
- }
-
- if (user.GetProperty().cash.ModificationTime() > lastTime)
- answer += "<Cash value=\"" + x2str(user.GetProperty().cash.Get()) + "\"/>";
- if (user.GetProperty().freeMb.ModificationTime() > lastTime)
- answer += "<FreeMb value=\"" + x2str(user.GetProperty().freeMb.Get()) + "\"/>";
- if (user.GetProperty().credit.ModificationTime() > lastTime)
- answer += "<Credit value=\"" + x2str(user.GetProperty().credit.Get()) + "\"/>";
-
- if (user.GetProperty().nextTariff.Get() != "")
- {
- if (user.GetProperty().tariffName.ModificationTime() > lastTime ||
- user.GetProperty().nextTariff.ModificationTime() > lastTime)
- answer += "<Tariff value=\"" + user.GetProperty().tariffName.Get() + "/" + user.GetProperty().nextTariff.Get() + "\"/>";
- }
- else
- {
- if (user.GetProperty().tariffName.ModificationTime() > lastTime)
- answer += "<Tariff value=\"" + user.GetProperty().tariffName.Get() + "\"/>";
- }
-
- if (user.GetProperty().note.ModificationTime() > lastTime)
- answer += "<Note value=\"" + Encode12str(user.GetProperty().note) + "\"/>";
- if (user.GetProperty().phone.ModificationTime() > lastTime)
- answer += "<Phone value=\"" + Encode12str(user.GetProperty().phone) + "\"/>";
- if (user.GetProperty().address.ModificationTime() > lastTime)
- answer += "<Address value=\"" + Encode12str(user.GetProperty().address) + "\"/>";
- if (user.GetProperty().email.ModificationTime() > lastTime)
- answer += "<Email value=\"" + Encode12str(user.GetProperty().email) + "\"/>";
-
- std::vector<const USER_PROPERTY_LOGGED<std::string> *> userdata;
- userdata.push_back(user.GetProperty().userdata0.GetPointer());
- userdata.push_back(user.GetProperty().userdata1.GetPointer());
- userdata.push_back(user.GetProperty().userdata2.GetPointer());
- userdata.push_back(user.GetProperty().userdata3.GetPointer());
- userdata.push_back(user.GetProperty().userdata4.GetPointer());
- userdata.push_back(user.GetProperty().userdata5.GetPointer());
- userdata.push_back(user.GetProperty().userdata6.GetPointer());
- userdata.push_back(user.GetProperty().userdata7.GetPointer());
- userdata.push_back(user.GetProperty().userdata8.GetPointer());
- userdata.push_back(user.GetProperty().userdata9.GetPointer());
-
- for (size_t i = 0; i < userdata.size(); i++)
- if (userdata[i]->ModificationTime() > lastTime)
- answer += "<UserData" + x2str(i) + " value=\"" + Encode12str(userdata[i]->Get()) + "\" />";
-
- if (user.GetProperty().realName.ModificationTime() > lastTime)
- answer += "<Name value=\"" + Encode12str(user.GetProperty().realName) + "\"/>";
- if (user.GetProperty().group.ModificationTime() > lastTime)
- answer += "<Group value=\"" + Encode12str(user.GetProperty().group) + "\"/>";
- if (user.GetConnectedModificationTime() > lastTime)
- answer += std::string("<Status value=\"") + (user.GetConnected() ? "1" : "0") + "\"/>";
- if (user.GetProperty().alwaysOnline.ModificationTime() > lastTime)
- answer += std::string("<AOnline value=\"") + (user.GetProperty().alwaysOnline.Get() ? "1" : "0") + "\"/>";
- if (user.GetCurrIPModificationTime() > lastTime)
- answer += "<CurrIP value=\"" + inet_ntostring(user.GetCurrIP()) + "\"/>";
- if (user.GetPingTime() > lastTime)
- answer += "<PingTime value=\"" + x2str(user.GetPingTime()) + "\"/>";
- if (user.GetProperty().ips.ModificationTime() > lastTime)
- answer += "<IP value=\"" + user.GetProperty().ips.Get().GetIpStr() + "\"/>";
-
- answer += "<Traff";
- const DIR_TRAFF & upload(user.GetProperty().up.Get());
- const DIR_TRAFF & download(user.GetProperty().down.Get());
- if (user.GetProperty().up.ModificationTime() > lastTime)
- for (size_t j = 0; j < DIR_NUM; j++)
- answer += " MU" + x2str(j) + "=\"" + x2str(upload[j]) + "\"";
- if (user.GetProperty().down.ModificationTime() > lastTime)
- for (size_t j = 0; j < DIR_NUM; j++)
- answer += " MD" + x2str(j) + "=\"" + x2str(download[j]) + "\"";
- if (user.GetSessionUploadModificationTime() > lastTime)
- for (size_t j = 0; j < DIR_NUM; j++)
- answer += " SU" + x2str(j) + "=\"" + x2str(user.GetSessionUpload()[j]) + "\"";
- if (user.GetSessionDownloadModificationTime() > lastTime)
- for (size_t j = 0; j < DIR_NUM; j++)
- answer += " SD" + x2str(j) + "=\"" + x2str(user.GetSessionDownload()[j]) + "\"";
- answer += "/>";
-
- if (user.GetProperty().disabled.ModificationTime() > lastTime)
- answer += std::string("<Down value=\"") + (user.GetProperty().disabled.Get() ? "1" : "0") + "\"/>";
- if (user.GetProperty().disabledDetailStat.ModificationTime() > lastTime)
- answer += std::string("<DisableDetailStat value=\"") + (user.GetProperty().disabledDetailStat.Get() ? "1" : "0") + "\"/>";
- if (user.GetProperty().passive.ModificationTime() > lastTime)
- answer += std::string("<Passive value=\"") + (user.GetProperty().passive.Get() ? "1" : "0") + "\"/>";
- if (user.GetProperty().lastCashAdd.ModificationTime() > lastTime)
- answer += "<LastCash value=\"" + x2str(user.GetProperty().lastCashAdd.Get()) + "\"/>";
- if (user.GetProperty().lastCashAddTime.ModificationTime() > lastTime)
- answer += "<LastTimeCash value=\"" + x2str(user.GetProperty().lastCashAddTime.Get()) + "\"/>";
- if (user.GetProperty().lastActivityTime.ModificationTime() > lastTime)
- answer += "<LastActivityTime value=\"" + x2str(user.GetProperty().lastActivityTime.Get()) + "\"/>";
- if (user.GetProperty().creditExpire.ModificationTime() > lastTime)
- answer += "<CreditExpire value=\"" + x2str(user.GetProperty().creditExpire.Get()) + "\"/>";
-
- if (lastTime == 0)
- {
- answer += "<AuthorizedBy>";
- std::vector<std::string> list(user.GetAuthorizers());
- for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
- answer += "<Auth name=\"" + *it + "\"/>";
- answer += "</AuthorizedBy>";
- }
-
- answer += "</User>";
-
- return answer;
-}
-
-} // namespace anonymous
-
-int GET_USERS::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- {
- printfd(__FILE__, "Got wrong tag: '%s' instead of '%s'\n", el, m_tag.c_str());
- return -1;
- }
-
- while (attr && *attr && *(attr + 1))
- {
- if (strcasecmp(*attr, "LastUpdate") == 0)
- str2x(*(attr + 1), m_lastUserUpdateTime);
- ++attr;
- }
-
- return 0;
-}
-
-void GET_USERS::CreateAnswer()
-{
- int h = m_users.OpenSearch();
- assert(h);
-
- if (m_lastUserUpdateTime > 0)
- m_answer = "<Users LastUpdate=\"" + x2str(time(NULL)) + "\">";
- else
- m_answer = "<Users>";
-
- USER_PTR u;
-
- while (m_users.SearchNext(h, &u) == 0)
- m_answer += UserToXML(*u, true, m_currAdmin.GetPriv()->userConf || m_currAdmin.GetPriv()->userPasswd, m_lastUserUpdateTime);
-
- m_users.CloseSearch(h);
-
- m_answer += "</Users>";
-}
-
-int GET_USER::Start(void *, const char * el, const char ** attr)
-{
- if (strcasecmp(el, m_tag.c_str()) != 0)
- return -1;
-
- if (attr[1] == NULL)
- return -1;
-
- m_login = attr[1];
- return 0;
-}
-
-void GET_USER::CreateAnswer()
-{
- CONST_USER_PTR u;
-
- if (m_users.FindByName(m_login, &u))
- m_answer = "<User result=\"error\" reason=\"User not found.\"/>";
- else
- m_answer = UserToXML(*u, false, m_currAdmin.GetPriv()->userConf || m_currAdmin.GetPriv()->userPasswd);
-}
-
-int ADD_USER::Start(void *, const char * el, const char ** attr)
-{
- m_depth++;
-
- if (m_depth == 1)
- {
- if (strcasecmp(el, m_tag.c_str()) == 0)
- return 0;
- }
- else
- {
- if (strcasecmp(el, "login") == 0)
- {
- m_login = attr[1];
- return 0;
- }
- }
- return -1;
-}
-
-void ADD_USER::CreateAnswer()
-{
- if (m_users.Exists(m_login))
- m_answer = "<" + m_tag + " result=\"error\" reason=\"User '" + m_login + "' exists.\"/>";
- else if (m_users.Add(m_login, &m_currAdmin) == 0)
- m_answer = "<" + m_tag + " result=\"ok\"/>";
- else
- m_answer = "<" + m_tag + " result=\"error\" reason=\"Access denied\"/>";
-}
-
-int CHG_USER::Start(void *, const char * el, const char ** attr)
-{
- m_depth++;
-
- if (m_depth == 1)
- {
- if (strcasecmp(el, m_tag.c_str()) == 0)
- return 0;
- }
- else
- {
- if (strcasecmp(el, "login") == 0)
- {
- m_login = attr[1];
- return 0;
- }
-
- if (strcasecmp(el, "ip") == 0)
- {
- m_ucr.ips = StrToIPS(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "password") == 0)
- {
- m_ucr.password = attr[1];
- return 0;
- }
-
- if (strcasecmp(el, "address") == 0)
- {
- m_ucr.address = Decode21str(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "aonline") == 0)
- {
- m_ucr.alwaysOnline = (*(attr[1]) != '0');
- return 0;
- }
-
- if (strcasecmp(el, "cash") == 0)
- {
- if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
- m_cashMsg = Decode21str(attr[3]);
-
- double cash = 0;
- if (strtodouble2(attr[1], cash) == 0)
- m_usr.cash = cash;
-
- m_cashMustBeAdded = (strcasecmp(attr[0], "add") == 0);
-
- return 0;
- }
-
- if (strcasecmp(el, "CreditExpire") == 0)
- {
- long int creditExpire = 0;
- if (str2x(attr[1], creditExpire) == 0)
- m_ucr.creditExpire = (time_t)creditExpire;
-
- return 0;
- }
-
- if (strcasecmp(el, "credit") == 0)
- {
- double credit = 0;
- if (strtodouble2(attr[1], credit) == 0)
- m_ucr.credit = credit;
- return 0;
- }
-
- if (strcasecmp(el, "freemb") == 0)
- {
- double freeMb = 0;
- if (strtodouble2(attr[1], freeMb) == 0)
- m_usr.freeMb = freeMb;
- return 0;
- }
-
- if (strcasecmp(el, "down") == 0)
- {
- int down = 0;
- if (str2x(attr[1], down) == 0)
- m_ucr.disabled = down;
- return 0;
- }
-
- if (strcasecmp(el, "DisableDetailStat") == 0)
- {
- int disabledDetailStat = 0;
- if (str2x(attr[1], disabledDetailStat) == 0)
- m_ucr.disabledDetailStat = disabledDetailStat;
- return 0;
- }
-
- if (strcasecmp(el, "email") == 0)
- {
- m_ucr.email = Decode21str(attr[1]);
- return 0;
- }
-
- for (int i = 0; i < USERDATA_NUM; i++)
- {
- char name[15];
- sprintf(name, "userdata%d", i);
- if (strcasecmp(el, name) == 0)
- {
- m_ucr.userdata[i] = Decode21str(attr[1]);
- return 0;
- }
- }
-
- if (strcasecmp(el, "group") == 0)
- {
- m_ucr.group = Decode21str(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "note") == 0)
- {
- m_ucr.note = Decode21str(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "passive") == 0)
- {
- int passive = 0;
- if (str2x(attr[1], passive) == 0)
- m_ucr.passive = passive;
- return 0;
- }
-
- if (strcasecmp(el, "phone") == 0)
- {
- m_ucr.phone = Decode21str(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "Name") == 0)
- {
- m_ucr.realName = Decode21str(attr[1]);
- return 0;
- }
-
- if (strcasecmp(el, "traff") == 0)
- {
- int j = 0;
- while (attr[j])
- {
- int dir = attr[j][2] - '0';
-
- if (strncasecmp(attr[j], "md", 2) == 0)
- {
- uint64_t t = 0;
- str2x(attr[j + 1], t);
- m_downr[dir] = t;
- }
- if (strncasecmp(attr[j], "mu", 2) == 0)
- {
- uint64_t t = 0;
- str2x(attr[j + 1], t);
- m_upr[dir] = t;
- }
- j += 2;
- }
- return 0;
- }
-
- if (strcasecmp(el, "tariff") == 0)
- {
- if (strcasecmp(attr[0], "now") == 0)
- m_ucr.tariffName = attr[1];
-
- if (strcasecmp(attr[0], "delayed") == 0)
- m_ucr.nextTariff = attr[1];
-
- return 0;
- }
- }
- return -1;
-}
-
-void CHG_USER::CreateAnswer()
-{
- if (ApplyChanges() == 0)
- m_answer = "<" + m_tag + " result=\"ok\"/>";
- else
- m_answer = "<" + m_tag + " result=\"error\"/>";
-}
-
-int CHG_USER::ApplyChanges()
-{
- printfd(__FILE__, "PARSER_CHG_USER::ApplyChanges()\n");
- USER_PTR u;
-
- if (m_users.FindByName(m_login, &u))
- return -1;
-
- bool check = false;
- bool alwaysOnline = u->GetProperty().alwaysOnline;
- if (!m_ucr.alwaysOnline.empty())
- {
- check = true;
- alwaysOnline = m_ucr.alwaysOnline.const_data();
- }
- bool onlyOneIP = u->GetProperty().ips.ConstData().OnlyOneIP();
- if (!m_ucr.ips.empty())
- {
- check = true;
- onlyOneIP = m_ucr.ips.const_data().OnlyOneIP();
- }
-
- if (check && alwaysOnline && !onlyOneIP)
- {
- printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
- GetStgLogger()("%s Requested change leads to a forbidden state: AlwaysOnline with multiple IP's", m_currAdmin.GetLogStr().c_str());
- return -1;
- }
-
- for (size_t i = 0; i < m_ucr.ips.const_data().Count(); ++i)
- {
- CONST_USER_PTR user;
- uint32_t ip = m_ucr.ips.const_data().operator[](i).ip;
- if (m_users.IsIPInUse(ip, m_login, &user))
- {
- printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
- GetStgLogger()("%s trying to assign an IP %s to '%s' that is currently in use by '%s'", m_currAdmin.GetLogStr().c_str(), inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
- return -1;
- }
- }
-
- if (!m_ucr.ips.empty())
- if (!u->GetProperty().ips.Set(m_ucr.ips.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.alwaysOnline.empty())
- if (!u->GetProperty().alwaysOnline.Set(m_ucr.alwaysOnline.const_data(),
- &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.address.empty())
- if (!u->GetProperty().address.Set(m_ucr.address.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.creditExpire.empty())
- if (!u->GetProperty().creditExpire.Set(m_ucr.creditExpire.const_data(),
- &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.credit.empty())
- if (!u->GetProperty().credit.Set(m_ucr.credit.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_usr.freeMb.empty())
- if (!u->GetProperty().freeMb.Set(m_usr.freeMb.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.disabled.empty())
- if (!u->GetProperty().disabled.Set(m_ucr.disabled.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.disabledDetailStat.empty())
- if (!u->GetProperty().disabledDetailStat.Set(m_ucr.disabledDetailStat.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.email.empty())
- if (!u->GetProperty().email.Set(m_ucr.email.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.group.empty())
- if (!u->GetProperty().group.Set(m_ucr.group.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.note.empty())
- if (!u->GetProperty().note.Set(m_ucr.note.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- std::vector<USER_PROPERTY_LOGGED<std::string> *> userdata;
- userdata.push_back(u->GetProperty().userdata0.GetPointer());
- userdata.push_back(u->GetProperty().userdata1.GetPointer());
- userdata.push_back(u->GetProperty().userdata2.GetPointer());
- userdata.push_back(u->GetProperty().userdata3.GetPointer());
- userdata.push_back(u->GetProperty().userdata4.GetPointer());
- userdata.push_back(u->GetProperty().userdata5.GetPointer());
- userdata.push_back(u->GetProperty().userdata6.GetPointer());
- userdata.push_back(u->GetProperty().userdata7.GetPointer());
- userdata.push_back(u->GetProperty().userdata8.GetPointer());
- userdata.push_back(u->GetProperty().userdata9.GetPointer());
-
- for (int i = 0; i < (int)userdata.size(); i++)
- if (!m_ucr.userdata[i].empty())
- if(!userdata[i]->Set(m_ucr.userdata[i].const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.passive.empty())
- if (!u->GetProperty().passive.Set(m_ucr.passive.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.password.empty())
- if (!u->GetProperty().password.Set(m_ucr.password.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.phone.empty())
- if (!u->GetProperty().phone.Set(m_ucr.phone.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_ucr.realName.empty())
- if (!u->GetProperty().realName.Set(m_ucr.realName.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (!m_usr.cash.empty())
- {
- if (m_cashMustBeAdded)
- {
- if (!u->GetProperty().cash.Set(m_usr.cash.const_data() + u->GetProperty().cash,
- &m_currAdmin,
- m_login,
- &m_store,
- m_cashMsg))
- return -1;
- }
- else
- {
- if (!u->GetProperty().cash.Set(m_usr.cash.const_data(), &m_currAdmin, m_login, &m_store, m_cashMsg))
- return -1;
- }
- }
-
- if (!m_ucr.tariffName.empty())
- {
- const TARIFF * newTariff = m_tariffs.FindByName(m_ucr.tariffName.const_data());
- if (newTariff)
- {
- const TARIFF * tariff = u->GetTariff();
- std::string message = tariff->TariffChangeIsAllowed(*newTariff, stgTime);
- if (message.empty())
- {
- if (!u->GetProperty().tariffName.Set(m_ucr.tariffName.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
- u->ResetNextTariff();
- }
- else
- {
- GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
- }
- }
- else
- {
- //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
- return -1;
- }
- }
-
- if (!m_ucr.nextTariff.empty())
- {
- if (m_tariffs.FindByName(m_ucr.nextTariff.const_data()))
- {
- if (!u->GetProperty().nextTariff.Set(m_ucr.nextTariff.const_data(), &m_currAdmin, m_login, &m_store))
- return -1;
- }
- else
- {
- //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
- return -1;
- }
- }
-
- DIR_TRAFF up = u->GetProperty().up;
- DIR_TRAFF down = u->GetProperty().down;
- int upCount = 0;
- int downCount = 0;
- for (int i = 0; i < DIR_NUM; i++)
- {
- if (!m_upr[i].empty())
- {
- up[i] = m_upr[i].data();
- upCount++;
- }
- if (!m_downr[i].empty())
- {
- down[i] = m_downr[i].data();
- downCount++;
- }
- }
-
- if (upCount)
- if (!u->GetProperty().up.Set(up, &m_currAdmin, m_login, &m_store))
- return -1;
-
- if (downCount)
- if (!u->GetProperty().down.Set(down, &m_currAdmin, m_login, &m_store))
- return -1;
-
- u->WriteConf();
- u->WriteStat();
-
- return 0;
-}
-
-int DEL_USER::Start(void *, const char *el, const char **attr)
-{
- res = 0;
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- if (attr[0] == NULL || attr[1] == NULL)
- {
- //CreateAnswer("Parameters error!");
- CreateAnswer();
- return 0;
- }
-
- if (m_users.FindByName(attr[1], &u))
- {
- res = 1;
- CreateAnswer();
- return 0;
- }
- CreateAnswer();
- return 0;
- }
- return -1;
-}
-
-int DEL_USER::End(void *, const char *el)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- if (!res)
- m_users.Del(u->GetLogin(), &m_currAdmin);
-
- return 0;
- }
- return -1;
-}
-
-void DEL_USER::CreateAnswer()
-{
- if (res)
- m_answer = "<" + m_tag + " value=\"error\" reason=\"User not found\"/>";
- else
- m_answer = "<" + m_tag + " value=\"ok\"/>";
-}
-
-int CHECK_USER::Start(void *, const char *el, const char **attr)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- {
- if (attr[0] == NULL || attr[1] == NULL ||
- attr[2] == NULL || attr[3] == NULL)
- {
- CreateAnswer("Invalid parameters.");
- printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
- return 0;
- }
-
- CONST_USER_PTR user;
- if (m_users.FindByName(attr[1], &user))
- {
- CreateAnswer("User not found.");
- printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
- return 0;
- }
-
- if (strcmp(user->GetProperty().password.Get().c_str(), attr[3]))
- {
- CreateAnswer("Wrong password.");
- printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
- return 0;
- }
-
- CreateAnswer(NULL);
- return 0;
- }
- return -1;
-}
-
-int CHECK_USER::End(void *, const char *el)
-{
- if (strcasecmp(el, m_tag.c_str()) == 0)
- return 0;
- return -1;
-}
-
-void CHECK_USER::CreateAnswer(const char * error)
-{
- if (error)
- m_answer = "<" + m_tag + " value=\"Err\" reason=\"" + error + "\"/>";
- else
- m_answer = "<" + m_tag + " value=\"Ok\"/>";
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_PARSER_USERS_H__
-#define __STG_SGCONFIG_PARSER_USERS_H__
-
-#include "parser.h"
-
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/common.h"
-#include "stg/resetable.h"
-
-#include <string>
-
-class USERS;
-class USER;
-class TARIFFS;
-class ADMIN;
-class STORE;
-
-namespace STG
-{
-namespace PARSER
-{
-
-class GET_USERS: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_USERS(admin, m_users); }
- static void Register(REGISTRY & registry, USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- USERS & m_users;
- };
-
- static const char * tag;
-
- GET_USERS(const ADMIN & admin, USERS & users)
- : BASE_PARSER(admin, tag), m_users(users),
- m_lastUserUpdateTime(0) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- USERS & m_users;
- time_t m_lastUserUpdateTime;
-
- void CreateAnswer();
-};
-
-class GET_USER: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(const USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_USER(admin, m_users); }
- static void Register(REGISTRY & registry, const USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- const USERS & m_users;
- };
-
- static const char * tag;
-
- GET_USER(const ADMIN & admin, const USERS & users)
- : BASE_PARSER(admin, tag), m_users(users) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- const USERS & m_users;
- std::string m_login;
-
- void CreateAnswer();
-};
-
-class ADD_USER: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_USER(admin, m_users); }
- static void Register(REGISTRY & registry, USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- USERS & m_users;
- };
-
- static const char * tag;
-
- ADD_USER(const ADMIN & admin, USERS & users)
- : BASE_PARSER(admin, tag), m_users(users) {}
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- USERS & m_users;
- std::string m_login;
-
- void CreateAnswer();
-};
-
-class CHG_USER: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- FACTORY(USERS & users, STORE & store, const TARIFFS & tariffs)
- : m_users(users), m_store(store), m_tariffs(tariffs)
- {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
- static void Register(REGISTRY & registry, USERS & users, STORE & store, const TARIFFS & tariffs)
- { registry[ToLower(tag)] = new FACTORY(users, store, tariffs); }
- private:
- USERS & m_users;
- STORE & m_store;
- const TARIFFS & m_tariffs;
- };
-
- static const char * tag;
-
- CHG_USER(const ADMIN & admin, USERS & users,
- STORE & store, const TARIFFS & tariffs)
- : BASE_PARSER(admin, tag),
- m_users(users),
- m_store(store),
- m_tariffs(tariffs),
- m_cashMustBeAdded(false) {}
-
- int Start(void * data, const char * el, const char ** attr);
-
- private:
- USERS & m_users;
- STORE & m_store;
- const TARIFFS & m_tariffs;
- USER_STAT_RES m_usr;
- USER_CONF_RES m_ucr;
- RESETABLE<uint64_t> m_upr[DIR_NUM];
- RESETABLE<uint64_t> m_downr[DIR_NUM];
- std::string m_cashMsg;
- std::string m_login;
- bool m_cashMustBeAdded;
-
- int ApplyChanges();
- void CreateAnswer();
-};
-
-class DEL_USER: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_USER(admin, m_users); }
- static void Register(REGISTRY & registry, USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- USERS & m_users;
- };
-
- static const char * tag;
-
- DEL_USER(const ADMIN & admin, USERS & users)
- : BASE_PARSER(admin, tag), m_users(users), res(0), u(NULL) {}
- int Start(void * data, const char * el, const char ** attr);
- int End(void * data, const char * el);
-
- private:
- USERS & m_users;
- int res;
- USER * u;
-
- void CreateAnswer();
-};
-
-class CHECK_USER: public BASE_PARSER
-{
- public:
- class FACTORY : public BASE_PARSER::FACTORY
- {
- public:
- explicit FACTORY(const USERS & users) : m_users(users) {}
- virtual BASE_PARSER * create(const ADMIN & admin) { return new CHECK_USER(admin, m_users); }
- static void Register(REGISTRY & registry, const USERS & users)
- { registry[ToLower(tag)] = new FACTORY(users); }
- private:
- const USERS & m_users;
- };
-
- static const char * tag;
-
- CHECK_USER(const ADMIN & admin, const USERS & users)
- : BASE_PARSER(admin, tag), m_users(users) {}
- int Start(void * data, const char * el, const char ** attr);
- int End(void * data, const char * el);
-
- private:
- const USERS & m_users;
-
- void CreateAnswer(const char * error);
- void CreateAnswer() {} // dummy
-};
-
-} // namespace PARSER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#include "stgconfig.h"
-
-#include "stg/plugin_creator.h"
-#include "stg/common.h"
-
-#include <algorithm>
-#include <csignal>
-#include <cstring>
-#include <cerrno>
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-static PLUGIN_CREATOR<STG_CONFIG> stgc;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-bool STG_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
- PARAM_VALUE pv;
- std::vector<PARAM_VALUE>::const_iterator pvi;
- ///////////////////////////
- pv.param = "Port";
- pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
- if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Port\' is not found.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return false;
- }
- int p;
- if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
- {
- errorStr = "Parameter \'Port\' should be an integral value in range (2, 65535). Actual value: '" + pvi->value[0] + "'.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return false;
- }
- m_port = static_cast<uint16_t>(p);
-
- pv.param = "BindAddress";
- pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
- if (pvi != s.moduleParams.end() && !pvi->value.empty())
- m_bindAddress = pvi->value[0];
-
- return true;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-extern "C" PLUGIN * GetPlugin()
-{
-return stgc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-STG_CONFIG::STG_CONFIG()
- : nonstop(false),
- isRunning(false),
- logger(GetPluginLogger(GetStgLogger(), "conf_sg")),
- config(logger)
-{
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::ParseSettings()
-{
- if (stgConfigSettings.ParseSettings(settings))
- return 0;
- errorStr = stgConfigSettings.GetStrError();
- return -1;
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::Start()
-{
- if (isRunning)
- return 0;
-
- nonstop = true;
-
- config.SetPort(stgConfigSettings.GetPort());
- config.SetBindAddress(stgConfigSettings.GetBindAddress());
-
- if (config.Prepare())
- {
- errorStr = config.GetStrError();
- return -1;
- }
-
- if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = std::string("Cannot create thread: '") + strerror(errno) + "'.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- logger(errorStr);
- return -1;
- }
-
- return 0;
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::Stop()
-{
- if (!isRunning)
- return 0;
-
- config.Stop();
-
- //5 seconds to thread stops itself
- for (size_t i = 0; i < 25; ++i)
- {
- if (!isRunning)
- break;
-
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
-
- if (isRunning)
- return -1;
-
- return 0;
-}
-//-----------------------------------------------------------------------------
-void * STG_CONFIG::Run(void * d)
-{
- sigset_t signalSet;
- sigfillset(&signalSet);
- pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
- STG_CONFIG & stgConf = *static_cast<STG_CONFIG *>(d);
- stgConf.isRunning = true;
-
- stgConf.config.Run();
-
- stgConf.isRunning = false;
-
- return NULL;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#ifndef STGCONFIG_H
-#define STGCONFIG_H
-
-#include "configproto.h"
-
-#include "stg/plugin.h"
-#include "stg/logger.h"
-
-#include <string>
-
-#include <pthread.h>
-
-class STG_CONFIG_SETTINGS
-{
- public:
- STG_CONFIG_SETTINGS() : m_port(0), m_bindAddress("0.0.0.0") {}
- virtual ~STG_CONFIG_SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- bool ParseSettings(const MODULE_SETTINGS & s);
- uint16_t GetPort() const { return m_port; }
- const std::string & GetBindAddress() const { return m_bindAddress; }
- private:
- std::string errorStr;
- uint16_t m_port;
- std::string m_bindAddress;
-};
-
-class STG_CONFIG : public PLUGIN
-{
- public:
- STG_CONFIG();
-
- void SetUsers(USERS * users) { config.SetUsers(users); }
- void SetTariffs(TARIFFS * tariffs) { config.SetTariffs(tariffs); }
- void SetAdmins(ADMINS * admins) { config.SetAdmins(admins); }
- void SetServices(SERVICES * services) { config.SetServices(services); }
- void SetCorporations(CORPORATIONS * corporations) { config.SetCorporations( corporations); }
- void SetStore(STORE * store) { config.SetStore(store); }
- void SetStgSettings(const SETTINGS * s) { config.SetSettings(s); }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return isRunning; }
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return "Stg Configurator v. 2.0"; }
- uint16_t GetStartPosition() const { return 20; }
- uint16_t GetStopPosition() const { return 20; }
-
- private:
- STG_CONFIG(const STG_CONFIG & rvalue);
- STG_CONFIG & operator=(const STG_CONFIG & rvalue);
-
- static void * Run(void *);
-
- mutable std::string errorStr;
- STG_CONFIG_SETTINGS stgConfigSettings;
- pthread_t thread;
- bool nonstop;
- bool isRunning;
- PLUGIN_LOGGER logger;
- CONFIGPROTO config;
- MODULE_SETTINGS settings;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.11 2008/12/04 17:21:14 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-LIBS += $(LIB_THREAD)
-
-PROG = mod_ping.so
-
-SRCS = ./ping.cpp
-
-STGLIBS = pinger \
- common \
- logger \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-#include "ping.h"
-
-#include "stg/user.h"
-#include "stg/locker.h"
-#include "stg/user_property.h"
-#include "stg/plugin_creator.h"
-
-#include <cstdio>
-#include <cassert>
-#include <csignal>
-#include <ctime>
-#include <algorithm>
-
-namespace
-{
-PLUGIN_CREATOR<PING> pc;
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-template <typename varType>
-class HAS_USER: public std::binary_function<varType, USER_PTR, bool>
-{
-public:
- explicit HAS_USER(const USER_PTR & u) : user(u) {}
- bool operator()(varType notifier) const
- {
- return notifier.GetUser() == user;
- }
-private:
- const USER_PTR & user;
-};
-}
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return pc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-int PING_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-PARAM_VALUE pv;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-
-pv.param = "PingDelay";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'PingDelay\' not found.";
- printfd(__FILE__, "Parameter 'PingDelay' not found\n");
- return -1;
- }
-if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
- {
- errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
- printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-PING::PING()
- : users(NULL),
- nonstop(false),
- isRunning(false),
- onAddUserNotifier(*this),
- onDelUserNotifier(*this),
- logger(GetPluginLogger(GetStgLogger(), "ping"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-PING::~PING()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int PING::ParseSettings()
-{
-int ret = pingSettings.ParseSettings(settings);
-if (ret)
- errorStr = pingSettings.GetStrError();
-return ret;
-}
-//-----------------------------------------------------------------------------
-int PING::Start()
-{
-GetUsers();
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-nonstop = true;
-
-pinger.SetDelayTime(pingSettings.GetPingDelay());
-pinger.Start();
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot start thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot start thread\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PING::Stop()
-{
-STG_LOCKER lock(&mutex);
-
-if (!isRunning)
- return 0;
-
-pinger.Stop();
-nonstop = false;
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (int i = 0; i < 25; i++)
- {
- if (!isRunning)
- break;
-
- nanosleep(&ts, NULL);
- }
-
-users->DelNotifierUserAdd(&onAddUserNotifier);
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-std::list<USER_PTR>::iterator users_iter;
-users_iter = usersList.begin();
-while (users_iter != usersList.end())
- {
- UnSetUserNotifiers(*users_iter);
- ++users_iter;
- }
-
-if (isRunning)
- return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool PING::IsRunning()
-{
-return isRunning;
-}
-//-----------------------------------------------------------------------------
-void * PING::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-PING * ping = static_cast<PING *>(d);
-ping->isRunning = true;
-
-long delay = (10000000 * ping->pingSettings.GetPingDelay()) / 3 + 50000000;
-
-while (ping->nonstop)
- {
- std::list<USER_PTR>::iterator iter = ping->usersList.begin();
- {
- STG_LOCKER lock(&ping->mutex);
- while (iter != ping->usersList.end())
- {
- if ((*iter)->GetProperty().ips.ConstData().OnlyOneIP())
- {
- uint32_t ip = (*iter)->GetProperty().ips.ConstData()[0].ip;
- time_t t;
- if (ping->pinger.GetIPTime(ip, &t) == 0)
- {
- if (t)
- (*iter)->UpdatePingTime(t);
- }
- }
- else
- {
- uint32_t ip = (*iter)->GetCurrIP();
- if (ip)
- {
- time_t t;
- if (ping->pinger.GetIPTime(ip, &t) == 0)
- {
- if (t)
- (*iter)->UpdatePingTime(t);
- }
- }
- }
- ++iter;
- }
- }
- struct timespec ts = {delay / 1000000000, delay % 1000000000};
- for (int i = 0; i < 100; i++)
- {
- if (ping->nonstop)
- {
- nanosleep(&ts, NULL);
- }
- }
- }
-
-ping->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void PING::SetUserNotifiers(USER_PTR u)
-{
-CHG_CURRIP_NOTIFIER_PING ChgCurrIPNotifier(*this, u);
-CHG_IPS_NOTIFIER_PING ChgIPNotifier(*this, u);
-
-ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
-ChgIPNotifierList.push_front(ChgIPNotifier);
-
-u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
-u->GetProperty().ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
-}
-//-----------------------------------------------------------------------------
-void PING::UnSetUserNotifiers(USER_PTR u)
-{
-// --- CurrIP ---
-HAS_USER<CHG_CURRIP_NOTIFIER_PING> IsContainsUserCurrIP(u);
-HAS_USER<CHG_IPS_NOTIFIER_PING> IsContainsUserIP(u);
-
-std::list<CHG_CURRIP_NOTIFIER_PING>::iterator currIPter;
-std::list<CHG_IPS_NOTIFIER_PING>::iterator IPIter;
-
-currIPter = find_if(ChgCurrIPNotifierList.begin(),
- ChgCurrIPNotifierList.end(),
- IsContainsUserCurrIP);
-
-if (currIPter != ChgCurrIPNotifierList.end())
- {
- currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
- ChgCurrIPNotifierList.erase(currIPter);
- }
-// --- CurrIP end ---
-
-// --- IP ---
-IPIter = find_if(ChgIPNotifierList.begin(),
- ChgIPNotifierList.end(),
- IsContainsUserIP);
-
-if (IPIter != ChgIPNotifierList.end())
- {
- IPIter->GetUser()->GetProperty().ips.DelAfterNotifier(&(*IPIter));
- ChgIPNotifierList.erase(IPIter);
- }
-// --- IP end ---
-}
-//-----------------------------------------------------------------------------
-void PING::GetUsers()
-{
-STG_LOCKER lock(&mutex);
-
-USER_PTR u;
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (users->SearchNext(h, &u) == 0)
- {
- usersList.push_back(u);
- SetUserNotifiers(u);
- if (u->GetProperty().ips.ConstData().OnlyOneIP())
- {
- pinger.AddIP(u->GetProperty().ips.ConstData()[0].ip);
- }
- else
- {
- uint32_t ip = u->GetCurrIP();
- if (ip)
- pinger.AddIP(ip);
- }
- }
-
-users->CloseSearch(h);
-}
-//-----------------------------------------------------------------------------
-void PING::AddUser(USER_PTR u)
-{
-STG_LOCKER lock(&mutex);
-
-SetUserNotifiers(u);
-usersList.push_back(u);
-}
-//-----------------------------------------------------------------------------
-void PING::DelUser(USER_PTR u)
-{
-STG_LOCKER lock(&mutex);
-
-UnSetUserNotifiers(u);
-
-std::list<USER_PTR>::iterator users_iter;
-users_iter = usersList.begin();
-
-while (users_iter != usersList.end())
- {
- if (u == *users_iter)
- {
- usersList.erase(users_iter);
- break;
- }
- ++users_iter;
- }
-}
-//-----------------------------------------------------------------------------
-void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
-{
-ping.pinger.DelIP(oldIP);
-if (newIP)
- ping.pinger.AddIP(newIP);
-}
-//-----------------------------------------------------------------------------
-void CHG_IPS_NOTIFIER_PING::Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS)
-{
-if (oldIPS.OnlyOneIP())
- ping.pinger.DelIP(oldIPS[0].ip);
-
-if (newIPS.OnlyOneIP())
- ping.pinger.AddIP(newIPS[0].ip);
-}
-//-----------------------------------------------------------------------------
-void ADD_USER_NONIFIER_PING::Notify(const USER_PTR & user)
-{
-ping.AddUser(user);
-}
-//-----------------------------------------------------------------------------
-void DEL_USER_NONIFIER_PING::Notify(const USER_PTR & user)
-{
-ping.DelUser(user);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
- /*
- $Revision: 1.16 $
- $Date: 2009/06/23 11:32:28 $
- $Author: faust $
- */
-
-#ifndef PING_H
-#define PING_H
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/pinger.h"
-#include "stg/users.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <list>
-
-#include <pthread.h>
-
-extern "C" PLUGIN * GetPlugin();
-
-class PING;
-class USER;
-class SETTINGS;
-//-----------------------------------------------------------------------------*/
-class CHG_CURRIP_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<uint32_t> {
-public:
- CHG_CURRIP_NOTIFIER_PING(const PING & p, USER_PTR u)
- : user(u), ping(p) {}
- void Notify(const uint32_t & oldIP, const uint32_t & newIP);
- USER_PTR GetUser() const { return user; }
-
-private:
- CHG_CURRIP_NOTIFIER_PING & operator=(const CHG_CURRIP_NOTIFIER_PING &);
-
- USER_PTR user;
- const PING & ping;
-};
-//-----------------------------------------------------------------------------
-class CHG_IPS_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<USER_IPS> {
-public:
- CHG_IPS_NOTIFIER_PING(const PING & p, USER_PTR u)
- : user(u), ping(p) {}
- void Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS);
- USER_PTR GetUser() const { return user; }
-
-private:
- CHG_IPS_NOTIFIER_PING & operator=(const CHG_IPS_NOTIFIER_PING &);
-
- USER_PTR user;
- const PING & ping;
-};
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER_PING: public NOTIFIER_BASE<USER_PTR> {
-public:
- explicit ADD_USER_NONIFIER_PING(PING & p) : ping(p) {}
- void Notify(const USER_PTR & user);
-
-private:
- ADD_USER_NONIFIER_PING(const ADD_USER_NONIFIER_PING &);
- ADD_USER_NONIFIER_PING & operator=(const ADD_USER_NONIFIER_PING &);
-
- PING & ping;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER_PING: public NOTIFIER_BASE<USER_PTR> {
-public:
- explicit DEL_USER_NONIFIER_PING(PING & p) : ping(p) {}
- void Notify(const USER_PTR & user);
-
-private:
- DEL_USER_NONIFIER_PING(const DEL_USER_NONIFIER_PING &);
- DEL_USER_NONIFIER_PING & operator=(const DEL_USER_NONIFIER_PING &);
-
- PING & ping;
-};
-//-----------------------------------------------------------------------------
-class PING_SETTINGS {
-public:
- PING_SETTINGS() : pingDelay(0) {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- int GetPingDelay() const { return pingDelay; }
-private:
- int pingDelay;
- mutable std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-class PING : public PLUGIN {
-friend class CHG_CURRIP_NOTIFIER_PING;
-friend class CHG_IPS_NOTIFIER_PING;
-public:
- PING();
- virtual ~PING();
-
- void SetUsers(USERS * u) { users = u; }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning();
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return "Pinger v.1.01"; }
- uint16_t GetStartPosition() const { return 10; }
- uint16_t GetStopPosition() const { return 10; }
-
- void AddUser(USER_PTR u);
- void DelUser(USER_PTR u);
-
-private:
- explicit PING(const PING & rvalue);
- PING & operator=(const PING & rvalue);
-
- void GetUsers();
- void SetUserNotifiers(USER_PTR u);
- void UnSetUserNotifiers(USER_PTR u);
- static void * Run(void * d);
-
- mutable std::string errorStr;
- PING_SETTINGS pingSettings;
- MODULE_SETTINGS settings;
- USERS * users;
- std::list<USER_PTR> usersList;
-
- pthread_t thread;
- pthread_mutex_t mutex;
- bool nonstop;
- bool isRunning;
- mutable STG_PINGER pinger;
-
- std::list<CHG_CURRIP_NOTIFIER_PING> ChgCurrIPNotifierList;
- std::list<CHG_IPS_NOTIFIER_PING> ChgIPNotifierList;
-
- ADD_USER_NONIFIER_PING onAddUserNotifier;
- DEL_USER_NONIFIER_PING onDelUserNotifier;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.3 2010/04/26 12:44:42 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-LIBS += $(LIB_THREAD) -lyajl
-
-PROG = mod_radius.so
-
-SRCS = radius.cpp \
- config.cpp \
- conn.cpp
-
-STGLIBS = common \
- crypto \
- logger \
- scriptexecuter \
- json
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "config.h"
-
-#include "stg/user.h"
-#include "stg/common.h"
-
-#include <vector>
-#include <stdexcept>
-
-#include <strings.h> // strncasecmp
-
-using STG::Config;
-
-namespace
-{
-
-struct ParserError : public std::runtime_error
-{
- ParserError(const std::string& message)
- : runtime_error("Config is not valid. " + message),
- position(0),
- error(message)
- {}
- ParserError(size_t pos, const std::string& message)
- : runtime_error("Parsing error at position " + x2str(pos) + ". " + message),
- position(pos),
- error(message)
- {}
- virtual ~ParserError() throw() {}
-
- size_t position;
- std::string error;
-};
-
-size_t skipSpaces(const std::string& value, size_t start)
-{
- while (start < value.length() && std::isspace(value[start]))
- ++start;
- return start;
-}
-
-size_t checkChar(const std::string& value, size_t start, char ch)
-{
- if (start >= value.length())
- throw ParserError(start, "Unexpected end of string. Expected '" + std::string(1, ch) + "'.");
- if (value[start] != ch)
- throw ParserError(start, "Expected '" + std::string(1, ch) + "', got '" + std::string(1, value[start]) + "'.");
- return start + 1;
-}
-
-std::pair<size_t, std::string> readString(const std::string& value, size_t start)
-{
- std::string dest;
- while (start < value.length() && !std::isspace(value[start]) &&
- value[start] != ',' && value[start] != '(' && value[start] != ')')
- dest.push_back(value[start++]);
- if (dest.empty()) {
- if (start == value.length())
- throw ParserError(start, "Unexpected end of string. Expected string.");
- else
- throw ParserError(start, "Unexpected whitespace. Expected string.");
- }
- return std::make_pair(start, dest);
-}
-
-Config::Pairs toPairs(const std::vector<std::string>& values)
-{
- if (values.empty())
- return Config::Pairs();
- std::string value(values[0]);
- Config::Pairs res;
- size_t start = 0;
- while (start < value.size()) {
- Config::Pair pair;
- start = skipSpaces(value, start);
- if (!res.empty())
- {
- start = checkChar(value, start, ',');
- start = skipSpaces(value, start);
- }
- size_t pairStart = start;
- start = checkChar(value, start, '(');
- const std::pair<size_t, std::string> key = readString(value, start);
- start = key.first;
- pair.first = key.second;
- start = skipSpaces(value, start);
- start = checkChar(value, start, ',');
- start = skipSpaces(value, start);
- const std::pair<size_t, std::string> val = readString(value, start);
- start = val.first;
- pair.second = val.second;
- start = skipSpaces(value, start);
- start = checkChar(value, start, ')');
- if (res.find(pair.first) != res.end())
- throw ParserError(pairStart, "Duplicate field.");
- res.insert(pair);
- }
- return res;
-}
-
-bool toBool(const std::vector<std::string>& values)
-{
- if (values.empty())
- return false;
- std::string value(values[0]);
- return strncasecmp(value.c_str(), "yes", 3) == 0;
-}
-
-std::string toString(const std::vector<std::string>& values)
-{
- if (values.empty())
- return "";
- return values[0];
-}
-
-uid_t toUID(const std::vector<std::string>& values)
-{
- if (values.empty())
- return -1;
- uid_t res = str2uid(values[0]);
- if (res == static_cast<uid_t>(-1))
- throw ParserError("Invalid user name: '" + values[0] + "'");
- return res;
-}
-
-gid_t toGID(const std::vector<std::string>& values)
-{
- if (values.empty())
- return -1;
- gid_t res = str2gid(values[0]);
- if (res == static_cast<gid_t>(-1))
- throw ParserError("Invalid group name: '" + values[0] + "'");
- return res;
-}
-
-mode_t toMode(const std::vector<std::string>& values)
-{
- if (values.empty())
- return -1;
- mode_t res = str2mode(values[0]);
- if (res == static_cast<mode_t>(-1))
- throw ParserError("Invalid mode: '" + values[0] + "'");
- return res;
-}
-
-template <typename T>
-T toInt(const std::vector<std::string>& values)
-{
- if (values.empty())
- return 0;
- T res = 0;
- if (str2x(values[0], res) == 0)
- return res;
- return 0;
-}
-
-uint16_t toPort(const std::string& value)
-{
- if (value.empty())
- return 0;
- uint16_t res = 0;
- if (str2x(value, res) == 0)
- return res;
- throw ParserError("'" + value + "' is not a valid port number.");
-}
-
-typedef std::map<std::string, Config::ReturnCode> Codes;
-
-// One-time call to initialize the list of codes.
-Codes getCodes()
-{
- Codes res;
- res["reject"] = Config::REJECT;
- res["fail"] = Config::FAIL;
- res["ok"] = Config::OK;
- res["handled"] = Config::HANDLED;
- res["invalid"] = Config::INVALID;
- res["userlock"] = Config::USERLOCK;
- res["notfound"] = Config::NOTFOUND;
- res["noop"] = Config::NOOP;
- res["updated"] = Config::UPDATED;
- return res;
-}
-
-Config::ReturnCode toReturnCode(const std::vector<std::string>& values)
-{
- static Codes codes(getCodes());
- if (values.empty())
- return Config::REJECT;
- std::string code = ToLower(values[0]);
- const Codes::const_iterator it = codes.find(code);
- if (it == codes.end())
- return Config::REJECT;
- return it->second;
-}
-
-Config::Pairs parseVector(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toPairs(params[i].value);
- return Config::Pairs();
-}
-
-Config::Authorize parseAuthorize(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return Config::Authorize(toPairs(params[i].value));
- return Config::Authorize();
-}
-
-Config::ReturnCode parseReturnCode(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toReturnCode(params[i].value);
- return Config::REJECT;
-}
-
-bool parseBool(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toBool(params[i].value);
- return false;
-}
-
-std::string parseString(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toString(params[i].value);
- return "";
-}
-
-std::string parseAddress(Config::Type connectionType, const std::string& value)
-{
- size_t pos = value.find_first_of(':');
- if (pos == std::string::npos)
- throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
- if (connectionType == Config::UNIX)
- return value.substr(pos + 1);
- std::string address(value.substr(pos + 1));
- pos = address.find_first_of(':', pos + 1);
- if (pos == std::string::npos)
- throw ParserError("Port is not specified.");
- return address.substr(0, pos - 1);
-}
-
-std::string parsePort(Config::Type connectionType, const std::string& value)
-{
- size_t pos = value.find_first_of(':');
- if (pos == std::string::npos)
- throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
- if (connectionType == Config::UNIX)
- return "";
- std::string address(value.substr(pos + 1));
- pos = address.find_first_of(':', pos + 1);
- if (pos == std::string::npos)
- throw ParserError("Port is not specified.");
- return address.substr(pos + 1);
-}
-
-Config::Type parseConnectionType(const std::string& address)
-{
- size_t pos = address.find_first_of(':');
- if (pos == std::string::npos)
- throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
- std::string type = ToLower(address.substr(0, pos));
- if (type == "unix")
- return Config::UNIX;
- else if (type == "tcp")
- return Config::TCP;
- throw ParserError("Invalid connection type. Should be either 'unix' or 'tcp', got '" + type + "'");
-}
-
-Config::Section parseSection(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return Config::Section(parseVector("match", params[i].sections),
- parseVector("modify", params[i].sections),
- parseVector("reply", params[i].sections),
- parseReturnCode("no_match", params[i].sections),
- parseAuthorize("authorize", params[i].sections));
- return Config::Section();
-}
-
-uid_t parseUID(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toUID(params[i].value);
- return -1;
-}
-
-gid_t parseGID(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toGID(params[i].value);
- return -1;
-}
-
-mode_t parseMode(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i].param == paramName)
- return toMode(params[i].value);
- return -1;
-}
-
-} // namespace anonymous
-
-bool Config::Authorize::check(const USER& user, const Config::Pairs& radiusData) const
-{
- if (!m_auth)
- return false; // No flag - no authorization.
-
- if (m_cond.empty())
- return true; // Empty parameter - always authorize.
-
- Config::Pairs::const_iterator it = m_cond.begin();
- for (; it != m_cond.end(); ++it)
- {
- const Config::Pairs::const_iterator pos = radiusData.find(it->first);
- if (pos == radiusData.end())
- return false; // No required Radius parameter.
- if (user.GetParamValue(it->second) != pos->second)
- return false; // No match with the user.
- }
-
- return true;
-}
-
-Config::Config(const MODULE_SETTINGS& settings)
- : autz(parseSection("autz", settings.moduleParams)),
- auth(parseSection("auth", settings.moduleParams)),
- postauth(parseSection("postauth", settings.moduleParams)),
- preacct(parseSection("preacct", settings.moduleParams)),
- acct(parseSection("acct", settings.moduleParams)),
- verbose(parseBool("verbose", settings.moduleParams)),
- address(parseString("bind_address", settings.moduleParams)),
- connectionType(parseConnectionType(address)),
- bindAddress(parseAddress(connectionType, address)),
- portStr(parsePort(connectionType, address)),
- port(toPort(portStr)),
- key(parseString("key", settings.moduleParams)),
- sockUID(parseUID("sock_owner", settings.moduleParams)),
- sockGID(parseGID("sock_group", settings.moduleParams)),
- sockMode(parseMode("sock_mode", settings.moduleParams))
-{
- size_t count = 0;
- if (autz.authorize.exists())
- ++count;
- if (auth.authorize.exists())
- ++count;
- if (postauth.authorize.exists())
- ++count;
- if (preacct.authorize.exists())
- ++count;
- if (acct.authorize.exists())
- ++count;
- if (count > 0)
- throw ParserError("Authorization flag is specified in more than one section.");
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_RADIUS_CONFIG_H__
-#define __STG_RADIUS_CONFIG_H__
-
-#include "stg/module_settings.h"
-
-#include "stg/os_int.h"
-
-#include <map>
-#include <string>
-
-#include <unistd.h> // uid_t, gid_t
-#include <sys/stat.h> // mode_t
-
-class USER;
-
-namespace STG
-{
-
-struct Config
-{
- typedef std::map<std::string, std::string> Pairs;
- typedef std::pair<std::string, std::string> Pair;
- enum Type { UNIX, TCP };
- enum ReturnCode
- {
- REJECT, // Reject the request immediately.
- FAIL, // Module failed.
- OK, // Module is OK, continue.
- HANDLED, // The request is handled, no further handling.
- INVALID, // The request is invalud.
- USERLOCK, // Reject the request, user is locked.
- NOTFOUND, // User not found.
- NOOP, // Module performed no action.
- UPDATED // Module sends some updates.
- };
-
- class Authorize
- {
- public:
- Authorize() : m_auth(false) {}
- Authorize(const Pairs& cond) : m_auth(true), m_cond(cond) {}
-
- bool check(const USER& user, const Pairs& radiusData) const;
- bool exists() const { return m_auth; }
- private:
- bool m_auth;
- Pairs m_cond;
- };
-
- struct Section
- {
- Section() {}
- Section(const Pairs& ma, const Pairs& mo, const Pairs& re, ReturnCode code, const Authorize& auth)
- : match(ma), modify(mo), reply(re), returnCode(code), authorize(auth) {}
- Pairs match;
- Pairs modify;
- Pairs reply;
- ReturnCode returnCode;
- Authorize authorize;
- };
-
- Config() {}
- Config(const MODULE_SETTINGS& settings);
-
- Section autz;
- Section auth;
- Section postauth;
- Section preacct;
- Section acct;
-
- bool verbose;
-
- std::string address;
- Type connectionType;
- std::string bindAddress;
- std::string portStr;
- uint16_t port;
- std::string key;
-
- uid_t sockUID;
- gid_t sockGID;
- mode_t sockMode;
-};
-
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "conn.h"
-
-#include "radius.h"
-#include "config.h"
-
-#include "stg/json_parser.h"
-#include "stg/json_generator.h"
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/logger.h"
-#include "stg/common.h"
-
-#include <yajl/yajl_gen.h>
-
-#include <map>
-#include <stdexcept>
-#include <cstring>
-#include <cerrno>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-using STG::Conn;
-using STG::Config;
-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;
-
-enum Packet
-{
- PING,
- PONG,
- DATA
-};
-
-enum Stage
-{
- AUTHORIZE,
- AUTHENTICATE,
- PREACCT,
- ACCOUNTING,
- POSTAUTH
-};
-
-std::map<std::string, Packet> packetCodes;
-std::map<std::string, Stage> stageCodes;
-
-class PacketParser : public EnumParser<Packet>
-{
- 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 StageParser : public EnumParser<Stage>
-{
- public:
- StageParser(NodeParser* next, Stage& stage, std::string& stageStr)
- : EnumParser(next, stage, stageStr, stageCodes)
- {
- if (!stageCodes.empty())
- return;
- stageCodes["authorize"] = AUTHORIZE;
- stageCodes["authenticate"] = AUTHENTICATE;
- stageCodes["preacct"] = PREACCT;
- stageCodes["accounting"] = ACCOUNTING;
- stageCodes["postauth"] = POSTAUTH;
- }
-};
-
-class TopParser : public NodeParser
-{
- public:
- typedef void (*Callback) (void* /*data*/);
- TopParser(Callback callback, void* data)
- : m_packetParser(this, m_packet, m_packetStr),
- m_stageParser(this, m_stage, m_stageStr),
- m_pairsParser(this, m_data),
- m_callback(callback), m_callbackData(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 == "stage")
- return &m_stageParser;
- else if (key == "pairs")
- return &m_pairsParser;
-
- return this;
- }
- virtual NodeParser* parseEndMap() { m_callback(m_callbackData); return this; }
-
- const std::string& packetStr() const { return m_packetStr; }
- Packet packet() const { return m_packet; }
- const std::string& stageStr() const { return m_stageStr; }
- Stage stage() const { return m_stage; }
- const Config::Pairs& data() const { return m_data; }
-
- private:
- std::string m_packetStr;
- Packet m_packet;
- std::string m_stageStr;
- Stage m_stage;
- Config::Pairs m_data;
-
- PacketParser m_packetParser;
- StageParser m_stageParser;
- PairsParser m_pairsParser;
-
- Callback m_callback;
- void* m_callbackData;
-};
-
-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& stageStr() const { return m_topParser.stageStr(); }
- Stage stage() const { return m_topParser.stage(); }
- const Config::Pairs& data() const { return m_topParser.data(); }
-
- private:
- TopParser m_topParser;
-};
-
-class PacketGen : public Gen
-{
- public:
- 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;
- }
- PacketGen& add(const std::string& key, MapGen& map)
- {
- m_gen.add(key, map);
- return *this;
- }
- private:
- MapGen m_gen;
- StringGen m_type;
-};
-
-std::string toString(Config::ReturnCode code)
-{
- switch (code)
- {
- case Config::REJECT: return "reject";
- case Config::FAIL: return "fail";
- case Config::OK: return "ok";
- case Config::HANDLED: return "handled";
- case Config::INVALID: return "invalid";
- case Config::USERLOCK: return "userlock";
- case Config::NOTFOUND: return "notfound";
- case Config::NOOP: return "noop";
- case Config::UPDATED: return "noop";
- }
- return "reject";
-}
-
-}
-
-class Conn::Impl
-{
- public:
- Impl(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote);
- ~Impl();
-
- int sock() const { return m_sock; }
-
- bool read();
- bool tick();
-
- bool isOk() const { return m_ok; }
-
- private:
- USERS& m_users;
- PLUGIN_LOGGER& m_logger;
- RADIUS& m_plugin;
- const Config& m_config;
- int m_sock;
- std::string m_remote;
- bool m_ok;
- time_t m_lastPing;
- time_t m_lastActivity;
- ProtoParser m_parser;
- std::set<std::string> m_authorized;
-
- template <typename T>
- const T& stageMember(T Config::Section::* member) const
- {
- switch (m_parser.stage())
- {
- case AUTHORIZE: return m_config.autz.*member;
- case AUTHENTICATE: return m_config.auth.*member;
- case POSTAUTH: return m_config.postauth.*member;
- case PREACCT: return m_config.preacct.*member;
- case ACCOUNTING: return m_config.acct.*member;
- }
- throw std::runtime_error("Invalid stage: '" + m_parser.stageStr() + "'.");
- }
-
- const Config::Pairs& match() const { return stageMember(&Config::Section::match); }
- const Config::Pairs& modify() const { return stageMember(&Config::Section::modify); }
- const Config::Pairs& reply() const { return stageMember(&Config::Section::reply); }
- Config::ReturnCode returnCode() const { return stageMember(&Config::Section::returnCode); }
- const Config::Authorize& authorize() const { return stageMember(&Config::Section::authorize); }
-
- static void process(void* data);
- void processPing();
- void processPong();
- void processData();
- bool answer(const USER& user);
- bool answerNo();
- bool sendPing();
- bool sendPong();
-
- static bool write(void* data, const char* buf, size_t size);
-};
-
-Conn::Conn(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote)
- : m_impl(new Impl(users, logger, plugin, config, fd, remote))
-{
-}
-
-Conn::~Conn()
-{
-}
-
-int Conn::sock() const
-{
- return m_impl->sock();
-}
-
-bool Conn::read()
-{
- return m_impl->read();
-}
-
-bool Conn::tick()
-{
- return m_impl->tick();
-}
-
-bool Conn::isOk() const
-{
- return m_impl->isOk();
-}
-
-Conn::Impl::Impl(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote)
- : m_users(users),
- m_logger(logger),
- m_plugin(plugin),
- m_config(config),
- m_sock(fd),
- m_remote(remote),
- m_ok(true),
- m_lastPing(time(NULL)),
- m_lastActivity(m_lastPing),
- m_parser(&Conn::Impl::process, this)
-{
-}
-
-Conn::Impl::~Impl()
-{
- close(m_sock);
-
- std::set<std::string>::const_iterator it = m_authorized.begin();
- for (; it != m_authorized.end(); ++it)
- m_plugin.unauthorize(*it, "Lost connection to RADIUS server " + m_remote + ".");
-}
-
-bool Conn::Impl::read()
-{
- static std::vector<char> buffer(1024);
- ssize_t res = ::read(m_sock, buffer.data(), buffer.size());
- if (res < 0)
- {
- m_logger("Failed to read data from '" + m_remote + "': " + strerror(errno));
- m_ok = false;
- return false;
- }
- printfd(__FILE__, "Read %d bytes.\n%s\n", res, std::string(buffer.data(), res).c_str());
- m_lastActivity = time(NULL);
- if (res == 0)
- {
- m_ok = false;
- return true;
- }
- 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);
- printfd(__FILE__, "Connection to '%s' timed out: %d sec.\n", m_remote.c_str(), delta);
- m_logger("Connection to " + m_remote + " timed out.");
- m_ok = false;
- return false;
- }
- if (difftime(now, m_lastPing) > PING_TIMEOUT)
- {
- int delta = difftime(now, m_lastPing);
- printfd(__FILE__, "Ping timeout: %d sec. Sending ping...\n", delta);
- sendPing();
- }
- return true;
-}
-
-void Conn::Impl::process(void* data)
-{
- Impl& impl = *static_cast<Impl*>(data);
- try
- {
- switch (impl.m_parser.packet())
- {
- case PING:
- impl.processPing();
- return;
- case PONG:
- impl.processPong();
- return;
- case DATA:
- impl.processData();
- return;
- }
- }
- catch (const std::exception& ex)
- {
- printfd(__FILE__, "Processing error. %s", ex.what());
- impl.m_logger("Processing error. %s", ex.what());
- }
- printfd(__FILE__, "Received invalid packet type: '%s'.\n", impl.m_parser.packetStr().c_str());
- impl.m_logger("Received invalid packet type: " + impl.m_parser.packetStr());
-}
-
-void Conn::Impl::processPing()
-{
- printfd(__FILE__, "Got ping. Sending pong...\n");
- sendPong();
-}
-
-void Conn::Impl::processPong()
-{
- printfd(__FILE__, "Got pong.\n");
- m_lastActivity = time(NULL);
-}
-
-void Conn::Impl::processData()
-{
- printfd(__FILE__, "Got data.\n");
- int handle = m_users.OpenSearch();
-
- USER_PTR user = NULL;
- bool matched = false;
- while (m_users.SearchNext(handle, &user) == 0)
- {
- if (user == NULL)
- continue;
-
- matched = true;
- for (Config::Pairs::const_iterator it = match().begin(); it != match().end(); ++it)
- {
- Config::Pairs::const_iterator pos = m_parser.data().find(it->first);
- if (pos == m_parser.data().end())
- {
- matched = false;
- break;
- }
- if (user->GetParamValue(it->second) != pos->second)
- {
- matched = false;
- break;
- }
- }
- if (!matched)
- continue;
- answer(*user);
- if (authorize().check(*user, m_parser.data()))
- {
- m_plugin.authorize(*user);
- m_authorized.insert(user->GetLogin());
- }
- break;
- }
-
- if (!matched)
- answerNo();
-
- m_users.CloseSearch(handle);
-}
-
-bool Conn::Impl::answer(const USER& user)
-{
- printfd(__FILE__, "Got match. Sending answer...\n");
- MapGen replyData;
- for (Config::Pairs::const_iterator it = reply().begin(); it != reply().end(); ++it)
- replyData.add(it->first, new StringGen(user.GetParamValue(it->second)));
-
- MapGen modifyData;
- for (Config::Pairs::const_iterator it = modify().begin(); it != modify().end(); ++it)
- modifyData.add(it->first, new StringGen(user.GetParamValue(it->second)));
-
- PacketGen gen("data");
- gen.add("result", "ok")
- .add("reply", replyData)
- .add("modify", modifyData);
-
- m_lastPing = time(NULL);
-
- return generate(gen, &Conn::Impl::write, this);
-}
-
-bool Conn::Impl::answerNo()
-{
- printfd(__FILE__, "No match. Sending answer...\n");
- PacketGen gen("data");
- gen.add("result", "no");
- gen.add("return_code", toString(returnCode()));
-
- m_lastPing = time(NULL);
-
- return generate(gen, &Conn::Impl::write, this);
-}
-
-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);
- printfd(__FILE__, "Writing JSON:\n%s\n", json.c_str());
- Conn::Impl& conn = *static_cast<Conn::Impl*>(data);
- while (size > 0)
- {
- ssize_t res = ::send(conn.m_sock, buf, size, MSG_NOSIGNAL);
- if (res < 0)
- {
- conn.m_logger("Failed to write pong to '" + conn.m_remote + "': " + strerror(errno));
- conn.m_ok = false;
- return false;
- }
- size -= res;
- }
- return true;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONFIG_CONN_H__
-#define __STG_SGCONFIG_CONN_H__
-
-#include <boost/scoped_ptr.hpp>
-
-#include <string>
-
-class USER;
-class USERS;
-class PLUGIN_LOGGER;
-class RADIUS;
-
-namespace STG
-{
-
-struct Config;
-
-class Conn
-{
- public:
- Conn(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote);
- ~Conn();
-
- int sock() const;
-
- bool read();
- bool tick();
-
- bool isOk() const;
-
- private:
- class Impl;
- boost::scoped_ptr<Impl> m_impl;
-};
-
-}
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "radius.h"
-
-#include "stg/store.h"
-#include "stg/users.h"
-#include "stg/plugin_creator.h"
-#include "stg/common.h"
-
-#include <algorithm>
-#include <stdexcept>
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h> // UNIX
-#include <netinet/in.h> // IP
-#include <netinet/tcp.h> // TCP
-#include <netdb.h>
-
-using STG::Config;
-using STG::Conn;
-
-namespace
-{
-
-PLUGIN_CREATOR<RADIUS> creator;
-
-}
-
-extern "C" PLUGIN * GetPlugin()
-{
- return creator.GetPlugin();
-}
-
-RADIUS::RADIUS()
- : m_config(),
- m_running(false),
- m_stopped(true),
- m_users(NULL),
- m_store(NULL),
- m_listenSocket(0),
- m_logger(GetPluginLogger(GetStgLogger(), "radius"))
-{
-}
-
-int RADIUS::ParseSettings()
-{
- try {
- m_config = STG::Config(m_settings);
- return reconnect() ? 0 : -1;
- } catch (const std::runtime_error& ex) {
- m_logger("Failed to parse settings. %s", ex.what());
- return -1;
- }
-}
-
-int RADIUS::Start()
-{
- if (m_running)
- return 0;
-
- int res = pthread_create(&m_thread, NULL, run, this);
- if (res == 0)
- return 0;
-
- m_error = strerror(res);
- m_logger("Failed to create thread: '" + m_error + "'.");
- return -1;
-}
-
-int RADIUS::Stop()
-{
- std::set<std::string>::const_iterator it = m_logins.begin();
- for (; it != m_logins.end(); ++it)
- m_users->Unauthorize(*it, this, "Stopping RADIUS plugin.");
- m_logins.clear();
-
- if (m_stopped)
- return 0;
-
- 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 0;
- }
-
- if (m_config.connectionType == Config::UNIX)
- unlink(m_config.bindAddress.c_str());
-
- m_error = "Failed to stop thread.";
- m_logger(m_error);
- return -1;
-}
-//-----------------------------------------------------------------------------
-void* RADIUS::run(void* d)
-{
- sigset_t signalSet;
- sigfillset(&signalSet);
- pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
- static_cast<RADIUS *>(d)->runImpl();
-
- return NULL;
-}
-
-bool RADIUS::reconnect()
-{
- if (!m_conns.empty())
- {
- std::deque<STG::Conn *>::const_iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- delete(*it);
- m_conns.clear();
- }
- if (m_listenSocket != 0)
- {
- shutdown(m_listenSocket, SHUT_RDWR);
- close(m_listenSocket);
- }
- if (m_config.connectionType == Config::UNIX)
- m_listenSocket = createUNIX();
- else
- m_listenSocket = createTCP();
- if (m_listenSocket == 0)
- return false;
- if (listen(m_listenSocket, 100) == -1)
- {
- m_error = std::string("Error starting to listen socket: ") + strerror(errno);
- m_logger(m_error);
- return false;
- }
- return true;
-}
-
-int RADIUS::createUNIX() const
-{
- int fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1)
- {
- m_error = std::string("Error creating UNIX socket: ") + strerror(errno);
- m_logger(m_error);
- return 0;
- }
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, m_config.bindAddress.c_str(), m_config.bindAddress.length());
- unlink(m_config.bindAddress.c_str());
- if (bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1)
- {
- shutdown(fd, SHUT_RDWR);
- close(fd);
- m_error = std::string("Error binding UNIX socket: ") + strerror(errno);
- m_logger(m_error);
- return 0;
- }
- chown(m_config.bindAddress.c_str(), m_config.sockUID, m_config.sockGID);
- if (m_config.sockMode != static_cast<mode_t>(-1))
- chmod(m_config.bindAddress.c_str(), m_config.sockMode);
- return fd;
-}
-
-int RADIUS::createTCP() const
-{
- addrinfo hints;
- memset(&hints, 0, sizeof(addrinfo));
-
- hints.ai_family = AF_INET; /* Allow IPv4 */
- hints.ai_socktype = SOCK_STREAM; /* Stream socket */
- hints.ai_flags = AI_PASSIVE; /* 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.bindAddress.c_str(), m_config.portStr.c_str(), &hints, &ais);
- if (res != 0)
- {
- m_error = "Error resolving address '" + m_config.bindAddress + "': " + gai_strerror(res);
- m_logger(m_error);
- return 0;
- }
-
- for (addrinfo* ai = ais; ai != NULL; ai = ai->ai_next)
- {
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1)
- {
- m_error = std::string("Error creating TCP socket: ") + strerror(errno);
- m_logger(m_error);
- freeaddrinfo(ais);
- return 0;
- }
- if (bind(fd, ai->ai_addr, ai->ai_addrlen) == -1)
- {
- shutdown(fd, SHUT_RDWR);
- close(fd);
- m_error = std::string("Error binding TCP socket: ") + strerror(errno);
- m_logger(m_error);
- continue;
- }
- freeaddrinfo(ais);
- return fd;
- }
-
- m_error = "Failed to resolve '" + m_config.bindAddress;
- m_logger(m_error);
-
- freeaddrinfo(ais);
- return 0;
-}
-
-void RADIUS::runImpl()
-{
- m_running = true;
- m_stopped = false;
-
- while (m_running) {
- fd_set fds;
-
- buildFDSet(fds);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 500000;
-
- int res = select(maxFD() + 1, &fds, NULL, NULL, &tv);
- if (res < 0)
- {
- if (errno == EINTR)
- continue;
- m_error = std::string("'select' is failed: '") + strerror(errno) + "'.";
- m_logger(m_error);
- break;
- }
-
- if (!m_running)
- break;
-
- if (res > 0)
- handleEvents(fds);
- else
- {
- for (std::deque<Conn*>::iterator it = m_conns.begin(); it != m_conns.end(); ++it)
- (*it)->tick();
- }
-
- cleanupConns();
- }
-
- m_stopped = true;
-}
-
-int RADIUS::maxFD() const
-{
- int maxFD = m_listenSocket;
- std::deque<STG::Conn *>::const_iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- if (maxFD < (*it)->sock())
- maxFD = (*it)->sock();
- return maxFD;
-}
-
-void RADIUS::buildFDSet(fd_set & fds) const
-{
- FD_ZERO(&fds);
- FD_SET(m_listenSocket, &fds);
- std::deque<STG::Conn *>::const_iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- FD_SET((*it)->sock(), &fds);
-}
-
-void RADIUS::cleanupConns()
-{
- std::deque<STG::Conn *>::iterator pos;
- for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
- if (!(*pos)->isOk()) {
- delete *pos;
- *pos = NULL;
- }
-
- pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
- m_conns.erase(pos, m_conns.end());
-}
-
-void RADIUS::handleEvents(const fd_set & fds)
-{
- if (FD_ISSET(m_listenSocket, &fds))
- acceptConnection();
- else
- {
- std::deque<STG::Conn *>::iterator it;
- for (it = m_conns.begin(); it != m_conns.end(); ++it)
- if (FD_ISSET((*it)->sock(), &fds))
- (*it)->read();
- else
- (*it)->tick();
- }
-}
-
-void RADIUS::acceptConnection()
-{
- if (m_config.connectionType == Config::UNIX)
- acceptUNIX();
- else
- acceptTCP();
-}
-
-void RADIUS::acceptUNIX()
-{
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(addr));
- socklen_t size = sizeof(addr);
- int res = accept(m_listenSocket, reinterpret_cast<sockaddr*>(&addr), &size);
- if (res == -1)
- {
- m_error = std::string("Failed to accept UNIX connection: ") + strerror(errno);
- m_logger(m_error);
- return;
- }
- printfd(__FILE__, "New UNIX connection: '%s'\n", addr.sun_path);
- m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, addr.sun_path));
-}
-
-void RADIUS::acceptTCP()
-{
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- socklen_t size = sizeof(addr);
- int res = accept(m_listenSocket, reinterpret_cast<sockaddr*>(&addr), &size);
- if (res == -1)
- {
- m_error = std::string("Failed to accept TCP connection: ") + strerror(errno);
- m_logger(m_error);
- return;
- }
- std::string remote = inet_ntostring(addr.sin_addr.s_addr) + ":" + x2str(ntohs(addr.sin_port));
- printfd(__FILE__, "New TCP connection: '%s'\n", remote.c_str());
- m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, remote));
-}
-
-void RADIUS::authorize(const USER& user)
-{
- uint32_t ip = 0;
- const std::string& login(user.GetLogin());
- if (!m_users->Authorize(login, ip, 0xffFFffFF, this))
- {
- m_error = "Unable to authorize user '" + login + "' with ip " + inet_ntostring(ip) + ".";
- m_logger(m_error);
- }
- else
- m_logins.insert(login);
-}
-
-void RADIUS::unauthorize(const std::string& login, const std::string& reason)
-{
- const std::set<std::string>::const_iterator it = m_logins.find(login);
- if (it == m_logins.end())
- return;
- m_logins.erase(it);
- m_users->Unauthorize(login, this, reason);
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_RADIUS_H__
-#define __STG_RADIUS_H__
-
-#include "stg/os_int.h"
-#include "stg/auth.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include "config.h"
-#include "conn.h"
-
-#include <string>
-#include <deque>
-#include <set>
-
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/select.h>
-#include <sys/types.h>
-
-extern "C" PLUGIN * GetPlugin();
-
-class STORE;
-class USERS;
-
-class RADIUS : public AUTH {
-public:
- RADIUS();
- virtual ~RADIUS() {}
-
- void SetUsers(USERS* u) { m_users = u; }
- void SetStore(STORE* s) { m_store = s; }
- void SetStgSettings(const SETTINGS*) {}
- void SetSettings(const MODULE_SETTINGS& s) { m_settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
- bool IsRunning() { return m_running; }
-
- const std::string& GetStrError() const { return m_error; }
- std::string GetVersion() const { return "RADIUS data access plugin v. 2.0"; }
- uint16_t GetStartPosition() const { return 30; }
- uint16_t GetStopPosition() const { return 30; }
-
- int SendMessage(const STG_MSG&, uint32_t) const { return 0; }
-
- void authorize(const USER& user);
- void unauthorize(const std::string& login, const std::string& reason);
-
-private:
- RADIUS(const RADIUS & rvalue);
- RADIUS & operator=(const RADIUS & rvalue);
-
- static void* run(void*);
-
- bool reconnect();
- int createUNIX() const;
- int createTCP() const;
- void runImpl();
- int maxFD() const;
- void buildFDSet(fd_set & fds) const;
- void cleanupConns();
- void handleEvents(const fd_set & fds);
- void acceptConnection();
- void acceptUNIX();
- void acceptTCP();
-
- mutable std::string m_error;
- STG::Config m_config;
-
- MODULE_SETTINGS m_settings;
-
- bool m_running;
- bool m_stopped;
-
- USERS* m_users;
- const STORE* m_store;
-
- int m_listenSocket;
- std::deque<STG::Conn*> m_conns;
- std::set<std::string> m_logins;
-
- pthread_t m_thread;
-
- PLUGIN_LOGGER m_logger;
-};
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.7 2010/02/16 11:41:00 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-LIBS += $(LIB_THREAD)
-
-PROG = mod_remote_script.so
-
-SRCS = ./rscript.cpp \
- ./nrmap_parser.cpp
-
-STGLIBS = common \
- crypto \
- logger \
- scriptexecuter
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.8 $
- $Author: faust $
- $Date: 2009/10/22 09:58:53 $
- */
-
-#include <fstream>
-#include <cerrno>
-#include <cstring>
-#include <algorithm>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include "stg/common.h"
-#include "nrmap_parser.h"
-
-bool NRMapParser::ReadFile(const std::string & fileName)
-{
-std::ifstream source(fileName.c_str());
-
-if (!source)
- {
- errorStr = "Error opening file ";
- errorStr += fileName;
- printfd(__FILE__, "NRMapParser::ReadFile(): %s\n", errorStr.c_str());
- return true;
- }
-
-int lineNumber = 0;
-std::string line;
-std::vector<NET_ROUTER> _nrmap;
-
-while (getline(source, line))
- {
- ++lineNumber;
- NET_ROUTER nr;
-
- if (Trim(line) == "")
- {
- continue;
- }
-
- if (ParseLine(line, nr))
- {
- printfd(__FILE__, "NRMapParser::ReadFile(): Error parsing line %d: '%s'\n", lineNumber, errorStr.c_str());
- return true;
- }
-
- _nrmap.push_back(nr);
- }
-
-nrmap = _nrmap;
-
-return false;
-}
-
-bool NRMapParser::ParseLine(const std::string & line, NET_ROUTER & nr) const
-{
-// xxx.xxx.xxx.xxx/yy zzz.zzz.zzz.zzz
-size_t pos = line.find_first_of(" \t");
-
-if (pos == std::string::npos)
- {
- errorStr = "No space between subnet and router";
- return true;
- }
-
-std::string subnet(line.substr(0, pos)); // xxx.xxx.xxx.xxx/yy
-
-uint32_t ip = 0;
-uint32_t mask = 0;
-
-if (ParseNet(subnet, ip, mask))
- {
- return true;
- }
-
-nr.subnetIP = ip;
-nr.subnetMask = mask;
-
-pos = line.find_first_not_of(" \t", pos);
-
-if (pos == std::string::npos)
- {
- errorStr = "No router address found";
- return true;
- }
-
-size_t pos2 = line.find_first_of(" \t", pos);
-
-std::string router(line.substr(pos, pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos)); //zzz.zzz.zzz.zzz
-
-uint32_t routerIP;
-
-if (ParseRouter(router, routerIP))
- {
- return true;
- }
-
-std::vector<uint32_t>::iterator it;
-
-it = std::lower_bound(
- nr.routers.begin(),
- nr.routers.end(),
- routerIP
- );
-nr.routers.insert(it, routerIP);
-
-//nr.routers.push_back(routerIP);
-
-while (pos2 != std::string::npos)
- {
- pos = line.find_first_not_of(" \t", pos2);
-
- if (pos == std::string::npos)
- {
- return false;
- }
-
- pos2 = line.find_first_of(" \t", pos);
-
- if (ParseRouter(line.substr(
- pos,
- pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos),
- routerIP))
- {
- return true;
- }
-
- it = std::lower_bound(
- nr.routers.begin(),
- nr.routers.end(),
- routerIP
- );
- nr.routers.insert(it, routerIP);
-
- //nr.routers.push_back(routerIP);
-
- }
-
-return false;
-}
-
-bool NRMapParser::ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const
-{
-// xxx.xxx.xxx.xxx/yy
-
-size_t pos = line.find_first_of('/');
-
-if (pos == std::string::npos)
- {
- errorStr = "Subnet is not in CIDR notation";
- return true;
- }
-
-int res = inet_pton(AF_INET, line.substr(0, pos).c_str(), &ip); //xxx.xxx.xxx.xxx
-
-if (res < 0)
- {
- errorStr = strerror(errno);
- return true;
- }
-else if (res == 0)
- {
- errorStr = "Invalid subnet address";
- return true;
- }
-
-if (str2x(line.substr(pos + 1, line.length() - pos - 1), mask)) //yy
- {
- errorStr = "Invalid subnet mask";
- return true;
- }
-if (mask > 32)
- {
- errorStr = "Subnet mask is out of range [0..32]";
- return true;
- }
-mask = htonl(0xffFFffFF << (32 - mask)); //bitmask
-
-return false;
-}
-
-bool NRMapParser::ParseRouter(const std::string & line, uint32_t & ip) const
-{
-int res = inet_pton(AF_INET, line.c_str(), &ip); //zzz.zzz.zzz.zzz
-
-if (res < 0)
- {
- errorStr = strerror(errno);
- return true;
- }
-else if (res == 0)
- {
- printfd(__FILE__, "NRMapParser::ParseRouter(): IP '%s' is invalid\n", line.c_str());
- errorStr = "Invalid router address";
- return true;
- }
-return false;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.2 $
- $Author: faust $
- $Date: 2009/09/23 12:51:42 $
- */
-
-#ifndef __NRMAP_PARSER_H__
-#define __NRMAP_PARSER_H__
-
-#include <string>
-#include <vector>
-
-#include "stg/os_int.h"
-
-struct NET_ROUTER
-{
- NET_ROUTER() : subnetIP(0), subnetMask(0), routers() {}
- NET_ROUTER(const NET_ROUTER & rvalue)
- : subnetIP(rvalue.subnetIP),
- subnetMask(rvalue.subnetMask),
- routers(rvalue.routers)
- {}
-
- uint32_t subnetIP;
- uint32_t subnetMask;
- std::vector<uint32_t> routers;
-
- NET_ROUTER & operator=(const NET_ROUTER & rvalue)
- {
- subnetIP = rvalue.subnetIP;
- subnetMask = rvalue.subnetMask;
- routers = rvalue.routers;
- return *this;
- }
-};
-
-class NRMapParser {
-public:
- NRMapParser() : nrmap(), errorStr() {}
- ~NRMapParser() {}
-
- bool ReadFile(const std::string & fileName);
- const std::vector<NET_ROUTER> & GetMap() const { return nrmap; }
- const std::string & GetErrorStr() const { return errorStr; }
-
-private:
- NRMapParser(const NRMapParser & rvalue);
- NRMapParser & operator=(const NRMapParser & rvalue);
-
- std::vector<NET_ROUTER> nrmap;
- mutable std::string errorStr;
-
- bool ParseLine(const std::string & line, NET_ROUTER & nr) const;
- bool ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const;
- bool ParseRouter(const std::string & line, uint32_t & ip) const;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "rscript.h"
-
-#include "ur_functor.h"
-#include "send_functor.h"
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/users.h"
-#include "stg/user_property.h"
-#include "stg/plugin_creator.h"
-#include "stg/logger.h"
-
-#include <algorithm>
-
-#include <csignal>
-#include <cassert>
-#include <cstdlib>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/time.h>
-#include <netinet/ip.h>
-
-extern volatile time_t stgTime;
-
-using RS::REMOTE_SCRIPT;
-
-namespace {
-
-template<typename T>
-struct USER_IS
-{
- explicit USER_IS(USER_PTR u) : user(u) {}
- bool operator()(const T & notifier) { return notifier.GetUser() == user; }
-
- USER_PTR user;
-};
-
-PLUGIN_CREATOR<REMOTE_SCRIPT> rsc;
-
-} // namespace anonymous
-
-extern "C" PLUGIN * GetPlugin();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-PLUGIN * GetPlugin()
-{
-return rsc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-RS::SETTINGS::SETTINGS()
- : sendPeriod(0),
- port(0)
-{
-}
-//-----------------------------------------------------------------------------
-int RS::SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-int p;
-PARAM_VALUE pv;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-netRouters.clear();
-///////////////////////////
-pv.param = "Port";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Port\' not found.";
- printfd(__FILE__, "Parameter 'Port' not found\n");
- return -1;
- }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
- {
- errorStr = "Cannot parse parameter \'Port\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'Port'\n");
- return -1;
- }
-port = static_cast<uint16_t>(p);
-///////////////////////////
-pv.param = "SendPeriod";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'SendPeriod\' not found.";
- printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
- return -1;
- }
-
-if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
- {
- errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
- return -1;
- }
-///////////////////////////
-pv.param = "UserParams";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'UserParams\' not found.";
- printfd(__FILE__, "Parameter 'UserParams' not found\n");
- return -1;
- }
-userParams = pvi->value;
-///////////////////////////
-pv.param = "Password";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Password\' not found.";
- printfd(__FILE__, "Parameter 'Password' not found\n");
- return -1;
- }
-password = pvi->value[0];
-///////////////////////////
-pv.param = "SubnetFile";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'SubnetFile\' not found.";
- printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
- return -1;
- }
-subnetFile = pvi->value[0];
-
-NRMapParser nrMapParser;
-
-if (!nrMapParser.ReadFile(subnetFile))
- {
- netRouters = nrMapParser.GetMap();
- }
-else
- {
- GetStgLogger()("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-REMOTE_SCRIPT::REMOTE_SCRIPT()
- : ctx(),
- ipNotifierList(),
- connNotifierList(),
- authorizedUsers(),
- errorStr(),
- rsSettings(),
- settings(),
- sendPeriod(15),
- halfPeriod(8),
- nonstop(false),
- isRunning(false),
- users(NULL),
- netRouters(),
- thread(),
- mutex(),
- sock(0),
- onAddUserNotifier(*this),
- onDelUserNotifier(*this),
- logger(GetPluginLogger(GetStgLogger(), "rscript"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-REMOTE_SCRIPT::~REMOTE_SCRIPT()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-void * REMOTE_SCRIPT::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
-
-rs->isRunning = true;
-
-while (rs->nonstop)
- {
- rs->PeriodicSend();
- sleep(2);
- }
-
-rs->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::ParseSettings()
-{
-int ret = rsSettings.ParseSettings(settings);
-if (ret)
- errorStr = rsSettings.GetStrError();
-
-sendPeriod = rsSettings.GetSendPeriod();
-halfPeriod = sendPeriod / 2;
-
-return ret;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Start()
-{
-netRouters = rsSettings.GetSubnetsMap();
-
-InitEncrypt(&ctx, rsSettings.GetPassword());
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-nonstop = true;
-
-if (GetUsers())
- {
- return -1;
- }
-
-if (PrepareNet())
- {
- return -1;
- }
-
-if (!isRunning)
- {
- if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
- }
-
-errorStr = "";
-return 0;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Stop()
-{
-if (!IsRunning())
- return 0;
-
-nonstop = false;
-
-std::for_each(
- authorizedUsers.begin(),
- authorizedUsers.end(),
- DisconnectUser(*this)
- );
-
-FinalizeNet();
-
-if (isRunning)
- {
- //5 seconds to thread stops itself
- for (int i = 0; i < 25 && isRunning; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- }
-
-users->DelNotifierUserDel(&onDelUserNotifier);
-users->DelNotifierUserAdd(&onAddUserNotifier);
-
-if (isRunning)
- {
- logger("Cannot stop thread.");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Reload(const MODULE_SETTINGS & /*ms*/)
-{
-NRMapParser nrMapParser;
-
-if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
- {
- errorStr = nrMapParser.GetErrorStr();
- logger("Map file reading error: %s", errorStr.c_str());
- return -1;
- }
-
- {
- STG_LOCKER lock(&mutex);
-
- printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
-
- netRouters = nrMapParser.GetMap();
- }
-
-std::for_each(authorizedUsers.begin(),
- authorizedUsers.end(),
- UpdateRouter(*this));
-
-logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
-printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::PrepareNet()
-{
-sock = socket(AF_INET, SOCK_DGRAM, 0);
-
-if (sock < 0)
- {
- errorStr = "Cannot create socket.";
- logger("Canot create a socket: %s", strerror(errno));
- printfd(__FILE__, "Cannot create socket\n");
- return true;
- }
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::FinalizeNet()
-{
-close(sock);
-return false;
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::PeriodicSend()
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
-while (it != authorizedUsers.end())
- {
- if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
- {
- Send(it->second);
- }
- ++it;
- }
-}
-//-----------------------------------------------------------------------------
-#ifdef NDEBUG
-bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
-#else
-bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
-#endif
-{
-RS::PACKET_HEADER packetHead;
-
-memset(packetHead.padding, 0, sizeof(packetHead.padding));
-strcpy((char*)packetHead.magic, RS_ID);
-packetHead.protoVer[0] = '0';
-packetHead.protoVer[1] = '2';
-if (forceDisconnect)
- {
- packetHead.packetType = RS_DISCONNECT_PACKET;
- printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
- }
-else
- {
- if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
- {
- //SendLong
- packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
- if (rsu.user->IsInetable())
- printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
- else
- printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
- }
- else
- {
- //SendShort
- packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
- if (rsu.user->IsInetable())
- printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
- else
- printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
- }
- }
-rsu.shortPacketsCount++;
-rsu.lastSentTime = stgTime;
-
-packetHead.ip = htonl(rsu.ip);
-packetHead.id = htonl(rsu.user->GetID());
-strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
-packetHead.login[RS_LOGIN_LEN - 1] = 0;
-
-memcpy(buf, &packetHead, sizeof(packetHead));
-
-if (packetHead.packetType == RS_ALIVE_PACKET)
- {
- return false;
- }
-
-RS::PACKET_TAIL packetTail;
-
-memset(packetTail.padding, 0, sizeof(packetTail.padding));
-strcpy((char*)packetTail.magic, RS_ID);
-std::vector<std::string>::const_iterator it;
-std::string params;
-for(it = rsSettings.GetUserParams().begin();
- it != rsSettings.GetUserParams().end();
- ++it)
- {
- std::string parameter(rsu.user->GetParamValue(it->c_str()));
- if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
- {
- logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + parameter.length(), RS_PARAMS_LEN);
- break;
- }
- params += parameter + " ";
- }
-strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
-packetTail.params[RS_PARAMS_LEN - 1] = 0;
-
-assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
-
-Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
-{
-char buffer[RS_MAX_PACKET_LEN];
-
-memset(buffer, 0, sizeof(buffer));
-
-if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
- {
- printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
- return true;
- }
-
-std::for_each(
- rsu.routers.begin(),
- rsu.routers.end(),
- PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
- );
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
-{
-char buffer[RS_MAX_PACKET_LEN];
-
-if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
- {
- printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
- return true;
- }
-
-struct sockaddr_in sendAddr;
-
-sendAddr.sin_family = AF_INET;
-sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
-sendAddr.sin_addr.s_addr = routerIP;
-
-ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
-
-if (res < 0)
- logger("sendto error: %s", strerror(errno));
-
-return (res != sizeof(buffer));
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::GetUsers()
-{
-USER_PTR u;
-
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (!users->SearchNext(h, &u))
- {
- SetUserNotifiers(u);
- }
-
-users->CloseSearch(h);
-return false;
-}
-//-----------------------------------------------------------------------------
-std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
-{
-STG_LOCKER lock(&mutex);
-for (size_t i = 0; i < netRouters.size(); ++i)
- {
- if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
- {
- return netRouters[i].routers;
- }
- }
-return std::vector<uint32_t>();
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u)
-{
-ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
-connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u)
-{
-ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
- ipNotifierList.end(),
- USER_IS<IP_NOTIFIER>(u)),
- ipNotifierList.end());
-connNotifierList.erase(std::remove_if(connNotifierList.begin(),
- connNotifierList.end(),
- USER_IS<CONNECTED_NOTIFIER>(u)),
- connNotifierList.end());
-
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::AddRSU(USER_PTR user)
-{
-RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
-Send(rsu);
-
-STG_LOCKER lock(&mutex);
-authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::DelRSU(USER_PTR user)
-{
-STG_LOCKER lock(&mutex);
-std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
-while (it != authorizedUsers.end())
- {
- if (it->second.user == user)
- {
- Send(it->second, true);
- authorizedUsers.erase(it);
- return;
- }
- ++it;
- }
-/*const std::map<uint32_t, RS::USER>::iterator it(
- authorizedUsers.find(user->GetCurrIP())
- );
-if (it != authorizedUsers.end())
- {
- Send(it->second, true);
- authorizedUsers.erase(it);
- }*/
-}
-//-----------------------------------------------------------------------------
-void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
-{
-if (newValue)
- rs.AddRSU(user);
-else
- rs.DelRSU(user);
-}
-//-----------------------------------------------------------------------------
-void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
-{
-if (newValue)
- rs.AddRSU(user);
-else
- rs.DelRSU(user);
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
-{
-unsigned char keyL[PASSWD_LEN]; // Пароль для шифровки
-memset(keyL, 0, PASSWD_LEN);
-strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-Blowfish_Init(ctx, keyL, PASSWD_LEN);
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
-{
-if (dst != src)
- memcpy(dst, src, len8 * 8);
-for (size_t i = 0; i < len8; ++i)
- Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef RSCRIPT_H
-#define RSCRIPT_H
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/os_int.h"
-#include "stg/notifer.h"
-#include "stg/user.h"
-#include "stg/blowfish.h"
-#include "stg/rs_packets.h"
-#include "stg/logger.h"
-
-#include "nrmap_parser.h"
-
-#include <string>
-#include <list>
-#include <map>
-#include <functional>
-#include <utility>
-
-#include <pthread.h>
-
-extern "C" PLUGIN * GetPlugin();
-
-#define RS_DEBUG (1)
-
-#define MAX_SHORT_PCKT (3)
-
-class SETTINGS;
-class USERS;
-
-namespace RS
-{
-
-class REMOTE_SCRIPT;
-class UpdateRouter;
-class DisconnectUser;
-
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
-public:
- explicit ADD_USER_NONIFIER(REMOTE_SCRIPT & r)
- : NOTIFIER_BASE<USER_PTR>(), rs(r) {}
- virtual ~ADD_USER_NONIFIER() {}
- void Notify(const USER_PTR & user);
-
-private:
- ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rhs);
- ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER);
-
- REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
-public:
- explicit DEL_USER_NONIFIER(REMOTE_SCRIPT & r)
- : NOTIFIER_BASE<USER_PTR>(), rs(r) {}
- virtual ~DEL_USER_NONIFIER() {}
- void Notify(const USER_PTR & user);
-
-private:
- DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rhs);
- DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER);
-
- REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class IP_NOTIFIER: public PROPERTY_NOTIFIER_BASE<uint32_t> {
-public:
- IP_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(), user(u), rs(r) { user->AddCurrIPAfterNotifier(this); }
- IP_NOTIFIER(const IP_NOTIFIER & rhs)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(), user(rhs.user), rs(rhs.rs) { user->AddCurrIPAfterNotifier(this); }
- ~IP_NOTIFIER() { user->DelCurrIPAfterNotifier(this); }
-
- IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs)
- {
- user->DelCurrIPAfterNotifier(this);
- user = rhs.user;
- user->AddCurrIPAfterNotifier(this);
- return *this;
- }
-
- void Notify(const uint32_t & oldValue, const uint32_t & newValue);
- USER_PTR GetUser() const { return user; }
-
-private:
-
- USER_PTR user;
- REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class CONNECTED_NOTIFIER: public PROPERTY_NOTIFIER_BASE<bool> {
-public:
- CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u)
- : PROPERTY_NOTIFIER_BASE<bool>(), user(u), rs(r) { user->AddConnectedAfterNotifier(this); }
- CONNECTED_NOTIFIER(const CONNECTED_NOTIFIER & rhs)
- : PROPERTY_NOTIFIER_BASE<bool>(), user(rhs.user), rs(rhs.rs) { user->AddConnectedAfterNotifier(this); }
- ~CONNECTED_NOTIFIER() { user->DelConnectedAfterNotifier(this); }
-
- CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs)
- {
- user->DelConnectedAfterNotifier(this);
- user = rhs.user;
- user->AddConnectedAfterNotifier(this);
- return *this;
- }
-
- void Notify(const bool & oldValue, const bool & newValue);
- USER_PTR GetUser() const { return user; }
-
-private:
-
- USER_PTR user;
- REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-struct USER {
- USER(const std::vector<uint32_t> & r, USER_PTR it)
- : lastSentTime(0),
- user(it),
- routers(r),
- shortPacketsCount(0),
- ip(user->GetCurrIP())
- {}
-
- time_t lastSentTime;
- USER_PTR user;
- std::vector<uint32_t> routers;
- int shortPacketsCount;
- uint32_t ip;
-};
-//-----------------------------------------------------------------------------
-class SETTINGS {
-public:
- SETTINGS();
- virtual ~SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
- int GetSendPeriod() const { return sendPeriod; }
- uint16_t GetPort() const { return port; }
- const std::vector<NET_ROUTER> & GetSubnetsMap() const { return netRouters; }
- const std::vector<std::string> & GetUserParams() const { return userParams; }
- const std::string & GetPassword() const { return password; }
- const std::string & GetMapFileName() const { return subnetFile; }
-
-private:
- int sendPeriod;
- uint16_t port;
- std::string errorStr;
- std::vector<NET_ROUTER> netRouters;
- std::vector<std::string> userParams;
- std::string password;
- std::string subnetFile;
-};
-//-----------------------------------------------------------------------------
-class REMOTE_SCRIPT : public PLUGIN {
-public:
- REMOTE_SCRIPT();
- virtual ~REMOTE_SCRIPT();
-
- void SetUsers(USERS * u) { users = u; }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & ms);
- bool IsRunning() { return isRunning; }
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return "Remote script v 0.3"; }
- uint16_t GetStartPosition() const { return 10; }
- uint16_t GetStopPosition() const { return 10; }
-
- void DelUser(USER_PTR u) { UnSetUserNotifiers(u); }
- void AddUser(USER_PTR u) { SetUserNotifiers(u); }
-
- void AddRSU(USER_PTR user);
- void DelRSU(USER_PTR user);
-
-private:
- REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs);
- REMOTE_SCRIPT & operator=(const REMOTE_SCRIPT & rhs);
-
- static void * Run(void *);
- bool PrepareNet();
- bool FinalizeNet();
-
- bool Send(USER & rsu, bool forceDisconnect = false) const;
- bool SendDirect(USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const;
- bool PreparePacket(char * buf, size_t bufSize, USER &rsu, bool forceDisconnect = false) const;
- void PeriodicSend();
-
- std::vector<uint32_t> IP2Routers(uint32_t ip);
- bool GetUsers();
-
- void SetUserNotifiers(USER_PTR u);
- void UnSetUserNotifiers(USER_PTR u);
-
- void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const;
- void Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const;
-
- mutable BLOWFISH_CTX ctx;
-
- std::list<IP_NOTIFIER> ipNotifierList;
- std::list<CONNECTED_NOTIFIER> connNotifierList;
- std::map<uint32_t, USER> authorizedUsers;
-
- mutable std::string errorStr;
- SETTINGS rsSettings;
- MODULE_SETTINGS settings;
- int sendPeriod;
- int halfPeriod;
-
- bool nonstop;
- bool isRunning;
-
- USERS * users;
-
- std::vector<NET_ROUTER> netRouters;
-
- pthread_t thread;
- pthread_mutex_t mutex;
-
- int sock;
-
- ADD_USER_NONIFIER onAddUserNotifier;
- DEL_USER_NONIFIER onDelUserNotifier;
-
- PLUGIN_LOGGER logger;
-
- friend class RS::UpdateRouter;
- friend class RS::DisconnectUser;
- friend class RS::CONNECTED_NOTIFIER;
-};
-//-----------------------------------------------------------------------------
-class DisconnectUser : public std::unary_function<std::pair<const uint32_t, USER> &, void> {
- public:
- explicit DisconnectUser(REMOTE_SCRIPT & rs) : rscript(rs) {}
- void operator()(std::pair<const uint32_t, USER> & p)
- {
- rscript.Send(p.second, true);
- }
- private:
- REMOTE_SCRIPT & rscript;
-};
-//-----------------------------------------------------------------------------
-inline void ADD_USER_NONIFIER::Notify(const USER_PTR & user)
-{
-rs.AddUser(user);
-}
-//-----------------------------------------------------------------------------
-inline void DEL_USER_NONIFIER::Notify(const USER_PTR & user)
-{
-rs.DelUser(user);
-}
-//-----------------------------------------------------------------------------
-
-} // namespace RS
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2010/03/04 12:11:09 $
- $Author: faust $
-*/
-
-#ifndef __SEND_FUNCTOR_H__
-#define __SEND_FUNCTOR_H__
-
-#include "stg/os_int.h"
-
-#include <functional>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-class PacketSender : public std::unary_function<uint32_t, ssize_t> {
- public:
- PacketSender(int s, char * b, size_t l, uint16_t p)
- : sock(s),
- buffer(b),
- length(l),
- port(p) {}
- ssize_t operator() (uint32_t ip)
- {
- struct sockaddr_in sendAddr;
-
- sendAddr.sin_family = AF_INET;
- sendAddr.sin_port = port;
- sendAddr.sin_addr.s_addr = ip;
-
- return sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
- }
- private:
- int sock;
- char * buffer;
- size_t length;
- uint16_t port;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __UR_FUNCTOR_H__
-#define __UR_FUNCTOR_H__
-
-#include "rscript.h"
-
-#include "stg/os_int.h"
-#include "stg/common.h"
-
-#include <functional>
-#include <algorithm>
-#include <utility>
-
-namespace RS
-{
-
-class UpdateRouter : public std::unary_function<std::pair<const uint32_t, RS::USER>, void>
-{
-public:
- explicit UpdateRouter(REMOTE_SCRIPT & t)
- : obj(t) {}
-
- void operator() (std::pair<const uint32_t, USER> & val)
- {
- std::vector<uint32_t> newRouters = obj.IP2Routers(val.second.ip);
- std::vector<uint32_t>::const_iterator oldIt(val.second.routers.begin());
- std::vector<uint32_t>::const_iterator newIt(newRouters.begin());
- val.second.shortPacketsCount = 0;
- while (oldIt != val.second.routers.end() ||
- newIt != newRouters.end())
- {
- if (oldIt == val.second.routers.end())
- {
- if (newIt != newRouters.end())
- {
- obj.SendDirect(val.second, *newIt); // Connect on new router
- ++newIt;
- }
- }
- else if (newIt == newRouters.end())
- {
- obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
- ++oldIt;
- }
- else if (*oldIt < *newIt)
- {
- obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
- ++oldIt;
- }
- else if (*oldIt > *newIt)
- {
- obj.SendDirect(val.second, *newIt); // Connect on new router
- ++newIt;
- }
- else
- {
- ++oldIt;
- if (newIt != newRouters.end())
- ++newIt;
- }
- }
- val.second.routers = newRouters;
- }
-private:
- REMOTE_SCRIPT & obj;
-};
-
-} // namespace RS
-
-#endif
+++ /dev/null
-include ../../../../../Makefile.conf
-
-LIBS += $(LIB_THREAD)
-
-PROG = mod_smux.so
-
-SRCS = smux.cpp \
- sensors.cpp \
- tables.cpp \
- handlers.cpp \
- utils.cpp \
- types.cpp
-
-STGLIBS = common \
- smux \
- logger \
- scriptexecuter
-
-CFLAGS += -I ../../../../../stglibs/smux.lib/include/stg
-CXXFLAGS += -I ../../../../../stglibs/smux.lib/include/stg
-
-include ../../Makefile.in
+++ /dev/null
-STG-MIB DEFINITIONS ::= BEGIN
-
-IMPORTS
- enterprises,
- MODULE-IDENTITY, OBJECT-TYPE,
- Integer32 FROM SNMPv2-SMI
- DisplayString FROM SNMPv2-TC;
-
-stgMIB MODULE-IDENTITY
- LAST-UPDATED "201101060000Z"
- ORGANIZATION "STG"
- CONTACT-INFO
- "Primary Contact: Maxim Mamontov
- email: faust@stg.dp.ua"
- DESCRIPTION
- "This MIB module defines objects for Stargazer data."
- REVISION "201101060000Z"
- DESCRIPTION "Initial revision"
- ::= { enterprises 38313 }
-
-stg24 OBJECT IDENTIFIER ::= { stgMIB 1 }
-
-users OBJECT IDENTIFIER ::= { stg24 1 }
-tariffs OBJECT IDENTIFIER ::= { stg24 2 }
-admins OBJECT IDENTIFIER ::= { stg24 3 }
-services OBJECT IDENTIFIER ::= { stg24 4 }
-corporations OBJECT IDENTIFIER ::= { stg24 5 }
-traffcounter OBJECT IDENTIFIER ::= { stg24 6 }
-
-totalUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total users registered in the billing"
- DEFVAL { 0 }
- ::= { users 1 }
-
-onlineUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of currently online users"
- DEFVAL { 0 }
- ::= { users 2 }
-
-authorizedUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of currently authorized users"
- DEFVAL { 0 }
- ::= { users 3 }
-
-alwaysOnlineUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users with 'always online' option"
- DEFVAL { 0 }
- ::= { users 4 }
-
-noCashUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users with negative cash"
- DEFVAL { 0 }
- ::= { users 5 }
-
-disabledDetailStatsUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users with disabled detail stats"
- DEFVAL { 0 }
- ::= { users 6 }
-
-disabledUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of disabled users"
- DEFVAL { 0 }
- ::= { users 7 }
-
-passiveUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of passive users"
- DEFVAL { 0 }
- ::= { users 8 }
-
-creditUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users with positive credit"
- DEFVAL { 0 }
- ::= { users 9 }
-
-freeMbUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users with positive freeMb"
- DEFVAL { 0 }
- ::= { users 10 }
-
-tariffChangeUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of users changing tariff next month"
- DEFVAL { 0 }
- ::= { users 11 }
-
-activeUsers OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The number of online users with traffic during session"
- DEFVAL {0}
- ::= { users 12 }
-
-totalTariffs OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total tariffs registered in the billing"
- DEFVAL { 0 }
- ::= { tariffs 1 }
-
-tariffUsageTable OBJECT-TYPE
- SYNTAX SEQUENCE OF TariffUsageTable
- MAX-ACCESS not-accessible
- STATUS current
- DESCRIPTION
- "The number of users by each tariff"
- DEFVAL { 0 }
- ::= { tariffs 2 }
-
-tariffUsageTableEntry OBJECT-TYPE
- SYNTAX TariffUsageTable
- MAX-ACCESS not-accessible
- STATUS current
- DESCRIPTION
- "A row describing a given tariff"
- INDEX { tariffIndex }
- ::= {tariffUsageTable 1 }
-
-TariffUsageTable ::= SEQUENCE {
- tariffIndex Integer32,
- tariffName DisplayString,
- userCount Integer32
-}
-
-tariffIndex OBJECT-TYPE
- SYNTAX Integer32 (0..255)
- MAX-ACCESS not-accessible
- STATUS current
- DESCRIPTION
- "The id of the tariff this table describes."
- ::= { tariffUsageTableEntry 1 }
-
-tariffName OBJECT-TYPE
- SYNTAX DisplayString
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The name of the tariff this table describes."
- ::= { tariffUsageTableEntry 2 }
-
-userCount OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "The count fo users of the tariff this table describes."
- ::= { tariffUsageTableEntry 3 }
-
-totalAdmins OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total admins registered in the billing"
- DEFVAL { 0 }
- ::= { admins 1 }
-
-totalServices OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total services registered in the billing"
- DEFVAL { 0 }
- ::= { services 1 }
-
-totalCorporations OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total corporations registered in the billing"
- DEFVAL { 0 }
- ::= { corporations 1 }
-
-totalRules OBJECT-TYPE
- SYNTAX Integer32
- MAX-ACCESS read-only
- STATUS current
- DESCRIPTION
- "Total traffic classification rules described by rules file"
- DEFVAL { 0 }
- ::= { traffcounter 1 }
-
-END
+++ /dev/null
-Количество пользователей всего в биллинге
-Количество пользователей онлайн
-Количество пользователей с отрицательный балансом
-Количество пользователей с всегда онлайн
-Количество пользователей по отношению к каждому из тарифов
-Количество пользователей по отношению к каждому UserData полю - ?
-Количество пользователей с отключенной детальной статистикой
-Количество отключенных пользователей
-Количество замороженных пользователей
-Количество пользователей, у которых есть кредит
-Количество пользователей, у которых есть предоплаченный трафик
-
-Количество тарифов
-Количество направлений
+++ /dev/null
-#include <cassert>
-
-#include "stg/GetRequest-PDU.h"
-#include "stg/GetResponse-PDU.h"
-#include "stg/VarBindList.h"
-#include "stg/VarBind.h"
-
-#include "stg/common.h"
-
-#include "utils.h"
-#include "smux.h"
-
-#ifdef SMUX_DEBUG
-bool SMUX::CloseHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::CloseHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::CloseHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-#ifdef SMUX_DEBUG
-bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::RegisterResponseHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-bool SMUX::PDUsRequestHandler(const SMUX_PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::PDUsRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-#endif
-PDUsHandlers::iterator it(pdusHandlers.find(pdus->choice.pdus.present));
-if (it != pdusHandlers.end())
- {
- return (this->*(it->second))(&pdus->choice.pdus);
- }
-#ifdef SMUX_DEBUG
-else
- {
- switch (pdus->present)
- {
- case PDUs_PR_NOTHING:
- printfd(__FILE__, "SMUX::PDUsRequestHandler() - nothing\n");
- break;
- case PDUs_PR_get_response:
- printfd(__FILE__, "SMUX::PDUsRequestHandler() - get response\n");
- break;
- case PDUs_PR_trap:
- printfd(__FILE__, "SMUX::PDUsRequestHandler() - trap\n");
- break;
- default:
- printfd(__FILE__, "SMUX::PDUsRequestHandler() - undefined\n");
- }
- }
-#endif
-return true;
-}
-
-#ifdef SMUX_DEBUG
-bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::CommitOrRollbackHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-bool SMUX::GetRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::GetRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
-GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
-assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
-VarBindList_t * varBindList = &msg->variable_bindings;
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg->request_id, id);
-asn_long2INTEGER(&msg->error_status, 0);
-asn_long2INTEGER(&msg->error_index, 0);
-
-const VarBindList_t * vbl = &getRequest->variable_bindings;
-for (int i = 0; i < vbl->list.count; ++i)
- {
- VarBind_t * vb = getRequest->variable_bindings.list.array[i];
- Sensors::iterator it;
- it = sensors.find(OID(&vb->name));
- if (it == sensors.end())
- {
- return SendGetResponseErrorPDU(sock, getRequest,
- PDU__error_status_noSuchName, i);
- }
-
- VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
- assert(newVb && "Enought mempry to allocate VarBind_t");
-
- it->first.ToOID(&newVb->name);
- it->second->GetValue(&newVb->value);
-
- ASN_SEQUENCE_ADD(varBindList, newVb);
- }
-
-bool res = SendGetResponsePDU(sock, msg);
-#ifdef SMUX_DEBUG
-asn_fprint(stderr, &asn_DEF_GetResponse_PDU, msg);
-#endif
-ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
-return res;
-}
-
-bool SMUX::GetNextRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::GetNextRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
-GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
-assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
-VarBindList_t * varBindList = &msg->variable_bindings;
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg->request_id, id);
-asn_long2INTEGER(&msg->error_status, 0);
-asn_long2INTEGER(&msg->error_index, 0);
-
-const VarBindList_t * vbl = &getRequest->variable_bindings;
-for (int i = 0; i < vbl->list.count; ++i)
- {
- VarBind_t * vb = getRequest->variable_bindings.list.array[i];
- Sensors::iterator it;
- it = sensors.upper_bound(OID(&vb->name));
- if (it == sensors.end())
- {
-#ifdef SMUX_DEBUG
- printfd(__FILE__, "SMUX::GetNextRequestHandler() - '%s' not found\n", OID(&vb->name).ToString().c_str());
-#endif
- return SendGetResponseErrorPDU(sock, getRequest,
- PDU__error_status_noSuchName, i);
- }
-
- VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
- assert(newVb && "Enought mempry to allocate VarBind_t");
-
- it->first.ToOID(&newVb->name);
- it->second->GetValue(&newVb->value);
-
- ASN_SEQUENCE_ADD(varBindList, newVb);
- }
-
-bool res = SendGetResponsePDU(sock, msg);
-#ifdef SMUX_DEBUG
-asn_fprint(stderr, &asn_DEF_PDU, msg);
-#endif
-ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
-return res;
-}
-
-bool SMUX::SetRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::SetRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-return SendGetResponseErrorPDU(sock, &pdus->choice.set_request,
- PDU__error_status_readOnly, 0);
-}
+++ /dev/null
-#ifndef __PEN_H__
-#define __PEN_H__
-
-#define PEN_PREFIX ".1.3.6.1.4.1.38313"
-
-#endif
+++ /dev/null
-#include <cassert>
-
-#include "stg/INTEGER.h"
-
-#include "stg/user.h"
-
-#include "sensors.h"
-
-bool UsersSensor::GetValue(ObjectSyntax_t * objectSyntax) const
-{
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-USER_PTR user;
-size_t count = 0;
-while (!users.SearchNext(handle, &user))
- {
- if (UserPredicate(user))
- ++count;
- }
-
-users.CloseSearch(handle);
-
-ValueToOS(count, objectSyntax);
-return true;
-}
-
-#ifdef DEBUG
-std::string UsersSensor::ToString() const
-{
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-USER_PTR user;
-size_t count = 0;
-while (!users.SearchNext(handle, &user))
- {
- if (UserPredicate(user))
- ++count;
- }
-
-users.CloseSearch(handle);
-
-std::string res;
-x2str(count, res);
-return res;
-}
-#endif
-
-bool ActiveUsersSensor::UserPredicate(USER_PTR userPtr) const
-{
-if (!userPtr->GetConnected())
- return false;
-for (size_t i = 0; i < DIR_NUM; ++i)
- {
- if (userPtr->GetSessionUpload()[i] > 0 ||
- userPtr->GetSessionDownload()[i] > 0)
- return true;
- }
-return false;
-}
+++ /dev/null
-#ifndef __SENSORS_H__
-#define __SENSORS_H__
-
-#include <map>
-
-#include "stg/users.h"
-#include "stg/tariffs.h"
-#include "stg/admins.h"
-#include "stg/services.h"
-#include "stg/corporations.h"
-#include "stg/traffcounter.h"
-#include "stg/user_property.h"
-
-#include "stg/ObjectSyntax.h"
-
-#include "value2os.h"
-#include "types.h"
-
-class Sensor {
- public:
- virtual ~Sensor() {}
- virtual bool GetValue(ObjectSyntax_t * objectSyntax) const = 0;
-#ifdef DEBUG
- virtual std::string ToString() const = 0;
-#endif
-};
-
-typedef std::map<OID, Sensor *> Sensors;
-
-class TotalUsersSensor : public Sensor {
- public:
- explicit TotalUsersSensor(const USERS & u) : users(u) {}
- virtual ~TotalUsersSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(users.Count(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(users.Count(), res); return res; }
-#endif
-
- private:
- const USERS & users;
-};
-
-class UsersSensor : public Sensor {
- public:
- explicit UsersSensor(USERS & u) : users(u) {}
- virtual ~UsersSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const;
-#ifdef DEBUG
- std::string ToString() const;
-#endif
-
- private:
- USERS & users;
-
- virtual bool UserPredicate(USER_PTR userPtr) const = 0;
-};
-
-class ConnectedUsersSensor : public UsersSensor {
- public:
- explicit ConnectedUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~ConnectedUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetConnected(); }
-};
-
-class AuthorizedUsersSensor : public UsersSensor {
- public:
- explicit AuthorizedUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~AuthorizedUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetAuthorized(); }
-};
-
-class AlwaysOnlineUsersSensor : public UsersSensor {
- public:
- explicit AlwaysOnlineUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~AlwaysOnlineUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().alwaysOnline; }
-};
-
-class NoCashUsersSensor : public UsersSensor {
- public:
- explicit NoCashUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~NoCashUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().cash < 0; }
-};
-
-class DisabledDetailStatsUsersSensor : public UsersSensor {
- public:
- explicit DisabledDetailStatsUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~DisabledDetailStatsUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().disabledDetailStat; }
-};
-
-class DisabledUsersSensor : public UsersSensor {
- public:
- explicit DisabledUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~DisabledUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().disabled; }
-};
-
-class PassiveUsersSensor : public UsersSensor {
- public:
- explicit PassiveUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~PassiveUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().passive; }
-};
-
-class CreditUsersSensor : public UsersSensor {
- public:
- explicit CreditUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~CreditUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().credit > 0; }
-};
-
-class FreeMbUsersSensor : public UsersSensor {
- public:
- explicit FreeMbUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~FreeMbUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return userPtr->GetProperty().freeMb > 0; }
-};
-
-class TariffChangeUsersSensor : public UsersSensor {
- public:
- explicit TariffChangeUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~TariffChangeUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const
- { return !userPtr->GetProperty().nextTariff.ConstData().empty(); }
-};
-
-class ActiveUsersSensor : public UsersSensor {
- public:
- explicit ActiveUsersSensor(USERS & u) : UsersSensor(u) {}
- virtual ~ActiveUsersSensor() {}
-
- private:
- bool UserPredicate(USER_PTR userPtr) const;
-};
-
-class TotalTariffsSensor : public Sensor {
- public:
- explicit TotalTariffsSensor(const TARIFFS & t) : tariffs(t) {}
- virtual ~TotalTariffsSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(tariffs.Count(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(tariffs.Count(), res); return res; }
-#endif
-
- private:
- const TARIFFS & tariffs;
-};
-
-class TotalAdminsSensor : public Sensor {
- public:
- explicit TotalAdminsSensor(const ADMINS & a) : admins(a) {}
- virtual ~TotalAdminsSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(admins.Count(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(admins.Count(), res); return res; }
-#endif
-
- private:
- const ADMINS & admins;
-};
-
-class TotalServicesSensor : public Sensor {
- public:
- explicit TotalServicesSensor(const SERVICES & s) : services(s) {}
- virtual ~TotalServicesSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(services.Count(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(services.Count(), res); return res; }
-#endif
-
- private:
- const SERVICES & services;
-};
-
-class TotalCorporationsSensor : public Sensor {
- public:
- explicit TotalCorporationsSensor(const CORPORATIONS & c) : corporations(c) {}
- virtual ~TotalCorporationsSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(corporations.Count(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(corporations.Count(), res); return res; }
-#endif
-
- private:
- const CORPORATIONS & corporations;
-};
-
-class TotalRulesSensor : public Sensor {
- public:
- explicit TotalRulesSensor(const TRAFFCOUNTER & t) : traffcounter(t) {}
- virtual ~TotalRulesSensor() {}
-
- bool GetValue(ObjectSyntax_t * objectSyntax) const
- {
- ValueToOS(traffcounter.RulesCount(), objectSyntax);
- return true;
- }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(traffcounter.RulesCount(), res); return res; }
-#endif
-
- private:
- const TRAFFCOUNTER & traffcounter;
-};
-
-template <typename T>
-class ConstSensor : public Sensor {
- public:
- explicit ConstSensor(const T & v) : value(v) {}
- virtual ~ConstSensor() {}
-
- bool GetValue(ObjectSyntax * objectSyntax) const
- { return ValueToOS(value, objectSyntax); }
-
-#ifdef DEBUG
- std::string ToString() const
- { std::string res; x2str(value, res); return res; }
-#endif
-
- private:
- T value;
-};
-
-#ifdef DEBUG
-template <>
-inline
-std::string ConstSensor<std::string>::ToString() const
-{
-return value;
-}
-#endif
-
-#endif
+++ /dev/null
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <cstring>
-#include <cerrno>
-#include <ctime>
-#include <csignal>
-#include <cassert>
-
-#include <vector>
-#include <algorithm>
-#include <iterator>
-#include <stdexcept>
-#include <utility>
-
-#include "stg/common.h"
-#include "stg/plugin_creator.h"
-
-#include "smux.h"
-#include "utils.h"
-
-namespace
-{
-PLUGIN_CREATOR<SMUX> smc;
-
-bool SPrefixLess(const Sensors::value_type & a,
- const Sensors::value_type & b)
-{
-return a.first.PrefixLess(b.first);
-}
-
-}
-
-extern "C" PLUGIN * GetPlugin();
-
-PLUGIN * GetPlugin()
-{
-return smc.GetPlugin();
-}
-
-SMUX_SETTINGS::SMUX_SETTINGS()
- : errorStr(),
- ip(0),
- port(0),
- password()
-{}
-
-int SMUX_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-PARAM_VALUE pv;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-int p;
-
-pv.param = "Port";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Port\' not found.";
- printfd(__FILE__, "Parameter 'Port' not found\n");
- return -1;
- }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
- {
- errorStr = "Cannot parse parameter \'Port\': " + errorStr;
- printfd(__FILE__, "Cannot parse parameter 'Port'\n");
- return -1;
- }
-port = static_cast<uint16_t>(p);
-
-pv.param = "Password";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Password\' not found.";
- printfd(__FILE__, "Parameter 'Password' not found\n");
- password = "";
- }
-else
- {
- password = pvi->value[0];
- }
-
-pv.param = "Server";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'Server\' not found.";
- printfd(__FILE__, "Parameter 'Server' not found\n");
- return -1;
- }
-ip = inet_strington(pvi->value[0]);
-
-return 0;
-}
-
-SMUX::SMUX()
- : PLUGIN(),
- users(NULL),
- tariffs(NULL),
- admins(NULL),
- services(NULL),
- corporations(NULL),
- traffcounter(NULL),
- errorStr(),
- smuxSettings(),
- settings(),
- thread(),
- mutex(),
- running(false),
- stopped(true),
- needReconnect(false),
- lastReconnectTry(0),
- reconnectTimeout(1),
- sock(-1),
- smuxHandlers(),
- pdusHandlers(),
- sensors(),
- tables(),
- notifiers(),
- addUserNotifier(*this),
- delUserNotifier(*this),
- addDelTariffNotifier(*this),
- logger(GetPluginLogger(GetStgLogger(), "smux"))
-{
-pthread_mutex_init(&mutex, NULL);
-
-smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
-smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
-smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsRequestHandler;
-smuxHandlers[SMUX_PDUs_PR_commitOrRollback] = &SMUX::CommitOrRollbackHandler;
-
-pdusHandlers[PDUs_PR_get_request] = &SMUX::GetRequestHandler;
-pdusHandlers[PDUs_PR_get_next_request] = &SMUX::GetNextRequestHandler;
-pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
-}
-
-SMUX::~SMUX()
-{
- {
- Sensors::iterator it;
- for (it = sensors.begin(); it != sensors.end(); ++it)
- delete it->second;
- }
- {
- Tables::iterator it;
- for (it = tables.begin(); it != tables.end(); ++it)
- delete it->second;
- }
-printfd(__FILE__, "SMUX::~SMUX()\n");
-pthread_mutex_destroy(&mutex);
-}
-
-int SMUX::ParseSettings()
-{
-return smuxSettings.ParseSettings(settings);
-}
-
-int SMUX::Start()
-{
-assert(users != NULL && "users must not be NULL");
-assert(tariffs != NULL && "tariffs must not be NULL");
-assert(admins != NULL && "admins must not be NULL");
-assert(services != NULL && "services must not be NULL");
-assert(corporations != NULL && "corporations must not be NULL");
-assert(traffcounter != NULL && "traffcounter must not be NULL");
-
-if (PrepareNet())
- needReconnect = true;
-
-// Users
-sensors[OID(".1.3.6.1.4.1.38313.1.1.1")] = new TotalUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.2")] = new ConnectedUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.3")] = new AuthorizedUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.4")] = new AlwaysOnlineUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.5")] = new NoCashUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.6")] = new DisabledDetailStatsUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.7")] = new DisabledUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.8")] = new PassiveUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.9")] = new CreditUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.10")] = new FreeMbUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new TariffChangeUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new ActiveUsersSensor(*users);
-// Tariffs
-sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
-// Admins
-sensors[OID(".1.3.6.1.4.1.38313.1.3.1")] = new TotalAdminsSensor(*admins);
-// Services
-sensors[OID(".1.3.6.1.4.1.38313.1.4.1")] = new TotalServicesSensor(*services);
-// Corporations
-sensors[OID(".1.3.6.1.4.1.38313.1.5.1")] = new TotalCorporationsSensor(*corporations);
-// Traffcounter
-sensors[OID(".1.3.6.1.4.1.38313.1.6.1")] = new TotalRulesSensor(*traffcounter);
-
-// Table data
-tables[".1.3.6.1.4.1.38313.1.2.2"] = new TariffUsersTable(".1.3.6.1.4.1.38313.1.2.2", *tariffs, *users);
-
-UpdateTables();
-SetNotifiers();
-
-#ifdef SMUX_DEBUG
-Sensors::const_iterator it(sensors.begin());
-while (it != sensors.end())
- {
- printfd(__FILE__, "%s = %s\n",
- it->first.ToString().c_str(),
- it->second->ToString().c_str());
- ++it;
- }
-#endif
-
-if (!running)
- {
- if (pthread_create(&thread, NULL, Runner, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
- }
-
-return 0;
-}
-
-int SMUX::Stop()
-{
-printfd(__FILE__, "SMUX::Stop() - Before\n");
-running = false;
-
-if (!stopped)
- {
- //5 seconds to thread stops itself
- for (int i = 0; i < 25 && !stopped; i++)
- {
- struct timespec ts = {0, 200000000};
- nanosleep(&ts, NULL);
- }
- }
-
-if (stopped)
- pthread_join(thread, NULL);
-
-ResetNotifiers();
-
- {
- Tables::iterator it;
- for (it = tables.begin(); it != tables.end(); ++it)
- delete it->second;
- }
- {
- Sensors::iterator it;
- for (it = sensors.begin(); it != sensors.end(); ++it)
- delete it->second;
- }
-
-tables.erase(tables.begin(), tables.end());
-sensors.erase(sensors.begin(), sensors.end());
-
-close(sock);
-
-if (!stopped)
- {
- running = true;
- return -1;
- }
-
-printfd(__FILE__, "SMUX::Stop() - After\n");
-return 0;
-}
-
-int SMUX::Reload(const MODULE_SETTINGS & /*ms*/)
-{
-if (Stop())
- return -1;
-if (Start())
- return -1;
-if (!needReconnect)
- {
- printfd(__FILE__, "SMUX reconnected succesfully.\n");
- logger("Reconnected successfully.");
- }
-return 0;
-}
-
-void * SMUX::Runner(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-SMUX * smux = static_cast<SMUX *>(d);
-
-smux->Run();
-
-return NULL;
-}
-
-void SMUX::Run()
-{
-stopped = true;
-if (!SendOpenPDU(sock))
- needReconnect = true;
-if (!SendRReqPDU(sock))
- needReconnect = true;
-running = true;
-stopped = false;
-
-while(running)
- {
- if (WaitPackets(sock) && !needReconnect)
- {
- SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
- if (pdus)
- {
- DispatchPDUs(pdus);
- ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
- }
- else if (running)
- Reconnect();
- }
- else if (running && needReconnect)
- Reconnect();
- if (!running)
- break;
- }
-SendClosePDU(sock);
-stopped = true;
-}
-
-bool SMUX::PrepareNet()
-{
-sock = socket(AF_INET, SOCK_STREAM, 0);
-
-if (sock < 0)
- {
- errorStr = "Cannot create socket.";
- logger("Cannot create a socket: %s", strerror(errno));
- printfd(__FILE__, "Cannot create socket\n");
- return true;
- }
-
-struct sockaddr_in addr;
-
-addr.sin_family = AF_INET;
-addr.sin_port = htons(smuxSettings.GetPort());
-addr.sin_addr.s_addr = smuxSettings.GetIP();
-
-if (connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)))
- {
- errorStr = "Cannot connect.";
- logger("Cannot connect the socket: %s", strerror(errno));
- printfd(__FILE__, "Cannot connect. Message: '%s'\n", strerror(errno));
- return true;
- }
-
-return false;
-}
-
-bool SMUX::Reconnect()
-{
-if (needReconnect && difftime(time(NULL), lastReconnectTry) < reconnectTimeout)
- return true;
-
-time(&lastReconnectTry);
-SendClosePDU(sock);
-close(sock);
-if (!PrepareNet())
- if (SendOpenPDU(sock))
- if (SendRReqPDU(sock))
- {
- reconnectTimeout = 1;
- needReconnect = false;
- logger("Connected successfully");
- printfd(__FILE__, "Connected successfully\n");
- return false;
- }
-
-if (needReconnect)
- if (reconnectTimeout < 60)
- reconnectTimeout *= 2;
-
-needReconnect = true;
-return true;
-}
-
-bool SMUX::DispatchPDUs(const SMUX_PDUs_t * pdus)
-{
-SMUXHandlers::iterator it(smuxHandlers.find(pdus->present));
-if (it != smuxHandlers.end())
- {
- return (this->*(it->second))(pdus);
- }
-#ifdef SMUX_DEBUG
-else
- {
- switch (pdus->present)
- {
- case SMUX_PDUs_PR_NOTHING:
- printfd(__FILE__, "PDUs: nothing\n");
- break;
- case SMUX_PDUs_PR_open:
- printfd(__FILE__, "PDUs: open\n");
- break;
- case SMUX_PDUs_PR_registerRequest:
- printfd(__FILE__, "PDUs: registerRequest\n");
- break;
- default:
- printfd(__FILE__, "PDUs: undefined\n");
- }
- asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
- }
-#endif
-return false;
-}
-
-bool SMUX::UpdateTables()
-{
-Sensors newSensors;
-bool done = true;
-Tables::iterator it(tables.begin());
-while (it != tables.end())
- {
- try
- {
- it->second->UpdateSensors(newSensors);
- }
- catch (const std::runtime_error & ex)
- {
- printfd(__FILE__,
- "SMUX::UpdateTables - failed to update table '%s': '%s'\n",
- it->first.c_str(), ex.what());
- done = false;
- break;
- }
- ++it;
- }
-if (!done)
- {
- Sensors::iterator it(newSensors.begin());
- while (it != newSensors.end())
- {
- delete it->second;
- ++it;
- }
- return false;
- }
-
-it = tables.begin();
-while (it != tables.end())
- {
- std::pair<Sensors::iterator, Sensors::iterator> res;
- res = std::equal_range(sensors.begin(),
- sensors.end(),
- std::pair<OID, Sensor *>(OID(it->first), NULL),
- SPrefixLess);
- Sensors::iterator sit(res.first);
- while (sit != res.second)
- {
- delete sit->second;
- ++sit;
- }
- sensors.erase(res.first, res.second);
- ++it;
- }
-
-sensors.insert(newSensors.begin(), newSensors.end());
-
-return true;
-}
-
-void SMUX::SetNotifier(USER_PTR userPtr)
-{
-notifiers.push_back(CHG_AFTER_NOTIFIER(*this, userPtr));
-userPtr->GetProperty().tariffName.AddAfterNotifier(¬ifiers.back());
-}
-
-void SMUX::UnsetNotifier(USER_PTR userPtr)
-{
-std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
-while (it != notifiers.end())
- {
- if (it->GetUserPtr() == userPtr)
- {
- userPtr->GetProperty().tariffName.DelAfterNotifier(&(*it));
- notifiers.erase(it);
- break;
- }
- ++it;
- }
-}
-
-void SMUX::SetNotifiers()
-{
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-USER_PTR u;
-while (!users->SearchNext(h, &u))
- SetNotifier(u);
-
-users->CloseSearch(h);
-
-users->AddNotifierUserAdd(&addUserNotifier);
-users->AddNotifierUserDel(&delUserNotifier);
-
-tariffs->AddNotifierAdd(&addDelTariffNotifier);
-tariffs->AddNotifierDel(&addDelTariffNotifier);
-}
-
-void SMUX::ResetNotifiers()
-{
-tariffs->DelNotifierDel(&addDelTariffNotifier);
-tariffs->DelNotifierAdd(&addDelTariffNotifier);
-
-users->DelNotifierUserDel(&delUserNotifier);
-users->DelNotifierUserAdd(&addUserNotifier);
-
-std::list<CHG_AFTER_NOTIFIER>::iterator it(notifiers.begin());
-while (it != notifiers.end())
- {
- it->GetUserPtr()->GetProperty().tariffName.DelAfterNotifier(&(*it));
- ++it;
- }
-notifiers.clear();
-}
+++ /dev/null
-#ifndef __SMUX_H__
-#define __SMUX_H__
-
-#include <pthread.h>
-
-#include <string>
-#include <map>
-#include <list>
-
-#include "stg/SMUX-PDUs.h"
-#include "stg/ObjectSyntax.h"
-
-#include "stg/os_int.h"
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include "sensors.h"
-#include "tables.h"
-#include "types.h"
-
-class USER;
-class SETTINGS;
-class SMUX;
-class USERS;
-class TARIFFS;
-class SERVICES;
-class CORPORATIONS;
-class TRAFFCOUNTER;
-
-typedef bool (SMUX::*SMUXPacketHandler)(const SMUX_PDUs_t * pdus);
-typedef bool (SMUX::*PDUsHandler)(const PDUs_t * pdus);
-typedef std::map<SMUX_PDUs_PR, SMUXPacketHandler> SMUXHandlers;
-typedef std::map<PDUs_PR, PDUsHandler> PDUsHandlers;
-//-----------------------------------------------------------------------------
-class SMUX_SETTINGS {
-public:
- SMUX_SETTINGS();
- virtual ~SMUX_SETTINGS() {}
- const std::string & GetStrError() const { return errorStr; }
- int ParseSettings(const MODULE_SETTINGS & s);
-
- uint32_t GetIP() const { return ip; }
- uint16_t GetPort() const { return port; }
- const std::string GetPassword() const { return password; }
-
-private:
- mutable std::string errorStr;
-
- uint32_t ip;
- uint16_t port;
- std::string password;
-};
-//-----------------------------------------------------------------------------
-class CHG_AFTER_NOTIFIER : public PROPERTY_NOTIFIER_BASE<std::string> {
-public:
- CHG_AFTER_NOTIFIER(SMUX & s, const USER_PTR & u)
- : PROPERTY_NOTIFIER_BASE<std::string>(),
- smux(s), userPtr(u) {}
- CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER & rvalue)
- : PROPERTY_NOTIFIER_BASE<std::string>(),
- smux(rvalue.smux), userPtr(rvalue.userPtr) {}
- void Notify(const std::string &, const std::string &);
-
- USER_PTR GetUserPtr() const { return userPtr; }
-
-private:
- CHG_AFTER_NOTIFIER & operator=(const CHG_AFTER_NOTIFIER & rvalue);
- SMUX & smux;
- USER_PTR userPtr;
-};
-//-----------------------------------------------------------------------------
-class ADD_DEL_TARIFF_NOTIFIER : public NOTIFIER_BASE<TARIFF_DATA>, private NONCOPYABLE {
-public:
- explicit ADD_DEL_TARIFF_NOTIFIER(SMUX & s)
- : NOTIFIER_BASE<TARIFF_DATA>(), smux(s) {}
- void Notify(const TARIFF_DATA &);
-
-private:
- SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class ADD_USER_NOTIFIER : public NOTIFIER_BASE<USER_PTR>, private NONCOPYABLE {
-public:
- explicit ADD_USER_NOTIFIER(SMUX & s) : NOTIFIER_BASE<USER_PTR>(), smux(s) {}
- void Notify(const USER_PTR &);
-
-private:
- SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NOTIFIER : public NOTIFIER_BASE<USER_PTR>, private NONCOPYABLE {
-public:
- explicit DEL_USER_NOTIFIER(SMUX & s) : NOTIFIER_BASE<USER_PTR>(), smux(s) {}
- void Notify(const USER_PTR &);
-
-private:
- SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class SMUX : public PLUGIN {
-public:
- SMUX();
- virtual ~SMUX();
-
- void SetUsers(USERS * u) { users = u; }
- void SetTariffs(TARIFFS * t) { tariffs = t; }
- void SetAdmins(ADMINS * a) { admins = a; }
- void SetServices(SERVICES * s) { services = s; }
- void SetTraffcounter(TRAFFCOUNTER * tc) { traffcounter = tc; }
- void SetCorporations(CORPORATIONS * c) { corporations = c; }
- void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- int Start();
- int Stop();
- int Reload(const MODULE_SETTINGS & ms);
- bool IsRunning() { return running && !stopped; }
-
- const std::string & GetStrError() const { return errorStr; }
- std::string GetVersion() const { return "Stg SMUX Plugin 1.1"; }
- uint16_t GetStartPosition() const { return 10; }
- uint16_t GetStopPosition() const { return 10; }
-
- bool UpdateTables();
-
- void SetNotifier(USER_PTR userPtr);
- void UnsetNotifier(USER_PTR userPtr);
-
-private:
- SMUX(const SMUX & rvalue);
- SMUX & operator=(const SMUX & rvalue);
-
- static void * Runner(void * d);
- void Run();
- bool PrepareNet();
- bool Reconnect();
-
- bool DispatchPDUs(const SMUX_PDUs_t * pdus);
-
- bool CloseHandler(const SMUX_PDUs_t * pdus);
- bool RegisterResponseHandler(const SMUX_PDUs_t * pdus);
- bool PDUsRequestHandler(const SMUX_PDUs_t * pdus);
- bool CommitOrRollbackHandler(const SMUX_PDUs_t * pdus);
-
- bool GetRequestHandler(const PDUs_t * pdus);
- bool GetNextRequestHandler(const PDUs_t * pdus);
- bool SetRequestHandler(const PDUs_t * pdus);
-
- void SetNotifiers();
- void ResetNotifiers();
-
- USERS * users;
- TARIFFS * tariffs;
- ADMINS * admins;
- SERVICES * services;
- CORPORATIONS * corporations;
- TRAFFCOUNTER * traffcounter;
-
- mutable std::string errorStr;
- SMUX_SETTINGS smuxSettings;
- MODULE_SETTINGS settings;
-
- pthread_t thread;
- pthread_mutex_t mutex;
- bool running;
- bool stopped;
- bool needReconnect;
-
- time_t lastReconnectTry;
- unsigned reconnectTimeout;
-
- int sock;
-
- SMUXHandlers smuxHandlers;
- PDUsHandlers pdusHandlers;
- Sensors sensors;
- Tables tables;
-
- std::list<CHG_AFTER_NOTIFIER> notifiers;
- ADD_USER_NOTIFIER addUserNotifier;
- DEL_USER_NOTIFIER delUserNotifier;
- ADD_DEL_TARIFF_NOTIFIER addDelTariffNotifier;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-inline
-void CHG_AFTER_NOTIFIER::Notify(const std::string &, const std::string &)
-{
-smux.UpdateTables();
-}
-
-inline
-void ADD_DEL_TARIFF_NOTIFIER::Notify(const TARIFF_DATA &)
-{
-smux.UpdateTables();
-}
-
-inline
-void ADD_USER_NOTIFIER::Notify(const USER_PTR & userPtr)
-{
-smux.SetNotifier(userPtr);
-smux.UpdateTables();
-}
-
-inline
-void DEL_USER_NOTIFIER::Notify(const USER_PTR & userPtr)
-{
-smux.UnsetNotifier(userPtr);
-smux.UpdateTables();
-}
-
-#endif
+++ /dev/null
-#include <cassert>
-#include <utility>
-#include <iterator>
-#include <algorithm>
-
-#include "stg/user_property.h"
-#include "stg/tariffs.h"
-#include "stg/users.h"
-
-#include "tables.h"
-
-std::pair<std::string, size_t> TD2Info(const TARIFF_DATA & td);
-
-void TariffUsersTable::UpdateSensors(Sensors & sensors) const
-{
-std::map<std::string, size_t> data;
-
-std::list<TARIFF_DATA> tdl;
-tariffs.GetTariffsData(&tdl);
-std::transform(tdl.begin(),
- tdl.end(),
- std::inserter(data, data.begin()),
- TD2Info);
-
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-USER_PTR user;
-while (!users.SearchNext(handle, &user))
- {
- if (user->GetDeleted())
- continue;
- std::string tariffName(user->GetProperty().tariffName.ConstData());
- std::map<std::string, size_t>::iterator it(data.lower_bound(tariffName));
- if (it == data.end() ||
- it->first != tariffName)
- {
- data.insert(it, std::make_pair(tariffName, 1));
- }
- else
- {
- ++it->second;
- }
- }
-
-users.CloseSearch(handle);
-
-size_t idx = 1;
-OID prefixOid(prefix);
-
-std::map<std::string, size_t>::const_iterator it(data.begin());
-while (it != data.end())
- {
- sensors[prefixOid.copyWithSuffix(2, static_cast<unsigned int>(idx))] = new ConstSensor<std::string>(it->first);
- sensors[prefixOid.copyWithSuffix(3, static_cast<unsigned int>(idx))] = new ConstSensor<unsigned long>(it->second);
- ++idx;
- ++it;
- }
-}
-
-std::pair<std::string, size_t> TD2Info(const TARIFF_DATA & td)
-{
-return std::make_pair(td.tariffConf.name, 0);
-}
+++ /dev/null
-#ifndef __TABLES_H__
-#define __TABLES_H__
-
-#include <string>
-#include <map>
-
-#include "sensors.h"
-
-class TARIFFS;
-class USERS;
-
-class TableSensor {
- public:
- explicit TableSensor(const std::string & p) : prefix(p) {}
- virtual ~TableSensor() {}
-
- const std::string & GetPrefix() const { return prefix; }
- virtual void UpdateSensors(Sensors & sensors) const = 0;
-
- protected:
- std::string prefix;
-};
-
-class TariffUsersTable : public TableSensor {
- public:
- TariffUsersTable(const std::string & p,
- TARIFFS & t,
- USERS & u)
- : TableSensor(p),
- tariffs(t),
- users(u)
- {}
- virtual ~TariffUsersTable() {}
-
- void UpdateSensors(Sensors & sensors) const;
-
- private:
- TARIFFS & tariffs;
- USERS & users;
-};
-
-typedef std::map<std::string, TableSensor *> Tables;
-
-#endif
+++ /dev/null
-#include <stdexcept>
-#include <algorithm>
-#include <iterator>
-#include <sstream>
-
-#include "types.h"
-
-namespace
-{
-
-bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos);
-bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
-bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
-
-bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos)
-{
-if (length == 0)
- return false;
-const char * left = str;
-if (*left == '.')
- ++left;
-size_t arcPos = 0;
-while ((left - str) < length)
- {
- char * pos = NULL;
- unsigned arc = static_cast<unsigned int>(strtoul(left, &pos, 10));
- if (pos == left)
- return false;
- a[arcPos++] = arc;
- if (arcPos >= 1024)
- return false;
- left = pos + 1;
- }
-*pos = arcPos;
-return true;
-}
-
-bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
-{
-unsigned a[1024];
-size_t pos = 0;
-
-if (!ParseArcs(str, length, a, &pos))
- return false;
-
-arcs.assign(a, a + pos);
-return true;
-}
-
-bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
-{
-unsigned a[1024];
-size_t pos = 0;
-
-if (!ParseArcs(str, length, a, &pos))
- return false;
-
-std::copy(&a[0], &a[pos], std::back_inserter(arcs));
-return true;
-}
-
-}
-
-OID::OID(const std::string & str)
- : arcs()
-{
-if (!StringToArcs(str.c_str(), str.length(), arcs))
- throw std::runtime_error("Invalid oid");
-}
-
-OID::OID(const char * str, size_t length)
- : arcs()
-{
-if (!StringToArcs(str, length, arcs))
- throw std::runtime_error("Invalid oid");
-}
-
-OID::OID(const std::vector<unsigned> & a)
- : arcs(a)
-{
-}
-
-OID::OID(const unsigned * a, size_t length)
- : arcs()
-{
-std::vector<unsigned> newArcs(a, a + length);
-arcs.swap(newArcs);
-}
-
-OID::OID(OBJECT_IDENTIFIER_t * oid)
- : arcs()
-{
-unsigned a[1024];
-int count = OBJECT_IDENTIFIER_get_arcs(oid, a, sizeof(a[0]), 1024);
-
-if (count > 1024)
- throw std::runtime_error("OID is too long");
-
-std::vector<unsigned> newArcs(a, a + count);
-arcs.swap(newArcs);
-}
-
-OID::OID(const OID & rvalue)
- : arcs(rvalue.arcs)
-{
-}
-
-OID::~OID()
-{
-}
-
-bool OID::addSuffix(const char * suffix, size_t length)
-{
-if (!AppendToArcs(suffix, length, arcs))
- return false;
-return true;
-}
-
-bool OID::addSuffix(const std::string & suffix)
-{
-if (!AppendToArcs(suffix.c_str(), suffix.length(), arcs))
- return false;
-return true;
-}
-
-bool OID::addSuffix(const unsigned * suffix, size_t length)
-{
-std::copy(suffix, suffix + length, std::back_inserter(arcs));
-return true;
-}
-
-bool OID::addSuffix(const std::vector<unsigned> & suffix)
-{
-std::copy(suffix.begin(), suffix.end(), std::back_inserter(arcs));
-return true;
-}
-
-bool OID::addSuffix(unsigned a, unsigned b)
-{
-arcs.push_back(a);
-arcs.push_back(b);
-return true;
-}
-
-OID OID::copyWithSuffix(const char * suffix, size_t length) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix, length))
- throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const std::string & suffix) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix))
- throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const unsigned * suffix, size_t length) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix, length))
- throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const std::vector<unsigned> & suffix) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix))
- throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(unsigned a, unsigned b) const
-{
-OID oid(*this);
-oid.addSuffix(a, b);
-return oid;
-}
-
-std::string OID::ToString() const
-{
-std::stringstream stream;
-for (size_t i = 0; i < arcs.size(); ++i)
- stream << "." << arcs[i];
-return stream.str();
-}
-
-void OID::ToOID(OBJECT_IDENTIFIER_t * oid) const
-{
-OBJECT_IDENTIFIER_set_arcs(oid, &arcs.front(), sizeof(unsigned), static_cast<unsigned int>(arcs.size()));
-}
-
-OID & OID::operator=(const OID & rvalue)
-{
-arcs = rvalue.arcs;
-return *this;
-}
-
-bool OID::operator==(const OID & rvalue) const
-{
-if (arcs.size() != rvalue.arcs.size())
- return false;
-for (size_t i = 0; i < arcs.size(); ++i)
- if (arcs[i] != rvalue.arcs[i])
- return false;
-return true;
-}
-
-bool OID::operator<(const OID & rvalue) const
-{
-size_t i = 0;
-size_t min = std::min(arcs.size(), rvalue.arcs.size());
-while (i < min &&
- arcs[i] == rvalue.arcs[i])
- ++i;
-if (i == min)
- {
- if (rvalue.arcs.size() > arcs.size())
- return true;
- return false;
- }
-
-if (arcs[i] < rvalue.arcs[i])
- return true;
-
-return false;
-}
-
-bool OID::PrefixLess(const OID & rvalue) const
-{
-size_t i = 0;
-size_t min = std::min(arcs.size(), rvalue.arcs.size());
-while (i < min &&
- arcs[i] == rvalue.arcs[i])
- ++i;
-if (i == min)
- return false;
-if (arcs[i] < rvalue.arcs[i])
- return true;
-return false;
-}
-
-std::ostream & operator<<(std::ostream & stream, const OID & oid)
-{
-for (size_t i = 0; i < oid.arcs.size(); ++i)
- stream << "." << oid.arcs[i];
-return stream;
-}
+++ /dev/null
-#ifndef __TYPES_H__
-#define __TYPES_H__
-
-#include <string>
-#include <vector>
-#include <iostream>
-
-#include "stg/OBJECT_IDENTIFIER.h"
-
-class OID {
- public:
- explicit OID(const std::string & str);
- OID(const char * str, size_t length);
- explicit OID(const std::vector<unsigned> & arcs);
- OID(const unsigned * arcs, size_t length);
- explicit OID(OBJECT_IDENTIFIER_t * oid);
- OID(const OID & rvalue);
- ~OID();
-
- bool addSuffix(const char * suffix, size_t length);
- bool addSuffix(const std::string & suffix);
- bool addSuffix(const unsigned * suffix, size_t length);
- bool addSuffix(const std::vector<unsigned> & suffix);
- bool addSuffix(unsigned a, unsigned b);
-
- OID copyWithSuffix(const char * suffix, size_t length) const;
- OID copyWithSuffix(const std::string & suffix) const;
- OID copyWithSuffix(const unsigned * suffix, size_t length) const;
- OID copyWithSuffix(const std::vector<unsigned> & suffix) const;
- OID copyWithSuffix(unsigned a, unsigned b) const;
-
- std::string ToString() const;
- const std::vector<unsigned> & ToVector() const { return arcs; }
- void ToOID(OBJECT_IDENTIFIER_t * oid) const;
-
- OID & operator=(const OID & rvalue);
- bool operator==(const OID & rvalue) const;
- bool operator!=(const OID & rvalue) const { return !operator==(rvalue); }
- bool operator<(const OID & rvalue) const;
- bool operator>(const OID & rvalue) const
- { return !operator==(rvalue) && !operator<(rvalue); }
-
- bool PrefixLess(const OID & rvalue) const;
-
- friend std::ostream & operator<<(std::ostream & stream, const OID & oid);
-
- private:
- std::vector<unsigned> arcs;
-};
-
-inline
-bool PrefixLess(const OID & a, const OID & b)
-{
-return a.PrefixLess(b);
-}
-
-#endif
+++ /dev/null
-#include <unistd.h> // write
-
-#include <cstring> // memset
-#include <cerrno>
-
-#include "stg/common.h"
-
-#include "stg/OpenPDU.h"
-#include "stg/ClosePDU.h"
-#include "stg/RReqPDU.h"
-#include "stg/ber_decoder.h"
-#include "stg/der_encoder.h"
-
-#include "pen.h"
-#include "utils.h"
-
-bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
-{
-size_t left = 0, pos = 0, arcPos = 0;
-int arcs[1024];
-pos = str.find_first_of('.', left);
-if (pos == 0)
- {
- left = 1;
- pos = str.find_first_of('.', left);
- }
-while (pos != std::string::npos)
- {
- int arc = 0;
- if (str2x(str.substr(left, left - pos), arc))
- {
- return false;
- }
- arcs[arcPos++] = arc;
- left = pos + 1;
- pos = str.find_first_of('.', left);
- }
-if (left < str.length())
- {
- int arc = 0;
- if (str2x(str.substr(left, left - pos), arc))
- {
- return false;
- }
- arcs[arcPos++] = arc;
- }
-OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), static_cast<unsigned int>(arcPos));
-return true;
-}
-
-bool SendOpenPDU(int fd)
-{
-const char * description = "Stg SMUX Plugin";
-asn_enc_rval_t error;
-OpenPDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-msg.present = OpenPDU_PR_simple;
-asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
-if (!String2OI(PEN_PREFIX, &msg.choice.simple.identity))
- {
- printfd(__FILE__,
- "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
- return false;
- }
-OCTET_STRING_fromString(&msg.choice.simple.description, description);
-OCTET_STRING_fromString(&msg.choice.simple.password, "");
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OpenPDU, &msg);
-
-if (error.encoded == -1)
- {
- printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
- error.failed_type ? error.failed_type->name : "unknown");
- return false;
- }
-else
- {
- if (write(fd, buffer, error.encoded) < 0)
- {
- printfd(__FILE__, "Failed to send OpenPDU: %s\n", strerror(errno));
- return false;
- }
- }
-return true;
-}
-
-bool SendClosePDU(int fd)
-{
-ClosePDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-asn_long2INTEGER(&msg, ClosePDU_goingDown);
-
-char buffer[1024];
-asn_enc_rval_t error;
-error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_ClosePDU, &msg);
-
-if (error.encoded == -1)
- {
- printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
- error.failed_type ? error.failed_type->name : "unknown");
- return false;
- }
-else
- {
- if (write(fd, buffer, error.encoded) < 0)
- {
- printfd(__FILE__, "Failed to send ClosePDU: %s\n", strerror(errno));
- return false;
- }
- }
-return true;
-}
-
-bool SendRReqPDU(int fd)
-{
-int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
-asn_enc_rval_t error;
-RReqPDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-msg.priority = 0;
-asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
-OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
- oid,
- sizeof(oid[0]),
- 8);
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RReqPDU, &msg);
-
-if (error.encoded == -1)
- {
- printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
- error.failed_type ? error.failed_type->name : "unknown");
- return false;
- }
-else
- {
- if (write(fd, buffer, error.encoded) < 0)
- {
- printfd(__FILE__, "Failed to send RReqPDU: %s\n", strerror(errno));
- return false;
- }
- }
-return true;
-}
-
-SMUX_PDUs_t * RecvSMUXPDUs(int fd)
-{
-char buffer[1024];
-SMUX_PDUs_t * pdus = NULL;
-
-memset(buffer, 0, sizeof(buffer));
-
-size_t length = read(fd, buffer, sizeof(buffer));
-if (length < 1)
- return NULL;
-asn_dec_rval_t error;
-error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
-
-if(error.code != RC_OK)
- {
- printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
- (long)error.consumed);
- return NULL;
- }
-return pdus;
-}
-
-bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
-{
-asn_enc_rval_t error;
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
- sizeof(buffer));
-
-if (error.encoded == -1)
- {
- printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
- error.failed_type ? error.failed_type->name : "unknown");
- return false;
- }
-else
- {
- if (write(fd, buffer, error.encoded) < 0)
- {
- printfd(__FILE__, "Failed to send GetResponsePDU: %s\n", strerror(errno));
- return false;
- }
- }
-return true;
-}
-
-bool SendGetResponseErrorPDU(int fd,
- const PDU_t * getRequest,
- int errorStatus,
- int errorIndex)
-{
-asn_enc_rval_t error;
-GetResponse_PDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg.request_id, id);
-asn_long2INTEGER(&msg.error_status, errorStatus);
-asn_long2INTEGER(&msg.error_index, errorIndex);
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
- sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetResponse_PDU, &msg);
-
-if (error.encoded == -1)
- {
- printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
- error.failed_type ? error.failed_type->name : "unknown");
- return false;
- }
-else
- {
- if (write(fd, buffer, error.encoded) < 0)
- {
- printfd(__FILE__, "Failed to send GetResponseErrorPDU: %s\n", strerror(errno));
- return false;
- }
- }
-return true;
-}
+++ /dev/null
-#ifndef __UTILS_H__
-#define __UTILS_H__
-
-#include <string>
-
-#include "stg/OBJECT_IDENTIFIER.h"
-#include "stg/SMUX-PDUs.h"
-#include "stg/GetResponse-PDU.h"
-
-bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi);
-bool SendOpenPDU(int fd);
-bool SendClosePDU(int fd);
-bool SendRReqPDU(int fd);
-SMUX_PDUs_t * RecvSMUXPDUs(int fd);
-bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse);
-bool SendGetResponseErrorPDU(int fd,
- const PDU_t * getRequest,
- int errorStatus,
- int errorIndex);
-
-#endif
+++ /dev/null
-#ifndef __VALUE_2_OS_H__
-#define __VALUE_2_OS_H__
-
-#include "stg/ObjectSyntax.h"
-
-template <typename T>
-bool ValueToOS(const T & value, ObjectSyntax * objectSyntax);
-
-template <>
-inline
-bool ValueToOS<int>(const int & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<unsigned int>(const unsigned int & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<long>(const long & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<unsigned long>(const unsigned long & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<std::string>(const std::string & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_string;
-OCTET_STRING_fromBuf(&simpleSyntax->choice.string, value.c_str(), static_cast<int>(value.length()));
-return true;
-}
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.16 2010/03/04 10:47:45 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_store_files.so
-
-SRCS = ./file_store.cpp
-
-STGLIBS = conffiles \
- common \
- logger \
- crypto
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.67 $
- $Date: 2010/10/07 19:53:11 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#include <cstdio>
-#include <ctime>
-#include <cerrno>
-#include <cstring>
-#include <sstream>
-#include <algorithm>
-
-#include "stg/common.h"
-#include "stg/user_ips.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/const.h"
-#include "stg/blowfish.h"
-#include "stg/logger.h"
-#include "stg/locker.h"
-#include "stg/plugin_creator.h"
-#include "file_store.h"
-
-#define DELETED_USERS_DIR "deleted_users"
-
-#define adm_enc_passwd "cjeifY8m3"
-
-int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext);
-
-const int pt_mega = 1024 * 1024;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-PLUGIN_CREATOR<FILES_STORE> fsc;
-
-bool CheckAndCreate(const std::string & dir, mode_t mode)
-{
-if (access(dir.c_str(), F_OK) == 0)
- return true;
-if (mkdir(dir.c_str(), mode) == 0)
- return true;
-return false;
-}
-
-}
-
-extern "C" STORE * GetStore();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-STORE * GetStore()
-{
-return fsc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
- : settings(NULL),
- statMode(0),
- statUID(0),
- statGID(0),
- confMode(0),
- confUID(0),
- confGID(0),
- userLogMode(0),
- userLogUID(0),
- userLogGID(0),
- removeBak(true),
- readBak(true)
-{
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseOwner(const std::vector<PARAM_VALUE> & moduleParams, const std::string & owner, uid_t * uid)
-{
-PARAM_VALUE pv;
-pv.param = owner;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'" + owner + "\' not found.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-if (User2UID(pvi->value[0].c_str(), uid) < 0)
- {
- errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseGroup(const std::vector<PARAM_VALUE> & moduleParams, const std::string & group, gid_t * gid)
-{
-PARAM_VALUE pv;
-pv.param = group;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'" + group + "\' not found.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-if (Group2GID(pvi->value[0].c_str(), gid) < 0)
- {
- errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseYesNo(const std::string & value, bool * val)
-{
-if (0 == strcasecmp(value.c_str(), "yes"))
- {
- *val = true;
- return 0;
- }
-if (0 == strcasecmp(value.c_str(), "no"))
- {
- *val = false;
- return 0;
- }
-
-errorStr = "Incorrect value \'" + value + "\'.";
-return -1;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseMode(const std::vector<PARAM_VALUE> & moduleParams, const std::string & modeStr, mode_t * mode)
-{
-PARAM_VALUE pv;
-pv.param = modeStr;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'" + modeStr + "\' not found.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
- {
- errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
- return -1;
-if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
- return -1;
-if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
- return -1;
-
-if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
- return -1;
-if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
- return -1;
-if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
- return -1;
-
-if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
- return -1;
-if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
- return -1;
-if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
- return -1;
-
-std::vector<PARAM_VALUE>::const_iterator pvi;
-PARAM_VALUE pv;
-pv.param = "RemoveBak";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- removeBak = true;
- }
-else
- {
- if (ParseYesNo(pvi->value[0], &removeBak))
- {
- printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
- return -1;
- }
- }
-
-pv.param = "ReadBak";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- readBak = false;
- }
-else
- {
- if (ParseYesNo(pvi->value[0], &readBak))
- {
- printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
- return -1;
- }
- }
-
-pv.param = "WorkDir";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'WorkDir\' not found.";
- printfd(__FILE__, "Parameter 'WorkDir' not found\n");
- return -1;
- }
-
-workDir = pvi->value[0];
-if (workDir.size() && workDir[workDir.size() - 1] == '/')
- {
- workDir.resize(workDir.size() - 1);
- }
-usersDir = workDir + "/users/";
-if (!CheckAndCreate(usersDir, GetConfModeDir()))
- {
- errorStr = usersDir + " doesn't exist. Failed to create.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-tariffsDir = workDir + "/tariffs/";
-if (!CheckAndCreate(tariffsDir, GetConfModeDir()))
- {
- errorStr = tariffsDir + " doesn't exist. Failed to create.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-adminsDir = workDir + "/admins/";
-if (!CheckAndCreate(adminsDir, GetConfModeDir()))
- {
- errorStr = adminsDir + " doesn't exist. Failed to create.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-servicesDir = workDir + "/services/";
-if (!CheckAndCreate(servicesDir, GetConfModeDir()))
- {
- errorStr = servicesDir + " doesn't exist. Failed to create.";
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-const std::string & FILES_STORE_SETTINGS::GetStrError() const
-{
-return errorStr;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
-{
-struct passwd * pw;
-pw = getpwnam(user);
-if (!pw)
- {
- errorStr = std::string("User \'") + std::string(user) + std::string("\' not found in system.");
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
-*uid = pw->pw_uid;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
-{
-struct group * grp;
-grp = getgrnam(gr);
-if (!grp)
- {
- errorStr = std::string("Group \'") + std::string(gr) + std::string("\' not found in system.");
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
-*gid = grp->gr_gid;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
-{
-char a;
-char b;
-char c;
-if (strlen(str) > 3)
- {
- errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
-for (int i = 0; i < 3; i++)
- if (str[i] > '7' || str[i] < '0')
- {
- errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
- printfd(__FILE__, "%s\n", errorStr.c_str());
- return -1;
- }
-
-a = str[0] - '0';
-b = str[1] - '0';
-c = str[2] - '0';
-
-*mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
-{
-mode_t mode = statMode;
-if (statMode & S_IRUSR) mode |= S_IXUSR;
-if (statMode & S_IRGRP) mode |= S_IXGRP;
-if (statMode & S_IROTH) mode |= S_IXOTH;
-return mode;
-}
-//-----------------------------------------------------------------------------
-mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
-{
-mode_t mode = confMode;
-if (confMode & S_IRUSR) mode |= S_IXUSR;
-if (confMode & S_IRGRP) mode |= S_IXGRP;
-if (confMode & S_IROTH) mode |= S_IXOTH;
-return mode;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-FILES_STORE::FILES_STORE()
- : errorStr(),
- version("file_store v.1.04"),
- storeSettings(),
- settings(),
- mutex(),
- logger(GetPluginLogger(GetStgLogger(), "store_files"))
-{
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::ParseSettings()
-{
-int ret = storeSettings.ParseSettings(settings);
-if (ret)
- {
- STG_LOCKER lock(&mutex);
- errorStr = storeSettings.GetStrError();
- }
-return ret;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetUsersList(std::vector<std::string> * userList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetUsersDir(), S_IFDIR, ""))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Failed to open '" + storeSettings.GetUsersDir() + "': " + std::string(strerror(errno));
- return -1;
- }
-
-STG_LOCKER lock(&mutex);
-
-userList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetAdminsList(std::vector<std::string> * adminList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetAdminsDir(), S_IFREG, ".adm"))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Failed to open '" + storeSettings.GetAdminsDir() + "': " + std::string(strerror(errno));
- return -1;
- }
-
-STG_LOCKER lock(&mutex);
-
-adminList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetTariffsList(std::vector<std::string> * tariffList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetTariffsDir(), S_IFREG, ".tf"))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Failed to open '" + storeSettings.GetTariffsDir() + "': " + std::string(strerror(errno));
- return -1;
- }
-
-STG_LOCKER lock(&mutex);
-
-tariffList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetServicesList(std::vector<std::string> * list) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetServicesDir(), S_IFREG, ".serv"))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Failed to open '" + storeSettings.GetServicesDir() + "': " + std::string(strerror(errno));
- return -1;
- }
-
-STG_LOCKER lock(&mutex);
-
-list->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RemoveDir(const char * path) const
-{
-DIR * d = opendir(path);
-
-if (!d)
- {
- errorStr = "failed to open dir. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILE_STORE::RemoveDir() - Failed to open dir '%s': '%s'\n", path, strerror(errno));
- return -1;
- }
-
-dirent * entry;
-while ((entry = readdir(d)))
- {
- if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
- continue;
-
- std::string str = path;
- str += "/" + std::string(entry->d_name);
-
- struct stat st;
- if (stat(str.c_str(), &st))
- continue;
-
- if ((st.st_mode & S_IFREG))
- {
- if (unlink(str.c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "unlink failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::RemoveDir() - unlink failed. Message: '%s'\n", strerror(errno));
- closedir(d);
- return -1;
- }
- }
-
- if (!(st.st_mode & S_IFDIR))
- {
- if (RemoveDir(str.c_str()))
- {
- closedir(d);
- return -1;
- }
-
- }
- }
-
-closedir(d);
-
-if (rmdir(path))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "rmdir failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::RemoveDir() - rmdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddUser(const std::string & login) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
-
-if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("mkdir failed. Message: '") + strerror(errno) + "'";
- printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (Touch(fileName))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file \"" + fileName + "\'";
- printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (Touch(fileName))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file \"" + fileName + "\'";
- printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelUser(const std::string & login) const
-{
-std::string dirName;
-std::string dirName1;
-
-strprintf(&dirName, "%s/%s", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR);
-if (access(dirName.c_str(), F_OK) != 0)
- {
- if (mkdir(dirName.c_str(), 0700) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Directory '" + dirName + "' cannot be created.";
- printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-
-if (access(dirName.c_str(), F_OK) == 0)
- {
- strprintf(&dirName, "%s/%s/%s.%lu", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR, login.c_str(), time(NULL));
- strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
- if (rename(dirName1.c_str(), dirName.c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
- printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-else
- {
- strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
- if (RemoveDir(dirName.c_str()))
- {
- return -1;
- }
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
-if (RestoreUserConf(conf, login, fileName))
- {
- if (!storeSettings.GetReadBak())
- {
- return -1;
- }
- return RestoreUserConf(conf, login, fileName + ".bak");
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login, const std::string & fileName) const
-{
-CONFIGFILE cf(fileName);
-int e = cf.Error();
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadString("Password", &conf->password, "") < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter Password.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
- return -1;
- }
-if (conf->password.empty())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' password is blank.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
- return -1;
- }
-if (conf->tariffName.empty())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' tariff is blank.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
- return -1;
- }
-
-std::string ipStr;
-cf.ReadString("IP", &ipStr, "?");
-USER_IPS ips;
-try
- {
- ips = StrToIPS(ipStr);
- }
-catch (const std::string & s)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
- return -1;
- }
-conf->ips = ips;
-
-if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadInt("down", &conf->disabled, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter Down.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadInt("passive", &conf->passive, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
-cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
-cf.ReadString("TariffChange", &conf->nextTariff, "");
-cf.ReadString("Group", &conf->group, "");
-cf.ReadString("RealName", &conf->realName, "");
-cf.ReadString("Address", &conf->address, "");
-cf.ReadString("Phone", &conf->phone, "");
-cf.ReadString("Note", &conf->note, "");
-cf.ReadString("email", &conf->email, "");
-
-char userdataName[12];
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- snprintf(userdataName, 12, "Userdata%d", i);
- cf.ReadString(userdataName, &conf->userdata[i], "");
- }
-
-if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
- printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
-
-if (RestoreUserStat(stat, login, fileName))
- {
- if (!storeSettings.GetReadBak())
- {
- return -1;
- }
- return RestoreUserStat(stat, login, fileName + ".bak");
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login, const std::string & fileName) const
-{
-CONFIGFILE cf(fileName);
-
-int e = cf.Error();
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-char s[22];
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- uint64_t traff;
- snprintf(s, 22, "D%d", i);
- if (cf.ReadULongLongInt(s, &traff, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
- return -1;
- }
- stat->monthDown[i] = traff;
-
- snprintf(s, 22, "U%d", i);
- if (cf.ReadULongLongInt(s, &traff, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
- return -1;
- }
- stat->monthUp[i] = traff;
- }
-
-if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
- printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveUserConf(const USER_CONF & conf, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
-
-CONFIGFILE cfstat(fileName, true);
-
-int e = cfstat.Error();
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("User \'") + login + "\' conf not written\n";
- printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-e = chmod(fileName.c_str(), storeSettings.GetConfMode());
-e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-cfstat.WriteString("Password", conf.password);
-cfstat.WriteInt ("Passive", conf.passive);
-cfstat.WriteInt ("Down", conf.disabled);
-cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
-cfstat.WriteInt ("AlwaysOnline", conf.alwaysOnline);
-cfstat.WriteString("Tariff", conf.tariffName);
-cfstat.WriteString("Address", conf.address);
-cfstat.WriteString("Phone", conf.phone);
-cfstat.WriteString("Email", conf.email);
-cfstat.WriteString("Note", conf.note);
-cfstat.WriteString("RealName", conf.realName);
-cfstat.WriteString("Group", conf.group);
-cfstat.WriteDouble("Credit", conf.credit);
-cfstat.WriteString("TariffChange", conf.nextTariff);
-
-char userdataName[12];
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- snprintf(userdataName, 12, "Userdata%d", i);
- cfstat.WriteString(userdataName, conf.userdata[i]);
- }
-cfstat.WriteInt("CreditExpire", conf.creditExpire);
-
-std::ostringstream ipStr;
-ipStr << conf.ips;
-cfstat.WriteString("IP", ipStr.str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveUserStat(const USER_STAT & stat, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
-
- {
- CONFIGFILE cfstat(fileName, true);
- int e = cfstat.Error();
-
- if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("User \'") + login + "\' stat not written\n";
- printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- char s[22];
- snprintf(s, 22, "D%d", i);
- cfstat.WriteInt(s, stat.monthDown[i]);
- snprintf(s, 22, "U%d", i);
- cfstat.WriteInt(s, stat.monthUp[i]);
- }
-
- cfstat.WriteDouble("Cash", stat.cash);
- cfstat.WriteDouble("FreeMb", stat.freeMb);
- cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
- cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
- cfstat.WriteInt("PassiveTime", stat.passiveTime);
- cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
- }
-
-int e = chmod(fileName.c_str(), storeSettings.GetStatMode());
-e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteLogString(const std::string & str, const std::string & login) const
-{
-FILE * f;
-time_t tm = time(NULL);
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
-f = fopen(fileName.c_str(), "at");
-
-if (f)
- {
- fprintf(f, "%s", LogDate(tm));
- fprintf(f, " -- ");
- fprintf(f, "%s", str.c_str());
- fprintf(f, "\n");
- fclose(f);
- }
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot open \'" + fileName + "\'";
- printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
-e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteLog2String(const std::string & str, const std::string & login) const
-{
-FILE * f;
-time_t tm = time(NULL);
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
-f = fopen(fileName.c_str(), "at");
-
-if (f)
- {
- fprintf(f, "%s", LogDate(tm));
- fprintf(f, " -- ");
- fprintf(f, "%s", str.c_str());
- fprintf(f, "\n");
- fclose(f);
- }
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot open \'" + fileName + "\'";
- printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
-e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message) const
-{
-std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
- + paramName + "\' parameter changed from \'" + oldValue +
- "\' to \'" + newValue + "\'. " + message;
-
-return WriteLogString(userLogMsg, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-std::string logStr = "Connect, " + inet_ntostring(ip);
-if (WriteLogString(logStr, login))
- return -1;
-return WriteLog2String(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & monthUp,
- const DIR_TRAFF & monthDown,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const
-{
-std::ostringstream logStr;
-logStr << "Disconnect, "
- << " session upload: \'"
- << sessionUp
- << "\' session download: \'"
- << sessionDown
- << "\' month upload: \'"
- << monthUp
- << "\' month download: \'"
- << monthDown
- << "\' cash: \'"
- << cash
- << "\'";
-
-if (WriteLogString(logStr.str(), login))
- return -1;
-
-logStr << " freeMb: \'"
- << freeMb
- << "\'"
- << " reason: \'"
- << reason
- << "\'";
-
-return WriteLog2String(logStr.str(), login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
-{
-// Classic stats
-std::string stat1;
-strprintf(&stat1,"%s/%s/stat.%d.%02d",
- storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
-
-CONFIGFILE s(stat1, true);
-
-if (s.Error())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file '" + stat1 + "'";
- printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-// New stats
-std::string stat2;
-strprintf(&stat2,"%s/%s/stat2.%d.%02d",
- storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
-
-CONFIGFILE s2(stat2, true);
-
-if (s2.Error())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file '" + stat2 + "'";
- printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
- return -1;
- }
-
-for (size_t i = 0; i < DIR_NUM; i++)
- {
- char dirName[3];
- snprintf(dirName, 3, "U%llu", (unsigned long long)i);
- s.WriteInt(dirName, stat.monthUp[i]); // Classic
- s2.WriteInt(dirName, stat.monthUp[i]); // New
- snprintf(dirName, 3, "D%llu", (unsigned long long)i);
- s.WriteInt(dirName, stat.monthDown[i]); // Classic
- s2.WriteInt(dirName, stat.monthDown[i]); // New
- }
-
-// Classic
-s.WriteDouble("cash", stat.cash);
-
-// New
-s2.WriteDouble("Cash", stat.cash);
-s2.WriteDouble("FreeMb", stat.freeMb);
-s2.WriteDouble("LastCashAdd", stat.lastCashAdd);
-s2.WriteInt("LastCashAddTime", stat.lastCashAddTime);
-s2.WriteInt("PassiveTime", stat.passiveTime);
-s2.WriteInt("LastActivityTime", stat.lastActivityTime);
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::AddAdmin(const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-
-if (Touch(fileName))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file " + fileName;
- printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::DelAdmin(const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-if (unlink(fileName.c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "unlink failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
- }
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::SaveAdmin(const ADMIN_CONF & ac) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
-
- {
- CONFIGFILE cf(fileName, true);
-
- int e = cf.Error();
-
- if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot write admin " + ac.login + ". " + fileName;
- printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
- return -1;
- }
-
- char pass[ADM_PASSWD_LEN + 1];
- memset(pass, 0, sizeof(pass));
-
- char adminPass[ADM_PASSWD_LEN + 1];
- memset(adminPass, 0, sizeof(adminPass));
-
- BLOWFISH_CTX ctx;
- InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
- strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
- adminPass[ADM_PASSWD_LEN - 1] = 0;
-
- for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
- {
- EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
- }
-
- pass[ADM_PASSWD_LEN - 1] = 0;
- char passwordE[2 * ADM_PASSWD_LEN + 2];
- Encode12(passwordE, pass, ADM_PASSWD_LEN);
-
- cf.WriteString("password", passwordE);
- cf.WriteInt("ChgConf", ac.priv.userConf);
- cf.WriteInt("ChgPassword", ac.priv.userPasswd);
- cf.WriteInt("ChgStat", ac.priv.userStat);
- cf.WriteInt("ChgCash", ac.priv.userCash);
- cf.WriteInt("UsrAddDel", ac.priv.userAddDel);
- cf.WriteInt("ChgTariff", ac.priv.tariffChg);
- cf.WriteInt("ChgAdmin", ac.priv.adminChg);
- cf.WriteInt("ChgService", ac.priv.serviceChg);
- cf.WriteInt("ChgCorp", ac.priv.corpChg);
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-CONFIGFILE cf(fileName);
-char pass[ADM_PASSWD_LEN + 1];
-char password[ADM_PASSWD_LEN + 1];
-char passwordE[2 * ADM_PASSWD_LEN + 2];
-BLOWFISH_CTX ctx;
-
-std::string p;
-
-if (cf.Error())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot open " + fileName;
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadString("password", &p, "*"))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter password";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-memset(passwordE, 0, sizeof(passwordE));
-strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
-
-memset(pass, 0, sizeof(pass));
-
-if (passwordE[0] != 0)
- {
- Decode21(pass, passwordE);
- InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
- for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
- {
- DecryptBlock(password + 8*i, pass + 8*i, &ctx);
- }
- }
-else
- {
- password[0] = 0;
- }
-
-ac->password = password;
-
-uint16_t a;
-
-if (cf.ReadUShortInt("ChgConf", &a, 0) == 0)
- ac->priv.userConf = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgConf";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgPassword", &a, 0) == 0)
- ac->priv.userPasswd = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgPassword";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgStat", &a, 0) == 0)
- ac->priv.userStat = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgStat";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgCash", &a, 0) == 0)
- ac->priv.userCash = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgCash";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("UsrAddDel", &a, 0) == 0)
- ac->priv.userAddDel = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter UsrAddDel";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgAdmin", &a, 0) == 0)
- ac->priv.adminChg = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgAdmin";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgTariff", &a, 0) == 0)
- ac->priv.tariffChg = a;
-else
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter ChgTariff";
- printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
- return -1;
- }
-
-if (cf.ReadUShortInt("ChgService", &a, 0) == 0)
- ac->priv.serviceChg = a;
-else
- ac->priv.serviceChg = 0;
-
-if (cf.ReadUShortInt("ChgCorp", &a, 0) == 0)
- ac->priv.corpChg = a;
-else
- ac->priv.corpChg = 0;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddTariff(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
-if (Touch(fileName))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file " + fileName;
- printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelTariff(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
-if (unlink(fileName.c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "unlink failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const
-{
-std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
-CONFIGFILE conf(fileName);
-std::string str;
-td->tariffConf.name = tariffName;
-
-if (conf.Error() != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read file " + fileName;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
-std::string param;
-for (int i = 0; i<DIR_NUM; i++)
- {
- strprintf(¶m, "Time%d", i);
- if (conf.ReadString(param, &str, "00:00-00:00") < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
- return -1;
- }
-
- ParseTariffTimeStr(str.c_str(),
- td->dirPrice[i].hDay,
- td->dirPrice[i].mDay,
- td->dirPrice[i].hNight,
- td->dirPrice[i].mNight);
-
- strprintf(¶m, "PriceDayA%d", i);
- if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
- td->dirPrice[i].priceDayA /= (1024*1024);
-
- strprintf(¶m, "PriceDayB%d", i);
- if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
- td->dirPrice[i].priceDayB /= (1024*1024);
-
- strprintf(¶m, "PriceNightA%d", i);
- if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
- td->dirPrice[i].priceNightA /= (1024*1024);
-
- strprintf(¶m, "PriceNightB%d", i);
- if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
- td->dirPrice[i].priceNightB /= (1024*1024);
-
- strprintf(¶m, "Threshold%d", i);
- if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
- strprintf(¶m, "SinglePrice%d", i);
- if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
- strprintf(¶m, "NoDiscount%d", i);
- if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
- }
-
-if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
- printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
-if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
- printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
-if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
- printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
-if (conf.ReadString("TraffType", &str, "") < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
- printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
- return -1;
- }
-
-td->tariffConf.traffType = TARIFF::StringToTraffType(str);
-
-if (conf.ReadString("Period", &str, "month") < 0)
- td->tariffConf.period = TARIFF::MONTH;
-else
- td->tariffConf.period = TARIFF::StringToPeriod(str);
-
-if (conf.ReadString("ChangePolicy", &str, "allow") < 0)
- td->tariffConf.changePolicy = TARIFF::ALLOW;
-else
- td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
-
-conf.ReadTime("ChangePolicyTimeout", &td->tariffConf.changePolicyTimeout, 0);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
-{
-std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
-
- {
- CONFIGFILE cf(fileName, true);
-
- int e = cf.Error();
-
- if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error writing tariff " + tariffName;
- printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
- return e;
- }
-
- std::string param;
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, "PriceDayA%d", i);
- cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
-
- strprintf(¶m, "PriceDayB%d", i);
- cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
-
- strprintf(¶m, "PriceNightA%d", i);
- cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
-
- strprintf(¶m, "PriceNightB%d", i);
- cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
-
- strprintf(¶m, "Threshold%d", i);
- cf.WriteInt(param, td.dirPrice[i].threshold);
-
- std::string s;
- strprintf(¶m, "Time%d", i);
-
- strprintf(&s, "%0d:%0d-%0d:%0d",
- td.dirPrice[i].hDay,
- td.dirPrice[i].mDay,
- td.dirPrice[i].hNight,
- td.dirPrice[i].mNight);
-
- cf.WriteString(param, s);
-
- strprintf(¶m, "NoDiscount%d", i);
- cf.WriteInt(param, td.dirPrice[i].noDiscount);
-
- strprintf(¶m, "SinglePrice%d", i);
- cf.WriteInt(param, td.dirPrice[i].singlePrice);
- }
-
- cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
- cf.WriteDouble("Fee", td.tariffConf.fee);
- cf.WriteDouble("Free", td.tariffConf.free);
- cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType));
- cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period));
- cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
- cf.WriteTime("ChangePolicyTimeout", td.tariffConf.changePolicyTimeout);
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::AddService(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-
-if (Touch(fileName))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot create file " + fileName;
- printfd(__FILE__, "FILES_STORE::AddService - failed to add service '%s'\n", name.c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::DelService(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-if (unlink(fileName.c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "unlink failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
- }
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::SaveService(const SERVICE_CONF & conf) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), conf.name.c_str());
-
- {
- CONFIGFILE cf(fileName, true);
-
- int e = cf.Error();
-
- if (e)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot write service " + conf.name + ". " + fileName;
- printfd(__FILE__, "FILES_STORE::SaveService - failed to save service '%s'\n", conf.name.c_str());
- return -1;
- }
-
- cf.WriteString("name", conf.name);
- cf.WriteString("comment", conf.comment);
- cf.WriteDouble("cost", conf.cost);
- cf.WriteInt("pay_day", conf.payDay);
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreService(SERVICE_CONF * conf, const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-CONFIGFILE cf(fileName);
-
-if (cf.Error())
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot open " + fileName;
- printfd(__FILE__, "FILES_STORE::RestoreService - failed to restore service '%s'\n", name.c_str());
- return -1;
- }
-
-if (cf.ReadString("name", &conf->name, name))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter 'name'";
- printfd(__FILE__, "FILES_STORE::RestoreService - name read failed for service '%s'\n", name.c_str());
- return -1;
- }
-
-if (cf.ReadString("comment", &conf->comment, ""))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter 'comment'";
- printfd(__FILE__, "FILES_STORE::RestoreService - comment read failed for service '%s'\n", name.c_str());
- return -1;
- }
-
-if (cf.ReadDouble("cost", &conf->cost, 0.0))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter 'cost'";
- printfd(__FILE__, "FILES_STORE::RestoreService - cost read failed for service '%s'\n", name.c_str());
- return -1;
- }
-
-unsigned short value = 0;
-if (cf.ReadUShortInt("pay_day", &value, 0))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error in parameter 'pay_day'";
- printfd(__FILE__, "FILES_STORE::RestoreService - pay day read failed for service '%s'\n", name.c_str());
- return -1;
- }
-conf->payDay = value;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
- time_t lastStat,
- const std::string & login) const
-{
-char fn[FN_STR_LEN];
-char dn[FN_STR_LEN];
-FILE * statFile;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (access(dn, F_OK) != 0)
- {
- if (mkdir(dn, 0700) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-
-int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-lt = localtime(&t);
-
-if (lt->tm_hour == 0 && lt->tm_min <= 5)
- {
- t -= 3600 * 24;
- lt = localtime(&t);
- }
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
- storeSettings.GetUsersDir().c_str(),
- login.c_str(),
- lt->tm_year+1900);
-
-if (access(dn, F_OK) != 0)
- {
- if (mkdir(dn, 0700) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-
-e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d",
- storeSettings.GetUsersDir().c_str(),
- login.c_str(),
- lt->tm_year+1900,
- lt->tm_mon+1 < 10 ? "0" : "",
- lt->tm_mon+1);
-if (access(dn, F_OK) != 0)
- {
- if (mkdir(dn, 0700) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-
-e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
-
-statFile = fopen (fn, "at");
-
-if (!statFile)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "File \'" + std::string(fn) + "\' cannot be written.";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-struct tm * lt1;
-struct tm * lt2;
-
-lt1 = localtime(&lastStat);
-
-int h1, m1, s1;
-int h2, m2, s2;
-
-h1 = lt1->tm_hour;
-m1 = lt1->tm_min;
-s1 = lt1->tm_sec;
-
-lt2 = localtime(&t);
-
-h2 = lt2->tm_hour;
-m2 = lt2->tm_min;
-s2 = lt2->tm_sec;
-
-if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
- h1, m1, s1, h2, m2, s2) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("fprint failed. Message: '") + strerror(errno) + "'";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
- fclose(statFile);
- return -1;
- }
-
-std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
-stIter = statTree.begin();
-
-while (stIter != statTree.end())
- {
- std::string u, d;
- x2str(stIter->second.up, u);
- x2str(stIter->second.down, d);
- #ifdef TRAFF_STAT_WITH_PORTS
- if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
- inet_ntostring(stIter->first.ip).c_str(),
- stIter->first.port,
- stIter->first.dir,
- d.c_str(),
- u.c_str(),
- stIter->second.cash) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "fprint failed. Message: '";
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
- fclose(statFile);
- return -1;
- }
- #else
- if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
- inet_ntostring(stIter->first.ip).c_str(),
- stIter->first.dir,
- d.c_str(),
- u.c_str(),
- stIter->second.cash) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("fprint failed. Message: '");
- errorStr += strerror(errno);
- errorStr += "'";
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
- fclose(statFile);
- return -1;
- }
- #endif
-
- ++stIter;
- }
-
-fclose(statFile);
-
-e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(fn, storeSettings.GetStatMode());
-
-if (e)
- {
- STG_LOCKER lock(&mutex);
- printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
-{
-std::string fn;
-std::string dn;
-struct timeval tv;
-
-strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (access(dn.c_str(), F_OK) != 0)
- {
- if (mkdir(dn.c_str(), 0700) != 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Directory \'";
- errorStr += dn;
- errorStr += "\' cannot be created.";
- printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- }
-
-chmod(dn.c_str(), storeSettings.GetConfModeDir());
-
-gettimeofday(&tv, NULL);
-
-msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
-strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
-
-if (Touch(fn))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "File \'";
- errorStr += fn;
- errorStr += "\' cannot be writen.";
- printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-return EditMessage(*msg, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
-{
-std::string fileName;
-
-FILE * msgFile;
-strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
-
-if (access(fileName.c_str(), F_OK) != 0)
- {
- std::string idstr;
- x2str(msg.header.id, idstr);
- STG_LOCKER lock(&mutex);
- errorStr = "Message for user \'";
- errorStr += login + "\' with ID \'";
- errorStr += idstr + "\' does not exist.";
- printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
- return -1;
- }
-
-Touch(fileName + ".new");
-
-msgFile = fopen((fileName + ".new").c_str(), "wt");
-if (!msgFile)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "File \'" + fileName + "\' cannot be writen.";
- printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-bool res = true;
-res &= (fprintf(msgFile, "%u\n", msg.header.type) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
-res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
-res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
-
-if (!res)
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("fprintf failed. Message: '") + strerror(errno) + "'";
- printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
- fclose(msgFile);
- return -1;
- }
-
-fclose(msgFile);
-
-chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
-
-if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
- printfd(__FILE__, "FILES_STORE::EditMessage - rename failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
-{
-std::string fn;
-strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
-msg->header.id = id;
-return ReadMessage(fn, &msg->header, &msg->text);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelMessage(uint64_t id, const std::string & login) const
-{
-std::string fn;
-strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
-
-return unlink(fn.c_str());
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
-{
-std::string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
-
-if (access(dn.c_str(), F_OK) != 0)
- {
- return 0;
- }
-
-std::vector<std::string> messages;
-GetFileList(&messages, dn, S_IFREG, "");
-
-for (unsigned i = 0; i < messages.size(); i++)
- {
- unsigned long long id = 0;
-
- if (str2x(messages[i].c_str(), id))
- {
- if (unlink((dn + messages[i]).c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
- printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- continue;
- }
-
- STG_MSG_HDR hdr;
- if (ReadMessage(dn + messages[i], &hdr, NULL))
- {
- return -1;
- }
-
- if (hdr.repeat < 0)
- {
- if (unlink((dn + messages[i]).c_str()))
- {
- STG_LOCKER lock(&mutex);
- errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
- printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
- continue;
- }
-
- hdr.id = id;
- hdrsList->push_back(hdr);
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::ReadMessage(const std::string & fileName,
- STG_MSG_HDR * hdr,
- std::string * text) const
-{
-FILE * msgFile;
-msgFile = fopen(fileName.c_str(), "rt");
-if (!msgFile)
- {
- STG_LOCKER lock(&mutex);
- errorStr = "File \'";
- errorStr += fileName;
- errorStr += "\' cannot be openned.";
- printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
- return -1;
- }
-char p[20];
-unsigned * d[6];
-d[0] = &hdr->type;
-d[1] = &hdr->lastSendTime;
-d[2] = &hdr->creationTime;
-d[3] = &hdr->showTime;
-d[4] = (unsigned*)(&hdr->repeat);
-d[5] = &hdr->repeatPeriod;
-
-memset(p, 0, sizeof(p));
-
-for (int pos = 0; pos < 6; pos++)
- {
- if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read file \'";
- errorStr += fileName;
- errorStr += "\'. Missing data.";
- printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
- printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
- fclose(msgFile);
- return -1;
- }
-
- char * ep;
- ep = strrchr(p, '\r');
- if (ep) *ep = 0;
- ep = strrchr(p, '\n');
- if (ep) *ep = 0;
-
- if (feof(msgFile))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read file \'";
- errorStr += fileName;
- errorStr += "\'. Missing data.";
- printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
- printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
- fclose(msgFile);
- return -1;
- }
-
- if (str2x(p, *(d[pos])))
- {
- STG_LOCKER lock(&mutex);
- errorStr = "Cannot read file \'";
- errorStr += fileName;
- errorStr += "\'. Incorrect value. \'";
- errorStr += p;
- errorStr += "\'";
- printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
- fclose(msgFile);
- return -1;
- }
- }
-
-char txt[2048];
-memset(txt, 0, sizeof(txt));
-if (text)
- {
- text->erase(text->begin(), text->end());
- while (!feof(msgFile))
- {
- txt[0] = 0;
- if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
- break;
- }
-
- (*text) += txt;
- }
- }
-fclose(msgFile);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::Touch(const std::string & path) const
-{
-FILE * f = fopen(path.c_str(), "wb");
-if (f)
- {
- fclose(f);
- return 0;
- }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext)
-{
-DIR * d = opendir(directory.c_str());
-
-if (!d)
- {
- printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
- return -1;
- }
-
-dirent * entry;
-while ((entry = readdir(d)))
- {
- if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
- continue;
-
- std::string str = directory + "/" + std::string(entry->d_name);
-
- struct stat st;
- if (stat(str.c_str(), &st))
- continue;
-
- if (!(st.st_mode & mode)) // Filter by mode
- continue;
-
- if (!ext.empty())
- {
- // Check extension
- size_t d_nameLen = strlen(entry->d_name);
- if (d_nameLen <= ext.size())
- continue;
-
- if (ext == entry->d_name + (d_nameLen - ext.size()))
- {
- entry->d_name[d_nameLen - ext.size()] = 0;
- fileList->push_back(entry->d_name);
- }
- }
- else
- {
- fileList->push_back(entry->d_name);
- }
- }
-
-closedir(d);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.22 $
- $Date: 2010/01/19 11:06:53 $
- $Author: faust $
- */
-
-
-#ifndef FILE_STORE_H
-#define FILE_STORE_H
-
-#include <sys/types.h>
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/module_settings.h"
-#include "stg/store.h"
-#include "stg/conffiles.h"
-#include "stg/user_traff.h"
-#include "stg/logger.h"
-
-//-----------------------------------------------------------------------------
-class FILES_STORE_SETTINGS {
-public:
- FILES_STORE_SETTINGS();
- int ParseSettings(const MODULE_SETTINGS & s);
- const std::string & GetStrError() const;
-
- std::string GetWorkDir() const { return workDir; }
- std::string GetUsersDir() const { return usersDir; }
- std::string GetAdminsDir() const { return adminsDir; }
- std::string GetTariffsDir() const { return tariffsDir; }
- std::string GetServicesDir() const { return servicesDir; }
-
- mode_t GetStatMode() const { return statMode; }
- mode_t GetStatModeDir() const;
- uid_t GetStatUID() const { return statUID; }
- gid_t GetStatGID() const { return statGID; }
-
- mode_t GetConfMode() const { return confMode; }
- mode_t GetConfModeDir() const;
- uid_t GetConfUID() const { return confUID; }
- gid_t GetConfGID() const { return confGID; }
-
- mode_t GetLogMode() const { return userLogMode; }
- uid_t GetLogUID() const { return userLogUID; }
- gid_t GetLogGID() const { return userLogGID; }
-
- bool GetRemoveBak() const { return removeBak; }
- bool GetReadBak() const { return readBak; }
-
-private:
- FILES_STORE_SETTINGS(const FILES_STORE_SETTINGS & rvalue);
- FILES_STORE_SETTINGS & operator=(const FILES_STORE_SETTINGS & rvalue);
-
- const MODULE_SETTINGS * settings;
-
- int User2UID(const char * user, uid_t * uid);
- int Group2GID(const char * gr, gid_t * gid);
- int Str2Mode(const char * str, mode_t * mode);
- int ParseOwner(const std::vector<PARAM_VALUE> & moduleParams, const std::string & owner, uid_t * uid);
- int ParseGroup(const std::vector<PARAM_VALUE> & moduleParams, const std::string & group, uid_t * uid);
- int ParseMode(const std::vector<PARAM_VALUE> & moduleParams, const std::string & modeStr, mode_t * mode);
- int ParseYesNo(const std::string & value, bool * val);
-
- std::string errorStr;
-
- std::string workDir;
- std::string usersDir;
- std::string adminsDir;
- std::string tariffsDir;
- std::string servicesDir;
-
- mode_t statMode;
- uid_t statUID;
- gid_t statGID;
-
- mode_t confMode;
- uid_t confUID;
- gid_t confGID;
-
- mode_t userLogMode;
- uid_t userLogUID;
- gid_t userLogGID;
-
- bool removeBak;
- bool readBak;
-};
-//-----------------------------------------------------------------------------
-class FILES_STORE: public STORE {
-public:
- FILES_STORE();
- virtual ~FILES_STORE() {}
- virtual const std::string & GetStrError() const { return errorStr; }
-
- //User
- virtual int GetUsersList(std::vector<std::string> * usersList) const;
- virtual int AddUser(const std::string & login) const;
- virtual int DelUser(const std::string & login) const;
- virtual int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
- virtual int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
-
- virtual int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
- virtual int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
-
- virtual int WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message = "") const;
- virtual int WriteUserConnect(const std::string & login, uint32_t ip) const;
- virtual int WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const;
-
- virtual int WriteDetailedStat(const TRAFF_STAT & statTree,
- time_t lastStat,
- const std::string & login) const;
-
- virtual int AddMessage(STG_MSG * msg, const std::string & login) const;
- virtual int EditMessage(const STG_MSG & msg, const std::string & login) const;
- virtual int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
- virtual int DelMessage(uint64_t id, const std::string & login) const;
- virtual int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
- virtual int ReadMessage(const std::string & fileName,
- STG_MSG_HDR * hdr,
- std::string * text) const;
-
- virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
-
- //Admin
- virtual int GetAdminsList(std::vector<std::string> * adminsList) const;
- virtual int AddAdmin(const std::string & login) const;
- virtual int DelAdmin(const std::string & login) const;
- virtual int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
- virtual int SaveAdmin(const ADMIN_CONF & ac) const;
-
- //Tariff
- virtual int GetTariffsList(std::vector<std::string> * tariffsList) const;
- virtual int AddTariff(const std::string & name) const;
- virtual int DelTariff(const std::string & name) const;
- virtual int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
- virtual int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
-
- //Corparation
- virtual int GetCorpsList(std::vector<std::string> *) const { return 0; }
- virtual int SaveCorp(const CORP_CONF &) const { return 0; }
- virtual int RestoreCorp(CORP_CONF *, const std::string &) const { return 0; }
- virtual int AddCorp(const std::string &) const { return 0; }
- virtual int DelCorp(const std::string &) const { return 0; }
-
- // Services
- virtual int GetServicesList(std::vector<std::string> *) const;
- virtual int SaveService(const SERVICE_CONF &) const;
- virtual int RestoreService(SERVICE_CONF *, const std::string &) const;
- virtual int AddService(const std::string &) const;
- virtual int DelService(const std::string &) const;
-
- virtual void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- virtual int ParseSettings();
- virtual const std::string & GetVersion() const { return version; }
-
-private:
- FILES_STORE(const FILES_STORE & rvalue);
- FILES_STORE & operator=(const FILES_STORE & rvalue);
-
- virtual int RestoreUserStat(USER_STAT * stat, const std::string & login, const std::string & fileName) const;
- virtual int RestoreUserConf(USER_CONF * conf, const std::string & login, const std::string & fileName) const;
-
- virtual int WriteLogString(const std::string & str, const std::string & login) const;
- virtual int WriteLog2String(const std::string & str, const std::string & login) const;
- int RemoveDir(const char * path) const;
- int Touch(const std::string & path) const;
-
- mutable std::string errorStr;
- std::string version;
- FILES_STORE_SETTINGS storeSettings;
- MODULE_SETTINGS settings;
- mutable pthread_mutex_t mutex;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.9 2008/12/04 17:15:53 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-DEFS += -DIBPP_LINUX
-
-PROG = mod_store_firebird.so
-
-SRCS = ./firebird_store.cpp \
- ./firebird_store_admins.cpp \
- ./firebird_store_corporations.cpp \
- ./firebird_store_messages.cpp \
- ./firebird_store_services.cpp \
- ./firebird_store_tariffs.cpp \
- ./firebird_store_users.cpp \
- ./firebird_store_utils.cpp
-
-STGLIBS = ibpp \
- common \
- logger \
- crypto
-
-CXXFLAGS += $(FB_CFLAGS)
-LDFLAGS += $(FB_LDFLAGS)
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * This file contains a realization of a base firebird-storage plugin class
- *
- * $Revision: 1.18 $
- * $Date: 2010/01/08 16:00:45 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/plugin_creator.h"
-
-#include <string>
-#include <vector>
-
-namespace
-{
-PLUGIN_CREATOR<FIREBIRD_STORE> frsc;
-}
-
-extern "C" STORE * GetStore();
-//-----------------------------------------------------------------------------
-STORE * GetStore()
-{
-return frsc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-FIREBIRD_STORE::FIREBIRD_STORE()
- : version("firebird_store v.1.4"),
- db_server("localhost"),
- db_database("/var/stg/stargazer.fdb"),
- db_user("stg"),
- db_password("123456"),
- til(IBPP::ilConcurrency),
- tlr(IBPP::lrWait),
- schemaVersion(0),
- logger(GetPluginLogger(GetStgLogger(), "store_firebird"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-FIREBIRD_STORE::~FIREBIRD_STORE()
-{
-db->Disconnect();
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::ParseSettings()
-{
-std::vector<PARAM_VALUE>::iterator i;
-std::string s;
-
-for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
- {
- if (i->value.empty())
- continue;
- s = ToLower(i->param);
-
- if (s == "server")
- db_server = i->value.front();
-
- if (s == "database")
- db_database = i->value.front();
-
- if (s == "user")
- db_user = i->value.front();
-
- if (s == "password")
- db_password = i->value.front();
-
- // Advanced settings block
-
- if (s == "isolationLevel")
- {
- if (i->value.front() == "Concurrency")
- til = IBPP::ilConcurrency;
- else if (i->value.front() == "DirtyRead")
- til = IBPP::ilReadDirty;
- else if (i->value.front() == "ReadCommitted")
- til = IBPP::ilReadCommitted;
- else if (i->value.front() == "Consistency")
- til = IBPP::ilConsistency;
- }
-
- if (s == "lockResolution")
- {
- if (i->value.front() == "Wait")
- tlr = IBPP::lrWait;
- else if (i->value.front() == "NoWait")
- tlr = IBPP::lrNoWait;
- }
- }
-
-try
- {
- db = IBPP::DatabaseFactory(db_server, db_database, db_user, db_password, "", "KOI8U", "");
- db->Connect();
- return CheckVersion();
- }
-catch (IBPP::Exception & ex)
- {
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::CheckVersion()
-{
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Execute("SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_NAME = 'TB_INFO'");
- if (!st->Fetch())
- {
- schemaVersion = 0;
- }
- else
- {
- st->Execute("SELECT version FROM tb_info");
- while (st->Fetch())
- st->Get(1, schemaVersion);
- }
- tr->Commit();
- logger("FIREBIRD_STORE: Current DB schema version: %d", schemaVersion);
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Firebird storage class definition
- *
- * $Revision: 1.13 $
- * $Date: 2010/01/19 11:07:25 $
- *
- */
-
-#ifndef FIREBIRD_STORE_H
-#define FIREBIRD_STORE_H
-
-#include <ctime>
-#include <string>
-#include <vector>
-
-#include "stg/store.h"
-#include "stg/locker.h"
-#include "stg/ibpp.h"
-#include "stg/logger.h"
-
-struct ToLower {
- char operator() (char c) const { return static_cast<char>(std::tolower(c)); }
-};
-
-class FIREBIRD_STORE : public STORE {
-public:
- FIREBIRD_STORE();
- virtual ~FIREBIRD_STORE();
-
- int GetUsersList(std::vector<std::string> * usersList) const;
- int AddUser(const std::string & login) const;
- int DelUser(const std::string & login) const;
- int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
- int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
- int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
- int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
- int WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message) const;
- int WriteUserConnect(const std::string & login, uint32_t ip) const;
- int WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const;
- int WriteDetailedStat(const TRAFF_STAT & statTree,
- time_t lastStat,
- const std::string & login) const;
-
- int AddMessage(STG_MSG * msg, const std::string & login) const;
- int EditMessage(const STG_MSG & msg, const std::string & login) const;
- int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
- int DelMessage(uint64_t id, const std::string & login) const;
- int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
-
- int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
-
- int GetAdminsList(std::vector<std::string> * adminsList) const;
- int SaveAdmin(const ADMIN_CONF & ac) const;
- int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
- int AddAdmin(const std::string & login) const;
- int DelAdmin(const std::string & login) const;
-
- int GetTariffsList(std::vector<std::string> * tariffsList) const;
- int AddTariff(const std::string & name) const;
- int DelTariff(const std::string & name) const;
- int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
- int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
-
- int GetCorpsList(std::vector<std::string> * corpsList) const;
- int SaveCorp(const CORP_CONF & cc) const;
- int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
- int AddCorp(const std::string & name) const;
- int DelCorp(const std::string & name) const;
-
- inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- inline const std::string & GetStrError() const { return strError; }
-
- inline const std::string & GetVersion() const { return version; }
-
- int GetServicesList(std::vector<std::string> * servicesList) const;
- int SaveService(const SERVICE_CONF & sc) const;
- int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
- int AddService(const std::string & name) const;
- int DelService(const std::string & name) const;
-
-private:
- FIREBIRD_STORE(const FIREBIRD_STORE & rvalue);
- FIREBIRD_STORE & operator=(const FIREBIRD_STORE & rvalue);
-
- std::string version;
- mutable std::string strError;
- std::string db_server, db_database, db_user, db_password;
- MODULE_SETTINGS settings;
- mutable IBPP::Database db;
- mutable pthread_mutex_t mutex;
- IBPP::TIL til;
- IBPP::TLR tlr;
- int schemaVersion;
- PLUGIN_LOGGER logger;
-
- int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
- int CheckVersion();
-};
-
-time_t ts2time_t(const IBPP::Timestamp & ts);
-void time_t2ts(time_t t, IBPP::Timestamp * ts);
-void ym2date(int year, int month, IBPP::Date * date);
-
-template <typename T>
-inline
-T Get(IBPP::Statement st, size_t pos)
-{
- T value;
- st->Get(pos, value);
- return value;
-}
-
-#endif //FIREBIRD_STORE_H
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Administrators manipulation methods
- *
- * $Revision: 1.11 $
- * $Date: 2008/12/04 17:10:06 $
- *
- */
-
-#include <string>
-#include <vector>
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-#include "stg/blowfish.h"
-
-#define adm_enc_passwd "cjeifY8m3"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string login;
-
-try
- {
- tr->Start();
- st->Execute("select login from tb_admins");
- while (st->Fetch())
- {
- st->Get(1, login);
- adminsList->push_back(login);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveAdmin(const ADMIN_CONF & ac) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-char encodedPass[2 * ADM_PASSWD_LEN + 2];
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
- EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
-
-cryptedPass[ADM_PASSWD_LEN] = 0;
-Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
-
-try
- {
- tr->Start();
- st->Prepare("update tb_admins set passwd=?, \
- chg_conf=?, \
- chg_password=?, \
- chg_stat=?, \
- chg_cash=?, \
- usr_add_del=?, \
- chg_tariff=?, \
- chg_admin=? \
- where login=?");
- st->Set(1, encodedPass);
- st->Set(2, static_cast<int16_t>(ac.priv.userConf));
- st->Set(3, static_cast<int16_t>(ac.priv.userPasswd));
- st->Set(4, static_cast<int16_t>(ac.priv.userStat));
- st->Set(5, static_cast<int16_t>(ac.priv.userCash));
- st->Set(6, static_cast<int16_t>(ac.priv.userAddDel));
- st->Set(7, static_cast<int16_t>(ac.priv.tariffChg));
- st->Set(8, static_cast<int16_t>(ac.priv.adminChg));
- st->Set(9, ac.login);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-try
- {
- tr->Start();
- st->Prepare("select * from tb_admins where login = ?");
- st->Set(1, login);
- st->Execute();
- if (st->Fetch())
- {
- st->Get(2, ac->login);
- st->Get(3, ac->password);
- st->Get(4, (int16_t &)ac->priv.userConf);
- st->Get(5, (int16_t &)ac->priv.userPasswd);
- st->Get(6, (int16_t &)ac->priv.userStat);
- st->Get(7, (int16_t &)ac->priv.userCash);
- st->Get(8, (int16_t &)ac->priv.userAddDel);
- st->Get(9, (int16_t &)ac->priv.tariffChg);
- st->Get(10, (int16_t &)ac->priv.adminChg);
- }
- else
- {
- strError = "Admin \"" + login + "\" not found in database";
- printfd(__FILE__, "Admin '%s' not found in database\n", login.c_str());
- tr->Rollback();
- return -1;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-if (ac->password == "")
- {
- return 0;
- }
-
-Decode21(cryptedPass, ac->password.c_str());
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
- {
- DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
- }
-ac->password = adminPass;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("insert into tb_admins(login, \
- passwd, \
- chg_conf, \
- chg_password, \
- chg_stat, \
- chg_cash, \
- usr_add_del, \
- chg_tariff, \
- chg_admin, \
- chg_service, \
- chg_corporation) \
- values (?, '', 0, 0, 0, 0, 0, 0, 0, 0, 0)");
- st->Set(1, login);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("delete from tb_admins where login = ?");
- st->Set(1, login);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Corporations manipulation methods
- *
- * $Revision: 1.5 $
- * $Date: 2007/12/23 13:39:59 $
- *
- */
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
- {
- tr->Start();
- st->Execute("select name from tb_corporations");
- while (st->Fetch())
- {
- st->Get(1, name);
- corpsList->push_back(name);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveCorp(const CORP_CONF & cc) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Execute("update tb_corporations set cash = ? where name = ?");
- st->Set(1, cc.cash);
- st->Set(2, cc.name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreCorp(CORP_CONF * cc, const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select cash from tb_corporations where name = ?");
- st->Set(1, name);
- st->Execute();
- if (st->Fetch())
- {
- st->Get(1, cc->cash);
- }
- else
- {
- strError = "Corporation \"" + name + "\" not found in database";
- tr->Rollback();
- printfd(__FILE__, "Corporation '%s' not found in database\n", name.c_str());
- return -1;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("insert into tb_corporations (name, cash), values (?, 0)");
- st->Set(1, name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("delete from tb_corporations where name = ?");
- st->Set(1, name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-
-/*
- * Messages manipualtion methods
- *
- * $Revision: 1.10 $
- * $Date: 2009/03/03 16:16:23 $
- *
- */
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_add_message(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
- st->Set(1, login);
- st->Set(2, (int32_t)msg->header.ver);
- st->Set(3, (int32_t)msg->header.type);
- st->Set(4, (int32_t)msg->header.lastSendTime);
- st->Set(5, (int32_t)msg->header.creationTime);
- st->Set(6, (int32_t)msg->header.showTime);
- st->Set(7, msg->header.repeat);
- st->Set(8, (int32_t)msg->header.repeatPeriod);
- st->Set(9, msg->text);
- st->Execute();
- st->Get(1, (int64_t &)msg->header.id);
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::EditMessage(const STG_MSG & msg,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_add_message(?, ?, ?, ?, ?, ?, ?, ?, ?)");
- st->Set(1, (int64_t)msg.header.id);
- st->Set(2, login);
- st->Set(3, (int32_t)msg.header.ver);
- st->Set(4, (int32_t)msg.header.type);
- st->Set(5, (int32_t)msg.header.lastSendTime);
- st->Set(6, (int32_t)msg.header.creationTime);
- st->Set(7, (int32_t)msg.header.showTime);
- st->Set(8, msg.header.repeat);
- st->Set(9, (int32_t)msg.header.repeatPeriod);
- st->Set(10, msg.text.c_str());
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetMessage(uint64_t id,
- STG_MSG * msg,
- const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select * from tb_messages where pk_message = ?");
- st->Set(1, (int64_t)id);
- st->Execute();
- if (st->Fetch())
- {
- st->Get(1, (int64_t &)msg->header.id);
- st->Get(3, (int32_t &)msg->header.ver);
- st->Get(4, (int32_t &)msg->header.type);
- st->Get(5, (int32_t &)msg->header.lastSendTime);
- st->Get(6, (int32_t &)msg->header.creationTime);
- st->Get(7, (int32_t &)msg->header.showTime);
- st->Get(8, msg->header.repeat);
- st->Get(9, (int32_t &)msg->header.repeatPeriod);
- st->Get(10, msg->text);
- }
- else
- {
- strprintf(&strError, "Message with id = %d not found in database", id);
- printfd(__FILE__, "Message with id - %d not found in database\n", id);
- tr->Rollback();
- return -1;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelMessage(uint64_t id, const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("delete from tb_messages where pk_message = ?");
- st->Set(1, (int64_t)id);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-STG_MSG_HDR header;
-
-try
- {
- tr->Start();
- st->Prepare("select pk_message, ver, msg_type, \
- last_send_time, creation_time, \
- show_time, repeat, repeat_period \
- from tb_messages where \
- fk_user = (select pk_user from tb_users where name = ?)");
- st->Set(1, login);
- st->Execute();
- while (st->Fetch())
- {
- st->Get(1, (int64_t &)header.id);
- st->Get(2, (int32_t &)header.ver);
- st->Get(3, (int32_t &)header.type);
- st->Get(4, (int32_t &)header.lastSendTime);
- st->Get(5, (int32_t &)header.creationTime);
- st->Get(6, (int32_t &)header.showTime);
- st->Get(7, header.repeat);
- st->Get(8, (int32_t &)header.repeatPeriod);
- hdrsList->push_back(header);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-
-/*
- * Services manipulation methods
- *
- * $Revision: 1.6 $
- * $Date: 2009/05/13 13:19:33 $
- *
- */
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetServicesList(std::vector<std::string> * servicesList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
- {
- tr->Start();
- st->Execute("select name from tb_services");
- while (st->Fetch())
- {
- st->Get(1, name);
- servicesList->push_back(name);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveService(const SERVICE_CONF & sc) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("update tb_services set \
- comments = ?, \
- cost = ?, \
- pay_day = ? \
- where name = ?");
- st->Set(1, sc.comment);
- st->Set(2, sc.cost);
- st->Set(3, static_cast<int16_t>(sc.payDay));
- st->Set(4, sc.name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreService(SERVICE_CONF * sc,
- const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select * from tb_services where name = ?");
- st->Set(1, name);
- st->Execute();
- if (st->Fetch())
- {
- st->Get(3, sc->comment);
- st->Get(4, sc->cost);
- int16_t pd;
- st->Get(5, pd);
- sc->payDay = static_cast<uint8_t>(pd);
- }
- else
- {
- strError = "Service \"" + name + "\" not found in database";
- printfd(__FILE__, "Service '%s' not found in database\n", name.c_str());
- tr->Rollback();
- return -1;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("insert into tb_services (name, comment, cost, pay_day) \
- values (?, '', 0, 0)");
- st->Set(1, name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_delete_service(?)");
- st->Set(1, name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Tariffs manipulation methods
- *
- * $Revision: 1.5 $
- * $Date: 2007/12/23 13:39:59 $
- *
- */
-
-#include <cmath>
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-namespace
-{
-
-const int pt_mega = 1024 * 1024;
-
-}
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
- {
- tr->Start();
- st->Execute("select name from tb_tariffs");
- while (st->Fetch())
- {
- st->Get(1, name);
- tariffsList->push_back(name);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_add_tariff(?, ?)");
- st->Set(1, name);
- st->Set(2, DIR_NUM);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_delete_tariff(?)");
- st->Set(1, name);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveTariff(const TARIFF_DATA & td,
- const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select pk_tariff from tb_tariffs where name = ?");
- st->Set(1, tariffName);
- st->Execute();
- if (!st->Fetch())
- {
- tr->Rollback();
- strprintf(&strError, "Tariff \"%s\" not found in database", tariffName.c_str());
- printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
- return -1;
- }
- int32_t id;
- st->Get(1, id);
- st->Close();
-
- std::string query = "update tb_tariffs set \
- fee = ?, \
- free = ?, \
- passive_cost = ?, \
- traff_type = ?";
-
- if (schemaVersion > 0)
- query += ", period = ?";
- if (schemaVersion > 1)
- query += ", change_policy = ?, \
- change_policy_timeout = ?";
-
- query += " where pk_tariff = ?";
-
- unsigned num = 5;
- st->Prepare(query);
- st->Set(1, td.tariffConf.fee);
- st->Set(2, td.tariffConf.free);
- st->Set(3, td.tariffConf.passiveCost);
- st->Set(4, td.tariffConf.traffType);
-
- if (schemaVersion > 0)
- {
- st->Set(5, TARIFF::PeriodToString(td.tariffConf.period));
- ++num;
- }
-
- if (schemaVersion > 1)
- {
- st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
- IBPP::Timestamp policyTimeout;
- time_t2ts(td.tariffConf.changePolicyTimeout, &policyTimeout);
- st->Set(7, policyTimeout);
- num += 2;
- }
-
- st->Set(num, id);
- st->Execute();
- st->Close();
-
- IBPP::Time tb;
- IBPP::Time te;
-
- for(int i = 0; i < DIR_NUM; i++)
- {
-
- tb.SetTime(td.dirPrice[i].hDay, td.dirPrice[i].mDay, 0);
- te.SetTime(td.dirPrice[i].hNight, td.dirPrice[i].mNight, 0);
-
- double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
- double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
- double pna = 0;
- double pnb = 0;
-
- if (td.dirPrice[i].singlePrice)
- {
- pna = pda;
- pnb = pdb;
- }
- else
- {
- pna = td.dirPrice[i].priceNightA;
- pnb = td.dirPrice[i].priceNightB;
- }
-
- int threshold = 0;
- if (td.dirPrice[i].noDiscount)
- {
- threshold = 0xffFFffFF;
- }
- else
- {
- threshold = td.dirPrice[i].threshold;
- }
-
- st->Prepare("update tb_tariffs_params set \
- price_day_a = ?, \
- price_day_b = ?, \
- price_night_a = ?, \
- price_night_b = ?, \
- threshold = ?, \
- time_day_begins = ?, \
- time_day_ends = ? \
- where fk_tariff = ? and dir_num = ?");
- st->Set(1, pda);
- st->Set(2, pdb);
- st->Set(3, pna);
- st->Set(4, pnb);
- st->Set(5, threshold);
- st->Set(6, tb);
- st->Set(7, te);
- st->Set(8, id);
- st->Set(9, i);
- st->Execute();
- st->Close();
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreTariff(TARIFF_DATA * td,
- const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-
-td->tariffConf.name = tariffName;
-
-try
- {
- tr->Start();
- st->Prepare("select * from tb_tariffs where name = ?"); // TODO: explicit field order!
- st->Set(1, tariffName);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "Tariff \"" + tariffName + "\" not found in database";
- printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
- tr->Rollback();
- return -1;
- }
- int32_t id;
- st->Get(1, id);
- st->Get(3, td->tariffConf.fee);
- st->Get(4, td->tariffConf.free);
- st->Get(5, td->tariffConf.passiveCost);
- td->tariffConf.traffType = TARIFF::IntToTraffType(Get<int>(st, 6));
- if (schemaVersion > 0)
- td->tariffConf.period = TARIFF::StringToPeriod(Get<std::string>(st, 7));
- if (schemaVersion > 1)
- {
- td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(Get<std::string>(st, 8));
- td->tariffConf.changePolicyTimeout = ts2time_t(Get<IBPP::Timestamp>(st, 9));
- }
- st->Close();
- st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
- st->Set(1, id);
- st->Execute();
- int i = 0;
- while (st->Fetch())
- {
- i++;
- if (i > DIR_NUM)
- {
- strError = "Too mach params for tariff \"" + tariffName + "\"";
- printfd(__FILE__, "Too mach params for tariff '%s'\n", tariffName.c_str());
- tr->Rollback();
- return -1;
- }
- int16_t dir;
- st->Get(3, dir);
- st->Get(4, td->dirPrice[dir].priceDayA);
- td->dirPrice[dir].priceDayA /= 1024*1024;
- st->Get(5, td->dirPrice[dir].priceDayB);
- td->dirPrice[dir].priceDayB /= 1024*1024;
- st->Get(6, td->dirPrice[dir].priceNightA);
- td->dirPrice[dir].priceNightA /= 1024*1024;
- st->Get(7, td->dirPrice[dir].priceNightB);
- td->dirPrice[dir].priceNightB /= 1024*1024;
- st->Get(8, td->dirPrice[dir].threshold);
- if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
- std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
- {
- td->dirPrice[dir].singlePrice = true;
- }
- else
- {
- td->dirPrice[dir].singlePrice = false;
- }
- if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
- {
- td->dirPrice[dir].noDiscount = true;
- }
- else
- {
-
- td->dirPrice[dir].noDiscount = false;
- }
- IBPP::Time tb;
- st->Get(9, tb);
- IBPP::Time te;
- st->Get(10, te);
- int h, m, s;
- tb.GetTime(h, m, s);
- td->dirPrice[dir].hDay = h;
- td->dirPrice[dir].mDay = m;
- te.GetTime(h, m, s);
- td->dirPrice[dir].hNight = h;
- td->dirPrice[dir].mNight = m;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * User manipulation methods
- *
- * $Revision: 1.19 $
- * $Date: 2010/01/19 11:07:25 $
- *
- */
-
-#include "stg/const.h"
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
- {
- tr->Start();
- st->Execute("select name from tb_users");
- while (st->Fetch())
- {
- st->Get(1, name);
- usersList->push_back(name);
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddUser(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_add_user(?, ?)");
- st->Set(1, name);
- st->Set(2, DIR_NUM);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelUser(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_delete_user(?)");
- st->Set(1, login);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveUserStat(const USER_STAT & stat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login);
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveStat(const USER_STAT & stat,
- const std::string & login,
- int year,
- int month) const
-{
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select pk_user from tb_users where name = ?");
- st->Set(1, login);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "User \"" + login + "\" not found in database";
- printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
- tr->Rollback();
- return -1;
- }
- int32_t uid = Get<int32_t>(st, 1);
- st->Close();
- st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
- st->Set(1, uid);
- st->Execute();
- if (!st->Fetch())
- {
- tr->Rollback();
- strError = "No stat info for user \"" + login + "\"";
- printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
- return -1;
- }
- int32_t sid;
- st->Get(1, sid);
- st->Close();
-
- IBPP::Timestamp actTime;
- time_t2ts(stat.lastActivityTime, &actTime);
- IBPP::Timestamp addTime;
- time_t2ts(stat.lastCashAddTime, &addTime);
- IBPP::Date dt;
- if (year != 0)
- ym2date(year, month, &dt);
- else
- dt.Today();
-
- st->Prepare("update tb_stats set \
- cash = ?, \
- free_mb = ?, \
- last_activity_time = ?, \
- last_cash_add = ?, \
- last_cash_add_time = ?, \
- passive_time = ?, \
- stats_date = ? \
- where pk_stat = ?");
-
- st->Set(1, stat.cash);
- st->Set(2, stat.freeMb);
- st->Set(3, actTime);
- st->Set(4, stat.lastCashAdd);
- st->Set(5, addTime);
- st->Set(6, (int32_t)stat.passiveTime);
- st->Set(7, dt);
- st->Set(8, sid);
-
- st->Execute();
- st->Close();
-
- for(int i = 0; i < DIR_NUM; i++)
- {
- st->Prepare("update tb_stats_traffic set \
- upload = ?, \
- download = ? \
- where fk_stat = ? and dir_num = ?");
- st->Set(1, (int64_t)stat.monthUp[i]);
- st->Set(2, (int64_t)stat.monthDown[i]);
- st->Set(3, sid);
- st->Set(4, i);
- st->Execute();
- st->Close();
- }
-
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveUserConf(const USER_CONF & conf,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select pk_user from tb_users where name = ?");
- st->Set(1, login);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "User \"" + login + "\" not found in database";
- printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
- tr->Rollback();
- return -1;
- }
- int32_t uid;
- st->Get(1, uid);
- st->Close();
-
- IBPP::Timestamp creditExpire;
- time_t2ts(conf.creditExpire, &creditExpire);
-
- st->Prepare("update tb_users set \
- address = ?, \
- always_online = ?, \
- credit = ?, \
- credit_expire = ?, \
- disabled = ?, \
- disabled_detail_stat = ?, \
- email = ?, \
- grp = ?, \
- note = ?, \
- passive = ?, \
- passwd = ?, \
- phone = ?, \
- fk_tariff = (select pk_tariff from tb_tariffs \
- where name = ?), \
- fk_tariff_change = (select pk_tariff from tb_tariffs \
- where name = ?), \
- fk_corporation = (select pk_corporation from tb_corporations \
- where name = ?), \
- real_name = ? \
- where pk_user = ?");
-
- st->Set(1, conf.address);
- st->Set(2, (bool)conf.alwaysOnline);
- st->Set(3, conf.credit);
- st->Set(4, creditExpire);
- st->Set(5, (bool)conf.disabled);
- st->Set(6, (bool)conf.disabledDetailStat);
- st->Set(7, conf.email);
- st->Set(8, conf.group);
- st->Set(9, conf.note);
- st->Set(10, (bool)conf.passive);
- st->Set(11, conf.password);
- st->Set(12, conf.phone);
- st->Set(13, conf.tariffName);
- st->Set(14, conf.nextTariff);
- st->Set(15, conf.corp);
- st->Set(16, conf.realName);
- st->Set(17, uid);
-
- st->Execute();
- st->Close();
-
- st->Prepare("delete from tb_users_services where fk_user = ?");
- st->Set(1, uid);
- st->Execute();
- st->Close();
-
- st->Prepare("insert into tb_users_services (fk_user, fk_service) \
- values (?, (select pk_service from tb_services \
- where name = ?))");
- for(std::vector<std::string>::const_iterator it = conf.services.begin(); it != conf.services.end(); ++it)
- {
- st->Set(1, uid);
- st->Set(2, *it);
- st->Execute();
- }
- st->Close();
-
- st->Prepare("delete from tb_users_data where fk_user = ?");
- st->Set(1, uid);
- st->Execute();
- st->Close();
-
- int i = 0;
- st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
- for (std::vector<std::string>::const_iterator it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
- {
- st->Set(1, uid);
- st->Set(2, *it);
- st->Set(3, i++);
- st->Execute();
- }
- st->Close();
-
- st->Prepare("delete from tb_allowed_ip where fk_user = ?");
- st->Set(1, uid);
- st->Execute();
-
- st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
- for(size_t i = 0; i < conf.ips.Count(); i++)
- {
- st->Set(1, uid);
- st->Set(2, (int32_t)conf.ips[i].ip);
- st->Set(3, (int32_t)conf.ips[i].mask);
- st->Execute();
- }
- tr->Commit();
- }
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreUserStat(USER_STAT * stat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select pk_user from tb_users where name = ?");
- st->Set(1, login);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "User \"" + login + "\" not found in database";
- printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
- return -1;
- }
- int32_t uid;
- st->Get(1, uid);
- st->Close();
-
- st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
- last_cash_add, last_cash_add_time, passive_time from tb_stats \
- where fk_user = ? order by stats_date desc");
- st->Set(1, uid);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "No stat info for user \"" + login + "\"";
- printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
- tr->Rollback();
- return -1;
- }
-
- int32_t sid;
- st->Get(1, sid);
- st->Get(2, stat->cash);
- st->Get(3, stat->freeMb);
- IBPP::Timestamp actTime;
- st->Get(4, actTime);
- st->Get(5, stat->lastCashAdd);
- IBPP::Timestamp addTime;
- st->Get(6, addTime);
- int32_t passiveTime;
- st->Get(7, passiveTime);
-
- stat->passiveTime = passiveTime;
-
- stat->lastActivityTime = ts2time_t(actTime);
-
- stat->lastCashAddTime = ts2time_t(addTime);
-
- st->Close();
- st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
- st->Set(1, sid);
- st->Execute();
- for(int i = 0; i < DIR_NUM; i++)
- {
- if (st->Fetch())
- {
- int dir;
- st->Get(3, dir);
- st->Get(5, (int64_t &)stat->monthUp[dir]);
- st->Get(4, (int64_t &)stat->monthDown[dir]);
- }
- else
- {
- break;
- }
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreUserConf(USER_CONF * conf,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
- {
- tr->Start();
- st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
- tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
- tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
- tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
- tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
- from tb_users left join tb_tariffs tf1 \
- on tf1.pk_tariff = tb_users.fk_tariff \
- left join tb_tariffs tf2 \
- on tf2.pk_tariff = tb_users.fk_tariff_change \
- left join tb_corporations \
- on tb_corporations.pk_corporation = tb_users.fk_corporation \
- where tb_users.name = ?");
- st->Set(1, login);
- st->Execute();
- if (!st->Fetch())
- {
- strError = "User \"" + login + "\" not found in database";
- printfd(__FILE__, "User '%s' not found in database", login.c_str());
- tr->Rollback();
- return -1;
- }
- int32_t uid;
- st->Get(1, uid);
- // Getting base config
- st->Get(2, conf->address);
- bool test;
- st->Get(3, test);
- conf->alwaysOnline = test;
- st->Get(4, conf->credit);
- IBPP::Timestamp timestamp;
- st->Get(5, timestamp);
-
- conf->creditExpire = ts2time_t(timestamp);
-
- st->Get(6, test);
- conf->disabled = test;
- st->Get(7, test);
- conf->disabledDetailStat = test;
- st->Get(8, conf->email);
- st->Get(9, conf->group);
- st->Get(10, conf->note);
- st->Get(11, test);
- conf->passive = test;
- st->Get(12, conf->password);
- st->Get(13, conf->phone);
- st->Get(14, conf->realName);
- st->Get(15, conf->tariffName);
- st->Get(16, conf->nextTariff);
- st->Get(17, conf->corp);
-
- if (conf->tariffName == "")
- conf->tariffName = NO_TARIFF_NAME;
- if (conf->corp == "")
- conf->corp = NO_CORP_NAME;
-
- // Services
- st->Close();
- st->Prepare("select name from tb_services \
- where pk_service in \
- (select fk_service from tb_users_services \
- where fk_user = ?)");
- st->Set(1, uid);
- st->Execute();
- while (st->Fetch())
- {
- std::string name;
- st->Get(1, name);
- conf->services.push_back(name);
- }
-
- // User data
- st->Close();
- st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
- st->Set(1, uid);
- st->Execute();
- while (st->Fetch())
- {
- int i;
- st->Get(2, i);
- st->Get(1, conf->userdata[i]);
- }
-
- // User IPs
- st->Close();
- st->Prepare("select ip, mask from tb_allowed_ip \
- where fk_user = ?");
- st->Set(1, uid);
- st->Execute();
- USER_IPS ips;
- while (st->Fetch())
- {
- IP_MASK im;
- st->Get(1, (int32_t &)im.ip);
- st->Get(2, (int32_t &)im.mask);
- ips.Add(im);
- }
- conf->ips = ips;
-
- tr->Commit();
- }
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message = "") const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-std::string temp = ""; // Composed message for log
-
-try
- {
- tr->Start();
- temp += "Admin \"" + admLogin + "\", ";
- temp += inet_ntostring(admIP);
- temp += ": ";
- temp = temp + message;
- //----------------------------------------------------------------------------------------
- // Checking and inserting parameters in params table
- st->Prepare("select pk_parameter from tb_parameters where name = ?");
- st->Set(1, paramName);
- st->Execute();
- if (!st->Fetch())
- {
- st->Close();
- st->Prepare("insert into tb_parameters (name) values (?)");
- st->Set(1, paramName);
- st->Execute();
- }
- st->Close();
- //----------------------------------------------------------------------------------------
- st->Prepare("insert into tb_params_log \
- (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
- values ((select pk_user from tb_users \
- where name = ?), \
- (select pk_parameter from tb_parameters \
- where name = ?), \
- ?, ?, ?, ?)");
- st->Set(1, login);
- st->Set(2, paramName);
- st->Set(3, now);
- st->Set(4, oldValue);
- st->Set(5, newValue);
- st->Set(6, temp);
- st->Execute();
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
- st->Set(1, login);
- st->Set(2, now);
- st->Set(3, (int32_t)ip);
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double /*cash*/,
- double /*freeMb*/,
- const std::string & /*reason*/) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-try
- {
- tr->Start();
- st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
- st->Set(1, login);
- st->Set(2, now);
- st->Execute();
- int32_t id;
- st->Get(1, id);
- st->Prepare("insert into tb_sessions_data \
- (fk_session_log, dir_num, session_upload, \
- session_download, month_upload, month_download) \
- values (?, ?, ?, ?, ?, ?)");
- for(int i = 0; i < DIR_NUM; i++)
- {
- st->Set(1, id);
- st->Set(2, i);
- st->Set(3, (int64_t)sessionUp[i]);
- st->Set(4, (int64_t)sessionDown[i]);
- st->Set(5, (int64_t)up[i]);
- st->Set(6, (int64_t)down[i]);
- st->Execute();
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
- time_t lastStat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-IBPP::Timestamp statTime, now;
-now.Now();
-
-time_t2ts(lastStat, &statTime);
-
-try
- {
- tr->Start();
- std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
- it = statTree.begin();
- st->Prepare("insert into tb_detail_stats \
- (till_time, from_time, fk_user, dir_num, \
- ip, download, upload, cost) \
- values (?, ?, (select pk_user from tb_users \
- where name = ?), \
- ?, ?, ?, ?, ?)");
- while (it != statTree.end())
- {
- st->Set(1, now);
- st->Set(2, statTime);
- st->Set(3, login);
- st->Set(4, it->first.dir);
- st->Set(5, (int32_t)it->first.ip);
- st->Set(6, (int64_t)it->second.down);
- st->Set(7, (int64_t)it->second.up);
- st->Set(8, it->second.cash);
- st->Execute();
- ++it;
- }
- tr->Commit();
- }
-
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-IBPP::Timestamp now;
-IBPP::Date nowDate;
-nowDate.Today();
-now.Now();
-
-if (SaveStat(stat, login, year, month))
- {
- return -1;
- }
-
-try
- {
- tr->Start();
-
- st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
- st->Set(1, login);
- st->Set(2, now);
- st->Set(3, now);
- st->Set(4, nowDate);
-
- st->Execute();
- int32_t id;
- st->Get(1, id);
- st->Close();
-
- st->Prepare("insert into tb_stats_traffic \
- (fk_stat, dir_num, upload, download) \
- values (?, ?, 0, 0)");
-
- for(int i = 0; i < DIR_NUM; i++)
- {
- st->Set(1, id);
- st->Set(2, i);
- st->Execute();
- }
-
- tr->Commit();
- }
-catch (IBPP::Exception & ex)
- {
- tr->Rollback();
- strError = "IBPP exception";
- printfd(__FILE__, ex.what());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Vairous utility methods
- *
- * $Revision: 1.8 $
- * $Date: 2010/03/04 12:20:32 $
- *
- */
-
-#include <cstdio>
-
-#include "firebird_store.h"
-#include "stg/ibpp.h"
-
-//-----------------------------------------------------------------------------
-time_t ts2time_t(const IBPP::Timestamp & ts)
-{
- char buf[32];
- int year, month, day, hour, min, sec;
- struct tm time_tm;
-
- memset(&time_tm, 0, sizeof(time_tm));
- ts.GetDate(year, month, day);
- ts.GetTime(hour, min, sec);
- if (year < 1990)
- return 0;
- sprintf(buf, "%d-%d-%d %d:%d:%d", year, month, day, hour, min, sec);
- stg_strptime(buf, "%Y-%m-%d %H:%M:%S", &time_tm);
-
- return mktime(&time_tm);
-}
-//-----------------------------------------------------------------------------
-void time_t2ts(time_t t, IBPP::Timestamp * ts)
-{
- struct tm res;
-
- localtime_r(&t, &res); // Reenterable
-
- *ts = IBPP::Timestamp(res.tm_year + 1900, res.tm_mon + 1, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);
-}
-//-----------------------------------------------------------------------------
-void ym2date(int year, int month, IBPP::Date * date)
-{
- date->SetDate(year + 1900, month + 1, 1);
- date->EndOfMonth();
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.6 2010/03/25 10:35:55 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_store_mysql.so
-
-SRCS = ./mysql_store.cpp
-
-STGLIBS = common \
- crypto \
- logger
-
-CXXFLAGS += $(MYSQL_CFLAGS)
-LIBS += $(MYSQL_LDFLAGS)
-
-include ../../Makefile.in
-
+++ /dev/null
-#include <sys/time.h>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <algorithm>
-
-#include <mysql.h>
-#include <errmsg.h>
-
-#include "stg/common.h"
-#include "stg/user_ips.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/blowfish.h"
-#include "stg/plugin_creator.h"
-#include "stg/logger.h"
-#include "mysql_store.h"
-
-#define adm_enc_passwd "cjeifY8m3"
-
-namespace
-{
-char qbuf[4096];
-
-const int pt_mega = 1024 * 1024;
-const std::string badSyms = "'`";
-const char repSym = '\"';
-const int RepitTimes = 3;
-
-template <typename T>
-int GetInt(const std::string & str, T * val, T defaultVal = T())
-{
- char *res;
-
- *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
-
- if (*res != 0)
- {
- *val = defaultVal; //Error!
- return EINVAL;
- }
-
- return 0;
-}
-
-int GetDouble(const std::string & str, double * val, double defaultVal)
-{
- char *res;
-
- *val = strtod(str.c_str(), &res);
-
- if (*res != 0)
- {
- *val = defaultVal; //Error!
- return EINVAL;
- }
-
- return 0;
-}
-
-int GetTime(const std::string & str, time_t * val, time_t defaultVal)
-{
- char *res;
-
- *val = strtol(str.c_str(), &res, 10);
-
- if (*res != 0)
- {
- *val = defaultVal; //Error!
- return EINVAL;
- }
-
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-std::string ReplaceStr(std::string source, const std::string & symlist, const char chgsym)
-{
- std::string::size_type pos=0;
-
- while( (pos = source.find_first_of(symlist,pos)) != std::string::npos)
- source.replace(pos, 1,1, chgsym);
-
- return source;
-}
-
-int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
-{
- char *res;
-
- *val = strtoull(str.c_str(), &res, 10);
-
- if (*res != 0)
- {
- *val = defaultVal; //Error!
- return EINVAL;
- }
-
- return 0;
-}
-
-PLUGIN_CREATOR<MYSQL_STORE> msc;
-}
-
-extern "C" STORE * GetStore();
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-STORE * GetStore()
-{
-return msc.GetPlugin();
-}
-//-----------------------------------------------------------------------------
-MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
- : settings(NULL)
-{
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE_SETTINGS::ParseParam(const std::vector<PARAM_VALUE> & moduleParams,
- const std::string & name, std::string & result)
-{
-PARAM_VALUE pv;
-pv.param = name;
-std::vector<PARAM_VALUE>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
- {
- errorStr = "Parameter \'" + name + "\' not found.";
- return -1;
- }
-
-result = pvi->value[0];
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
-{
-if (ParseParam(s.moduleParams, "user", dbUser) < 0 &&
- ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
- return -1;
-if (ParseParam(s.moduleParams, "password", dbPass) < 0 &&
- ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
- return -1;
-if (ParseParam(s.moduleParams, "database", dbName) < 0 &&
- ParseParam(s.moduleParams, "dbname", dbName) < 0)
- return -1;
-if (ParseParam(s.moduleParams, "server", dbHost) < 0 &&
- ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
- return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-MYSQL_STORE::MYSQL_STORE()
- : version("mysql_store v.0.67"),
- schemaVersion(0),
- logger(GetPluginLogger(GetStgLogger(), "store_mysql"))
-{
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
-{
- int ret;
-
- if( (ret = mysql_query(sock,sQuery)) )
- {
- for(int i=0; i<RepitTimes; i++)
- {
- if( (ret = mysql_query(sock,sQuery)) )
- ;//need to send error result
- else
- return 0;
- }
- }
-
- return ret;
-}
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::ParseSettings()
-{
-int ret = storeSettings.ParseSettings(settings);
-MYSQL mysql;
-mysql_init(&mysql);
-if (ret)
- errorStr = storeSettings.GetStrError();
-else
-{
- if(storeSettings.GetDBPassword().length() == 0)
- {
- errorStr = "Database password must be not empty. Please read Manual.";
- return -1;
- }
- MYSQL * sock;
- if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
- storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
- 0,0,NULL,0)))
- {
- errorStr = "Couldn't connect to mysql engine! With error:\n";
- errorStr += mysql_error(&mysql);
- mysql_close(sock);
- ret = -1;
- }
- else
- {
- if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
- {
- std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create database! With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- ret = -1;
- }
- else
- {
- if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
- {
- errorStr = "Couldn't select database! With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- ret = -1;
- }
- else
- ret = CheckAllTables(sock);
- }
- }
- else
- {
- ret = CheckAllTables(sock);
- }
- if (!ret)
- {
- logger("MYSQL_STORE: Current DB schema version: %d", schemaVersion);
- MakeUpdates(sock);
- }
- mysql_close(sock);
- }
-}
-return ret;
-}
-//-----------------------------------------------------------------------------
-bool MYSQL_STORE::IsTablePresent(const std::string & str,MYSQL * sock)
-{
-MYSQL_RES* result;
-
-if (!(result=mysql_list_tables(sock,str.c_str() )))
-{
- errorStr = "Couldn't get tables list With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-my_ulonglong num_rows = mysql_num_rows(result);
-
-if(result)
- mysql_free_result(result);
-
-return num_rows == 1;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::CheckAllTables(MYSQL * sock)
-{
-//info-------------------------------------------------------------------------
-if(!IsTablePresent("info",sock))
-{
- sprintf(qbuf,"CREATE TABLE info (version INTEGER NOT NULL)");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create info table With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-
- sprintf(qbuf,"INSERT INTO info SET version=0");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't write default version. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- schemaVersion = 0;
-}
-else
-{
- std::vector<std::string> info;
- if (GetAllParams(&info, "info", "version"))
- schemaVersion = 0;
- else
- {
- if (info.empty())
- schemaVersion = 0;
- else
- GetInt(info.front(), &schemaVersion, 0);
- }
-}
-//admins-----------------------------------------------------------------------
-if(!IsTablePresent("admins",sock))
-{
- sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
- "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
- "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
- "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
- "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create admin table list With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-
- sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
- "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
- "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create default admin. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-
-//tariffs-----------------------------------------------------------------------
-std::string param, res;
-if(!IsTablePresent("tariffs",sock))
-{
- res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " PriceDayA%d DOUBLE DEFAULT 0.0,", i);
- res += param;
-
- strprintf(¶m, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
- res += param;
-
- strprintf(¶m, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
- res += param;
-
- strprintf(¶m, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
- res += param;
-
- strprintf(¶m, " Threshold%d INT DEFAULT 0,", i);
- res += param;
-
- strprintf(¶m, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
- res += param;
-
- strprintf(¶m, " NoDiscount%d INT DEFAULT 0,", i);
- res += param;
-
- strprintf(¶m, " SinglePrice%d INT DEFAULT 0,", i);
- res += param;
- }
-
- res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
- "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
- "period VARCHAR(32) NOT NULL DEFAULT 'month',"
- "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow',"
- "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)";
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create tariffs table list With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-
- res = "INSERT INTO tariffs SET name='tariff',";
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " NoDiscount%d=1,", i);
- res += param;
-
- strprintf(¶m, " Threshold%d=0,", i);
- res += param;
-
- strprintf(¶m, " Time%d='0:0-0:0',", i);
- res += param;
-
- if(i != 0 && i != 1)
- {
- strprintf(¶m, " SinglePrice%d=0,", i);
- res += param;
- }
-
- if(i != 1)
- {
- strprintf(¶m, " PriceDayA%d=0.0,", i);
- res += param;
- }
- if(i != 1)
- {
- strprintf(¶m, " PriceDayB%d=0.0,", i);
- res += param;
- }
-
- if(i != 0)
- {
- strprintf(¶m, " PriceNightA%d=0.0,", i);
- res += param;
- }
- if(i != 0)
- {
- strprintf(¶m, " PriceNightB%d=0.0,", i);
- res += param;
- }
- }
-
- res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
- "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
- "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
- "change_policy='allow', change_policy_timeout=0";
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create default tariff. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-
- sprintf(qbuf,"UPDATE info SET version=1");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't write default version. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- schemaVersion = 2;
-}
-
-//users-----------------------------------------------------------------------
-if(!IsTablePresent("users",sock))
-{
- res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
- "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
- "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
- "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
- "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
-
- for (int i = 0; i < USERDATA_NUM; i++)
- {
- strprintf(¶m, " Userdata%d VARCHAR(254) NOT NULL,", i);
- res += param;
- }
-
- param = " CreditExpire INT(11) DEFAULT 0,";
- res += param;
-
- strprintf(¶m, " IP VARCHAR(254) DEFAULT '*',");
- res += param;
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " D%d BIGINT(30) DEFAULT 0,", i);
- res += param;
-
- strprintf(¶m, " U%d BIGINT(30) DEFAULT 0,", i);
- res += param;
- }
-
- strprintf(¶m, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
- "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
- "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
- " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
- res += param;
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create users table list With error:\n";
- errorStr += mysql_error(sock);
- errorStr += "\n\n" + res;
- mysql_close(sock);
- return -1;
- }
-
- res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
- "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
- "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
- "Phone='', RealName='',Tariff='tariff',TariffChange='',NAS='',";
-
- for (int i = 0; i < USERDATA_NUM; i++)
- {
- strprintf(¶m, " Userdata%d='',", i);
- res += param;
- }
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " D%d=0,", i);
- res += param;
-
- strprintf(¶m, " U%d=0,", i);
- res += param;
- }
-
- res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
- "LastCashAddTime=0, PassiveTime=0";
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create default user. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-/*
-//logs-----------------------------------------------------------------------
-if(!IsTablePresent("logs"))
-{
- sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
-
- if(MysqlQuery(qbuf))
- {
- errorStr = "Couldn't create admin table list With error:\n";
- errorStr += mysql_error(sock);
- return -1;
- }
-}
-*/
-//messages---------------------------------------------------------------------
-if(!IsTablePresent("messages",sock))
-{
- sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
- "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
- "stgRepeat INT, repeatPeriod INT, text TEXT)");
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create messages table. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-
-//month_stat-------------------------------------------------------------------
-if(!IsTablePresent("stat",sock))
-{
- res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
-
- for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " U%d BIGINT,", i);
- res += param;
-
- strprintf(¶m, " D%d BIGINT,", i);
- res += param;
- }
-
- res += " cash DOUBLE, INDEX (login))";
-
- if(MysqlQuery(res.c_str(),sock))
- {
- errorStr = "Couldn't create stat table. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::MakeUpdates(MYSQL * sock)
-{
-if (schemaVersion < 1)
- {
- if (MysqlQuery("ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month'", sock))
- {
- errorStr = "Couldn't update tariffs table to version 1. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- if (MysqlQuery("UPDATE info SET version = 1", sock))
- {
- errorStr = "Couldn't update DB schema version to 1. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- schemaVersion = 1;
- logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
- }
-
-if (schemaVersion < 2)
- {
- if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) ||
- MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock))
- {
- errorStr = "Couldn't update tariffs table to version 2. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- if (MysqlQuery("UPDATE info SET version = 2", sock))
- {
- errorStr = "Couldn't update DB schema version to 2. With error:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
- schemaVersion = 2;
- logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-
-int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList,
- const std::string & table, const std::string & name) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock=NULL;
-my_ulonglong num, i;
-
-ParamList->clear();
-
-sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
-
-if(MysqlGetQuery(qbuf,sock))
-{
- errorStr = "Couldn't GetAllParams Query for: ";
- errorStr += name + " - " + table + "\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't GetAllParams Results for: ";
- errorStr += name + " - " + table + "\n";
- errorStr += mysql_error(sock);
- return -1;
-}
-
-num = mysql_num_rows(res);
-
-for(i = 0; i < num; i++)
-{
- row = mysql_fetch_row(res);
- ParamList->push_back(row[0]);
-}
-
-mysql_free_result(res);
-mysql_close(sock);
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-if(GetAllParams(usersList, "users", "login"))
- return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-if(GetAllParams(adminsList, "admins", "login"))
- return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-if(GetAllParams(tariffsList, "tariffs", "name"))
- return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddUser(const std::string & login) const
-{
-std::string query = "INSERT INTO users SET login='" + login + "',Note='',NAS=''";
-
-for (int i = 0; i < USERDATA_NUM; i++)
- query += ",Userdata" + x2str(i) + "=''";
-
-if(MysqlSetQuery(query.c_str()))
-{
- errorStr = "Couldn't add user:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelUser(const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't delete user:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-std::string query;
-
-query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
- AlwaysOnline, Tariff, Address, Phone, Email, Note, \
- RealName, StgGroup, Credit, TariffChange, ";
-
-for (int i = 0; i < USERDATA_NUM; i++)
-{
- sprintf(qbuf, "Userdata%d, ", i);
- query += qbuf;
-}
-
-query += "CreditExpire, IP FROM users WHERE login='";
-query += login + "' LIMIT 1";
-
-//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-
-if(MysqlGetQuery(query.c_str(),sock))
-{
- errorStr = "Couldn't restore Tariff(on query):\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't restore Tariff(on getting result):\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (mysql_num_rows(res) != 1)
-{
- errorStr = "User not found";
- mysql_close(sock);
- return -1;
-}
-
-row = mysql_fetch_row(res);
-
-conf->password = row[1];
-
-if (conf->password.empty())
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' password is blank.";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[2],&conf->passive) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[3], &conf->disabled) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter Down.";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[4], &conf->disabledDetailStat) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[5], &conf->alwaysOnline) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
- mysql_close(sock);
- return -1;
- }
-
-conf->tariffName = row[6];
-
-if (conf->tariffName.empty())
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' tariff is blank.";
- mysql_close(sock);
- return -1;
- }
-
-conf->address = row[7];
-conf->phone = row[8];
-conf->email = row[9];
-conf->note = row[10];
-conf->realName = row[11];
-conf->group = row[12];
-
-if (GetDouble(row[13], &conf->credit, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
- mysql_close(sock);
- return -1;
- }
-
-conf->nextTariff = row[14];
-
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- conf->userdata[i] = row[15+i];
- }
-
-GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
-
-std::string ipStr = row[16+USERDATA_NUM];
-USER_IPS i;
-try
- {
- i = StrToIPS(ipStr);
- }
-catch (const std::string & s)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
- mysql_close(sock);
- return -1;
- }
-conf->ips = i;
-
-mysql_free_result(res);
-mysql_close(sock);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-
-std::string query;
-
-query = "SELECT ";
-
-for (int i = 0; i < DIR_NUM; i++)
-{
- sprintf(qbuf, "D%d, U%d, ", i, i);
- query += qbuf;
-}
-
-query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
- FROM users WHERE login = '";
-query += login + "'";
-
-//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-
-if(MysqlGetQuery(query.c_str() ,sock))
-{
- errorStr = "Couldn't restore UserStat(on query):\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't restore UserStat(on getting result):\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-row = mysql_fetch_row(res);
-
-unsigned int startPos=0;
-
-char s[22];
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- uint64_t traff;
- sprintf(s, "D%d", i);
- if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
- mysql_close(sock);
- return -1;
- }
- stat->monthDown[i] = traff;
-
- sprintf(s, "U%d", i);
- if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
- mysql_close(sock);
- return -1;
- }
- stat->monthUp[i] = traff;
- }//for
-
-startPos += (2*DIR_NUM);
-
-if (GetDouble(row[startPos], &stat->cash, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
- mysql_close(sock);
- return -1;
- }
-
-if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
- mysql_close(sock);
- return -1;
- }
-
-if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
- mysql_close(sock);
- return -1;
- }
-
-if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
- mysql_close(sock);
- return -1;
- }
-
-if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
- mysql_close(sock);
- return -1;
- }
-
-if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
- {
- mysql_free_result(res);
- errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
- mysql_close(sock);
- return -1;
- }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const std::string & login) const
-{
-std::string param;
-std::string res;
-
-strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
- "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
- "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ",
- conf.password.c_str(),
- conf.passive,
- conf.disabled,
- conf.disabledDetailStat,
- conf.alwaysOnline,
- conf.tariffName.c_str(),
- (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
- (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
- (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
- (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
- (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
- (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
- conf.credit,
- conf.nextTariff.c_str()
- );
-
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- strprintf(¶m, " Userdata%d='%s',", i,
- (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
- res += param;
- }
-
-strprintf(¶m, " CreditExpire=%d,", conf.creditExpire);
-res += param;
-
-std::ostringstream ipStr;
-ipStr << conf.ips;
-
-strprintf(¶m, " IP='%s'", ipStr.str().c_str());
-res += param;
-
-strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
- errorStr = "Couldn't save user conf:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const std::string & login) const
-{
-std::string param;
-std::string res;
-
-res = "UPDATE users SET";
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " D%d=%lld,", i, stat.monthDown[i]);
- res += param;
-
- strprintf(¶m, " U%d=%lld,", i, stat.monthUp[i]);
- res += param;
- }
-
-strprintf(¶m, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
- " PassiveTime=%d, LastActivityTime=%d",
- stat.cash,
- stat.freeMb,
- stat.lastCashAdd,
- stat.lastCashAddTime,
- stat.passiveTime,
- stat.lastActivityTime
- );
-res += param;
-
-strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
- errorStr = "Couldn't save user stat:\n";
-// errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteLogString(const std::string & str, const std::string & login) const
-{
-std::string res, tempStr;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-lt = localtime(&t);
-
-MYSQL_RES* result;
-MYSQL * sock;
-strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
-if (!(sock=MysqlConnect())){
- errorStr = "Couldn't connect to Server";
- return -1;
-}
-if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
-{
- errorStr = "Couldn't get table " + tempStr + ":\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-my_ulonglong num_rows = mysql_num_rows(result);
-
-mysql_free_result(result);
-
-if (num_rows < 1)
-{
- sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
- lt->tm_mon+1, lt->tm_year+1900);
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create WriteDetailedStat table:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-
-strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
-
-std::string send;
-
-strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
- lt->tm_mon+1, lt->tm_year+1900,
- login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
-
-if(MysqlQuery(send.c_str(),sock))
-{
- errorStr = "Couldn't write log string:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-mysql_close(sock);
-return 0;
-
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message) const
-{
-std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
- + paramName + "\' parameter changed from \'" + oldValue +
- "\' to \'" + newValue + "\'. " + message;
-
-return WriteLogString(userLogMsg, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-std::string logStr = "Connect, " + inet_ntostring(ip);
-return WriteLogString(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double /*freeMb*/,
- const std::string & /*reason*/) const
-{
-std::string logStr = "Disconnect, ";
-std::ostringstream sssu;
-std::ostringstream sssd;
-std::ostringstream ssmu;
-std::ostringstream ssmd;
-std::ostringstream sscash;
-
-ssmu << up;
-ssmd << down;
-
-sssu << sessionUp;
-sssd << sessionDown;
-
-sscash << cash;
-
-logStr += " session upload: \'";
-logStr += sssu.str();
-logStr += "\' session download: \'";
-logStr += sssd.str();
-logStr += "\' month upload: \'";
-logStr += ssmu.str();
-logStr += "\' month download: \'";
-logStr += ssmd.str();
-logStr += "\' cash: \'";
-logStr += sscash.str();
-logStr += "\'";
-
-return WriteLogString(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
- const std::string & login) const
-{
-std::string param, res;
-
-strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,",
- login.c_str(), month+1, year+1900);
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " U%d=%lld,", i, stat.monthUp[i]);
- res += param;
-
- strprintf(¶m, " D%d=%lld,", i, stat.monthDown[i]);
- res += param;
- }
-
-strprintf(¶m, " cash=%f", stat.cash);
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
- errorStr = "Couldn't SaveMonthStat:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::AddAdmin(const std::string & login) const
-{
-sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't add admin:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::DelAdmin(const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't delete admin:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
-{
-char passwordE[2 * ADM_PASSWD_LEN + 2];
-char pass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-
-memset(pass, 0, sizeof(pass));
-memset(adminPass, 0, sizeof(adminPass));
-
-BLOWFISH_CTX ctx;
-InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-adminPass[ADM_PASSWD_LEN - 1] = 0;
-
-for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
- {
- EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
- }
-
-pass[ADM_PASSWD_LEN - 1] = 0;
-Encode12(passwordE, pass, ADM_PASSWD_LEN);
-
-sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
- "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
- "WHERE login='%s' LIMIT 1",
- passwordE,
- ac.priv.userConf,
- ac.priv.userPasswd,
- ac.priv.userStat,
- ac.priv.userCash,
- ac.priv.userAddDel,
- ac.priv.tariffChg,
- ac.priv.adminChg,
- ac.login.c_str()
- );
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't save admin:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
-{
-char pass[ADM_PASSWD_LEN + 1];
-char password[ADM_PASSWD_LEN + 1];
-char passwordE[2*ADM_PASSWD_LEN + 2];
-BLOWFISH_CTX ctx;
-
-memset(password, 0, sizeof(password));
-
-std::string p;
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
-
-if(MysqlGetQuery(qbuf,sock))
-{
- errorStr = "Couldn't restore admin:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't restore admin:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if ( mysql_num_rows(res) == 0)
-{
- mysql_free_result(res);
- errorStr = "Couldn't restore admin as couldn't found him in table.\n";
- mysql_close(sock);
- return -1;
-}
-
-row = mysql_fetch_row(res);
-
-p = row[1];
-
-if(p.length() == 0)
-{
- mysql_free_result(res);
- errorStr = "Error in parameter password";
- mysql_close(sock);
- return -1;
-}
-
-memset(passwordE, 0, sizeof(passwordE));
-strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
-
-memset(pass, 0, sizeof(pass));
-
-if (passwordE[0] != 0)
- {
- Decode21(pass, passwordE);
- InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
- for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
- {
- DecryptBlock(password + 8*i, pass + 8*i, &ctx);
- }
- }
-else
- {
- password[0] = 0;
- }
-
-ac->password = password;
-
-uint16_t a;
-
-if (GetInt(row[2], &a) == 0)
- ac->priv.userConf = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgConf";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[3], &a) == 0)
- ac->priv.userPasswd = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgPassword";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[4], &a) == 0)
- ac->priv.userStat = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgStat";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[5], &a) == 0)
- ac->priv.userCash = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgCash";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[6], &a) == 0)
- ac->priv.userAddDel = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter UsrAddDel";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[7], &a) == 0)
- ac->priv.tariffChg = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgTariff";
- mysql_close(sock);
- return -1;
- }
-
-if (GetInt(row[8], &a) == 0)
- ac->priv.adminChg = a;
-else
- {
- mysql_free_result(res);
- errorStr = "Error in parameter ChgAdmin";
- mysql_close(sock);
- return -1;
- }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddTariff(const std::string & name) const
-{
-sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't add tariff:\n";
-// errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelTariff(const std::string & name) const
-{
-sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't delete tariff: ";
-// errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
-
-if(MysqlGetQuery(qbuf,sock))
-{
- errorStr = "Couldn't restore Tariff:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't restore Tariff:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-std::string str;
-td->tariffConf.name = tariffName;
-
-row = mysql_fetch_row(res);
-
-std::string param;
-for (int i = 0; i<DIR_NUM; i++)
- {
- strprintf(¶m, "Time%d", i);
- str = row[6+i*8];
- if (str.length() == 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- ParseTariffTimeStr(str.c_str(),
- td->dirPrice[i].hDay,
- td->dirPrice[i].mDay,
- td->dirPrice[i].hNight,
- td->dirPrice[i].mNight);
-
- strprintf(¶m, "PriceDayA%d", i);
- if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
- td->dirPrice[i].priceDayA /= (1024*1024);
-
- strprintf(¶m, "PriceDayB%d", i);
- if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
- td->dirPrice[i].priceDayB /= (1024*1024);
-
- strprintf(¶m, "PriceNightA%d", i);
- if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
- td->dirPrice[i].priceNightA /= (1024*1024);
-
- strprintf(¶m, "PriceNightB%d", i);
- if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
- td->dirPrice[i].priceNightB /= (1024*1024);
-
- strprintf(¶m, "Threshold%d", i);
- if (GetInt(row[5+i*8], &td->dirPrice[i].threshold) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- strprintf(¶m, "SinglePrice%d", i);
- if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- strprintf(¶m, "NoDiscount%d", i);
- if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
- }//main for
-
-if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
- mysql_close(sock);
- return -1;
- }
-
-if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
- mysql_close(sock);
- return -1;
- }
-
-if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
- mysql_close(sock);
- return -1;
- }
-
- str = row[4+8*DIR_NUM];
- param = "TraffType";
-
- if (str.length() == 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
-td->tariffConf.traffType = TARIFF::StringToTraffType(str);
-
-if (schemaVersion > 0)
-{
- str = row[5+8*DIR_NUM];
- param = "Period";
-
- if (str.length() == 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- td->tariffConf.period = TARIFF::StringToPeriod(str);
- }
-else
- {
- td->tariffConf.period = TARIFF::MONTH;
- }
-
-if (schemaVersion > 1)
- {
- str = row[6+8*DIR_NUM];
- param = "ChangePolicy";
-
- if (str.length() == 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
-
- str = row[7+8*DIR_NUM];
- param = "ChangePolicyTimeout";
-
- if (str.length() == 0)
- {
- mysql_free_result(res);
- errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
- mysql_close(sock);
- return -1;
- }
-
- td->tariffConf.changePolicyTimeout = readTime(str);
- }
-else
- {
- td->tariffConf.changePolicy = TARIFF::ALLOW;
- td->tariffConf.changePolicyTimeout = 0;
- }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
-{
-std::string param;
-
-std::string res="UPDATE tariffs SET";
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- strprintf(¶m, " PriceDayA%d=%f,", i,
- td.dirPrice[i].priceDayA * pt_mega);
- res += param;
-
- strprintf(¶m, " PriceDayB%d=%f,", i,
- td.dirPrice[i].priceDayB * pt_mega);
- res += param;
-
- strprintf(¶m, " PriceNightA%d=%f,", i,
- td.dirPrice[i].priceNightA * pt_mega);
- res += param;
-
- strprintf(¶m, " PriceNightB%d=%f,", i,
- td.dirPrice[i].priceNightB * pt_mega);
- res += param;
-
- strprintf(¶m, " Threshold%d=%d,", i,
- td.dirPrice[i].threshold);
- res += param;
-
- std::string s;
- strprintf(¶m, " Time%d", i);
-
- strprintf(&s, "%0d:%0d-%0d:%0d",
- td.dirPrice[i].hDay,
- td.dirPrice[i].mDay,
- td.dirPrice[i].hNight,
- td.dirPrice[i].mNight);
-
- res += (param + "='" + s + "',");
-
- strprintf(¶m, " NoDiscount%d=%d,", i,
- td.dirPrice[i].noDiscount);
- res += param;
-
- strprintf(¶m, " SinglePrice%d=%d,", i,
- td.dirPrice[i].singlePrice);
- res += param;
- }
-
-strprintf(¶m, " PassiveCost=%f,", td.tariffConf.passiveCost);
-res += param;
-
-strprintf(¶m, " Fee=%f,", td.tariffConf.fee);
-res += param;
-
-strprintf(¶m, " Free=%f,", td.tariffConf.free);
-res += param;
-
-res += " TraffType='" + TARIFF::TraffTypeToString(td.tariffConf.traffType) + "'";
-
-if (schemaVersion > 0)
- res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'";
-
-if (schemaVersion > 1)
- res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"\
- ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'";
-
-strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
- errorStr = "Couldn't save tariff:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
- time_t lastStat,
- const std::string & login) const
-{
-std::string res, stTime, endTime, tempStr;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-lt = localtime(&t);
-
-if (lt->tm_hour == 0 && lt->tm_min <= 5)
- {
- t -= 3600 * 24;
- lt = localtime(&t);
- }
-
-MYSQL_RES* result;
-MYSQL * sock;
-strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
-
-if (!(sock=MysqlConnect())){
- mysql_close(sock);
- return -1;
-}
-
-if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
-{
- errorStr = "Couldn't get table " + tempStr + ":\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-my_ulonglong num_rows = mysql_num_rows(result);
-
-mysql_free_result(result);
-
-if (num_rows < 1)
-{
- sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
- "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
- "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
- "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
- lt->tm_mon+1, lt->tm_year+1900);
-
- if(MysqlQuery(qbuf,sock))
- {
- errorStr = "Couldn't create WriteDetailedStat table:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-}
-
-struct tm * lt1;
-struct tm * lt2;
-
-lt1 = localtime(&lastStat);
-
-int h1, m1, s1;
-int h2, m2, s2;
-
-h1 = lt1->tm_hour;
-m1 = lt1->tm_min;
-s1 = lt1->tm_sec;
-
-lt2 = localtime(&t);
-
-h2 = lt2->tm_hour;
-m2 = lt2->tm_min;
-s2 = lt2->tm_sec;
-
-strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
-strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
-
-strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
- "day=%d,startTime='%s',endTime='%s',",
- lt->tm_mon+1, lt->tm_year+1900,
- login.c_str(),
- lt->tm_mday,
- stTime.c_str(),
- endTime.c_str()
- );
-
-std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
-stIter = statTree.begin();
-
-while (stIter != statTree.end())
- {
- strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f",
- inet_ntostring(stIter->first.ip).c_str(),
- stIter->first.dir,
- stIter->second.down,
- stIter->second.up,
- stIter->second.cash
- );
-
- if( MysqlQuery((res+tempStr).c_str(),sock) )
- {
- errorStr = "Couldn't insert data in WriteDetailedStat:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
- }
-
- result=mysql_store_result(sock);
- if(result)
- mysql_free_result(result);
-
- ++stIter;
- }
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
-{
-struct timeval tv;
-
-gettimeofday(&tv, NULL);
-
-msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(tv.tv_usec);
-
-sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld",
- login.c_str(),
- static_cast<long long>(msg->header.id)
- );
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't add message:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return EditMessage(*msg, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
-{
-std::string res;
-
-strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
- "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
- "WHERE login='%s' AND id=%lld LIMIT 1",
- msg.header.type,
- msg.header.lastSendTime,
- msg.header.creationTime,
- msg.header.showTime,
- msg.header.repeat,
- msg.header.repeatPeriod,
- (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
- login.c_str(),
- msg.header.id
- );
-
-if(MysqlSetQuery(res.c_str()))
-{
- errorStr = "Couldn't edit message:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-
-sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
- login.c_str(), static_cast<unsigned long long>(id));
-
-if(MysqlGetQuery(qbuf,sock))
-{
- errorStr = "Couldn't GetMessage:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't GetMessage:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-row = mysql_fetch_row(res);
-
-if(row[2]&&str2x(row[2], msg->header.type))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-if(row[3] && str2x(row[3], msg->header.lastSendTime))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-if(row[4] && str2x(row[4], msg->header.creationTime))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-if(row[5] && str2x(row[5], msg->header.showTime))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-if(row[6] && str2x(row[6], msg->header.repeat))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-if(row[7] && str2x(row[7], msg->header.repeatPeriod))
-{
- mysql_free_result(res);
- errorStr = "Invalid value in message header for user: " + login;
- mysql_close(sock);
- return -1;
-}
-
-msg->header.id = id;
-msg->text = row[8];
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelMessage(uint64_t id, const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
- login.c_str(), static_cast<long long>(id));
-
-if(MysqlSetQuery(qbuf))
-{
- errorStr = "Couldn't delete Message:\n";
- //errorStr += mysql_error(sock);
- return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
-
-if(MysqlGetQuery(qbuf,sock))
-{
- errorStr = "Couldn't GetMessageHdrs:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
- errorStr = "Couldn't GetMessageHdrs:\n";
- errorStr += mysql_error(sock);
- mysql_close(sock);
- return -1;
-}
-
-unsigned int i;
-my_ulonglong num_rows = mysql_num_rows(res);
-uint64_t id = 0;
-
-for (i = 0; i < num_rows; i++)
-{
- row = mysql_fetch_row(res);
- if (str2x(row[1], id))
- continue;
-
- STG_MSG_HDR hdr;
- if (row[2])
- if(str2x(row[2], hdr.type))
- continue;
-
- if (row[3])
- if(str2x(row[3], hdr.lastSendTime))
- continue;
-
- if (row[4])
- if(str2x(row[4], hdr.creationTime))
- continue;
-
- if (row[5])
- if(str2x(row[5], hdr.showTime))
- continue;
-
- if (row[6])
- if(str2x(row[6], hdr.repeat))
- continue;
-
- if (row[7])
- if(str2x(row[7], hdr.repeatPeriod))
- continue;
-
- hdr.id = id;
- hdrsList->push_back(hdr);
-}
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-
-int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
-
- MYSQL * sock;
- int ret=MysqlGetQuery(Query,sock);
- mysql_close(sock);
- return ret;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
- if (!(sock=MysqlConnect())) {
- return -1;
- }
- return MysqlQuery(Query,sock);
-}
-//-----------------------------------------------------------------------------
-MYSQL * MYSQL_STORE::MysqlConnect() const {
- MYSQL * sock;
- if ( !(sock=mysql_init(NULL)) ){
- errorStr= "mysql init susck\n";
- return NULL;
- }
- if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
- storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
- 0,0,NULL,0)))
- {
- errorStr = "Couldn't connect to mysql engine! With error:\n";
- errorStr += mysql_error(sock);
- return NULL;
- }
- else{
- if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
- errorStr = "Database lost !\n";
- return NULL;
- }
- }
- return sock;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
- /*
- $Revision: 1.5 $
- $Date: 2010/10/07 19:45:52 $
- */
-
-
-#ifndef MYSQL_STORE_H
-#define MYSQL_STORE_H
-
-#include <mysql/mysql.h>
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "stg/module_settings.h"
-#include "stg/store.h"
-#include "stg/user_traff.h"
-#include "stg/logger.h"
-
-//-----------------------------------------------------------------------------
-class MYSQL_STORE_SETTINGS
-{
-public:
- MYSQL_STORE_SETTINGS();
- virtual ~MYSQL_STORE_SETTINGS() {}
- virtual int ParseSettings(const MODULE_SETTINGS & s);
- virtual const std::string & GetStrError() const { return errorStr; }
-
- const std::string & GetDBUser() const { return dbUser; }
- const std::string & GetDBPassword() const { return dbPass; }
- const std::string & GetDBHost() const { return dbHost; }
- const std::string & GetDBName() const { return dbName; }
-
-private:
- MYSQL_STORE_SETTINGS(const MYSQL_STORE_SETTINGS & rvalue);
- MYSQL_STORE_SETTINGS & operator=(const MYSQL_STORE_SETTINGS & rvalue);
-
- const MODULE_SETTINGS * settings;
-
- int ParseParam(const std::vector<PARAM_VALUE> & moduleParams,
- const std::string & name, std::string & result);
-
- std::string errorStr;
-
- std::string dbUser;
- std::string dbPass;
- std::string dbName;
- std::string dbHost;
-};
-//-----------------------------------------------------------------------------
-class MYSQL_STORE: public STORE
-{
-public:
- MYSQL_STORE();
- virtual ~MYSQL_STORE() {}
- virtual const std::string & GetStrError() const { return errorStr; }
-
- //User
- virtual int GetUsersList(std::vector<std::string> * usersList) const;
- virtual int AddUser(const std::string & login) const;
- virtual int DelUser(const std::string & login) const;
- virtual int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
- virtual int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
- virtual int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
- virtual int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
- virtual int WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message = "") const;
- virtual int WriteUserConnect(const std::string & login, uint32_t ip) const;
- virtual int WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const;
-
- virtual int WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
- time_t lastStat,
- const std::string & login) const;
-
- virtual int AddMessage(STG_MSG * msg, const std::string & login) const;
- virtual int EditMessage(const STG_MSG & msg, const std::string & login) const;
- virtual int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
- virtual int DelMessage(uint64_t id, const std::string & login) const;
- virtual int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
-
- virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
-
- //Admin
- virtual int GetAdminsList(std::vector<std::string> * adminsList) const;
- virtual int AddAdmin(const std::string & login) const;
- virtual int DelAdmin(const std::string & login) const;
- virtual int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
- virtual int SaveAdmin(const ADMIN_CONF & ac) const;
-
- //Tariff
- virtual int GetTariffsList(std::vector<std::string> * tariffsList) const;
- virtual int AddTariff(const std::string & name) const;
- virtual int DelTariff(const std::string & name) const;
- virtual int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
- virtual int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
-
- //Corparation
- virtual int GetCorpsList(std::vector<std::string> *) const {return 0;}
- virtual int SaveCorp(const CORP_CONF &) const {return 0;}
- virtual int RestoreCorp(CORP_CONF *, const std::string &) const {return 0;}
- virtual int AddCorp(const std::string &) const {return 0;}
- virtual int DelCorp(const std::string &) const {return 0;}
-
- // Services
- virtual int GetServicesList(std::vector<std::string> *) const {return 0;}
- virtual int SaveService(const SERVICE_CONF &) const {return 0;}
- virtual int RestoreService(SERVICE_CONF *, const std::string &) const {return 0;}
- virtual int AddService(const std::string &) const {return 0;}
- virtual int DelService(const std::string &) const {return 0;}
-
- virtual void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- virtual int ParseSettings();
- virtual const std::string & GetVersion() const { return version; }
-
-private:
- MYSQL_STORE(const MYSQL_STORE & rvalue);
- MYSQL_STORE & operator=(const MYSQL_STORE & rvalue);
-
- virtual int WriteLogString(const std::string & str, const std::string & login) const;
- int GetAllParams(std::vector<std::string> * ParamList, const std::string & table, const std::string & name) const;
- int CheckAllTables(MYSQL * sock);
- int MakeUpdates(MYSQL * sock);
- bool IsTablePresent(const std::string & str,MYSQL * sock);
- mutable std::string errorStr;
- int MysqlQuery(const char* sQuery,MYSQL * sock) const;
- int MysqlGetQuery(const char * Query,MYSQL * & sock) const;
- int MysqlSetQuery(const char * Query) const;
- MYSQL * MysqlConnect() const ;
- std::string version;
- MYSQL_STORE_SETTINGS storeSettings;
- MODULE_SETTINGS settings;
- int schemaVersion;
-
- PLUGIN_LOGGER logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.4 2010/04/26 12:44:42 faust Exp $
-###############################################################################
-
-include ../../../../../Makefile.conf
-
-PROG = mod_store_postgresql.so
-
-SRCS = ./postgresql_store.cpp \
- ./postgresql_store_admins.cpp \
- ./postgresql_store_corporations.cpp \
- ./postgresql_store_messages.cpp \
- ./postgresql_store_services.cpp \
- ./postgresql_store_tariffs.cpp \
- ./postgresql_store_users.cpp \
- ./postgresql_store_utils.cpp
-
-STGLIBS = common \
- crypto \
- logger
-
-CXXFLAGS += $(PG_CFLAGS)
-LDFLAGS += $(PG_LDFLAGS)
-
-LIBS += -lpq
-
-include ../../Makefile.in
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * This file contains a realization of a base postgresql-storage plugin class
- *
- * v. 1.3
- * FreeMb logging on disconnects added
- *
- * v. 1.2
- * Reconnection on faults added
- *
- * v. 1.1
- * tb_stats removed
- *
- * v. 1.0
- * Initial implementation
- *
- * $Revision: 1.5 $
- * $Date: 2010/01/06 10:43:48 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "postgresql_store_utils.h"
-#include "postgresql_store.h"
-
-#include "stg/module_settings.h"
-#include "stg/plugin_creator.h"
-
-#include <string>
-#include <vector>
-
-#include <libpq-fe.h>
-
-namespace
-{
-PLUGIN_CREATOR<POSTGRESQL_STORE> pgsc;
-}
-
-extern "C" STORE * GetStore();
-
-//-----------------------------------------------------------------------------
-STORE * GetStore()
-{
-return pgsc.GetPlugin();
-}
-
-//-----------------------------------------------------------------------------
-POSTGRESQL_STORE::POSTGRESQL_STORE()
- : versionString("postgresql_store v.1.3"),
- server("localhost"),
- database("stargazer"),
- user("stg"),
- password("123456"),
- clientEncoding("KOI8"),
- version(0),
- retries(3),
- connection(NULL),
- logger(GetPluginLogger(GetStgLogger(), "store_postgresql"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-POSTGRESQL_STORE::~POSTGRESQL_STORE()
-{
-if (connection)
- {
- PQfinish(connection);
- }
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::ParseSettings()
-{
-std::vector<PARAM_VALUE>::iterator i;
-
-for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
- {
- if (i->value.empty())
- continue;
- std::string s = ToLower(i->param);
- if (s == "server")
- {
- server = i->value.front();
- }
- if (s == "database")
- {
- database = i->value.front();
- }
- if (s == "user")
- {
- user = i->value.front();
- }
- if (s == "password")
- {
- password = i->value.front();
- }
- if (s == "retries")
- {
- if (str2x(i->value.front(), retries))
- {
- strError = "Invalid 'retries' value";
- printfd(__FILE__, "POSTGRESQL_STORE::ParseSettings(): '%s'\n", strError.c_str());
- return -1;
- }
- }
- }
-
-clientEncoding = "KOI8";
-
-return Connect();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::Connect()
-{
-std::string params;
-params = "host=" + server + " "
- + "dbname=" + database + " "
- + "user=" + user + " "
- + "password=" + password;
-
-connection = PQconnectdb(params.c_str());
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- strError = PQerrorMessage(connection);
- printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
- // Will try to connect later
- return 0;
- }
-
-if (PQsetClientEncoding(connection, clientEncoding.c_str()))
- {
- strError = PQerrorMessage(connection);
- printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
- return 1;
- }
-
-return CheckVersion();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::Reset() const
-{
-for (int i = 0; i < retries && PQstatus(connection) != CONNECTION_OK; ++i)
- {
- struct timespec ts = {1, 0};
- nanosleep(&ts, NULL);
- PQreset(connection);
- }
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- strError = PQerrorMessage(connection);
- printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
- return 1;
- }
-
-if (PQsetClientEncoding(connection, clientEncoding.c_str()))
- {
- strError = PQerrorMessage(connection);
- printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
- return -1;
- }
-
-return CheckVersion();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::CheckVersion() const
-{
-
-if (StartTransaction())
- {
- strError = "Failed to start transaction";
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
- RollbackTransaction();
- return -1;
- }
-
-if (str2x(PQgetvalue(result, 0, 0), version))
- {
- strError = "Invalid DB version";
- PQclear(result);
- RollbackTransaction();
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PQclear(result);
-
-if (version < DB_MIN_VERSION)
- {
- strError = "DB version too old";
- RollbackTransaction();
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
- return -1;
- }
-
-if (version < 6)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
- }
-
-if (CommitTransaction())
- {
- strError = "Failed to commit transaction";
- printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
- return -1;
- }
-
-logger("POSTGRESQL_STORE: Current DB schema version: %d", version);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * PostgreSQL storage class definition
- *
- * $Revision: 1.8 $
- * $Date: 2010/01/19 11:06:53 $
- *
- */
-
-#ifndef POSTGRESQL_STORE_H
-#define POSTGRESQL_STORE_H
-
-#include <libpq-fe.h>
-
-#include <string>
-#include <vector>
-
-#include "stg/store.h"
-#include "stg/logger.h"
-
-// Minimal DB version is 5
-// Recommended DB version is 6 (support FreeMb logging on disconnects)
-#define DB_MIN_VERSION 5
-
-class POSTGRESQL_STORE : public STORE {
-public:
- POSTGRESQL_STORE();
- virtual ~POSTGRESQL_STORE();
-
- // Users
- int GetUsersList(std::vector<std::string> * usersList) const;
- int AddUser(const std::string & login) const;
- int DelUser(const std::string & login) const;
- int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
- int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
- int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
- int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
- int WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message) const;
- int WriteUserConnect(const std::string & login, uint32_t ip) const;
- int WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & up,
- const DIR_TRAFF & down,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const;
- int WriteDetailedStat(const TRAFF_STAT & statTree,
- time_t lastStat,
- const std::string & login) const;
-
- // Messages
- int AddMessage(STG_MSG * msg, const std::string & login) const;
- int EditMessage(const STG_MSG & msg, const std::string & login) const;
- int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
- int DelMessage(uint64_t id, const std::string & login) const;
- int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
-
- // Stats
- int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
-
- // Admins
- int GetAdminsList(std::vector<std::string> * adminsList) const;
- int SaveAdmin(const ADMIN_CONF & ac) const;
- int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
- int AddAdmin(const std::string & login) const;
- int DelAdmin(const std::string & login) const;
-
- // Tariffs
- int GetTariffsList(std::vector<std::string> * tariffsList) const;
- int AddTariff(const std::string & name) const;
- int DelTariff(const std::string & name) const;
- int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
- int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
-
- // Corporations
- int GetCorpsList(std::vector<std::string> * corpsList) const;
- int SaveCorp(const CORP_CONF & cc) const;
- int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
- int AddCorp(const std::string & name) const;
- int DelCorp(const std::string & name) const;
-
- // Services
- int GetServicesList(std::vector<std::string> * servicesList) const;
- int SaveService(const SERVICE_CONF & sc) const;
- int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
- int AddService(const std::string & name) const;
- int DelService(const std::string & name) const;
-
- // Settings
- inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
- int ParseSettings();
-
- inline const std::string & GetStrError() const { return strError; }
- inline const std::string & GetVersion() const { return versionString; }
-private:
- POSTGRESQL_STORE(const POSTGRESQL_STORE & rvalue);
- POSTGRESQL_STORE & operator=(const POSTGRESQL_STORE & rvalue);
-
- int StartTransaction() const;
- int CommitTransaction() const;
- int RollbackTransaction() const;
-
- int EscapeString(std::string & value) const;
-
- int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
-
- int SaveUserServices(uint32_t uid, const std::vector<std::string> & services) const;
- int SaveUserData(uint32_t uid, const std::vector<std::string> & data) const;
- int SaveUserIPs(uint32_t uid, const USER_IPS & ips) const;
-
- void MakeDate(std::string & date, int year = 0, int month = 0) const;
-
- int Connect();
- int Reset() const;
- int CheckVersion() const;
-
- std::string versionString;
- mutable std::string strError;
- std::string server;
- std::string database;
- std::string user;
- std::string password;
- std::string clientEncoding;
- MODULE_SETTINGS settings;
- mutable pthread_mutex_t mutex;
- mutable int version;
- int retries;
-
- PGconn * connection;
-
- PLUGIN_LOGGER logger;
-};
-
-#endif //POSTGRESQL_STORE_H
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Administrators manipulation methods
- *
- * $Revision: 1.3 $
- * $Date: 2010/11/08 10:10:24 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-#include "stg/locker.h"
-#include "stg/admin_conf.h"
-#include "stg/blowfish.h"
-#include "postgresql_store.h"
-
-#define adm_enc_passwd "cjeifY8m3"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to start transaction'\n");
- return -1;
- }
-
-result = PQexec(connection, "SELECT login FROM tb_admins WHERE login <> '@stargazer'");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- adminsList->push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to start transaction'\n");
- return -1;
- }
-
-char encodedPass[2 * ADM_PASSWD_LEN + 2];
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
- EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
-
-cryptedPass[ADM_PASSWD_LEN] = 0;
-Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
-
-std::string pass = encodedPass;
-std::string login = ac.login;
-
-if (EscapeString(pass))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape password'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(login))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::stringstream query;
-query << "UPDATE tb_admins SET "
- << "passwd = '" << pass << "', "
- << "chg_conf = " << ac.priv.userConf << ", "
- << "chg_password = " << ac.priv.userPasswd << ", "
- << "chg_stat = " << ac.priv.userStat << ", "
- << "chg_cash = " << ac.priv.userCash << ", "
- << "usr_add_del = " << ac.priv.userAddDel << ", "
- << "chg_tariff = " << ac.priv.tariffChg << ", "
- << "chg_admin = " << ac.priv.adminChg << " "
- << "WHERE login = '" << login << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to start transaction'\n");
- return -1;
- }
-
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT login, passwd, \
- chg_conf, chg_password, chg_stat, \
- chg_cash, usr_add_del, chg_tariff, \
- chg_admin, chg_service, chg_corporation \
- FROM tb_admins \
- WHERE login = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch admin's data";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-ac->login = PQgetvalue(result, 0, 0);
-ac->password = PQgetvalue(result, 0, 1);
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 2) << " "
- << PQgetvalue(result, 0, 3) << " "
- << PQgetvalue(result, 0, 4) << " "
- << PQgetvalue(result, 0, 5) << " "
- << PQgetvalue(result, 0, 6) << " "
- << PQgetvalue(result, 0, 7) << " "
- << PQgetvalue(result, 0, 8) << " "
- << PQgetvalue(result, 0, 9) << " "
- << PQgetvalue(result, 0, 10);
-
-PQclear(result);
-
-tuple >> ac->priv.userConf
- >> ac->priv.userPasswd
- >> ac->priv.userStat
- >> ac->priv.userCash
- >> ac->priv.userAddDel
- >> ac->priv.tariffChg
- >> ac->priv.adminChg;
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to commit transacion'\n");
- return -1;
- }
-
-if (ac->password == "")
- {
- return 0;
- }
-
-Decode21(cryptedPass, ac->password.c_str());
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
- {
- DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
- }
-ac->password = adminPass;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "INSERT INTO tb_admins \
- (login, passwd, \
- chg_conf, chg_password, chg_stat, \
- chg_cash, usr_add_del, chg_tariff, \
- chg_admin, chg_service, chg_corporation) \
- VALUES "
- << "('" << elogin << "', \
- '', 0, 0, 0, 0, 0, 0, 0, 0, 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_admins WHERE login = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Corporations manipulation methods
- *
- * $Revision: 1.2 $
- * $Date: 2009/06/09 12:32:39 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-#include "postgresql_store.h"
-#include "stg/locker.h"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to start transaction'\n");
- return -1;
- }
-
-result = PQexec(connection, "SELECT name FROM tb_corporations");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- corpsList->push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveCorp(const CORP_CONF & cc) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = cc.name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "UPDATE tb_corporations SET "
- << "cash = " << cc.cash
- << "WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreCorp(CORP_CONF * cc, const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT cash FROM tb_corporations WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch corp's data";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0);
-
-PQclear(result);
-
-tuple >> cc->cash;
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "INSERT INTO tb_corporations \
- (name, cash) \
- VALUES \
- ('" << ename << "', 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_corporations WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-
-/*
- * Messages manipualtion methods
- *
- * $Revision: 1.6 $
- * $Date: 2009/07/15 11:19:42 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-#include "stg/common.h"
-#include "postgresql_store.h"
-#include "stg/locker.h"
-#include "stg/message.h"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-std::string etext = msg->text;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(etext))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape message text'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT sp_add_message("
- << "'" << elogin << "', "
- << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually
- << "CAST(" << msg->header.type << " AS SMALLINT), "
- << "CAST('" << formatTime(msg->header.lastSendTime) << "' AS TIMESTAMP), "
- << "CAST('" << formatTime(msg->header.creationTime) << "' AS TIMESTAMP), "
- << msg->header.showTime << ", "
- << "CAST(" << msg->header.repeat << " AS SMALLINT), "
- << msg->header.repeatPeriod << ", "
- << "'" << etext << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch newlly added message ID";
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0);
-
-PQclear(result);
-
-tuple >> msg->header.id;
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::EditMessage(const STG_MSG & msg,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-std::string etext = msg.text;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(etext))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape message text'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "UPDATE tb_messages SET "
- << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
- << "ver = " << msg.header.ver << ", "
- << "msg_type = " << msg.header.type << ", "
- << "last_send_time = CAST('" << formatTime(msg.header.lastSendTime) << "' AS TIMESTAMP), "
- << "creation_time = CAST('" << formatTime(msg.header.creationTime) << "' AS TIMESTAMP), "
- << "show_time = " << msg.header.showTime << ", "
- << "repeat = " << msg.header.repeat << ", "
- << "repeat_period = " << msg.header.repeatPeriod << ", "
- << "msg_text = '" << etext << "' "
- << "WHERE pk_message = " << msg.header.id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetMessage(uint64_t id,
- STG_MSG * msg,
- const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT ver, msg_type, last_send_time, \
- creation_time, show_time, repeat, \
- repeat_period, msg_text \
- FROM tb_messages \
- WHERE pk_message = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch message data";
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-str2x(PQgetvalue(result, 0, 0), msg->header.ver);
-str2x(PQgetvalue(result, 0, 1), msg->header.type);
-msg->header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 2)));
-msg->header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 3)));
-str2x(PQgetvalue(result, 0, 4), msg->header.showTime);
-str2x(PQgetvalue(result, 0, 5), msg->header.repeat);
-str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod);
-msg->text = PQgetvalue(result, 0, 7);
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelMessage(uint64_t id, const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_messages WHERE pk_message = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT pk_message, ver, msg_type, \
- last_send_time, creation_time, show_time, \
- repeat, repeat_period \
- FROM tb_messages \
- WHERE fk_user IN \
- (SELECT pk_user FROM tb_users \
- WHERE name = '" << elogin << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- std::stringstream tuple;
- STG_MSG_HDR header;
- tuple << PQgetvalue(result, i, 0) << " ";
- tuple << PQgetvalue(result, i, 1) << " ";
- tuple << PQgetvalue(result, i, 2) << " ";
- header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 3)));
- header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 4)));
- tuple << PQgetvalue(result, i, 5) << " ";
- tuple << PQgetvalue(result, i, 6) << " ";
- tuple << PQgetvalue(result, i, 7) << " ";
-
- tuple >> header.id;
- tuple >> header.ver;
- tuple >> header.type;
- tuple >> header.showTime;
- tuple >> header.repeat;
- tuple >> header.repeatPeriod;
- hdrsList->push_back(header);
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-
-/*
- * Services manipulation methods
- *
- * $Revision: 1.2 $
- * $Date: 2009/06/09 12:32:40 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-#include "postgresql_store.h"
-#include "stg/locker.h"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetServicesList(std::vector<std::string> * servicesList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
- return -1;
- }
-
-result = PQexec(connection, "SELECT name FROM tb_services");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- servicesList->push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveService(const SERVICE_CONF & sc) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = sc.name;
-std::string ecomment = sc.comment;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(ecomment))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "UPDATE tb_services SET "
- << "comment = '" << ecomment << "', "
- << "cost = " << sc.cost << ", "
- << "pay_day = " << sc.payDay << " "
- << "WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreService(SERVICE_CONF * sc,
- const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch service's data";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0) << " "
- << PQgetvalue(result, 0, 1) << " "
- << PQgetvalue(result, 0, 2);
-
-PQclear(result);
-
-tuple >> sc->comment
- >> sc->cost
- >> sc->payDay;
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "INSERT INTO tb_services \
- (name, comment, cost, pay_day) \
- VALUES \
- ('" << ename << "', '', 0, 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Tariffs manipulation methods
- *
- * $Revision: 1.2 $
- * $Date: 2009/06/09 12:32:40 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-#include <cmath>
-
-#include <libpq-fe.h>
-
-#include "stg/common.h"
-#include "postgresql_store.h"
-#include "stg/locker.h"
-
-namespace
-{
-
-const int pt_mega = 1024 * 1024;
-
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
- return -1;
- }
-
-result = PQexec(connection, "SELECT name FROM tb_tariffs");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- tariffsList->push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = name;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
- const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = tariffName;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- {
- std::ostringstream query;
- query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch tariff ID";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int32_t id;
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0);
-
- PQclear(result);
-
- tuple >> id;
- }
-
- {
- std::ostringstream query;
- query << "UPDATE tb_tariffs SET \
- fee = " << td.tariffConf.fee << ", \
- free = " << td.tariffConf.free << ", \
- passive_cost = " << td.tariffConf.passiveCost << ", \
- traff_type = " << td.tariffConf.traffType;
-
- if (version > 6)
- query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'";
-
- if (version > 7)
- query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "', \
- change_policy_timeout = CAST('" << formatTime(td.tariffConf.changePolicyTimeout) << "' AS TIMESTAMP)";
-
- query << " WHERE pk_tariff = " << id;
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-for(int i = 0; i < DIR_NUM; i++)
- {
- double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
- double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
- double pna = 0;
- double pnb = 0;
-
- if (td.dirPrice[i].singlePrice)
- {
- pna = pda;
- pnb = pdb;
- }
- else
- {
- pna = td.dirPrice[i].priceNightA * 1024 * 1024;
- pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
- }
-
- int threshold = 0;
- if (td.dirPrice[i].noDiscount)
- {
- threshold = 0xffFFffFF;
- }
- else
- {
- threshold = td.dirPrice[i].threshold;
- }
-
- {
- std::ostringstream query;
- query << "UPDATE tb_tariffs_params SET \
- price_day_a = " << pda << ", \
- price_day_b = " << pdb << ", \
- price_night_a = " << pna << ", \
- price_night_b = " << pnb << ", \
- threshold = " << threshold << ", \
- time_day_begins = CAST('" << td.dirPrice[i].hDay
- << ":"
- << td.dirPrice[i].mDay << "' AS TIME), \
- time_day_ends = CAST('" << td.dirPrice[i].hNight
- << ":"
- << td.dirPrice[i].mNight << "' AS TIME) \
- WHERE fk_tariff = " << id << " AND dir_num = " << i;
-
- result = PQexec(connection, query.str().c_str());
- }
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- PQclear(result);
- }
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
- const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string ename = tariffName;
-
-if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-td->tariffConf.name = tariffName;
-
-std::ostringstream query;
-query << "SELECT pk_tariff, \
- fee, \
- free, \
- passive_cost, \
- traff_type";
-
-if (version > 6)
- query << ", period";
-
-if (version > 7)
- query << ", change_policy \
- , change_policy_timeout";
-
-query << " FROM tb_tariffs WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch tariff data";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int id;
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0) << " ";
- tuple << PQgetvalue(result, 0, 1) << " ";
- tuple << PQgetvalue(result, 0, 2) << " ";
- tuple << PQgetvalue(result, 0, 3) << " ";
- tuple << PQgetvalue(result, 0, 4) << " ";
-
- tuple >> id;
- tuple >> td->tariffConf.fee;
- tuple >> td->tariffConf.free;
- tuple >> td->tariffConf.passiveCost;
- tuple >> td->tariffConf.traffType;
- }
-
-if (version > 6)
- td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5));
-
-if (version > 7)
- {
- td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(PQgetvalue(result, 0, 6));
- td->tariffConf.changePolicyTimeout = readTime(PQgetvalue(result, 0, 7));
- }
-
-PQclear(result);
-
-query.str("");
-query << "SELECT dir_num, \
- price_day_a, \
- price_day_b, \
- price_night_a, \
- price_night_b, \
- threshold, \
- EXTRACT(hour FROM time_day_begins), \
- EXTRACT(minute FROM time_day_begins), \
- EXTRACT(hour FROM time_day_ends), \
- EXTRACT(minute FROM time_day_ends) \
- FROM tb_tariffs_params \
- WHERE fk_tariff = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-tuples = PQntuples(result);
-
-if (tuples != DIR_NUM)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
- }
-
-for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
- {
- int dir;
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, i, 0) << " ";
- tuple << PQgetvalue(result, i, 1) << " ";
- tuple << PQgetvalue(result, i, 2) << " ";
- tuple << PQgetvalue(result, i, 3) << " ";
- tuple << PQgetvalue(result, i, 4) << " ";
- tuple << PQgetvalue(result, i, 5) << " ";
- tuple << PQgetvalue(result, i, 6) << " ";
- tuple << PQgetvalue(result, i, 7) << " ";
- tuple << PQgetvalue(result, i, 8) << " ";
- tuple << PQgetvalue(result, i, 9) << " ";
-
- tuple >> dir;
- tuple >> td->dirPrice[dir].priceDayA;
- td->dirPrice[dir].priceDayA /= 1024 * 1024;
- tuple >> td->dirPrice[dir].priceDayB;
- td->dirPrice[dir].priceDayB /= 1024 * 1024;
- tuple >> td->dirPrice[dir].priceNightA;
- td->dirPrice[dir].priceNightA /= 1024 * 1024;
- tuple >> td->dirPrice[dir].priceNightB;
- td->dirPrice[dir].priceNightB /= 1024 * 1024;
- tuple >> td->dirPrice[dir].threshold;
- tuple >> td->dirPrice[dir].hDay;
- tuple >> td->dirPrice[dir].mDay;
- tuple >> td->dirPrice[dir].hNight;
- tuple >> td->dirPrice[dir].mNight;
- }
-
- if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
- std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
- {
- td->dirPrice[dir].singlePrice = true;
- }
- else
- {
- td->dirPrice[dir].singlePrice = false;
- }
- if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
- {
- td->dirPrice[dir].noDiscount = true;
- }
- else
- {
-
- td->dirPrice[dir].noDiscount = false;
- }
-
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * User manipulation methods
- *
- * $Revision: 1.14 $
- * $Date: 2010/05/07 07:26:36 $
- *
- */
-
-#include <string>
-#include <vector>
-#include <sstream>
-#include <ctime>
-
-#include <libpq-fe.h>
-
-#include "stg/common.h"
-#include "stg/const.h"
-#include "stg/locker.h"
-#include "../../../stg_timer.h"
-#include "postgresql_store.h"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to start transaction'\n");
- return -1;
- }
-
-result = PQexec(connection, "SELECT name FROM tb_users");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- usersList->push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddUser(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = name;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT sp_add_user('" << elogin << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelUser(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserStat(const USER_STAT & stat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login);
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveStat(const USER_STAT & stat,
- const std::string & login,
- int year,
- int month) const
-{
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "UPDATE tb_users SET "
- "cash = " << stat.cash << ", "
- "free_mb = " << stat.freeMb << ", "
- "last_activity_time = CAST('" << formatTime(stat.lastActivityTime) << "' AS TIMESTAMP), "
- "last_cash_add = " << stat.lastCashAdd << ", "
- "last_cash_add_time = CAST('" << formatTime(stat.lastCashAddTime) << "' AS TIMESTAMP), "
- "passive_time = " << stat.passiveTime << " "
- "WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-std::string date;
-
-MakeDate(date, year, month);
-
-for (int dir = 0; dir < DIR_NUM; ++dir)
- {
- query.str("");
- query << "SELECT sp_add_stats_traffic ("
- "'" << elogin << "', "
- "CAST('" << date << "' AS DATE), "
- "CAST(" << dir << " AS SMALLINT), "
- "CAST(" << stat.monthUp[dir] << " AS BIGINT), "
- "CAST(" << stat.monthDown[dir] << " AS BIGINT))";
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- PQclear(result);
- }
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserConf(const USER_CONF & conf,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch user's ID";
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-uint32_t uid;
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0);
-
- PQclear(result);
-
- tuple >> uid;
- }
-
-std::string eaddress = conf.address;
-std::string eemail = conf.email;
-std::string egroup = conf.group;
-std::string enote = conf.note;
-std::string epassword = conf.password;
-std::string ephone = conf.phone;
-std::string erealname = conf.realName;
-std::string etariffname = conf.tariffName;
-std::string enexttariff = conf.nextTariff;
-std::string ecorporation = conf.corp;
-
-if (EscapeString(eaddress))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape address'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(eemail))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape email'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(egroup))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape group'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(enote))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape note'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(epassword))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape password'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(ephone))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape phone'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(erealname))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape real name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(etariffname))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape tariff name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(enexttariff))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape next tariff name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(ecorporation))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape corporation name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-query.str("");
-query << "UPDATE tb_users SET "
- "address = '" << eaddress << "', "
- "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", "
- "credit = " << conf.credit << ", "
- "credit_expire = CAST('" << formatTime(conf.creditExpire) << "' AS TIMESTAMP), "
- "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", "
- "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", "
- "email = '" << eemail << "', "
- "grp = '" << egroup << "', "
- "note = '" << enote << "', "
- "passive = " << (conf.passive ? "'t'" : "'f'") << ", "
- "passwd = '" << epassword << "', "
- "phone = '" << ephone << "', "
- "real_name = '" << erealname << "', "
- "fk_tariff = (SELECT pk_tariff "
- "FROM tb_tariffs "
- "WHERE name = '" << etariffname << "'), "
- "fk_tariff_change = (SELECT pk_tariff "
- "FROM tb_tariffs "
- "WHERE name = '" << enexttariff << "'), "
- "fk_corporation = (SELECT pk_corporation "
- "FROM tb_corporations "
- "WHERE name = '" << ecorporation << "') "
- "WHERE pk_user = " << uid;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (SaveUserServices(uid, conf.services))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (SaveUserData(uid, conf.userdata))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's data'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (SaveUserIPs(uid, conf.ips))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's IPs'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreUserStat(USER_STAT * stat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- {
- std::ostringstream query;
- query << "SELECT cash, free_mb, "
- "last_activity_time, last_cash_add, "
- "last_cash_add_time, passive_time "
- "FROM tb_users "
- "WHERE name = '" << elogin << "'";
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch user's stat";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0) << " ";
- tuple << PQgetvalue(result, 0, 1) << " ";
- stat->lastActivityTime = readTime(PQgetvalue(result, 0, 2));
- tuple << PQgetvalue(result, 0, 3) << " ";
- stat->lastCashAddTime = readTime(PQgetvalue(result, 0, 4));
- tuple << PQgetvalue(result, 0, 5) << " ";
-
- PQclear(result);
-
- tuple >> stat->cash
- >> stat->freeMb
- >> stat->lastCashAdd
- >> stat->passiveTime;
- }
-
- {
- std::ostringstream query;
- query << "SELECT dir_num, upload, download "
- "FROM tb_stats_traffic "
- "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
- "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << formatTime(stgTime) << "' AS TIMESTAMP))";
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, i, 0) << " ";
- tuple << PQgetvalue(result, i, 1) << " ";
- tuple << PQgetvalue(result, i, 2) << " ";
-
- int dir;
-
- tuple >> dir;
- tuple >> stat->monthUp[dir];
- tuple >> stat->monthDown[dir];
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreUserConf(USER_CONF * conf,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- {
- std::ostringstream query;
- query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
- "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
- "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
- "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
- "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
- "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
- "ON tf1.pk_tariff = tb_users.fk_tariff "
- "LEFT JOIN tb_tariffs AS tf2 "
- "ON tf2.pk_tariff = tb_users.fk_tariff_change "
- "LEFT JOIN tb_corporations "
- "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
- "WHERE tb_users.name = '" << elogin << "'";
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch user's stat";
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-uint32_t uid;
-
- {
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0) << " "; // uid
- conf->address = PQgetvalue(result, 0, 1); // address
- conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
- tuple << PQgetvalue(result, 0, 3) << " "; // credit
- conf->creditExpire = readTime(PQgetvalue(result, 0, 4)); // creditExpire
- conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
- conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
- conf->email = PQgetvalue(result, 0, 7); // email
- conf->group = PQgetvalue(result, 0, 8); // group
- conf->note = PQgetvalue(result, 0, 9); // note
- conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
- conf->password = PQgetvalue(result, 0, 11); // password
- conf->phone = PQgetvalue(result, 0, 12); // phone
- conf->realName = PQgetvalue(result, 0, 13); // realName
- conf->tariffName = PQgetvalue(result, 0, 14); // tariffName
- conf->nextTariff = PQgetvalue(result, 0, 15); // nextTariff
- conf->corp = PQgetvalue(result, 0, 16); // corp
-
- PQclear(result);
-
- if (conf->tariffName == "")
- conf->tariffName = NO_TARIFF_NAME;
- if (conf->corp == "")
- conf->corp = NO_CORP_NAME;
-
- tuple >> uid
- >> conf->credit;
- }
-
- {
- std::ostringstream query;
- query << "SELECT name FROM tb_services "
- "WHERE pk_service IN (SELECT fk_service "
- "FROM tb_users_services "
- "WHERE fk_user = " << uid << ")";
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- conf->services.push_back(PQgetvalue(result, i, 0));
- }
-
-PQclear(result);
-
- {
- std::ostringstream query;
- query << "SELECT num, data "
- "FROM tb_users_data "
- "WHERE fk_user = " << uid;
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
- {
- int num;
- if (str2x(PQgetvalue(result, i, 0), num))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to convert string to int'\n");
- }
- else
- {
- if (num < USERDATA_NUM &&
- num >= 0)
- {
- conf->userdata[num] = PQgetvalue(result, i, 1);
- }
- }
- }
-
-PQclear(result);
-
- {
- std::ostringstream query;
- query << "SELECT host(ip), masklen(ip) "
- "FROM tb_allowed_ip "
- "WHERE fk_user = " << uid;
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-tuples = PQntuples(result);
-
-USER_IPS ips;
-for (int i = 0; i < tuples; ++i)
- {
- IP_MASK im;
-
- im.ip = inet_strington(PQgetvalue(result, i, 0));
-
- if (str2x(PQgetvalue(result, i, 1), im.mask))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to fetch mask'\n");
- continue;
- }
-
- ips.Add(im);
- }
-conf->ips = ips;
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserChgLog(const std::string & login,
- const std::string & admLogin,
- uint32_t admIP,
- const std::string & paramName,
- const std::string & oldValue,
- const std::string & newValue,
- const std::string & message = "") const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin(login);
-std::string eadminLogin(admLogin);
-std::string eparam(paramName);
-std::string eold(oldValue);
-std::string enew(newValue);
-std::string emessage(message);
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(eadminLogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape admin's login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(eparam))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape param's name'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(eold))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape old value'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-if (EscapeString(enew))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape new value'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-query << "SELECT sp_add_param_log_entry("
- "'" << elogin << "', "
- "'" << eadminLogin << "', CAST('"
- << inet_ntostring(admIP) << "/32' AS INET), "
- "'" << eparam << "', "
- "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
- "'" << eold << "', "
- "'" << enew << "', "
- "'" << emessage << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::ostringstream query;
-if (version < 6)
- {
- query << "SELECT sp_add_session_log_entry("
- "'" << elogin << "', "
- "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
- "'c', CAST('"
- << inet_ntostring(ip) << "/32' AS INET), 0)";
- }
-else
- {
- query << "SELECT sp_add_session_log_entry("
- "'" << elogin << "', "
- "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
- "'c', CAST('"
- << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')";
- }
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserDisconnect(const std::string & login,
- const DIR_TRAFF & monthUp,
- const DIR_TRAFF & monthDown,
- const DIR_TRAFF & sessionUp,
- const DIR_TRAFF & sessionDown,
- double cash,
- double freeMb,
- const std::string & reason) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-PGresult * result;
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::string ereason(reason);
-
-if (EscapeString(ereason))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape reason'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- {
- std::ostringstream query;
- if (version < 6)
- {
- // Old database version - no freeMb logging support
- query << "SELECT sp_add_session_log_entry("
- "'" << elogin << "', "
- "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
- "'d', CAST('0.0.0.0/0' AS INET), "
- << cash << ")";
- }
- else
- {
- query << "SELECT sp_add_session_log_entry("
- "'" << elogin << "', "
- "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
- "'d', CAST('0.0.0.0/0' AS INET), "
- << cash << ", " << freeMb << ", '" << ereason << "')";
- }
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
- {
- strError = "Failed to fetch session's log ID";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-uint32_t lid;
-
-if (str2x(PQgetvalue(result, 0, 0), lid))
- {
- strError = "Failed to convert string to int";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
- PQclear(result);
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-PQclear(result);
-
-for (int i = 0; i < DIR_NUM; ++i)
- {
- std::ostringstream query;
- query << "INSERT INTO tb_sessions_data "
- "(fk_session_log, "
- "dir_num, "
- "session_upload, "
- "session_download, "
- "month_upload, "
- "month_download)"
- "VALUES ("
- << lid << ", "
- << i << ", "
- << sessionUp[i] << ", "
- << sessionDown[i] << ", "
- << monthUp[i] << ", "
- << monthDown[i] << ")";
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- PQclear(result);
- }
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
- time_t lastStat,
- const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
- if (Reset())
- {
- strError = "Connection lost";
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
- return -1;
- }
- }
-
-if (StartTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to start transaction'\n");
- return -1;
- }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to escape login'\n");
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
-std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
-time_t currTime = time(NULL);
-
-for (it = statTree.begin(); it != statTree.end(); ++it)
- {
- std::ostringstream query;
- query << "INSERT INTO tb_detail_stats "
- "(till_time, from_time, fk_user, "
- "dir_num, ip, download, upload, cost) "
- "VALUES ("
- "CAST('" << formatTime(currTime) << "' AS TIMESTAMP), "
- "CAST('" << formatTime(lastStat) << "' AS TIMESTAMP), "
- "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
- << it->first.dir << ", "
- << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), "
- << it->second.down << ", "
- << it->second.up << ", "
- << it->second.cash << ")";
-
- PGresult * result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
- if (RollbackTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
- }
- return -1;
- }
-
- PQclear(result);
- }
-
-if (CommitTransaction())
- {
- printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to commit transaction'\n");
- return -1;
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login, year, month);
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserServices(uint32_t uid,
- const std::vector<std::string> & services) const
-{
-PGresult * result;
-
- {
- std::ostringstream query;
- query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
- return -1;
- }
-
- PQclear(result);
- }
-
-std::vector<std::string>::const_iterator it;
-
-for (it = services.begin(); it != services.end(); ++it)
- {
- std::string ename = *it;
-
- if (EscapeString(ename))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): 'Failed to escape service name'\n");
- return -1;
- }
-
- std::ostringstream query;
- query << "INSERT INTO tb_users_services "
- "(fk_user, fk_service) "
- "VALUES "
- "(" << uid << ", "
- "(SELECT pk_service "
- "FROM tb_services "
- "WHERE name = '" << ename << "'))";
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
- return -1;
- }
-
- PQclear(result);
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserIPs(uint32_t uid,
- const USER_IPS & ips) const
-{
-PGresult * result;
-
- {
- std::ostringstream query;
- query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
-
- result = PQexec(connection, query.str().c_str());
- }
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PQclear(result);
-
-for (size_t i = 0; i < ips.Count(); ++i)
- {
- std::ostringstream query;
- query << "INSERT INTO tb_allowed_ip "
- "(fk_user, ip) "
- "VALUES "
- "(" << uid << ", CAST('"
- << inet_ntostring(ips[i].ip) << "/"
- << static_cast<int>(ips[i].mask) << "' AS INET))";
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
- return -1;
- }
-
- PQclear(result);
- }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserData(uint32_t uid,
- const std::vector<std::string> & data) const
-{
-for (unsigned i = 0; i < data.size(); ++i)
- {
- std::string edata = data[i];
-
- if (EscapeString(edata))
- {
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): 'Failed to escape userdata field'\n");
- return -1;
- }
-
- PGresult * result;
-
- std::ostringstream query;
- query << "SELECT sp_set_user_data("
- << uid << ", "
- << "CAST(" << i << " AS SMALLINT), "
- << "'" << edata << "')";
-
- result = PQexec(connection, query.str().c_str());
-
- if (PQresultStatus(result) != PGRES_TUPLES_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): '%s'\n", strError.c_str());
- return -1;
- }
-
- PQclear(result);
- }
-
-return 0;
-}
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- * Vairous utility methods
- *
- * $Revision: 1.3 $
- * $Date: 2009/10/22 10:01:08 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/common.h"
-
-#include <string>
-#include <ctime>
-
-#include <libpq-fe.h>
-
-extern volatile time_t stgTime;
-
-int POSTGRESQL_STORE::StartTransaction() const
-{
-PGresult * result = PQexec(connection, "BEGIN");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::StartTransaction(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::CommitTransaction() const
-{
-PGresult * result = PQexec(connection, "COMMIT");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::CommitTransaction(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::RollbackTransaction() const
-{
-PGresult * result = PQexec(connection, "ROLLBACK");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- strError = PQresultErrorMessage(result);
- PQclear(result);
- printfd(__FILE__, "POSTGRESQL_STORE::RollbackTransaction(): '%s'\n", strError.c_str());
- return -1;
- }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::EscapeString(std::string & value) const
-{
-int error = 0;
-char * buf = new char[(value.length() << 1) + 1];
-
-PQescapeStringConn(connection,
- buf,
- value.c_str(),
- value.length(),
- &error);
-
-if (error)
- {
- strError = PQerrorMessage(connection);
- printfd(__FILE__, "POSTGRESQL_STORE::EscapeString(): '%s'\n", strError.c_str());
- delete[] buf;
- return -1;
- }
-
-value = buf;
-
-delete[] buf;
-return 0;
-}
-
-void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const
-{
-struct tm brokenTime;
-
-brokenTime.tm_wday = 0;
-brokenTime.tm_yday = 0;
-brokenTime.tm_isdst = 0;
-
-if (year)
- {
- brokenTime.tm_hour = 0;
- brokenTime.tm_min = 0;
- brokenTime.tm_sec = 0;
- brokenTime.tm_year = year;
- brokenTime.tm_mon = month;
- }
-else
- {
- time_t curTime = stgTime;
- localtime_r(&curTime, &brokenTime);
- }
-
-brokenTime.tm_mday = DaysInMonth(brokenTime.tm_year + 1900, brokenTime.tm_mon);
-
-char buf[32];
-
-strftime(buf, 32, "%Y-%m-%d", &brokenTime);
-
-date = buf;
-}
+++ /dev/null
-#ifndef POSTGRESQL_UTILS_STORE_H
-#define POSTGRESQL_UTILS_STORE_H
-
-#include <functional>
-
-struct ToLower : public std::unary_function<char, char>
-{
-char operator() (char c) const { return static_cast<char>(std::tolower(c)); }
-};
-
-#endif
+++ /dev/null
-#!/bin/bash
-
-# Этот скрипт производит очистку файловой БД stargazer-а.
-# Его можно вызывать вручную или покрону, к примеру раз в неделю или раз в месяц.
-
-
-# Эта переменная задает сколько месяцев детальной статистики оставить в БД
-SAVE_MONTHS=3
-
-# Эта переменная задает сколько строк оставить в логах юзеров
-MAX_LOG_LINES=5000
-
-# Тут определяется путь к БД
-DB=/var/stargazer/
-
-
-
-
-declare -i NOW=`date +%s`
-declare -i DT=SAVE_MONTHS*31*24*3600
-declare -i stat_time=0
-
-for usr in $DB/users/*
-do
- echo cleaning `basename $usr`
- for ys in $usr/detail_stat/*
- do
- year=`basename $ys`
-
- for ms in $ys/*
- do
- month=`basename $ms`
- stat_time=`date --date="$year/$month/01" +%s`
-
- if (( $NOW - $stat_time > $DT ))
- then
- rm -fr $ms
- fi
- done
- done
- tail -n $MAX_LOG_LINES $usr/log > /tmp/stg_usr_log.`basename $usr`
- mv -f /tmp/stg_usr_log.`basename $usr` $usr/log
-done
-
+++ /dev/null
-#!/bin/bash
-
-# Данный скрипт производит мониторинг СТГ-сервера на зависание и в
-# случае его зависания перезапускает.
-# Для работы скрипта в настройках СТГ должен быть указан параметер
-# MonitorDir
-# Скрипт отрабатывает один раз и выходит. Т.е. он не работает постоянно
-# и следит за СТГ. Его нужно вызывать по крону или как-то еще с нужной
-# периодичностью!!!
-
-
-# Путь к файлам монитора. Должен совпадать со значением MonitorDir
-# в настройках сервера
-MONITOR_DIR=/var/stargazer/monitor/
-
-
-# Максимальная задержка обновления файлов монитора в секундах.
-# При привышении этого значения сервер считается зависшим и будет
-# перезапущен
-DT=300
-
-
-
-
-declare -i now=`date +%s`
-declare -i DT=300
-declare -i file_time=0
-
-stg_running=`ps ax | grep stargazer`
-if [ -z "$stg_running" ]
-then
- echo "Stargazer is not running"
- exit 0
-fi
-
-#wakeuper for traffcounter
-ping -c 1 127.0.0.1 > /dev/null
-sleep 1
-
-for mon in $MONITOR_DIR/*
-do
- if [ ! -r $mon ]
- then
- echo "no monitor files"
- exit 0
- fi
- file_time=`stat -c%Y $mon`
-
- if (( $now - $file_time > $DT ))
- then
- echo "Stargazer is deadlocked!"
-
- # Команда остаовки СТГ
- killall -KILL stargazer
-
- rm -f $MONITOR_DIR/*
- sleep 15
-
- # Команда запуска СТГ
- /etc/init.d/stargazer start
-
- fi
-
-done
-
-
+++ /dev/null
-#!/bin/bash
-
-int_iface=eth1
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-default_speed=32kbit
-
-# =========== shaping by tariff ===========
-#tariff=$(grep -i "^tariff=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-#echo "tariff=$tariff" > /var/stargazer/users/$LOGIN/connect.log
-#case $tariff in
-# minimum) speedkb=128kbit;; # 128 kbit
-# middle) speedkb=256kbit;; # 256 kbi
-# maximum) speedkb=512kbit;; # 512 kbit
-# *) speedkb=$default_speed;; # default speed
-#esac
-# ========= shaping by tariff end =========
-
-# ========= shaping by userdata0 ==========
-speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
-
-if [ -z "$speed" ]
-then
- speedkb=$default_speed
-else
- speedkb="$speed"kbit
-fi
-# ======= shaping by userdata0 end ========
-
-declare -i mark=$ID+10
-
-echo "$mark" > /var/stargazer/users/$LOGIN/shaper_mark
-echo "$speedkb" > /var/stargazer/users/$LOGIN/shaper_rate
-
-iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
-
-tc class add dev $int_iface parent 1:1 classid 1:$mark htb rate $speedkb burst 40k
-tc filter add dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
-
+++ /dev/null
-#!/bin/bash
-
-int_iface=eth1
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$4
-
-mark=$(cat /var/stargazer/users/$LOGIN/shaper_mark)
-rate=$(cat /var/stargazer/users/$LOGIN/shaper_rate)
-
-if [ -n "$mark" ]
-then
- iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
- while [ $? == 0 ]
- do
- iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
- done
-fi
-
-tc filter del dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
-tc class del dev $int_iface parent 1:1 classid 1:$mark htb rate $rate burst 40k
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
-
+++ /dev/null
-Настройка шейпера для STG в Linux.
-
-По мотивам форума:
-http://local.com.ua/forum/index.php?showtopic=7920
-
-Настройка сводится к указанию сетевого интерфейса, обращенного к пользователю
-в скриптах shaper.sh, shaper.stop.sh, OnConnect и OnDisconnect, и уточнению
-скоростоей и тарифов в скрипте OnConnect (если нужно).
-
-Скрипты сделаны для БД на файлах, однако, сделать их для БД на Firebird или
-MySQL не составит большого труда.
-
-В OnConnect есть два типа шейпинга.
-1. На основании тарифа. Т.е. для каждого тарифа у задана скорость и задано
-дефолтное значение, на случай отсутсвия тарифа в списке скоростей или
-забывчивости админа.
-2. На основании Userdata0. В этом поле просто прописывается число равное
-скорости в kbit/sec. Также есть дефолтное значение скорости в 32 kbit/sec
-на случай отсутсвия в Userdata0 корректного значения.
-
-В скрипте первый способ закомментирован. Для того чтобы выбрать один из них нужно
-либо удалить, либо закомментировать строчики между
-
-# ========= shaping by tariff ==========
-.........
-# ======= shaping by tariff end ========
-
-и
-
-# ========= shaping by userdata0 ==========
-.........
-# ======= shaping by userdata0 end ========
-
-
-и нужную часть расскоментировать, если она закомментрована.
-
-Скрипт shaper.sh должен быть выполнен один раз при загрузке системы.
-
-Интерфейс обращенный к пользователю определяется в переменной
-int_iface=
-(присутствует во всех 4-х файлах shaper.sh, shaper.stop.sh, OnConnect и
-OnDisconnect !!!)
-
-Скорость по умолчанию в OnConnect в переменной default_speed
-
-Зависимость скорости от тарифа задается в следующем фрагменте кода:
-case $tariff in
- minimum) speedkb=128kbit;;
- middle) speedkb=256kbit;;
- maximum) speedkb=512kbit;;
- *) speedkb=$default_speed;;
-esac
-
-Т.е. тут нужно вместо minimum, ... maximum подставить имена ваших тарифов
-и соотв. скорость. Пользователи с тарифами не указанными в списке будут иметь
-дефолтную скорость.
-
-Скорость ограничевается только для входящего тарафика, однако расширить
-эти скрипты для исходящего не составит труда.
+++ /dev/null
-#!/bin/bash
-
-int_iface=eth1
-
-iptables -t mangle --flush
-
-tc qdisc add dev $int_iface root handle 1: htb
-tc class add dev $int_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
-
+++ /dev/null
-#!/bin/bash
-
-int_iface=eth1
-
-#iptables -t mangle --flush
-
-tc qdisc del dev $int_iface root handle 1: htb
-
+++ /dev/null
-Настройка такой конфигурации происходит в 3 этапа:
-1. Настройка VPN с использованием pptpd;
-2. Настройка авторизации VPN через FreeRADIUS;
-3. Настройка шейпера;
-
-1. Настройка VPN
-
-Необходимо установить пакеты ppp и pptpd. Также необходима поддержка PPP в ядре:
- Device Drivers --->
- Network device support --->
- <M> PPP (point-to-point protocol) support
- <M> PPP support for sync tty ports
- <M> PPP Deflate compression
- <M> PPP BSD-Compress compression
- <M> PPP MPPE compression (encryption) (EXPERIMENTAL)
- <M> PPP over Ethernet (EXPERIMENTAL)
-В файле /etc/pptpd.conf прописываем файл настроек PPP (параметр option). Также
-указываем адреса сервера внутри сети VPN (параметр localip) и диапазон адресов
-клиентов (параметр remoteip). См. пример файла конфигурации.
-В настройках PPP указываем имя сервера (параметр name), параметры шифрования.
-Для использования шифрования MPPE необходима его поддержка в ядре. Кроме того,
-в процессе аутентификации MPPE использует MS-CHAPv2. По этому при
-использовании шифрования MPPE также необходимо указать необходимость
-поддержки MS-CHAPv2 клиентом. По желанию указываем proxyarp (для того чтобы
-клиенты в сети VPN "видели" друг друга) и defaultroute. Прописываем в файле
-/etc/ppp/chap-secrets тестового пользователя и проверяем работоспособность
-VPN.
-
-2. Настройка авторизации VPN через FreeRADIUS
-
-Необходимо установить пакет freeradius.
-Настройку сервера (файл radiusd.conf) проводим в соответствии с документацией
-на модуль rlm_stg.so (см. документацию на систему Stargazer).
-Настройку Stargazer с плагином для FreeRADIUS проводим в соответствиии с
-документацией на модуль mod_radius.so (см. документацию на систему Stargazer).
-В файле clients.conf, расположенном в дирректории с конфигурационными файлами
-FreeRADIUS, описываем, какие клиенты могут использовать FreeRADIUS.
-Рекомендуется заменить стандартный пароль, которым шифруется обмен информации
-с клиентом, "testing123" на что-то более приемлимое с точки зрения безопасности.
-После этого запускаем FreeRADIUS и удостоверяемся, что он работает строчкой
-"Mon Mar 31 16:06:17 2008 : Info: Ready to process requests." в журнале
-(обычно, /var/log/radius/radius.log). Если журнал FreeRADIUS не позволяет
-определить проблему - можно запустить сервер в отладочном режме с ключем -X.
-В этом режиме более детальное журналирование проводится в консоль.
-Если на данном этапе все работает - в файл насттроек PPP прописываем строчку
-plugin radius.so. После этого VPN должен нормально авторизоваться
-пользователями системы Stargazer.
-
-3. Настройка шейпера
-
-Собственно настройки шейпер не требует. Всё, что нужно прописано в скриптах
-OnConnect и OnDisconnect. Шейпер предназначен для работы с хранилищем на
-файлах, однако, переделать скипт под MySQL или Firebird не составит труда.
-Скорость для пользоватлея задается в поле Userdata0 в kbit/sec. В этом поле
-должно быть прописано просто число без всяких kbit/sec и т.п. Если в этом поле
-у пользователя нет данных или стоит некорректное значение, пользователь будет
-ограничен скоростью определенной в переменной default_speed в скрипте
-OnConnect.
+++ /dev/null
-#!/bin/bash
-
-#adsl-start
-
-modprobe ip_queue
-
-int_addr=10.0.0.2
-ext_addr=192.168.1.34
-
-int_net=10.0.0.0/16
-ext_net=192.168.1.0/24
-
-echo 1 > /proc/sys/net/ipv4/ip_forward
-
-iptables -P INPUT DROP
-iptables -P OUTPUT ACCEPT
-iptables -P FORWARD ACCEPT
-
-iptables -t nat -F
-iptables -t filter -F
-
-#
-#iptables -A INPUT -d $ip1 -j ACCEPT
-#iptables -A OUTPUT -s $ip1 -j ACCEPT
-
-# Разрешам говорить самому с собой
-iptables -A INPUT -d 127.0.0.1 -j ACCEPT
-iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
-
-#iptables -A INPUT -d $ip4 -j ACCEPT
-#iptables -A INPUT -s $ip4 -j ACCEPT
-#iptables -A OUTPUT -s $ip4 -j ACCEPT
-#iptables -A OUTPUT -d $ip4 -j ACCEPT
-
-iptables -A INPUT -p icmp -j ACCEPT
-iptables -A OUTPUT -p icmp -j ACCEPT
-
-iptables -A INPUT -p 47 -j ACCEPT
-iptables -A FORWARD -p 47 -j ACCEPT
-iptables -A OUTPUT -p 47 -j ACCEPT
-
-#SSH On this machine
-iptables -A INPUT -p tcp -d $int_addr --dport 22 -j ACCEPT
-iptables -A OUTPUT -p tcp -s $int_addr --sport 22 -j ACCEPT
-iptables -A INPUT -p tcp -d $ext_addr --dport 22 -j ACCEPT
-iptables -A OUTPUT -p tcp -s $ext_addr --sport 22 -j ACCEPT
-
-#WEB On this machine
-#iptables -A INPUT -p tcp -d $ip2 --dport 80 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 80 -j ACCEPT
-#iptables -A INPUT -p tcp -d $ip3 --dport 80 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 80 -j ACCEPT
-
-#PPTP
-iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
-iptables -A OUTPUT -p tcp --sport 1723 -j ACCEPT
-iptables -A INPUT -p udp --dport 1723 -j ACCEPT
-iptables -A OUTPUT -p udp --sport 1723 -j ACCEPT
-
-#FTP
-#iptables -A INPUT -p tcp -d $ip2 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 -j ACCEPT
-#iptables -A INPUT -p tcp -d $ip3 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 -j ACCEPT
-
-#iptables -A INPUT -p tcp -d $ip2 --dport 20:21 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 20:21 -j ACCEPT
-#iptables -A INPUT -p tcp -d $ip3 --dport 20:21 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 20:21 -j ACCEPT
-
-#iptables -A INPUT -p tcp -d $ip2 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
-#iptables -A INPUT -p tcp -d $ip3 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
-
-#DNS
-iptables -A INPUT -p tcp --sport 53 -j ACCEPT
-iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
-iptables -A INPUT -p udp --sport 53 -j ACCEPT
-iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
-
-#iptables -t nat -A PREROUTING -p tcp -d $ip1 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip2 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip3 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip4 --dport 80 -j ACCEPT
-
-#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.7 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.16 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128
-
-iptables -t nat -A POSTROUTING -d 0.0.0.0/0 -s 192.168.2.0/24 -j MASQUERADE
-
-
-
+++ /dev/null
-#
-# clients.conf - client configuration directives
-#
-#######################################################################
-
-#######################################################################
-#
-# Definition of a RADIUS client (usually a NAS).
-#
-# The information given here over rides anything given in the
-# 'clients' file, or in the 'naslist' file. The configuration here
-# contains all of the information from those two files, and allows
-# for more configuration items.
-#
-# The "shortname" is be used for logging. The "nastype", "login" and
-# "password" fields are mainly used for checkrad and are optional.
-#
-
-#
-# Defines a RADIUS client. The format is 'client [hostname|ip-address]'
-#
-# '127.0.0.1' is another name for 'localhost'. It is enabled by default,
-# to allow testing of the server after an initial installation. If you
-# are not going to be permitting RADIUS queries from localhost, we suggest
-# that you delete, or comment out, this entry.
-#
-client 127.0.0.1 {
- #
- # The shared secret use to "encrypt" and "sign" packets between
- # the NAS and FreeRADIUS. You MUST change this secret from the
- # default, otherwise it's not a secret any more!
- #
- # The secret can be any string, up to 31 characters in length.
- #
- secret = testing123
-
- #
- # The short name is used as an alias for the fully qualified
- # domain name, or the IP address.
- #
- shortname = localhost
-
- #
- # the following three fields are optional, but may be used by
- # checkrad.pl for simultaneous use checks
- #
-
- #
- # The nastype tells 'checkrad.pl' which NAS-specific method to
- # use to query the NAS for simultaneous use.
- #
- # Permitted NAS types are:
- #
- # cisco
- # computone
- # livingston
- # max40xx
- # multitech
- # netserver
- # pathras
- # patton
- # portslave
- # tc
- # usrhiper
- # other # for all other types
-
- #
- nastype = other # localhost isn't usually a NAS...
-
- #
- # The following two configurations are for future use.
- # The 'naspasswd' file is currently used to store the NAS
- # login name and password, which is used by checkrad.pl
- # when querying the NAS for simultaneous use.
- #
-# login = !root
-# password = someadminpas
-}
+++ /dev/null
-##
-## radiusd.conf -- FreeRADIUS server configuration file.
-##
-## http://www.freeradius.org/
-## $Id: radiusd.conf,v 1.1 2008/03/31 13:54:59 faust Exp $
-##
-
-# The location of other config files and
-# logfiles are declared in this file
-#
-# Also general configuration for modules can be done
-# in this file, it is exported through the API to
-# modules that ask for it.
-#
-# The configuration variables defined here are of the form ${foo}
-# They are local to this file, and do not change from request to
-# request.
-#
-# The per-request variables are of the form %{Attribute-Name}, and
-# are taken from the values of the attribute in the incoming
-# request. See 'doc/variables.txt' for more information.
-
-prefix = /usr
-exec_prefix = /usr
-sysconfdir = /etc
-localstatedir = /var
-sbindir = ${exec_prefix}/sbin
-logdir = /var/log/freeradius
-raddbdir = /etc/freeradius
-radacctdir = ${logdir}/radacct
-
-# Location of config and logfiles.
-confdir = ${raddbdir}
-run_dir = ${localstatedir}/run/freeradius
-
-#
-# The logging messages for the server are appended to the
-# tail of this file.
-#
-log_file = ${logdir}/radius.log
-
-#
-# libdir: Where to find the rlm_* modules.
-#
-# This should be automatically set at configuration time.
-#
-# If the server builds and installs, but fails at execution time
-# with an 'undefined symbol' error, then you can use the libdir
-# directive to work around the problem.
-#
-# The cause is usually that a library has been installed on your
-# system in a place where the dynamic linker CANNOT find it. When
-# executing as root (or another user), your personal environment MAY
-# be set up to allow the dynamic linker to find the library. When
-# executing as a daemon, FreeRADIUS MAY NOT have the same
-# personalized configuration.
-#
-# To work around the problem, find out which library contains that symbol,
-# and add the directory containing that library to the end of 'libdir',
-# with a colon separating the directory names. NO spaces are allowed.
-#
-# e.g. libdir = /usr/local/lib:/opt/package/lib
-#
-# You can also try setting the LD_LIBRARY_PATH environment variable
-# in a script which starts the server.
-#
-# If that does not work, then you can re-configure and re-build the
-# server to NOT use shared libraries, via:
-#
-# ./configure --disable-shared
-# make
-# make install
-#
-libdir = /usr/lib/freeradius
-
-# pidfile: Where to place the PID of the RADIUS server.
-#
-# The server may be signalled while it's running by using this
-# file.
-#
-# This file is written when ONLY running in daemon mode.
-#
-# e.g.: kill -HUP `cat /var/run/freeradius/freeradius.pid`
-#
-pidfile = ${run_dir}/freeradius.pid
-
-
-# user/group: The name (or #number) of the user/group to run radiusd as.
-#
-# If these are commented out, the server will run as the user/group
-# that started it. In order to change to a different user/group, you
-# MUST be root ( or have root privleges ) to start the server.
-#
-# We STRONGLY recommend that you run the server with as few permissions
-# as possible. That is, if you're not using shadow passwords, the
-# user and group items below should be set to 'nobody'.
-#
-# On SCO (ODT 3) use "user = nouser" and "group = nogroup".
-#
-# NOTE that some kernels refuse to setgid(group) when the value of
-# (unsigned)group is above 60000; don't use group nobody on these systems!
-#
-# On systems with shadow passwords, you might have to set 'group = shadow'
-# for the server to be able to read the shadow password file. If you can
-# authenticate users while in debug mode, but not in daemon mode, it may be
-# that the debugging mode server is running as a user that can read the
-# shadow info, and the user listed below can not.
-#
-user = freerad
-group = freerad
-
-# max_request_time: The maximum time (in seconds) to handle a request.
-#
-# Requests which take more time than this to process may be killed, and
-# a REJECT message is returned.
-#
-# WARNING: If you notice that requests take a long time to be handled,
-# then this MAY INDICATE a bug in the server, in one of the modules
-# used to handle a request, OR in your local configuration.
-#
-# This problem is most often seen when using an SQL database. If it takes
-# more than a second or two to receive an answer from the SQL database,
-# then it probably means that you haven't indexed the database. See your
-# SQL server documentation for more information.
-#
-# Useful range of values: 5 to 120
-#
-max_request_time = 30
-
-# delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
-# to be handled, then maybe the server should delete it.
-#
-# If you're running in threaded, or thread pool mode, this setting
-# should probably be 'no'. Setting it to 'yes' when using a threaded
-# server MAY cause the server to crash!
-#
-delete_blocked_requests = no
-
-# cleanup_delay: The time to wait (in seconds) before cleaning up
-# a reply which was sent to the NAS.
-#
-# The RADIUS request is normally cached internally for a short period
-# of time, after the reply is sent to the NAS. The reply packet may be
-# lost in the network, and the NAS will not see it. The NAS will then
-# re-send the request, and the server will respond quickly with the
-# cached reply.
-#
-# If this value is set too low, then duplicate requests from the NAS
-# MAY NOT be detected, and will instead be handled as seperate requests.
-#
-# If this value is set too high, then the server will cache too many
-# requests, and some new requests may get blocked. (See 'max_requests'.)
-#
-# Useful range of values: 2 to 10
-#
-cleanup_delay = 5
-
-# max_requests: The maximum number of requests which the server keeps
-# track of. This should be 256 multiplied by the number of clients.
-# e.g. With 4 clients, this number should be 1024.
-#
-# If this number is too low, then when the server becomes busy,
-# it will not respond to any new requests, until the 'cleanup_delay'
-# time has passed, and it has removed the old requests.
-#
-# If this number is set too high, then the server will use a bit more
-# memory for no real benefit.
-#
-# If you aren't sure what it should be set to, it's better to set it
-# too high than too low. Setting it to 1000 per client is probably
-# the highest it should be.
-#
-# Useful range of values: 256 to infinity
-#
-max_requests = 1024
-
-# bind_address: Make the server listen on a particular IP address, and
-# send replies out from that address. This directive is most useful
-# for machines with multiple IP addresses on one interface.
-#
-# It can either contain "*", or an IP address, or a fully qualified
-# Internet domain name. The default is "*"
-#
-# As of 1.0, you can also use the "listen" directive. See below for
-# more information.
-#
-bind_address = *
-
-# port: Allows you to bind FreeRADIUS to a specific port.
-#
-# The default port that most NAS boxes use is 1645, which is historical.
-# RFC 2138 defines 1812 to be the new port. Many new servers and
-# NAS boxes use 1812, which can create interoperability problems.
-#
-# The port is defined here to be 0 so that the server will pick up
-# the machine's local configuration for the radius port, as defined
-# in /etc/services.
-#
-# If you want to use the default RADIUS port as defined on your server,
-# (usually through 'grep radius /etc/services') set this to 0 (zero).
-#
-# A port given on the command-line via '-p' over-rides this one.
-#
-# As of 1.0, you can also use the "listen" directive. See below for
-# more information.
-#
-port = 0
-
-#
-# By default, the server uses "bind_address" to listen to all IP's
-# on a machine, or just one IP. The "port" configuration is used
-# to select the authentication port used when listening on those
-# addresses.
-#
-# If you want the server to listen on additional addresses, you can
-# use the "listen" section. A sample section (commented out) is included
-# below. This "listen" section duplicates the functionality of the
-# "bind_address" and "port" configuration entries, but it only listens
-# for authentication packets.
-#
-# If you comment out the "bind_address" and "port" configuration entries,
-# then it becomes possible to make the server accept only accounting,
-# or authentication packets. Previously, it always listened for both
-# types of packets, and it was impossible to make it listen for only
-# one type of packet.
-#
-#listen {
- # IP address on which to listen.
- # Allowed values are:
- # dotted quad (1.2.3.4)
- # hostname (radius.example.com)
- # wildcard (*)
-# ipaddr = *
-
- # Port on which to listen.
- # Allowed values are:
- # integer port number (1812)
- # 0 means "use /etc/services for the proper port"
-# port = 0
-
- # Type of packets to listen for.
- # Allowed values are:
- # auth listen for authentication packets
- # acct listen for accounting packets
- #
-# type = auth
-#}
-
-
-# hostname_lookups: Log the names of clients or just their IP addresses
-# e.g., www.freeradius.org (on) or 206.47.27.232 (off).
-#
-# The default is 'off' because it would be overall better for the net
-# if people had to knowingly turn this feature on, since enabling it
-# means that each client request will result in AT LEAST one lookup
-# request to the nameserver. Enabling hostname_lookups will also
-# mean that your server may stop randomly for 30 seconds from time
-# to time, if the DNS requests take too long.
-#
-# Turning hostname lookups off also means that the server won't block
-# for 30 seconds, if it sees an IP address which has no name associated
-# with it.
-#
-# allowed values: {no, yes}
-#
-hostname_lookups = no
-
-# Core dumps are a bad thing. This should only be set to 'yes'
-# if you're debugging a problem with the server.
-#
-# allowed values: {no, yes}
-#
-allow_core_dumps = no
-
-# Regular expressions
-#
-# These items are set at configure time. If they're set to "yes",
-# then setting them to "no" turns off regular expression support.
-#
-# If they're set to "no" at configure time, then setting them to "yes"
-# WILL NOT WORK. It will give you an error.
-#
-regular_expressions = yes
-extended_expressions = yes
-
-# Log the full User-Name attribute, as it was found in the request.
-#
-# allowed values: {no, yes}
-#
-log_stripped_names = no
-
-# Log authentication requests to the log file.
-#
-# allowed values: {no, yes}
-#
-log_auth = no
-
-# Log passwords with the authentication requests.
-# log_auth_badpass - logs password if it's rejected
-# log_auth_goodpass - logs password if it's correct
-#
-# allowed values: {no, yes}
-#
-log_auth_badpass = no
-log_auth_goodpass = no
-
-# usercollide: Turn "username collision" code on and off. See the
-# "doc/duplicate-users" file
-#
-# WARNING
-# !!!!!!! Setting this to "yes" may result in the server behaving
-# !!!!!!! strangely. The "username collision" code will ONLY work
-# !!!!!!! with clear-text passwords. Even then, it may not do what
-# !!!!!!! you want, or what you expect.
-# !!!!!!!
-# !!!!!!! We STRONGLY RECOMMEND that you do not use this feature,
-# !!!!!!! and that you find another way of acheiving the same goal.
-# !!!!!!!
-# !!!!!!! e,g. module fail-over. See 'doc/configurable_failover'
-# WARNING
-#
-usercollide = no
-
-# lower_user / lower_pass:
-# Lower case the username/password "before" or "after"
-# attempting to authenticate.
-#
-# If "before", the server will first modify the request and then try
-# to auth the user. If "after", the server will first auth using the
-# values provided by the user. If that fails it will reprocess the
-# request after modifying it as you specify below.
-#
-# This is as close as we can get to case insensitivity. It is the
-# admin's job to ensure that the username on the auth db side is
-# *also* lowercase to make this work
-#
-# Default is 'no' (don't lowercase values)
-# Valid values = "before" / "after" / "no"
-#
-lower_user = no
-lower_pass = no
-
-# nospace_user / nospace_pass:
-#
-# Some users like to enter spaces in their username or password
-# incorrectly. To save yourself the tech support call, you can
-# eliminate those spaces here:
-#
-# Default is 'no' (don't remove spaces)
-# Valid values = "before" / "after" / "no" (explanation above)
-#
-nospace_user = no
-nospace_pass = no
-
-# The program to execute to do concurrency checks.
-checkrad = ${sbindir}/checkrad
-
-# SECURITY CONFIGURATION
-#
-# There may be multiple methods of attacking on the server. This
-# section holds the configuration items which minimize the impact
-# of those attacks
-#
-security {
- #
- # max_attributes: The maximum number of attributes
- # permitted in a RADIUS packet. Packets which have MORE
- # than this number of attributes in them will be dropped.
- #
- # If this number is set too low, then no RADIUS packets
- # will be accepted.
- #
- # If this number is set too high, then an attacker may be
- # able to send a small number of packets which will cause
- # the server to use all available memory on the machine.
- #
- # Setting this number to 0 means "allow any number of attributes"
- max_attributes = 200
-
- #
- # reject_delay: When sending an Access-Reject, it can be
- # delayed for a few seconds. This may help slow down a DoS
- # attack. It also helps to slow down people trying to brute-force
- # crack a users password.
- #
- # Setting this number to 0 means "send rejects immediately"
- #
- # If this number is set higher than 'cleanup_delay', then the
- # rejects will be sent at 'cleanup_delay' time, when the request
- # is deleted from the internal cache of requests.
- #
- # Useful ranges: 1 to 5
- reject_delay = 1
-
- #
- # status_server: Whether or not the server will respond
- # to Status-Server requests.
- #
- # Normally this should be set to "no", because they're useless.
- # See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
- #
- # However, certain NAS boxes may require them.
- #
- # When sent a Status-Server message, the server responds with
- # an Access-Accept packet, containing a Reply-Message attribute,
- # which is a string describing how long the server has been
- # running.
- #
- status_server = no
-}
-
-# PROXY CONFIGURATION
-#
-# proxy_requests: Turns proxying of RADIUS requests on or off.
-#
-# The server has proxying turned on by default. If your system is NOT
-# set up to proxy requests to another server, then you can turn proxying
-# off here. This will save a small amount of resources on the server.
-#
-# If you have proxying turned off, and your configuration files say
-# to proxy a request, then an error message will be logged.
-#
-# To disable proxying, change the "yes" to "no", and comment the
-# $INCLUDE line.
-#
-# allowed values: {no, yes}
-#
-proxy_requests = yes
-$INCLUDE ${confdir}/proxy.conf
-
-
-# CLIENTS CONFIGURATION
-#
-# Client configuration is defined in "clients.conf".
-#
-
-# The 'clients.conf' file contains all of the information from the old
-# 'clients' and 'naslist' configuration files. We recommend that you
-# do NOT use 'client's or 'naslist', although they are still
-# supported.
-#
-# Anything listed in 'clients.conf' will take precedence over the
-# information from the old-style configuration files.
-#
-$INCLUDE ${confdir}/clients.conf
-
-
-# SNMP CONFIGURATION
-#
-# Snmp configuration is only valid if SNMP support was enabled
-# at compile time.
-#
-# To enable SNMP querying of the server, set the value of the
-# 'snmp' attribute to 'yes'
-#
-snmp = no
-$INCLUDE ${confdir}/snmp.conf
-
-
-# THREAD POOL CONFIGURATION
-#
-# The thread pool is a long-lived group of threads which
-# take turns (round-robin) handling any incoming requests.
-#
-# You probably want to have a few spare threads around,
-# so that high-load situations can be handled immediately. If you
-# don't have any spare threads, then the request handling will
-# be delayed while a new thread is created, and added to the pool.
-#
-# You probably don't want too many spare threads around,
-# otherwise they'll be sitting there taking up resources, and
-# not doing anything productive.
-#
-# The numbers given below should be adequate for most situations.
-#
-thread pool {
- # Number of servers to start initially --- should be a reasonable
- # ballpark figure.
- start_servers = 5
-
- # Limit on the total number of servers running.
- #
- # If this limit is ever reached, clients will be LOCKED OUT, so it
- # should NOT BE SET TOO LOW. It is intended mainly as a brake to
- # keep a runaway server from taking the system with it as it spirals
- # down...
- #
- # You may find that the server is regularly reaching the
- # 'max_servers' number of threads, and that increasing
- # 'max_servers' doesn't seem to make much difference.
- #
- # If this is the case, then the problem is MOST LIKELY that
- # your back-end databases are taking too long to respond, and
- # are preventing the server from responding in a timely manner.
- #
- # The solution is NOT do keep increasing the 'max_servers'
- # value, but instead to fix the underlying cause of the
- # problem: slow database, or 'hostname_lookups=yes'.
- #
- # For more information, see 'max_request_time', above.
- #
- max_servers = 32
-
- # Server-pool size regulation. Rather than making you guess
- # how many servers you need, FreeRADIUS dynamically adapts to
- # the load it sees, that is, it tries to maintain enough
- # servers to handle the current load, plus a few spare
- # servers to handle transient load spikes.
- #
- # It does this by periodically checking how many servers are
- # waiting for a request. If there are fewer than
- # min_spare_servers, it creates a new spare. If there are
- # more than max_spare_servers, some of the spares die off.
- # The default values are probably OK for most sites.
- #
- min_spare_servers = 3
- max_spare_servers = 10
-
- # There may be memory leaks or resource allocation problems with
- # the server. If so, set this value to 300 or so, so that the
- # resources will be cleaned up periodically.
- #
- # This should only be necessary if there are serious bugs in the
- # server which have not yet been fixed.
- #
- # '0' is a special value meaning 'infinity', or 'the servers never
- # exit'
- max_requests_per_server = 0
-}
-
-# MODULE CONFIGURATION
-#
-# The names and configuration of each module is located in this section.
-#
-# After the modules are defined here, they may be referred to by name,
-# in other sections of this configuration file.
-#
-modules {
- #
- # Each module has a configuration as follows:
- #
- # name [ instance ] {
- # config_item = value
- # ...
- # }
- #
- # The 'name' is used to load the 'rlm_name' library
- # which implements the functionality of the module.
- #
- # The 'instance' is optional. To have two different instances
- # of a module, it first must be referred to by 'name'.
- # The different copies of the module are then created by
- # inventing two 'instance' names, e.g. 'instance1' and 'instance2'
- #
- # The instance names can then be used in later configuration
- # INSTEAD of the original 'name'. See the 'radutmp' configuration
- # below for an example.
- #
-
- # PAP module to authenticate users based on their stored password
- #
- # Supports multiple encryption schemes
- # clear: Clear text
- # crypt: Unix crypt
- # md5: MD5 ecnryption
- # sha1: SHA1 encryption.
- # DEFAULT: crypt
- pap {
- encryption_scheme = crypt
- }
-
- # CHAP module
- #
- # To authenticate requests containing a CHAP-Password attribute.
- #
- chap {
- authtype = CHAP
- }
-
- # Extensible Authentication Protocol
- #
- # For all EAP related authentications.
- # Now in another file, because it is very large.
- #
-$INCLUDE ${confdir}/eap.conf
-
- # Microsoft CHAP authentication
- #
- # This module supports MS-CHAP and MS-CHAPv2 authentication.
- # It also enforces the SMB-Account-Ctrl attribute.
- #
- mschap {
- #
- # As of 0.9, the mschap module does NOT support
- # reading from /etc/smbpasswd.
- #
- # If you are using /etc/smbpasswd, see the 'passwd'
- # module for an example of how to use /etc/smbpasswd
-
- # if use_mppe is not set to no mschap will
- # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
- # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
- #
- use_mppe = yes
- authtype = MS-CHAP
-
- # if mppe is enabled require_encryption makes
- # encryption moderate
- #
- #require_encryption = yes
-
- # require_strong always requires 128 bit key
- # encryption
- #
- #require_strong = yes
-
- # Windows sends us a username in the form of
- # DOMAIN\user, but sends the challenge response
- # based on only the user portion. This hack
- # corrects for that incorrect behavior.
- #
- #with_ntdomain_hack = no
-
- # The module can perform authentication itself, OR
- # use a Windows Domain Controller. This configuration
- # directive tells the module to call the ntlm_auth
- # program, which will do the authentication, and return
- # the NT-Key. Note that you MUST have "winbindd" and
- # "nmbd" running on the local machine for ntlm_auth
- # to work. See the ntlm_auth program documentation
- # for details.
- #
- # Be VERY careful when editing the following line!
- #
- #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
- }
-
- # Preprocess the incoming RADIUS request, before handing it off
- # to other modules.
- #
- # This module processes the 'huntgroups' and 'hints' files.
- # In addition, it re-writes some weird attributes created
- # by some NASes, and converts the attributes into a form which
- # is a little more standard.
- #
- preprocess {
- huntgroups = ${confdir}/huntgroups
- hints = ${confdir}/hints
-
- # This hack changes Ascend's wierd port numberings
- # to standard 0-??? port numbers so that the "+" works
- # for IP address assignments.
- with_ascend_hack = no
- ascend_channels_per_line = 23
-
- # Windows NT machines often authenticate themselves as
- # NT_DOMAIN\username
- #
- # If this is set to 'yes', then the NT_DOMAIN portion
- # of the user-name is silently discarded.
- #
- # This configuration entry SHOULD NOT be used.
- # See the "realms" module for a better way to handle
- # NT domains.
- with_ntdomain_hack = no
-
- # Specialix Jetstream 8500 24 port access server.
- #
- # If the user name is 10 characters or longer, a "/"
- # and the excess characters after the 10th are
- # appended to the user name.
- #
- # If you're not running that NAS, you don't need
- # this hack.
- with_specialix_jetstream_hack = no
-
- # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
- # with the attribute name *again* in the string, like:
- #
- # H323-Attribute = "h323-attribute=value".
- #
- # If this configuration item is set to 'yes', then
- # the redundant data in the the attribute text is stripped
- # out. The result is:
- #
- # H323-Attribute = "value"
- #
- # If you're not running a Cisco or Quintum NAS, you don't
- # need this hack.
- with_cisco_vsa_hack = no
- }
-
- # Write a detailed log of all accounting records received.
- #
- detail {
- # Note that we do NOT use NAS-IP-Address here, as
- # that attribute MAY BE from the originating NAS, and
- # NOT from the proxy which actually sent us the
- # request. The Client-IP-Address attribute is ALWAYS
- # the address of the client which sent us the
- # request.
- #
- # The following line creates a new detail file for
- # every radius client (by IP address or hostname).
- # In addition, a new detail file is created every
- # day, so that the detail file doesn't have to go
- # through a 'log rotation'
- #
- # If your detail files are large, you may also want
- # to add a ':%H' (see doc/variables.txt) to the end
- # of it, to create a new detail file every hour, e.g.:
- #
- # ..../detail-%Y%m%d:%H
- #
- # This will create a new detail file for every hour.
- #
- detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
-
- #
- # The Unix-style permissions on the 'detail' file.
- #
- # The detail file often contains secret or private
- # information about users. So by keeping the file
- # permissions restrictive, we can prevent unwanted
- # people from seeing that information.
- detailperm = 0600
-
- #
- # Certain attributes such as User-Password may be
- # "sensitive", so they should not be printed in the
- # detail file. This section lists the attributes
- # that should be suppressed.
- #
- # The attributes should be listed one to a line.
- #
- #suppress {
- # User-Password
- #}
- }
-
- #
- # Create a unique accounting session Id. Many NASes re-use
- # or repeat values for Acct-Session-Id, causing no end of
- # confusion.
- #
- # This module will add a (probably) unique session id
- # to an accounting packet based on the attributes listed
- # below found in the packet. See doc/rlm_acct_unique for
- # more information.
- #
- acct_unique {
- key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
- }
-
- # Write a 'utmp' style file, of which users are currently
- # logged in, and where they've logged in from.
- #
- # This file is used mainly for Simultaneous-Use checking,
- # and also 'radwho', to see who's currently logged in.
- #
- radutmp {
- # Where the file is stored. It's not a log file,
- # so it doesn't need rotating.
- #
- filename = ${logdir}/radutmp
-
- # The field in the packet to key on for the
- # 'user' name, If you have other fields which you want
- # to use to key on to control Simultaneous-Use,
- # then you can use them here.
- #
- # Note, however, that the size of the field in the
- # 'utmp' data structure is small, around 32
- # characters, so that will limit the possible choices
- # of keys.
- #
- # You may want instead: %{Stripped-User-Name:-%{User-Name}}
- username = %{User-Name}
-
-
- # Whether or not we want to treat "user" the same
- # as "USER", or "User". Some systems have problems
- # with case sensitivity, so this should be set to
- # 'no' to enable the comparisons of the key attribute
- # to be case insensitive.
- #
- case_sensitive = yes
-
- # Accounting information may be lost, so the user MAY
- # have logged off of the NAS, but we haven't noticed.
- # If so, we can verify this information with the NAS,
- #
- # If we want to believe the 'utmp' file, then this
- # configuration entry can be set to 'no'.
- #
- check_with_nas = yes
-
- # Set the file permissions, as the contents of this file
- # are usually private.
- perm = 0600
-
- callerid = "yes"
- }
-
- # "Safe" radutmp - does not contain caller ID, so it can be
- # world-readable, and radwho can work for normal users, without
- # exposing any information that isn't already exposed by who(1).
- #
- # This is another 'instance' of the radutmp module, but it is given
- # then name "sradutmp" to identify it later in the "accounting"
- # section.
- radutmp sradutmp {
- filename = ${logdir}/sradutmp
- perm = 0644
- callerid = "no"
- }
-
- # attr_filter - filters the attributes received in replies from
- # proxied servers, to make sure we send back to our RADIUS client
- # only allowed attributes.
- attr_filter {
- attrsfile = ${confdir}/attrs
- }
-
- # counter module:
- # This module takes an attribute (count-attribute).
- # It also takes a key, and creates a counter for each unique
- # key. The count is incremented when accounting packets are
- # received by the server. The value of the increment depends
- # on the attribute type.
- # If the attribute is Acct-Session-Time or of an integer type we add the
- # value of the attribute. If it is anything else we increase the
- # counter by one.
- #
- # The 'reset' parameter defines when the counters are all reset to
- # zero. It can be hourly, daily, weekly, monthly or never.
- #
- # hourly: Reset on 00:00 of every hour
- # daily: Reset on 00:00:00 every day
- # weekly: Reset on 00:00:00 on sunday
- # monthly: Reset on 00:00:00 of the first day of each month
- #
- # It can also be user defined. It should be of the form:
- # num[hdwm] where:
- # h: hours, d: days, w: weeks, m: months
- # If the letter is ommited days will be assumed. In example:
- # reset = 10h (reset every 10 hours)
- # reset = 12 (reset every 12 days)
- #
- #
- # The check-name attribute defines an attribute which will be
- # registered by the counter module and can be used to set the
- # maximum allowed value for the counter after which the user
- # is rejected.
- # Something like:
- #
- # DEFAULT Max-Daily-Session := 36000
- # Fall-Through = 1
- #
- # You should add the counter module in the instantiate
- # section so that it registers check-name before the files
- # module reads the users file.
- #
- # If check-name is set and the user is to be rejected then we
- # send back a Reply-Message and we log a Failure-Message in
- # the radius.log
- # If the count attribute is Acct-Session-Time then on each login
- # we send back the remaining online time as a Session-Timeout attribute
- #
- # The counter-name can also be used instead of using the check-name
- # like below:
- #
- # DEFAULT Daily-Session-Time > 3600, Auth-Type = Reject
- # Reply-Message = "You've used up more than one hour today"
- #
- # The allowed-servicetype attribute can be used to only take
- # into account specific sessions. For example if a user first
- # logs in through a login menu and then selects ppp there will
- # be two sessions. One for Login-User and one for Framed-User
- # service type. We only need to take into account the second one.
- #
- # The module should be added in the instantiate, authorize and
- # accounting sections. Make sure that in the authorize
- # section it comes after any module which sets the
- # 'check-name' attribute.
- #
- counter daily {
- filename = ${raddbdir}/db.daily
- key = User-Name
- count-attribute = Acct-Session-Time
- reset = daily
- counter-name = Daily-Session-Time
- check-name = Max-Daily-Session
- allowed-servicetype = Framed-User
- cache-size = 5000
- }
-
- #
- # The "always" module is here for debugging purposes. Each
- # instance simply returns the same result, always, without
- # doing anything.
- always fail {
- rcode = fail
- }
- always reject {
- rcode = reject
- }
- always ok {
- rcode = ok
- simulcount = 0
- mpp = no
- }
-
- stg {
- local_port = 6667
- server = localhost
- port = 6666
- password = 123456
- }
-
-}
-
-# Instantiation
-#
-# This section orders the loading of the modules. Modules
-# listed here will get loaded BEFORE the later sections like
-# authorize, authenticate, etc. get examined.
-#
-# This section is not strictly needed. When a section like
-# authorize refers to a module, it's automatically loaded and
-# initialized. However, some modules may not be listed in any
-# of the following sections, so they can be listed here.
-#
-# Also, listing modules here ensures that you have control over
-# the order in which they are initalized. If one module needs
-# something defined by another module, you can list them in order
-# here, and ensure that the configuration will be OK.
-#
-instantiate {
- stg
-}
-
-# Authorization. First preprocess (hints and huntgroups files),
-# then realms, and finally look in the "users" file.
-#
-# The order of the realm modules will determine the order that
-# we try to find a matching realm.
-#
-# Make *sure* that 'preprocess' comes before any realm if you
-# need to setup hints for the remote radius server
-authorize {
- #
- # The preprocess module takes care of sanitizing some bizarre
- # attributes in the request, and turning them into attributes
- # which are more standard.
- #
- # It takes care of processing the 'raddb/hints' and the
- # 'raddb/huntgroups' files.
- #
- # It also adds the %{Client-IP-Address} attribute to the request.
- preprocess
-
- #
- # The chap module will set 'Auth-Type := CHAP' if we are
- # handling a CHAP request and Auth-Type has not already been set
- chap
-
- #
- # If the users are logging in with an MS-CHAP-Challenge
- # attribute for authentication, the mschap module will find
- # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
- # to the request, which will cause the server to then use
- # the mschap module for authentication.
- mschap
-
- #
- # This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
- # authentication.
- #
- # It also sets the EAP-Type attribute in the request
- # attribute list to the EAP type from the packet.
- eap
-
- stg
-}
-
-
-# Authentication.
-#
-#
-# This section lists which modules are available for authentication.
-# Note that it does NOT mean 'try each module in order'. It means
-# that a module from the 'authorize' section adds a configuration
-# attribute 'Auth-Type := FOO'. That authentication type is then
-# used to pick the apropriate module from the list below.
-#
-
-# In general, you SHOULD NOT set the Auth-Type attribute. The server
-# will figure it out on its own, and will do the right thing. The
-# most common side effect of erroneously setting the Auth-Type
-# attribute is that one authentication method will work, but the
-# others will not.
-#
-# The common reasons to set the Auth-Type attribute by hand
-# is to either forcibly reject the user, or forcibly accept him.
-#
-authenticate {
- #
- # PAP authentication, when a back-end database listed
- # in the 'authorize' section supplies a password. The
- # password can be clear-text, or encrypted.
- Auth-Type PAP {
- stg
- pap
- }
-
- #
- # Most people want CHAP authentication
- # A back-end database listed in the 'authorize' section
- # MUST supply a CLEAR TEXT password. Encrypted passwords
- # won't work.
- Auth-Type CHAP {
- stg
- chap
- }
-
- #
- # MSCHAP authentication.
- Auth-Type MS-CHAP {
- stg
- mschap
- }
-
- #
- # Allow EAP authentication.
- eap
-}
-
-
-#
-# Pre-accounting. Decide which accounting type to use.
-#
-preacct {
- preprocess
-
- #
- # Ensure that we have a semi-unique identifier for every
- # request, and many NAS boxes are broken.
- acct_unique
-}
-
-#
-# Accounting. Log the accounting data.
-#
-accounting {
- #
- # Create a 'detail'ed log of the packets.
- # Note that accounting requests which are proxied
- # are also logged in the detail file.
- detail
-# daily
-
- #
- # For Simultaneous-Use tracking.
- #
- # Due to packet losses in the network, the data here
- # may be incorrect. There is little we can do about it.
- radutmp
-
- stg
-
-}
-
-
-# Session database, used for checking Simultaneous-Use. Either the radutmp
-# or rlm_sql module can handle this.
-# The rlm_sql module is *much* faster
-session {
- radutmp
-}
-
-
-# Post-Authentication
-# Once we KNOW that the user has been authenticated, there are
-# additional steps we can take.
-post-auth {
- stg
-}
-
-#
-# When the server decides to proxy a request to a home server,
-# the proxied request is first passed through the pre-proxy
-# stage. This stage can re-write the request, or decide to
-# cancel the proxy.
-#
-# Only a few modules currently have this method.
-#
-pre-proxy {
-}
-
-#
-# When the server receives a reply to a request it proxied
-# to a home server, the request may be massaged here, in the
-# post-proxy stage.
-#
-post-proxy {
- #
- # If you are proxying LEAP, you MUST configure the EAP
- # module, and you MUST list it here, in the post-proxy
- # stage.
- #
- # You MUST also use the 'nostrip' option in the 'realm'
- # configuration. Otherwise, the User-Name attribute
- # in the proxied request will not match the user name
- # hidden inside of the EAP packet, and the end server will
- # reject the EAP request.
- #
- eap
-}
+++ /dev/null
-#!/bin/sh
-
-rm -f /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
+++ /dev/null
-#!/bin/sh
-
-echo $PPP_IFACE > /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
+++ /dev/null
-###############################################################################
-# $Id: pptpd-options,v 1.1 2008/03/31 13:55:20 faust Exp $
-#
-# Sample Poptop PPP options file /etc/ppp/pptpd-options
-# Options used by PPP when a connection arrives from a client.
-# This file is pointed to by /etc/pptpd.conf option keyword.
-# Changes are effective on the next connection. See "man pppd".
-#
-# You are expected to change this file to suit your system. As
-# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
-###############################################################################
-
-
-# Authentication
-
-# Name of the local system for authentication purposes
-# (must match the second field in /etc/ppp/chap-secrets entries)
-name pptpd
-
-# Optional: domain name to use for authentication
-# domain mydomain.net
-
-# Strip the domain prefix from the username before authentication.
-# (applies if you use pppd with chapms-strip-domain patch)
-#chapms-strip-domain
-
-
-# Encryption
-# Debian: on systems with a kernel built with the package
-# kernel-patch-mppe >= 2.4.2 and using ppp >= 2.4.2, ...
-# {{{
-refuse-pap
-refuse-chap
-refuse-mschap
-# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
-# Challenge Handshake Authentication Protocol, Version 2] authentication.
-require-mschap-v2
-# Require MPPE 128-bit encryption
-# (note that MPPE requires the use of MSCHAP-V2 during authentication)
-require-mppe-128
-# }}}
-
-
-
-
-# Network and Routing
-
-# If pppd is acting as a server for Microsoft Windows clients, this
-# option allows pppd to supply one or two DNS (Domain Name Server)
-# addresses to the clients. The first instance of this option
-# specifies the primary DNS address; the second instance (if given)
-# specifies the secondary DNS address.
-# Attention! This information may not be taken into account by a Windows
-# client. See KB311218 in Microsoft's knowledge base for more information.
-#ms-dns 10.0.0.1
-#ms-dns 10.0.0.2
-
-# If pppd is acting as a server for Microsoft Windows or "Samba"
-# clients, this option allows pppd to supply one or two WINS (Windows
-# Internet Name Services) server addresses to the clients. The first
-# instance of this option specifies the primary WINS address; the
-# second instance (if given) specifies the secondary WINS address.
-#ms-wins 10.0.0.3
-#ms-wins 10.0.0.4
-
-# Add an entry to this system's ARP [Address Resolution Protocol]
-# table with the IP address of the peer and the Ethernet address of this
-# system. This will have the effect of making the peer appear to other
-# systems to be on the local ethernet.
-# (you do not need this if your PPTP server is responsible for routing
-# packets to the clients -- James Cameron)
-proxyarp
-
-# Debian: do not replace the default route
-defaultroute
-
-
-# Logging
-
-# Enable connection debugging facilities.
-# (see your syslog configuration for where pppd sends to)
-#debug
-
-# Print out all the option values which have been set.
-# (often requested by mailing list to verify options)
-#dump
-
-
-# Miscellaneous
-
-# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
-# access.
-lock
-
-# Disable BSD-Compress compression
-nobsdcomp
-plugin radius.so
\ No newline at end of file
+++ /dev/null
-###############################################################################
-# $Id: pptpd.conf,v 1.1 2008/03/31 13:54:13 faust Exp $
-#
-# Sample Poptop configuration file /etc/pptpd.conf
-#
-# Changes are effective when pptpd is restarted.
-###############################################################################
-
-# TAG: ppp
-# Path to the pppd program, default '/usr/sbin/pppd' on Linux
-#
-#ppp /usr/sbin/pppd
-
-# TAG: option
-# Specifies the location of the PPP options file.
-# By default PPP looks in '/etc/ppp/options'
-#
-option /etc/ppp/pptpd-options
-
-# TAG: debug
-# Turns on (more) debugging to syslog
-#
-#debug
-
-# TAG: stimeout
-# Specifies timeout (in seconds) on starting ctrl connection
-#
-# stimeout 10
-
-# TAG: noipparam
-# Suppress the passing of the client's IP address to PPP, which is
-# done by default otherwise.
-#
-#noipparam
-
-# TAG: logwtmp
-# Use wtmp(5) to record client connections and disconnections.
-#
-logwtmp
-
-# TAG: bcrelay <if>
-# Turns on broadcast relay to clients from interface <if>
-#
-#bcrelay eth1
-
-# TAG: localip
-# TAG: remoteip
-# Specifies the local and remote IP address ranges.
-#
-# Any addresses work as long as the local machine takes care of the
-# routing. But if you want to use MS-Windows networking, you should
-# use IP addresses out of the LAN address space and use the proxyarp
-# option in the pppd options file, or run bcrelay.
-#
-# You can specify single IP addresses seperated by commas or you can
-# specify ranges, or both. For example:
-#
-# 192.168.0.234,192.168.0.245-249,192.168.0.254
-#
-# IMPORTANT RESTRICTIONS:
-#
-# 1. No spaces are permitted between commas or within addresses.
-#
-# 2. If you give more IP addresses than MAX_CONNECTIONS, it will
-# start at the beginning of the list and go until it gets
-# MAX_CONNECTIONS IPs. Others will be ignored.
-#
-# 3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
-# you must type 234-238 if you mean this.
-#
-# 4. If you give a single localIP, that's ok - all local IPs will
-# be set to the given one. You MUST still give at least one remote
-# IP for each simultaneous client.
-#
-# (Recommended)
-#localip 192.168.0.1
-#remoteip 192.168.0.234-238,192.168.0.245
-# or
-#localip 192.168.0.234-238,192.168.0.245
-#remoteip 192.168.1.234-238,192.168.1.245
-localip 192.168.2.1
-remoteip 192.168.2.2-254
+++ /dev/null
-localhost testing123
+++ /dev/null
-#! /bin/sh
-
-login=$1
-param=$2
-oldValue=$3
-newValue=$4
-
-#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
+++ /dev/null
-#!/bin/bash
-
-#Этот скрипт вызывается в момент, когда пользователь
-#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
-#файрвол так, что бы пользователь получил доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-iptables -A INPUT -s $IP -j QUEUE
-iptables -A OUTPUT -d $IP -j QUEUE
-iptables -A FORWARD -s $IP -j QUEUE
-iptables -A FORWARD -d $IP -j QUEUE
-
-# shaper
-
-default_speed=32
-
-speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-#echo "speedR=$speedR" >> /var/stargazer/users/$LOGIN/connect.log
-speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
-
-if [ -z "$speed" ]
-then
- speed=$default_speed
-fi
-
-speedkbit=$speed"kbit"
-
-#echo "speed=$speedkbit" >> /var/stargazer/users/$LOGIN/connect.log
-declare -i mark=$ID+1
-
-iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
-
-sleep 1
-
-if [ -f "/var/stargazer/ifaces/$IP" ]
-then
- #echo "1" >> /var/stargazer/users/$LOGIN/connect.log
- ppp_iface=$(cat /var/stargazer/ifaces/$IP)
-else
- #echo "2" >> /var/stargazer/users/$LOGIN/connect.log
- exit 0
-fi
-
-tc qdisc add dev $ppp_iface root handle 1: htb
-tc class add dev $ppp_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
-tc class add dev $ppp_iface parent 1:1 classid 1:10 htb rate $speedkbit burst 20k
-tc filter add dev $ppp_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:10
-
-#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH $ID $mark $speed $ppp_iface" >> /var/stargazer/users/$LOGIN/connect.log
-
+++ /dev/null
-#!/bin/bash
-
-# Этот скрипт вызывается в момент, когда пользователь
-# желает отключится от интернета или вышел таймаут у пользователя
-# и сервер сам отключает пользователя
-# Задача скрипта подобна задаче скрипта OnConnect - перестроить
-# файрвол так, что бы пользователю закрыть доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$4
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
-iptables -D INPUT -s $IP -j QUEUE
-while [ $? == 0 ]
-do
- iptables -D INPUT -s $IP -j QUEUE
-done
-
-iptables -D OUTPUT -d $IP -j QUEUE
-while [ $? == 0 ]
-do
- iptables -D OUTPUT -d $IP -j QUEUE
-done
-
-iptables -D FORWARD -s $IP -j QUEUE
-while [ $? == 0 ]
-do
- iptables -D FORWARD -s $IP -j QUEUE
-done
-
-iptables -D FORWARD -d $IP -j QUEUE
-while [ $? == 0 ]
-do
- iptables -D FORWARD -d $IP -j QUEUE
-done
-
-
-
-declare -i mark=$ID+1
-
-iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-while [ $? == 0 ]
-do
- iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-done
-
-
-if [ -f /var/stargazer/ifaces/$IP ]
-then
- ppp_iface=$(cat /var/stargazer/ifaces/$IP)
-else
- exit 0
-fi
-
-tc qdisc del dev $ppp_iface root
-
-
+++ /dev/null
-#! /bin/sh
-
-# Использование (неиспользование) этого скрипта дело вкуса.
-# Он не выполняет критических функций. Его задача автматизировать
-# действия характерные при добавлении пользователя сети, например добавлекние
-# пользователю почты
-
-# Login
-login=$1
-
-#echo "added user $login" >> /var/stargazer/add_del.log
-
-
-
+++ /dev/null
-#! /bin/sh
-
-# Login
-login=$1
-
-#echo "deleted user $login" >> /var/stargazer/add_del.log
-
+++ /dev/null
-ALL 192.168.0.0/16 DIR1
-ALL 10.0.0.0/8 DIR2
-ALL 0.0.0.0/0 DIR0
\ No newline at end of file
+++ /dev/null
-
-# Имя лог-файла куда пишутся события
-LogFile = /var/log/stargazer.log
-
-
-
-# Имя файла в котором определяются правила подсчета трафика
-Rules = /etc/stargazer/rules
-
-
-
-# Время через которое пишется d БД детальная статистика пользователя
-# Значения: 1, 1/2, 1/4, 1/6.
-# 1 - раз в чаc, 1/2 - раз в пол часа, 1/4 - раз в 15 мин, 1/6 - раз в 10 мин
-DetailStatWritePeriod=1/6
-
-
-
-# Периодичность записи записи в БД информации о статистике пользователя (минуты)
-# При большом кол-ве пользователей эту величину стоит увеличить, т.к.
-# запись в БД может занимать длительное время.
-# Значения: 1...1440 (минуты)
-StatWritePeriod = 10
-
-
-
-# День снятия абонплаты
-# Значения: 0...31. 0 - Последний день месяца
-DayFee = 1
-
-
-
-# Абонплата снимается в последний (yes) или первый (no) день учетного периода.
-# Это влияет на то, как будет снята абонплата (АП) при переходе на новый тариф.
-# Если у пользователя был тариф A с АП=100 и он хочет перейти на тариф B с АП=200,
-# то при переходе на новый тариф со счета пользователя снимется 100, если
-# DayFeeIsLastDay = yes и 200, если DayFeeIsLastDay = no
-DayFeeIsLastDay = yes
-
-
-
-# День сброса данных о трафике за месяц и день перехода пользователей на новые тарифы
-# Значения: 0...31. 0 - Последний день месяца
-DayResetTraff = 1
-
-
-
-# "Размазанное" снятие абонплаты. Снятие АП не раз в месяц, а каждый
-# день 1/30 или 1/31 части АП
-# Значения: yes, no
-SpreadFee = no
-
-
-
-# Данная опция определяет может ли пользователь получить доступ в интерент
-# если у него на счету нет денег, но остался предоплаченный трафик
-# Значения: yes, no
-FreeMbAllowInet = no
-
-
-
-# Эта опция определяет что будет писаться в стоимость трафика в detail_stat.
-# Если у пользователя еще есть предоплаченный трафик и WriteFreeMbTraffCost = no,
-# то в detail_stat стоимость будет 0. Если у пользователя уже нет
-# предоплаченного трафика и WriteFreeMbTraffCost = no, то в detail_stat
-# будет записана стоиость трафика. При WriteFreeMbTraffCost = yes стоимость
-# трафика будет записана в любом случае.
-WriteFreeMbTraffCost = no
-
-
-
-# Необязательный параметр. Указывает снимать полную абонплату у пользователя даже
-# если он быз заморожен только часть учетного периода.
-# По умолчанию установлен в no
-# FullFee=no
-
-# Необязательный параметр указывающий показывать на счету и позволять
-# использовать пользователю абонплату. По умолчанию установлен в yes
-# ShowFeeInCash=yes
-
-
-
-# Названия направлений. Направления без названий не будут отображаться в
-# авторизаторе и конфигураторе. Названия состоящие из нескольких слов должны
-# быть взяты в кавычки
-<DirNames>
- DirName0 = Local
- DirName1 = City
- DirName2 = World
- DirName3 =
- DirName4 =
- DirName5 =
- DirName6 =
- DirName7 =
- DirName8 =
- DirName9 =
-</DirNames>
-
-
-
-# Кол-во запускаемых процессов stg-exec.
-# Эти процессы отвечают за выполнение скриптов OnConnect, OnDisconnect, ...
-# Кол-во процессов означает сколько скриптов могут выполнятся одновременно.
-# Значения: 1...1024
-ExecutersNum = 2
-
-
-
-# Message Key для stg-exec.
-# Идентификатор очереди сообщений для выполнятеля скриптов.
-# Его изменение может понадобится если есть необходимость запустить несколько
-# экземпляров stg. Если вы не понимаете, что это, не трогайте этот параметр!
-# Значения: 0...2^32
-# Значение по умолчанию: 5555
-# ExecMsgKey = 5555
-
-
-
-# Путь к директории, в которой находятся модули сервера
-ModulesPath = /usr/lib/stg
-
-# Определяет директорию, в которой будут находится файлы "монитора"
-# работы сервера. В этой директории будут созданы пустые файлы, время
-# модификации которых будет меняться примерно раз в минуту. Если какой-то
-# компонент сервера зависнет, файл(ы) перестанет обновлятся, и по этому
-# признаку можно определить сбой в работе сервера и при надобности
-# перезапустить. Если параметр не указан или пустой, мониторинг производится
-# не будет. Параметр не является обязательным, по умолчанию пустой.
-# MonitorDir=/var/stargazer/monitor
-
-
-################################################################################
-# Store module
-# Настройки плагина работающего с БД сервера
-
-# Второй параметр - это имя модуля без mod_ в начале и .so в конце
-# Т.е. полное имя модуля mod_store_files.so
-<StoreModule store_files>
-
- # Рабочая директория сервера, тут содержатся данные о тарифах, пользователях,
- # администраторах и т.д.
- WorkDir = /var/stargazer
-
-
- # Владелец, группа и права доступа на файлы статистики (stat) пользователя
- ConfOwner = root
- ConfGroup = root
- ConfMode = 600
-
-
- # Владелец, группа и права доступа на файлы конфигурации (conf) пользователя
- StatOwner = root
- StatGroup = root
- StatMode = 640
-
- # Владелец, группа и права доступа на лог-файлы (log) пользователя
- UserLogOwner = root
- UserLogGroup = root
- UserLogMode = 640
-
-</StoreModule>
-
-#<StoreModule store_firebird>
-# # Адрес сервера БД
-# server=localhost
-#
-# # Путь к БД на сервере или ее алиас
-# path=/var/stg/stargazer.fdb
-#
-# # Имя пользователя БД
-# user=stg
-#
-# # Пароль пользователя БД
-# password=123456
-#</StoreModule>
-
-#<StoreModule store_mysql>
-# # Имя пользователя БД
-# dbuser = stg
-#
-# # Пароль пользователя БД
-# rootdbpass = 123456
-#
-# # Имя БД на сервере
-# dbname = stg
-#
-# # Адрес сервера БД
-# dbhost = localhost
-#</StoreModule>
-
-
-
-################################################################################
-# Прочие модули
-
-<Modules>
-
- # Настройки плагина авторизации Always Online "mod_auth_ao.so"
- # Второй параметр - это имя модуля без mod_ в начале и .so в конце
- # Т.е. полное имя модуля mod_auth_ao.so
- #<Module auth_ao>
- #</Module>
-
-
-
- # Настройки плагина авторизации InetAccess "mod_auth_ia.so"
- # Второй параметр - это имя модуля без mod_ в начале и .so в конце
- # Т.е. полное имя модуля mod_auth_ia.so
- #<Module auth_ia>
- # Port = 5555
- # UserDelay = 15
- # UserTimeout = 65
- # FreeMb = 0
- #</Module>
-
-
-
- # Настройки модуля конфигурации SgConfig "mod_conf_sg.so"
- # Второй параметр - это имя модуля без mod_ в начале и .so в конце
- <Module conf_sg>
-
- # Порт по которому сервер взаимодействует с конфигуратором
- # Значения: 1...65535
- Port = 5555
-
- </Module>
-
-
-
- # Модуль захвата трафика "mod_cap_ether.so"
- # Второй параметер - это имя модуля без mod_ в начале и .so в конце
- # Без параметров. Только имя модуля.
- <Module cap_ipq>
- # Модуль без параметров
- </Module>
-
-
-
- # Настройки модуля пингующего пользователей "mod_ping.so"
- # Второй параметр - это имя модуля без mod_ в начале и .so в конце
- <Module ping>
-
- # Время, в секундах, между пингами одного и того же пользователя
- # Значения: 10...3600
- PingDelay = 15
-
- </Module>
-
- <Module radius>
- Password = 123456
- ServerIP = 127.0.0.1
- Port = 6666
- AuthServices = Login-User
- AcctServices = Framed-User
- </Module>
-
-# # Настройки модуля для удаленного выполнения скриптов OnConnect и
-# # OnDisconnect "mod_remote_script.so"
-# # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-# <Module remote_script>
-#
-# # Время, в секундах, между посылками подтверждений, того, что пользователь
-# # всё еще онлайн
-# # Значения: 10...600
-# SendPeriod = 15
-#
-# # Соответствие подсетей, в которой находится пользователь и
-# # соответствующего роутера. Первая часть строки - подсеть, заданная
-# # как IP-адрес и маска, через пробел - IP-адрес роутера на котором
-# # должны выполняться скрипты
-# # Например эта запись "192.168.1.0/24 192.168.1.1" означает, что для
-# # всех пользователей из подсети 192.168.1.0/24, скрипты будут
-# # выполняться на роутере с адресом 192.168.1.1
-# # Subnet0...Subnet100
-# Subnet0 = 192.168.1.0/24 192.168.1.7
-# Subnet1 = 192.168.2.0/24 192.168.2.5
-# Subnet2 = 192.168.3.0/24 192.168.2.5
-# Subnet3 = 192.168.4.0/24 192.168.2.5
-#
-# # Пароль для шифрования пакетов между stg-сервером и сервером,
-# # выполняющим скрипты
-# Password = 123456
-#
-# # Этот параметр определяет какие параметры пользователя передаются
-# # на удаленный сервер
-# # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
-# # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
-# UserParams=Cash Tariff EnabledDirs
-#
-# # Порт по которому сервер отсылает сообщения на роутер
-# # Значения: 1...65535
-# Port = 9999
-#
-# </Module>
-
-</Modules>
-################################################################################
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include <cerrno>
-#include <cassert>
-#include <algorithm>
-
-#include "stg/admin.h"
-#include "stg/common.h"
-#include "services_impl.h"
-
-//-----------------------------------------------------------------------------
-SERVICES_IMPL::SERVICES_IMPL(STORE * st)
- : SERVICES(),
- data(),
- store(st),
- WriteServLog(GetStgLogger()),
- searchDescriptors(),
- handle(0),
- mutex(),
- strError()
-{
-pthread_mutex_init(&mutex, NULL);
-Read();
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::Add(const SERVICE_CONF & service, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->serviceChg)
- {
- std::string s = admin->GetLogStr() + " Add service \'" + service.name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-iterator si(std::find(data.begin(), data.end(), service));
-
-if (si != data.end())
- {
- strError = "Service \'" + service.name + "\' cannot not be added. Service already exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-data.push_back(service);
-
-if (store->AddService(service.name) == 0)
- {
- WriteServLog("%s Service \'%s\' added.",
- admin->GetLogStr().c_str(), service.name.c_str());
- return 0;
- }
-
-strError = "Service \'" + service.name + "\' was not added. Error: " + store->GetStrError();
-WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::Del(const std::string & name, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->serviceChg)
- {
- std::string s = admin->GetLogStr() + " Delete service \'" + name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
-
-if (si == data.end())
- {
- strError = "Service \'" + name + "\' cannot be deleted. Service does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-std::map<int, const_iterator>::iterator csi;
-csi = searchDescriptors.begin();
-while (csi != searchDescriptors.end())
- {
- if (csi->second == si)
- (csi->second)++;
- ++csi;
- }
-
-data.remove(*si);
-if (store->DelService(name) < 0)
- {
- strError = "Service \'" + name + "\' was not deleted. Error: " + store->GetStrError();
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
-
- return -1;
- }
-
-WriteServLog("%s Service \'%s\' deleted.", admin->GetLogStr().c_str(), name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::Change(const SERVICE_CONF & service, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->serviceChg)
- {
- std::string s = admin->GetLogStr() + " Change service \'" + service.name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-iterator si(std::find(data.begin(), data.end(), service));
-
-if (si == data.end())
- {
- strError = "Service \'" + service.name + "\' cannot be changed " + ". Service does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-printfd(__FILE__, "Old cost = %f, old pay day = %d\n", si->cost, (unsigned)si->payDay);
-*si = service;
-printfd(__FILE__, "New cost = %f, New pay day = %d\n", si->cost, (unsigned)si->payDay);
-if (store->SaveService(service))
- {
- WriteServLog("Cannot write service %s.", service.name.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
-
-WriteServLog("%s Service \'%s\' changed.",
- admin->GetLogStr().c_str(), service.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool SERVICES_IMPL::Read()
-{
-STG_LOCKER lock(&mutex);
-std::vector<std::string> servicesList;
-if (store->GetServicesList(&servicesList) < 0)
- {
- WriteServLog(store->GetStrError().c_str());
- return true;
- }
-
-for (size_t i = 0; i < servicesList.size(); i++)
- {
- SERVICE_CONF service;
-
- if (store->RestoreService(&service, servicesList[i]))
- {
- WriteServLog(store->GetStrError().c_str());
- return true;
- }
-
- data.push_back(service);
- }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool SERVICES_IMPL::Find(const std::string & name, SERVICE_CONF * service) const
-{
-assert(service != NULL && "Pointer to service is not null");
-
-STG_LOCKER lock(&mutex);
-if (data.empty())
- return true;
-
-const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
-
-if (si != data.end())
- {
- *service = *si;
- return false;
- }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool SERVICES_IMPL::Find(const std::string & name, SERVICE_CONF_RES * service) const
-{
-assert(service != NULL && "Pointer to service is not null");
-
-STG_LOCKER lock(&mutex);
-if (data.empty())
- return true;
-
-const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
-
-if (si != data.end())
- {
- *service = *si;
- return false;
- }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool SERVICES_IMPL::Exists(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-if (data.empty())
- {
- printfd(__FILE__, "No services in the system!\n");
- return true;
- }
-
-const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
-
-if (si != data.end())
- return true;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::OpenSearch() const
-{
-STG_LOCKER lock(&mutex);
-handle++;
-searchDescriptors[handle] = data.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::SearchNext(int h, SERVICE_CONF * service) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) == searchDescriptors.end())
- {
- WriteServLog("SERVICES. Incorrect search handle.");
- return -1;
- }
-
-if (searchDescriptors[h] == data.end())
- return -1;
-
-*service = *searchDescriptors[h]++;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int SERVICES_IMPL::CloseSearch(int h) const
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
- {
- searchDescriptors.erase(searchDescriptors.find(h));
- return 0;
- }
-
-WriteServLog("SERVICES. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef SERVICES_IMPL_H
-#define SERVICES_IMPL_H
-
-#include "stg/services.h"
-#include "stg/service_conf.h"
-#include "stg/locker.h"
-#include "stg/store.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include <list>
-#include <map>
-#include <string>
-
-#include <pthread.h>
-
-class ADMIN;
-
-class SERVICES_IMPL : private NONCOPYABLE, public SERVICES {
-public:
- explicit SERVICES_IMPL(STORE * st);
- virtual ~SERVICES_IMPL() {}
-
- int Add(const SERVICE_CONF & service, const ADMIN * admin);
- int Del(const std::string & name, const ADMIN * admin);
- int Change(const SERVICE_CONF & service, const ADMIN * admin);
- bool Find(const std::string & name, SERVICE_CONF * service) const;
- bool Find(const std::string & name, SERVICE_CONF_RES * service) const;
- bool Exists(const std::string & name) const;
- const std::string & GetStrError() const { return strError; }
-
- size_t Count() const { return data.size(); }
-
- int OpenSearch() const;
- int SearchNext(int, SERVICE_CONF * service) const;
- int CloseSearch(int) const;
-
-private:
- SERVICES_IMPL(const SERVICES_IMPL & rvalue);
- SERVICES_IMPL & operator=(const SERVICES_IMPL & rvalue);
-
- typedef std::list<SERVICE_CONF>::iterator iterator;
- typedef std::list<SERVICE_CONF>::const_iterator const_iterator;
-
- bool Read();
-
- std::list<SERVICE_CONF> data;
- STORE * store;
- STG_LOGGER & WriteServLog;
- mutable std::map<int, const_iterator> searchDescriptors;
- mutable unsigned int handle;
- mutable pthread_mutex_t mutex;
- std::string strError;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#include "settings_impl.h"
-
-#include "stg/logger.h"
-#include "stg/dotconfpp.h"
-#include "stg/common.h"
-
-#include <stdexcept>
-#include <cstring>
-#include <cerrno>
-
-namespace
-{
-
-struct Error : public std::runtime_error
-{
- Error(const std::string& message) : runtime_error(message) {}
-};
-
-std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
-{
- std::vector<std::string> values;
-
- size_t i = 0;
- const char* value = NULL;
- while ((value = node.getValue(i++)) != NULL)
- values.push_back(value);
-
- return values;
-}
-
-std::vector<PARAM_VALUE> toPVS(const DOTCONFDocumentNode& node)
-{
- std::vector<PARAM_VALUE> pvs;
-
- const DOTCONFDocumentNode* child = node.getChildNode();
- while (child != NULL)
- {
- if (child->getName() == NULL)
- continue;
-
- if (child->getChildNode() == NULL)
- pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child)));
- else
- pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child), toPVS(*child)));
-
- child = child->getNextNode();
- }
-
- return pvs;
-}
-
-unsigned toPeriod(const char* value)
-{
- if (value == NULL)
- throw Error("No detail stat period value.");
-
- std::string period(value);
- if (period == "1")
- return dsPeriod_1;
- else if (period == "1/2")
- return dsPeriod_1_2;
- else if (period == "1/4")
- return dsPeriod_1_4;
- else if (period == "1/6")
- return dsPeriod_1_6;
-
- throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'.");
-}
-
-}
-
-//-----------------------------------------------------------------------------
-SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd)
- : modulesPath("/usr/lib/stg"),
- dirName(DIR_NUM),
- confDir(cd.empty() ? "/etc/stargazer" : cd),
- scriptsDir(confDir),
- rules(confDir + "/rules"),
- logFile("/var/log/stargazer.log"),
- pidFile("/var/run/stargazer.pid"),
- monitorDir("/var/stargazer/monitoring"),
- monitoring(false),
- detailStatWritePeriod(dsPeriod_1_6),
- statWritePeriod(10),
- stgExecMsgKey(5555),
- executersNum(1),
- fullFee(false),
- dayFee(0),
- dayResetTraff(0),
- spreadFee(false),
- freeMbAllowInet(false),
- dayFeeIsLastDay(false),
- stopOnError(true),
- writeFreeMbTraffCost(false),
- showFeeInCash(true),
- messageTimeout(0),
- feeChargeType(0),
- reconnectOnTariffChange(false),
- disableSessionLog(false),
- logger(GetStgLogger())
-{
- filterParamsLog.push_back("*");
-}
-//-----------------------------------------------------------------------------
-SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval)
- : modulesPath(rval.modulesPath),
- dirName(rval.dirName),
- confDir(rval.confDir),
- scriptsDir(rval.scriptsDir),
- rules(rval.rules),
- logFile(rval.logFile),
- pidFile(rval.pidFile),
- monitorDir(rval.monitorDir),
- monitoring(rval.monitoring),
- detailStatWritePeriod(rval.detailStatWritePeriod),
- statWritePeriod(rval.statWritePeriod),
- stgExecMsgKey(rval.stgExecMsgKey),
- executersNum(rval.executersNum),
- fullFee(rval.fullFee),
- dayFee(rval.dayFee),
- dayResetTraff(rval.dayResetTraff),
- spreadFee(rval.spreadFee),
- freeMbAllowInet(rval.freeMbAllowInet),
- dayFeeIsLastDay(rval.dayFeeIsLastDay),
- stopOnError(rval.stopOnError),
- writeFreeMbTraffCost(rval.writeFreeMbTraffCost),
- showFeeInCash(rval.showFeeInCash),
- messageTimeout(rval.messageTimeout),
- feeChargeType(rval.feeChargeType),
- reconnectOnTariffChange(rval.reconnectOnTariffChange),
- disableSessionLog(rval.disableSessionLog),
- filterParamsLog(rval.filterParamsLog),
- modulesSettings(rval.modulesSettings),
- storeModuleSettings(rval.storeModuleSettings),
- logger(GetStgLogger())
-{
-}
-//-----------------------------------------------------------------------------
-SETTINGS_IMPL & SETTINGS_IMPL::operator=(const SETTINGS_IMPL & rhs)
-{
- modulesPath = rhs.modulesPath;
- dirName = rhs.dirName;
- confDir = rhs.confDir;
- scriptsDir = rhs.scriptsDir;
- rules = rhs.rules;
- logFile = rhs.logFile;
- pidFile = rhs.pidFile;
- monitorDir = rhs.monitorDir;
- scriptParams = rhs.scriptParams;
- monitoring = rhs.monitoring;
- detailStatWritePeriod = rhs.detailStatWritePeriod;
- statWritePeriod = rhs.statWritePeriod;
- stgExecMsgKey = rhs.stgExecMsgKey;
- executersNum = rhs.executersNum;
- fullFee = rhs.fullFee;
- dayFee = rhs.dayFee;
- dayResetTraff = rhs.dayResetTraff;
- spreadFee = rhs.spreadFee;
- freeMbAllowInet = rhs.freeMbAllowInet;
- dayFeeIsLastDay = rhs.dayFeeIsLastDay;
- stopOnError = rhs.stopOnError;
- writeFreeMbTraffCost = rhs.writeFreeMbTraffCost;
- showFeeInCash = rhs.showFeeInCash;
- messageTimeout = rhs.messageTimeout;
- feeChargeType = rhs.feeChargeType;
- reconnectOnTariffChange = rhs.reconnectOnTariffChange;
- disableSessionLog = rhs.disableSessionLog;
- filterParamsLog = rhs.filterParamsLog;
-
- modulesSettings = rhs.modulesSettings;
- storeModuleSettings = rhs.storeModuleSettings;
- return *this;
-}
-//-----------------------------------------------------------------------------
-void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf)
-{
- printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf);
- SETTINGS_IMPL * settings = static_cast<SETTINGS_IMPL *>(data);
- settings->logger("%s", buf);
-}
-//-----------------------------------------------------------------------------
-int SETTINGS_IMPL::ReadSettings()
-{
-const char * requiredOptions[] = {
- "ModulesPath",
- "Modules",
- "StoreModule",
- "Rules",
- "LogFile",
- "DetailStatWritePeriod",
- "DayFee",
- "DayResetTraff",
- "SpreadFee",
- "FreeMbAllowInet",
- "DayFeeIsLastDay",
- "WriteFreeMbTraffCost",
- NULL
- };
-int storeModulesCount = 0;
-modulesSettings.clear();
-
-DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
-conf.setErrorCallback(SETTINGS_IMPL::ErrorCallback, this);
-conf.setRequiredOptionNames(requiredOptions);
-std::string confFile = confDir + "/stargazer.conf";
-
-if(conf.setContent(confFile.c_str()) != 0)
- {
- strError = "Cannot read file " + confFile;
- return -1;
- }
-
-const DOTCONFDocumentNode * node = conf.getFirstNode();
-
-while (node)
- {
- if (strcasecmp(node->getName(), "ScriptDir") == 0)
- {
- scriptsDir = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "LogFile") == 0)
- {
- logFile = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "PIDFile") == 0)
- {
- pidFile = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "ModulesPath") == 0)
- {
- modulesPath = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "Rules") == 0)
- {
- rules = node->getValue(0);
- }
-
- if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
- {
- try
- {
- detailStatWritePeriod = toPeriod(node->getValue(0));
- }
- catch (const Error& error)
- {
- strError = error.what();
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
- {
- if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
- {
- strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
- {
- if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
- {
- strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "ExecutersNum") == 0)
- {
- if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
- {
- strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "DayFee") == 0)
- {
- if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
- {
- strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "FullFee") == 0)
- {
- if (ParseYesNo(node->getValue(0), &fullFee) != 0)
- {
- strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "DayResetTraff") == 0)
- {
- if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
- {
- strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "SpreadFee") == 0)
- {
- if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
- {
- strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
- {
- if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
- {
- strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
- {
- if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
- {
- strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "StopOnError") == 0)
- {
- if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
- {
- strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
- {
- if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
- {
- strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
- {
- if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
- {
- strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "MonitorDir") == 0)
- {
- monitorDir = node->getValue(0);
- struct stat stat;
- monitoring = false;
-
- if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
- {
- monitoring = true;
- }
- }
-
- if (strcasecmp(node->getName(), "MessageTimeout") == 0)
- {
- if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
- {
- strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "FeeChargeType") == 0)
- {
- if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0)
- {
- strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
- {
- if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
- {
- strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "DisableSessionLog") == 0)
- {
- if (ParseYesNo(node->getValue(0), &disableSessionLog) != 0)
- {
- strError = "Incorrect DisableSessionLog value: \'" + std::string(node->getValue(0)) + "\'";
- return -1;
- }
- }
-
- if (strcasecmp(node->getName(), "FilterParamsLog") == 0)
- {
- filterParamsLog.clear();
- for (int i = 0; node->getValue(i) != NULL; ++i)
- filterParamsLog.push_back(node->getValue(i));
- }
-
- if (strcasecmp(node->getName(), "DirNames") == 0)
- {
- const DOTCONFDocumentNode * child = node->getChildNode();
- if (child)
- {
- const DOTCONFDocumentNode * dirNameNode;
- dirName.reserve(DIR_NUM);
- for (int i = 0; i < DIR_NUM; i++)
- {
- char strDirName[12];
- sprintf(strDirName, "DirName%d", i);
- dirNameNode = conf.findNode(strDirName, node);
- if (dirNameNode && dirNameNode->getValue(0))
- {
- dirName[i] = dirNameNode->getValue(0);
- }
- }
- }
- }
-
- if (strcasecmp(node->getName(), "StoreModule") == 0)
- {
- if (node->getValue(1))
- {
- strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
- return -1;
- }
-
- if (storeModulesCount)
- {
- strError = "Should be only one StoreModule.";
- return -1;
- }
- storeModulesCount++;
-
- if (node->getValue(0) == NULL)
- {
- strError = "No module name in the StoreModule section.";
- return -1;
- }
- storeModuleSettings.moduleName = node->getValue(0);
- storeModuleSettings.moduleParams = toPVS(*node);
- }
-
- if (strcasecmp(node->getName(), "Modules") == 0)
- {
- if (node->getValue(0))
- {
- strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'.";
- return -1;
- }
- const DOTCONFDocumentNode * child = node->getChildNode();
- while (child)
- {
- if (strcasecmp(child->getName(), "Module") != 0)
- {
- child = child->getNextNode();
- continue;
- }
-
- if (child->getValue(0) == NULL)
- {
- strError = "No module name in the Module section.";
- return -1;
- }
-
- modulesSettings.push_back(MODULE_SETTINGS(child->getValue(0), toPVS(*child)));
-
- child = child->getNextNode();
- }
- }
-
- if (strcasecmp(node->getName(), "ScriptParams") == 0)
- {
- for (int i = 0; node->getValue(i) != NULL; ++i)
- scriptParams.push_back(node->getValue(i));
- }
- node = node->getNextNode();
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#ifndef SETTINGS_IMPL_H
-#define SETTINGS_IMPL_H
-
-#include "stg/settings.h"
-#include "stg/common.h"
-#include "stg/module_settings.h"
-#include "stg/ref.h"
-
-#include <string>
-#include <vector>
-
-//-----------------------------------------------------------------------------
-enum DETAIL_STAT_PERIOD {
- dsPeriod_1,
- dsPeriod_1_2,
- dsPeriod_1_4,
- dsPeriod_1_6
-};
-//-----------------------------------------------------------------------------
-class STG_LOGGER;
-class DOTCONFDocumentNode;
-//-----------------------------------------------------------------------------
-class SETTINGS_IMPL : public SETTINGS {
-public:
- explicit SETTINGS_IMPL(const std::string &);
- SETTINGS_IMPL(const SETTINGS_IMPL & rhs);
- virtual ~SETTINGS_IMPL() {}
- SETTINGS_IMPL & operator=(const SETTINGS_IMPL &);
-
- int Reload() { return ReadSettings(); }
- int ReadSettings();
-
- std::string GetStrError() const { return strError; }
-
- int GetExecMsgKey() const { return stgExecMsgKey; }
- unsigned GetExecutersNum() const { return executersNum; }
- const std::string & GetDirName(size_t num) const { return dirName[num]; }
- const std::string & GetConfDir() const { return confDir; }
- const std::string & GetScriptsDir() const { return scriptsDir; }
- const std::string & GetRulesFileName() const { return rules; }
- const std::string & GetLogFileName() const { return logFile; }
- const std::string & GetPIDFileName() const { return pidFile; }
- unsigned GetDetailStatWritePeriod() const
- { return detailStatWritePeriod; }
- unsigned GetStatWritePeriod() const { return statWritePeriod * 60; }
- unsigned GetDayFee() const { return dayFee; }
- bool GetFullFee() const { return fullFee; }
- unsigned GetDayResetTraff() const { return dayResetTraff; }
- bool GetSpreadFee() const { return spreadFee; }
- bool GetFreeMbAllowInet() const { return freeMbAllowInet; }
- bool GetDayFeeIsLastDay() const { return dayFeeIsLastDay; }
- bool GetStopOnError() const { return stopOnError; }
- bool GetWriteFreeMbTraffCost() const
- { return writeFreeMbTraffCost; }
- bool GetShowFeeInCash() const { return showFeeInCash; }
- const std::string & GetMonitorDir() const { return monitorDir; }
- bool GetMonitoring() const { return monitoring; }
- unsigned GetMessageTimeout() const { return messageTimeout * 3600 * 24; }
- unsigned GetFeeChargeType() const { return feeChargeType; }
- bool GetReconnectOnTariffChange() const { return reconnectOnTariffChange; }
- bool GetDisableSessionLog() const { return disableSessionLog; }
- const std::vector<std::string> & GetFilterParamsLog() const { return filterParamsLog; }
-
- const std::string & GetModulesPath() const { return modulesPath; }
- const MODULE_SETTINGS & GetStoreModuleSettings() const
- { return storeModuleSettings; }
- const std::vector<MODULE_SETTINGS> & GetModulesSettings() const
- { return modulesSettings; }
- const std::vector<std::string> & GetScriptParams() const { return scriptParams; }
-
-private:
-
- static void ErrorCallback(void * data, const char * buf);
-
- std::string strError;
-
- //////////settings
- std::string modulesPath;
- std::vector<std::string> dirName;
- std::string confDir;
- std::string scriptsDir;
- std::string rules;
- std::string logFile;
- std::string pidFile;
- std::string monitorDir;
- std::vector<std::string> scriptParams;
- bool monitoring;
- unsigned detailStatWritePeriod;
- unsigned statWritePeriod;
- int stgExecMsgKey;
- unsigned executersNum;
- bool fullFee;
- unsigned dayFee;
- unsigned dayResetTraff;
- bool spreadFee;
- bool freeMbAllowInet;
- bool dayFeeIsLastDay;
- bool stopOnError;
- bool writeFreeMbTraffCost;
- bool showFeeInCash;
- unsigned messageTimeout;
- unsigned feeChargeType;
- bool reconnectOnTariffChange;
- bool disableSessionLog;
- std::vector<std::string> filterParamsLog;
-
- std::vector<MODULE_SETTINGS> modulesSettings;
- MODULE_SETTINGS storeModuleSettings;
- STG::RefWrapper<STG_LOGGER> logger;
-};
-//-----------------------------------------------------------------------------
-
-#endif
+++ /dev/null
-#include "stg_timer.h"
-
-#include "stg/common.h"
-
-#include <ctime>
-#include <cstring>
-#include <csignal>
-
-#include <pthread.h>
-
-void * StgTimer(void *);
-
-static int nonstop;
-static pthread_t thrStgTimer;
-static bool isTimerRunning = false;
-volatile time_t stgTime;
-
-#ifdef STG_TIMER_DEBUG
-const int TIME_SPEED = 1;
-/*
- 1 - 1x speed
- 2 - 2x speed
- 5 - 5x speed
- 10 - 10x speed
- */
-
-const int START_TIME = 2;
-/*
- 0 - as is
- 1 - start before new day (3 min before) 29.11.2005 23:57:00
- 2 - start before new month (3 min before) 30.11.2005 23:57:00
- */
-#endif
-
-//-----------------------------------------------------------------------------
-void * StgTimer(void *)
-{
-#ifdef STG_TIMER_DEBUG
-struct tm lt;
-memset(<, 0, sizeof(lt));
-
-lt.tm_year = 2016 - 1900; // 2005
-lt.tm_mon = 7 - 1; // Nov
-lt.tm_hour = 23; // 23 h
-lt.tm_min = 57; // 50 min
-lt.tm_sec = 0; // 00 sec
-lt.tm_isdst = -1;
-
-switch (START_TIME)
- {
- case 0:
- stgTime = time(NULL);
- break;
-
- case 1:
- lt.tm_mday = 29;
- stgTime = mktime(<);
- break;
-
- case 2:
- lt.tm_mday = 31;
- stgTime = mktime(<);
- break;
- }
-#else
-stgTime = time(NULL);
-#endif
-
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-nonstop = 1;
-isTimerRunning = true;
-while (nonstop)
- {
- #ifdef STG_TIMER_DEBUG
- struct timespec ts;
- if (TIME_SPEED == 1)
- {
- ts.tv_sec = 1;
- ts.tv_nsec = 0;
- }
- else
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 1000000000 / TIME_SPEED;
- }
- nanosleep(&ts, NULL);
- stgTime++;
- #else
- struct timespec ts = {0, 500000000};
- nanosleep(&ts, NULL);
- stgTime = time(NULL);
- #endif
- }
-isTimerRunning = false;
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int RunStgTimer()
-{
-static int a = 0;
-isTimerRunning = false;
-
-if (a == 0)
- if (pthread_create(&thrStgTimer, NULL, &StgTimer, NULL))
- {
- isTimerRunning = false;
- return -1;
- }
-
-a = 1;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void StopStgTimer()
-{
-nonstop = 0;
-pthread_join(thrStgTimer, NULL); // Cleanup thread resources
-printfd(__FILE__, "STG_TIMER stopped\n");
-}
-//-----------------------------------------------------------------------------
-bool IsStgTimerRunning()
-{
-return isTimerRunning;
-}
-//-----------------------------------------------------------------------------
-int stgUsleep(unsigned long t)
-{
-#ifdef STG_TIMER_DEBUG
-struct timespec ts = {static_cast<time_t>((t / TIME_SPEED) / 1000000), static_cast<long>(((t / TIME_SPEED) % 1000000) * 1000)};
-return nanosleep(&ts, NULL);
-#else
-struct timespec ts = {static_cast<time_t>(t / 1000000), static_cast<long>((t % 1000000) * 1000)};
-return nanosleep(&ts, NULL);
-#endif
-}
-//-----------------------------------------------------------------------------
-void WaitTimer()
-{
- for (int i = 0; i < 5 && !isTimerRunning; i++)
- stgUsleep(200000);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
- /*
- $Revision: 1.9 $
- $Date: 2010/11/03 10:37:52 $
- $Author: faust $
- */
-
-#ifndef STG_TIMER_H
-#define STG_TIMER_H
-
-#include <ctime>
-
-extern volatile time_t stgTime;
-int RunStgTimer();
-void StopStgTimer();
-void WaitTimer();
-bool IsStgTimerRunning();
-int stgUsleep(unsigned long t);
-
-#endif //STG_TIMER_H
-
-
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.6 $
- $Date: 2010/03/04 12:24:19 $
- $Author: faust $
- */
-
-/*
- * An implementation of RAII store plugin loader
- */
-
-#include <dlfcn.h>
-
-#include "stg/common.h"
-#include "stg/store.h"
-#include "store_loader.h"
-#include "settings_impl.h"
-
-STORE_LOADER::STORE_LOADER(const SETTINGS_IMPL & settings)
- : isLoaded(false),
- handle(NULL),
- plugin(NULL),
- errorStr(),
- storeSettings(settings.GetStoreModuleSettings()),
- pluginFileName(settings.GetModulesPath() + "/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 = reinterpret_cast<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()
-{
-printfd(__FILE__, "STORE_LOADER::Unload()\n");
-if (!isLoaded)
- {
- return true;
- }
-
-delete plugin;
-
-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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-/*
- $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 "stg/module_settings.h"
-#include "stg/noncopyable.h"
-
-#include <string>
-
-class STORE;
-class SETTINGS_IMPL;
-
-class STORE_LOADER : private NONCOPYABLE {
-public:
- explicit STORE_LOADER(const SETTINGS_IMPL & settings);
- ~STORE_LOADER();
-
- bool Load();
- bool Unload();
-
- STORE & GetStore() { return *plugin; }
-
- const std::string & GetStrError() const { return errorStr; }
-
-private:
- STORE_LOADER(const STORE_LOADER & rvalue);
- STORE_LOADER & operator=(const STORE_LOADER & rvalue);
-
- bool isLoaded;
- void * handle;
- STORE * plugin;
- std::string errorStr;
- MODULE_SETTINGS storeSettings;
- std::string pluginFileName;
-};
-
-#endif
+++ /dev/null
-/*
- * 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: 07.11.2007
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.11 $
- $Date: 2010/10/07 16:57:21 $
- $Author: faust $
- */
-
-#include "tariff_impl.h"
-
-#include "stg_timer.h"
-#include "stg/common.h"
-
-#include <ctime>
-#include <algorithm> // std::max
-
-//-----------------------------------------------------------------------------
-TARIFF_IMPL & TARIFF_IMPL::operator=(const TARIFF_DATA & td)
-{
-tariffData = td;
-return *this;
-}
-//-----------------------------------------------------------------------------
-double TARIFF_IMPL::GetPriceWithTraffType(uint64_t up,
- uint64_t down,
- int dir,
- time_t t) const
-{
-return GetPriceWithoutFreeMb(dir, GetTraffByType(up, down) / (1024 * 1024), t);
-}
-//-----------------------------------------------------------------------------
-int64_t TARIFF_IMPL::GetTraffByType(uint64_t up, uint64_t down) const
-{
-switch (tariffData.tariffConf.traffType)
- {
- case TRAFF_UP:
- return up;
-
- case TRAFF_DOWN:
- return down;
-
- case TRAFF_MAX:
- return std::max(up, down);
-
- default: //TRAFF_UP_DOWN:
- return up + down;
- }
-}
-//-----------------------------------------------------------------------------
-int TARIFF_IMPL::GetThreshold(int dir) const
-{
- return tariffData.dirPrice[dir].threshold;
-}
-//-----------------------------------------------------------------------------
-void TARIFF_IMPL::Print() const
-{
-printfd(__FILE__, "Traiff name: %s\n", tariffData.tariffConf.name.c_str());
-}
-//-----------------------------------------------------------------------------
-int TARIFF_IMPL::Interval(int dir, time_t t) const
-{
-// Start of the day (and end of the night) in sec from 00:00:00
-int s1 = tariffData.dirPrice[dir].hDay * 3600 +
- tariffData.dirPrice[dir].mDay * 60;
-// Start of the night (and end of the day) in sec from 00:00:00
-int s2 = tariffData.dirPrice[dir].hNight * 3600 +
- tariffData.dirPrice[dir].mNight * 60;
-
-struct tm * lt;
-
-lt = localtime(&t);
-
-// Position of time t in sec from 00:00:00
-// Ignoring seconds due to minute precision
-int lts = lt->tm_hour * 3600 + lt->tm_min * 60;
-
-if (s1 < s2)
- {
- // Normal situation (00:00:00 is a night)
- if (lts > s1 && lts < s2)
- return TARIFF_DAY;
- else
- return TARIFF_NIGHT;
- }
-else
- {
- // Not so common but possible situation (00:00:00 is a day)
- if (lts < s1 && lts > s2)
- return TARIFF_NIGHT;
- else
- return TARIFF_DAY;
- }
-}
-//-----------------------------------------------------------------------------
-double TARIFF_IMPL::GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const
-{
-int interval = Interval(dir, t);
-
-/*
- * 0011 - NB
- * *01* - NA
- * 0**1 - DB
- * **** - DA
- */
-
-bool nd = tariffData.dirPrice[dir].noDiscount;
-bool sp = tariffData.dirPrice[dir].singlePrice;
-bool th = (interval == TARIFF_NIGHT);
-bool tr = (mb > tariffData.dirPrice[dir].threshold);
-
-if (!nd && !sp && th && tr)
- return tariffData.dirPrice[dir].priceNightB;
-else if (!nd && tr)
- return tariffData.dirPrice[dir].priceDayB;
-else if (!sp && th)
- return tariffData.dirPrice[dir].priceNightA;
-else
- return tariffData.dirPrice[dir].priceDayA;
-}
-//-----------------------------------------------------------------------------
-std::string TARIFF_IMPL::TariffChangeIsAllowed(const TARIFF & to, time_t currentTime) const
-{
-time_t timeout = GetChangePolicyTimeout();
-if (currentTime > timeout && timeout != 0)
- return "";
-switch (GetChangePolicy())
- {
- case TARIFF::ALLOW:
- return "";
- case TARIFF::TO_CHEAP:
- if (to.GetFee() < GetFee())
- return "";
- else
- return "New tariff '" + to.GetName() + "' is more expensive than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
- case TARIFF::TO_EXPENSIVE:
- if (to.GetFee() >= GetFee())
- return "";
- else
- return "New tariff '" + to.GetName() + "' is more cheap than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
- case TARIFF::DENY:
- return "Current tariff '" + GetName() + "', new tariff '" + to.GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
- }
-return "";
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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: 07.11.2007
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.9 $
- $Date: 2010/10/07 17:53:39 $
- $Author: faust $
- */
-
-#ifndef TARIFF_IMPL_H
-#define TARIFF_IMPL_H
-
-#include "stg/tariff.h"
-#include "stg/os_int.h"
-#include "stg/tariff_conf.h"
-
-#include <string>
-#include <list>
-
-#include <ctime>
-
-#define TARIFF_DAY 0
-#define TARIFF_NIGHT 1
-
-class TARIFF_IMPL : public TARIFF {
-public:
- explicit TARIFF_IMPL(const std::string & name)
- : TARIFF(),
- tariffData(name)
- {}
- explicit TARIFF_IMPL(const TARIFF_DATA & td)
- : TARIFF(),
- tariffData(td)
- {}
- virtual ~TARIFF_IMPL() {}
-
- double GetPriceWithTraffType(uint64_t up,
- uint64_t down,
- int dir,
- time_t t) const;
- double GetFreeMb() const { return tariffData.tariffConf.free; }
- double GetPassiveCost() const { return tariffData.tariffConf.passiveCost; }
- double GetFee() const { return tariffData.tariffConf.fee; }
- double GetFree() const { return tariffData.tariffConf.free; }
- PERIOD GetPeriod() const { return tariffData.tariffConf.period; }
- CHANGE_POLICY GetChangePolicy() const { return tariffData.tariffConf.changePolicy; }
- time_t GetChangePolicyTimeout() const { return tariffData.tariffConf.changePolicyTimeout; }
-
- void Print() const;
-
- const std::string & GetName() const { return tariffData.tariffConf.name; }
- void SetName(const std::string & name) { tariffData.tariffConf.name = name; }
-
- int GetTraffType() const { return tariffData.tariffConf.traffType; }
- int64_t GetTraffByType(uint64_t up, uint64_t down) const;
- int GetThreshold(int dir) const;
- const TARIFF_DATA & GetTariffData() const { return tariffData; }
-
- TARIFF_IMPL & operator=(const TARIFF_DATA & td);
- bool operator==(const TARIFF_IMPL & rhs) const { return GetName() == rhs.GetName(); }
- bool operator!=(const TARIFF_IMPL & rhs) const { return GetName() != rhs.GetName(); }
- std::string TariffChangeIsAllowed(const TARIFF & to, time_t currentTime) const;
-
-private:
- TARIFF_DATA tariffData;
-
- double GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const;
- int Interval(int dir, time_t t) const;
-};
-
-#endif
+++ /dev/null
-/*
- * 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: 07.11.2007
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.9 $
- $Date: 2010/10/07 18:43:21 $
- $Author: faust $
- */
-
-#include <cassert>
-#include <algorithm>
-#include <vector>
-
-#include "stg/locker.h"
-#include "stg/logger.h"
-#include "stg/store.h"
-#include "stg/admin.h"
-#include "tariffs_impl.h"
-
-//-----------------------------------------------------------------------------
-TARIFFS_IMPL::TARIFFS_IMPL(STORE * st)
- : TARIFFS(),
- tariffs(),
- store(st),
- WriteServLog(GetStgLogger()),
- mutex(),
- strError(),
- noTariff(NO_TARIFF_NAME),
- onAddNotifiers(),
- onDelNotifiers()
-{
-pthread_mutex_init(&mutex, NULL);
-ReadTariffs();
-}
-//-----------------------------------------------------------------------------
-TARIFFS_IMPL::~TARIFFS_IMPL()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int TARIFFS_IMPL::ReadTariffs()
-{
-STG_LOCKER lock(&mutex);
-
-std::vector<std::string> tariffsList;
-if (store->GetTariffsList(&tariffsList))
- {
- WriteServLog("Cannot get tariffs list.");
- WriteServLog("%s", store->GetStrError().c_str());
- }
-
-Tariffs::size_type tariffsNum = tariffsList.size();
-
-for (Tariffs::size_type i = 0; i < tariffsNum; i++)
- {
- TARIFF_DATA td;
- if (store->RestoreTariff(&td, tariffsList[i]))
- {
- WriteServLog("Cannot read tariff %s.", tariffsList[i].c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
- tariffs.push_back(TARIFF_IMPL(td));
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-size_t TARIFFS_IMPL::Count() const
-{
-STG_LOCKER lock(&mutex);
-return tariffs.size();
-}
-//-----------------------------------------------------------------------------
-const TARIFF * TARIFFS_IMPL::FindByName(const std::string & name) const
-{
-if (name == NO_TARIFF_NAME)
- return &noTariff;
-
-STG_LOCKER lock(&mutex);
-std::list<TARIFF_IMPL>::const_iterator ti;
-ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
-
-if (ti != tariffs.end())
- return &(*ti);
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int TARIFFS_IMPL::Chg(const TARIFF_DATA & td, const ADMIN * admin)
-{
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->tariffChg)
- {
- std::string s = admin->GetLogStr() + " Change tariff \'"
- + td.tariffConf.name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-STG_LOCKER lock(&mutex);
-
-std::list<TARIFF_IMPL>::iterator ti;
-ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(td.tariffConf.name));
-
-if (ti == tariffs.end())
- {
- strError = "Tariff \'" + td.tariffConf.name + "\' cannot be changed. Tariff does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
-*ti = td;
-
-if (store->SaveTariff(td, td.tariffConf.name))
- {
- std::string error = "Tariff " + td.tariffConf.name + " writing error. " + store->GetStrError();
- WriteServLog(error.c_str());
- return -1;
- }
-
-WriteServLog("%s Tariff \'%s\' changed.",
- admin->GetLogStr().c_str(), td.tariffConf.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TARIFFS_IMPL::Del(const std::string & name, const ADMIN * admin)
-{
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->tariffChg)
- {
- std::string s = admin->GetLogStr() + " Delete tariff \'"
- + name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
-TARIFF_DATA td;
-
- {
- STG_LOCKER lock(&mutex);
-
- std::list<TARIFF_IMPL>::iterator ti;
- ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
-
- if (ti == tariffs.end())
- {
- strError = "Tariff \'" + name + "\' cannot be deleted. Tariff does not exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
- if (store->DelTariff(name))
- {
- WriteServLog("Cannot delete tariff %s.", name.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
-
- td = ti->GetTariffData();
-
- tariffs.erase(ti);
- }
-
-std::set<NOTIFIER_BASE<TARIFF_DATA> *>::iterator ni = onDelNotifiers.begin();
-while (ni != onDelNotifiers.end())
- {
- (*ni)->Notify(td);
- ++ni;
- }
-
-WriteServLog("%s Tariff \'%s\' deleted.",
- admin->GetLogStr().c_str(),
- name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TARIFFS_IMPL::Add(const std::string & name, const ADMIN * admin)
-{
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->tariffChg)
- {
- std::string s = admin->GetLogStr() + " Add tariff \'"
- + name + "\'. Access denied.";
- strError = "Access denied.";
- WriteServLog(s.c_str());
- return -1;
- }
-
- {
- STG_LOCKER lock(&mutex);
-
- std::list<TARIFF_IMPL>::iterator ti;
- ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
-
- if (ti != tariffs.end())
- {
- strError = "Tariff \'" + name + "\' cannot be added. Tariff already exist.";
- WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
- return -1;
- }
-
- tariffs.push_back(TARIFF_IMPL(name));
- }
-
-if (store->AddTariff(name) < 0)
- {
- strError = "Tariff " + name + " adding error. " + store->GetStrError();
- WriteServLog(strError.c_str());
- return -1;
- }
-
-// Fire all "on add" notifiers
-std::set<NOTIFIER_BASE<TARIFF_DATA> *>::iterator ni = onAddNotifiers.begin();
-while (ni != onAddNotifiers.end())
- {
- (*ni)->Notify(tariffs.back().GetTariffData());
- ++ni;
- }
-
-WriteServLog("%s Tariff \'%s\' added.",
- admin->GetLogStr().c_str(), name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void TARIFFS_IMPL::GetTariffsData(std::list<TARIFF_DATA> * tdl) const
-{
-assert(tdl != NULL && "Tariffs data list is not null");
-STG_LOCKER lock(&mutex);
-
-Tariffs::const_iterator it = tariffs.begin();
-for (; it != tariffs.end(); ++it)
- {
- tdl->push_back(it->GetTariffData());
- }
-}
-//-----------------------------------------------------------------------------
-void TARIFFS_IMPL::AddNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void TARIFFS_IMPL::DelNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void TARIFFS_IMPL::AddNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void TARIFFS_IMPL::DelNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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: 07.11.2007
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#ifndef TARIFFS_IMPL_H
-#define TARIFFS_IMPL_H
-
-#include "stg/tariff.h"
-#include "stg/tariffs.h"
-#include "stg/tariff_conf.h"
-#include "tariff_impl.h"
-
-#include <string>
-#include <list>
-#include <set>
-
-#include <pthread.h>
-
-#define TARIFF_DAY 0
-#define TARIFF_NIGHT 1
-
-class STORE;
-class STG_LOGGER;
-class ADMIN;
-
-class TARIFFS_IMPL : public TARIFFS {
-public:
- typedef std::list<TARIFF_IMPL> Tariffs;
-
- explicit TARIFFS_IMPL(STORE * store);
- virtual ~TARIFFS_IMPL();
- int ReadTariffs ();
- const TARIFF * FindByName(const std::string & name) const;
- const TARIFF * GetNoTariff() const { return &noTariff; }
- size_t Count() const;
- int Del(const std::string & name, const ADMIN * admin);
- int Add(const std::string & name, const ADMIN * admin);
- int Chg(const TARIFF_DATA & td, const ADMIN * admin);
-
- void AddNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * notifier);
- void DelNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * notifier);
-
- void AddNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * notifier);
- void DelNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * notifier);
-
- void GetTariffsData(std::list<TARIFF_DATA> * tdl) const;
-
- const std::string & GetStrError() const { return strError; }
-
-private:
- TARIFFS_IMPL(const TARIFFS_IMPL & rvalue);
- TARIFFS_IMPL & operator=(const TARIFFS_IMPL & rvalue);
-
- Tariffs tariffs;
- STORE * store;
- STG_LOGGER & WriteServLog;
- mutable pthread_mutex_t mutex;
- std::string strError;
- TARIFF_IMPL noTariff;
-
- std::set<NOTIFIER_BASE<TARIFF_DATA>*> onAddNotifiers;
- std::set<NOTIFIER_BASE<TARIFF_DATA>*> onDelNotifiers;
-};
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.58 $
- $Date: 2010/11/03 11:28:07 $
- $Author: faust $
- */
-
-/* inet_aton */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <csignal>
-#include <cassert>
-#include <cstdio> // fopen and similar
-#include <cstdlib> // strtol
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/const.h" // MONITOR_TIME_DELAY_SEC
-#include "traffcounter_impl.h"
-#include "stg_timer.h"
-#include "users_impl.h"
-
-#define FLUSH_TIME (10)
-#define REMOVE_TIME (31)
-
-const char protoName[PROTOMAX][8] =
-{"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
-
-enum protoNum
-{
-tcp = 0, udp, icmp, tcp_udp, all
-};
-
-//-----------------------------------------------------------------------------
-TRAFFCOUNTER_IMPL::TRAFFCOUNTER_IMPL(USERS_IMPL * u, const std::string & fn)
- : WriteServLog(GetStgLogger()),
- rulesFileName(fn),
- monitoring(false),
- touchTimeP(stgTime - MONITOR_TIME_DELAY_SEC),
- users(u),
- running(false),
- stopped(true),
- addUserNotifier(*this),
- delUserNotifier(*this)
-{
-for (int i = 0; i < DIR_NUM; i++)
- strprintf(&dirName[i], "DIR%d", i);
-
-dirName[DIR_NUM] = "NULL";
-
-users->AddNotifierUserAdd(&addUserNotifier);
-users->AddNotifierUserDel(&delUserNotifier);
-
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-TRAFFCOUNTER_IMPL::~TRAFFCOUNTER_IMPL()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int TRAFFCOUNTER_IMPL::Start()
-{
-STG_LOCKER lock(&mutex);
-
-if (!stopped)
- return 0;
-
-if (ReadRules())
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot read rules\n");
- WriteServLog("TRAFFCOUNTER: Cannot read rules.");
- return -1;
- }
-
-printfd(__FILE__, "TRAFFCOUNTER::Start()\n");
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-USER_IMPL * u;
-
-while (users->SearchNext(h, &u) == 0)
- SetUserNotifiers(u);
-users->CloseSearch(h);
-
-running = true;
-if (pthread_create(&thread, NULL, Run, this))
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot start thread\n");
- WriteServLog("TRAFFCOUNTER: Error: Cannot start thread.");
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TRAFFCOUNTER_IMPL::Stop()
-{
-if (stopped)
- return 0;
-
-running = false;
-
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-USER_IMPL * u;
-while (users->SearchNext(h, &u) == 0)
- UnSetUserNotifiers(u);
-users->CloseSearch(h);
-
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (int i = 0; i < 25 && !stopped; i++)
- {
- nanosleep(&ts, NULL);
- }
-
-if (!stopped)
- return -1;
-
-printfd(__FILE__, "TRAFFCOUNTER::Stop()\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * TRAFFCOUNTER_IMPL::Run(void * data)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-TRAFFCOUNTER_IMPL * tc = static_cast<TRAFFCOUNTER_IMPL *>(data);
-tc->stopped = false;
-int c = 0;
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-struct timespec ts = {0, 500000000};
-while (tc->running)
- {
- nanosleep(&ts, 0);
- if (!tc->running)
- {
- tc->FlushAndRemove();
- break;
- }
-
- if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
- {
- std::string monFile(tc->monitorDir + "/traffcounter_r");
- printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
- touchTime = stgTime;
- TouchFile(monFile);
- }
-
- if (++c % FLUSH_TIME == 0)
- tc->FlushAndRemove();
- }
-
-tc->stopped = true;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::Process(const RAW_PACKET & rawPacket)
-{
-if (!running)
- return;
-
-if (monitoring && (touchTimeP + MONITOR_TIME_DELAY_SEC <= stgTime))
- {
- std::string monFile = monitorDir + "/traffcounter_p";
- printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", monitoring, monFile.c_str());
- touchTimeP = stgTime;
- TouchFile(monFile);
- }
-
-STG_LOCKER lock(&mutex);
-
-//printfd(__FILE__, "TRAFFCOUNTER::Process()\n");
-//TODO replace find with lower_bound.
-
-// Searching a new packet in a tree.
-pp_iter pi = packets.find(rawPacket);
-
-// Packet found - update length and time
-if (pi != packets.end())
- {
- pi->second.lenU += rawPacket.GetLen();
- pi->second.lenD += rawPacket.GetLen();
- pi->second.updateTime = stgTime;
- /*printfd(__FILE__, "=============================\n");
- printfd(__FILE__, "Packet found!\n");
- printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
- printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
- printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
- printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
- printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
- printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
- printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
- printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
- printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
- printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
- printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
- printfd(__FILE__, "=============================\n");*/
- return;
- }
-
-PACKET_EXTRA_DATA ed;
-
-// Packet not found - add new packet
-
-ed.updateTime = stgTime;
-ed.flushTime = stgTime;
-
-/*
- userU is that whose user_ip == packet_ip_src
- userD is that whose user_ip == packet_ip_dst
- */
-
-uint32_t ipU = rawPacket.GetSrcIP();
-uint32_t ipD = rawPacket.GetDstIP();
-
-// Searching users with such IP
-if (users->FindByIPIdx(ipU, &ed.userU) == 0)
- {
- ed.userUPresent = true;
- }
-
-if (users->FindByIPIdx(ipD, &ed.userD) == 0)
- {
- ed.userDPresent = true;
- }
-
-if (ed.userUPresent ||
- ed.userDPresent)
- {
- DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
-
- ed.lenD = ed.lenU = rawPacket.GetLen();
-
- //TODO use result of lower_bound to inserting new record
-
- // Adding packet to a tree.
- std::pair<pp_iter, bool> insertResult = packets.insert(std::make_pair(rawPacket, ed));
- pp_iter newPacket = insertResult.first;
-
- // Adding packet reference to an IP index.
- ip2packets.insert(std::make_pair(ipU, newPacket));
- ip2packets.insert(std::make_pair(ipD, newPacket));
- }
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::FlushAndRemove()
-{
-STG_LOCKER lock(&mutex);
-
-Packets::size_type oldPacketsSize = packets.size();
-Index::size_type oldIp2packetsSize = ip2packets.size();
-
-pp_iter pi;
-pi = packets.begin();
-Packets newPackets;
-ip2packets.erase(ip2packets.begin(), ip2packets.end());
-while (pi != packets.end())
- {
- //Flushing
- if (stgTime - pi->second.flushTime > FLUSH_TIME)
- {
- if (pi->second.userUPresent)
- {
- //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
-
- // Add stat
- if (pi->second.dirU < DIR_NUM)
- {
- #ifdef TRAFF_STAT_WITH_PORTS
- pi->second.userU->AddTraffStatU(pi->second.dirU,
- pi->first.GetDstIP(),
- pi->first.GetDstPort(),
- pi->second.lenU);
- #else
- pi->second.userU->AddTraffStatU(pi->second.dirU,
- pi->first.GetDstIP(),
- pi->second.lenU);
- #endif
- }
-
- pi->second.lenU = 0;
- pi->second.flushTime = stgTime;
- }
-
- if (pi->second.userDPresent)
- {
- //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
-
- // Add stat
- if (pi->second.dirD < DIR_NUM)
- {
- #ifdef TRAFF_STAT_WITH_PORTS
- pi->second.userD->AddTraffStatD(pi->second.dirD,
- pi->first.GetSrcIP(),
- pi->first.GetSrcPort(),
- pi->second.lenD);
- #else
- pi->second.userD->AddTraffStatD(pi->second.dirD,
- pi->first.GetSrcIP(),
- pi->second.lenD);
- #endif
- }
-
- pi->second.lenD = 0;
- pi->second.flushTime = stgTime;
- }
- }
-
- if (stgTime - pi->second.updateTime < REMOVE_TIME)
- {
- std::pair<pp_iter, bool> res = newPackets.insert(*pi);
- if (res.second)
- {
- ip2packets.insert(std::make_pair(pi->first.GetSrcIP(), res.first));
- ip2packets.insert(std::make_pair(pi->first.GetDstIP(), res.first));
- }
- }
- ++pi;
- }
-swap(packets, newPackets);
-printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
- packets.size(),
- oldPacketsSize - packets.size(),
- ip2packets.size(),
- oldIp2packetsSize - ip2packets.size());
-
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::AddUser(USER_IMPL * user)
-{
-printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
-uint32_t uip = user->GetCurrIP();
-std::pair<ip2p_iter, ip2p_iter> pi;
-
-STG_LOCKER lock(&mutex);
-// Find all packets with IP belongs to this user
-pi = ip2packets.equal_range(uip);
-
-while (pi.first != pi.second)
- {
- if (pi.first->second->first.GetSrcIP() == uip)
- {
- assert((!pi.first->second->second.userUPresent ||
- pi.first->second->second.userU == user) &&
- "U user present but it's not current user");
-
- pi.first->second->second.lenU = 0;
- pi.first->second->second.userU = user;
- pi.first->second->second.userUPresent = true;
- }
-
- if (pi.first->second->first.GetDstIP() == uip)
- {
- assert((!pi.first->second->second.userDPresent ||
- pi.first->second->second.userD == user) &&
- "D user present but it's not current user");
-
- pi.first->second->second.lenD = 0;
- pi.first->second->second.userD = user;
- pi.first->second->second.userDPresent = true;
- }
-
- ++pi.first;
- }
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::DelUser(uint32_t uip)
-{
-printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
-std::pair<ip2p_iter, ip2p_iter> pi;
-
-STG_LOCKER lock(&mutex);
-pi = ip2packets.equal_range(uip);
-
-while (pi.first != pi.second)
- {
- if (pi.first->second->first.GetSrcIP() == uip)
- {
- if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
- {
- #ifdef TRAFF_STAT_WITH_PORTS
- pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
- pi.first->second->first.GetDstIP(),
- pi.first->second->first.GetDstPort(),
- pi.first->second->second.lenU);
- #else
- pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
- pi.first->second->first.GetDstIP(),
- pi.first->second->second.lenU);
- #endif
- }
- pi.first->second->second.userUPresent = false;
- }
-
- if (pi.first->second->first.GetDstIP() == uip)
- {
- if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
- {
- #ifdef TRAFF_STAT_WITH_PORTS
- pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
- pi.first->second->first.GetSrcIP(),
- pi.first->second->first.GetSrcPort(),
- pi.first->second->second.lenD);
- #else
- pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
- pi.first->second->first.GetSrcIP(),
- pi.first->second->second.lenD);
- #endif
- }
-
- pi.first->second->second.userDPresent = false;
- }
-
- ++pi.first;
- }
-
-ip2packets.erase(pi.first, pi.second);
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::SetUserNotifiers(USER_IMPL * user)
-{
-// Adding user. Adding notifiers to user.
-TRF_IP_BEFORE ipBNotifier(*this, user);
-ipBeforeNotifiers.push_front(ipBNotifier);
-user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
-
-TRF_IP_AFTER ipANotifier(*this, user);
-ipAfterNotifiers.push_front(ipANotifier);
-user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::UnSetUserNotifiers(USER_IMPL * user)
-{
-// Removing user. Removing notifiers from user.
-std::list<TRF_IP_BEFORE>::iterator bi;
-std::list<TRF_IP_AFTER>::iterator ai;
-
-bi = ipBeforeNotifiers.begin();
-while (bi != ipBeforeNotifiers.end())
- {
- if (user->GetLogin() == bi->GetUser()->GetLogin())
- {
- user->DelCurrIPBeforeNotifier(&(*bi));
- ipBeforeNotifiers.erase(bi);
- break;
- }
- ++bi;
- }
-
-ai = ipAfterNotifiers.begin();
-while (ai != ipAfterNotifiers.end())
- {
- if (user->GetLogin() == ai->GetUser()->GetLogin())
- {
- user->DelCurrIPAfterNotifier(&(*ai));
- ipAfterNotifiers.erase(ai);
- break;
- }
- ++ai;
- }
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::DeterminateDir(const RAW_PACKET & packet,
- int * dirU, // Direction for incoming packet
- int * dirD) const // Direction for outgoing packet
-{
-bool addrMatchU = false;
-bool portMatchU = false;
-bool addrMatchD = false;
-bool portMatchD = false;
-bool foundU = false; // Was rule for U found ?
-bool foundD = false; // Was rule for D found ?
-//printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
-
-enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
-
-std::list<RULE>::const_iterator ln;
-ln = rules.begin();
-
-while (ln != rules.end())
- {
- if (!foundU)
- {
- portMatchU = false;
-
- switch (ln->proto)
- {
- case all:
- portMatchU = true;
- break;
-
- case icmp:
- portMatchU = (packet.GetProto() == ICMP_RPOTO);
- break;
-
- case tcp_udp:
- if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
- portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
- break;
-
- case tcp:
- if (packet.GetProto() == TCP_PROTO)
- portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
- break;
-
- case udp:
- if (packet.GetProto() == UDP_PROTO)
- portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
- break;
-
- default:
- printfd(__FILE__, "Error! Incorrect rule!\n");
- break;
- }
-
- addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
-
- if (!foundU && addrMatchU && portMatchU)
- {
- foundU = true;
- *dirU = ln->dir;
- //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
- }
-
- } //if (!foundU)
-
- if (!foundD)
- {
- portMatchD = false;
-
- switch (ln->proto)
- {
- case all:
- portMatchD = true;
- break;
-
- case icmp:
- portMatchD = (packet.GetProto() == ICMP_RPOTO);
- break;
-
- case tcp_udp:
- if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
- portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
- break;
-
- case tcp:
- if (packet.GetProto() == TCP_PROTO)
- portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
- break;
-
- case udp:
- if (packet.GetProto() == UDP_PROTO)
- portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
- break;
-
- default:
- printfd(__FILE__, "Error! Incorrect rule!\n");
- break;
- }
-
- addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
-
- if (!foundD && addrMatchD && portMatchD)
- {
- foundD = true;
- *dirD = ln->dir;
- //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
- }
- } //if (!foundD)
-
- ++ln;
- } //while (ln != rules.end())
-
-if (!foundU)
- *dirU = DIR_NUM;
-
-if (!foundD)
- *dirD = DIR_NUM;
-}
-//-----------------------------------------------------------------------------
-bool TRAFFCOUNTER_IMPL::ReadRules(bool test)
-{
-//printfd(__FILE__, "TRAFFCOUNTER::ReadRules()\n");
-
-RULE rul;
-FILE * f;
-char str[1024];
-char tp[100]; // protocol
-char ta[100]; // address
-char td[100]; // target direction
-int r;
-int lineNumber = 0;
-f = fopen(rulesFileName.c_str(), "rt");
-
-if (!f)
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - File '%s' cannot be opened.\n", rulesFileName.c_str());
- WriteServLog("File '%s' cannot be oppened.", rulesFileName.c_str());
- return true;
- }
-
-while (fgets(str, 1023, f))
- {
- lineNumber++;
- if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
- {
- continue;
- }
-
- r = sscanf(str,"%99s %99s %99s", tp, ta, td);
- if (r != 3)
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. There must be 3 parameters.\n", rulesFileName.c_str(), lineNumber);
- WriteServLog("Error in file '%s' at line %d. There must be 3 parameters.", rulesFileName.c_str(), lineNumber);
- fclose(f);
- return true;
- }
-
- rul.proto = 0xff;
- rul.dir = 0xff;
-
- for (uint8_t i = 0; i < PROTOMAX; i++)
- {
- if (strcasecmp(tp, protoName[i]) == 0)
- rul.proto = i;
- }
-
- for (uint32_t i = 0; i < DIR_NUM + 1; i++)
- {
- if (td == dirName[i])
- rul.dir = i;
- }
-
- if (rul.dir == 0xff || rul.proto == 0xff)
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d.\n", rulesFileName.c_str(), lineNumber);
- WriteServLog("Error in file %s. Line %d.",
- rulesFileName.c_str(), lineNumber);
- fclose(f);
- return true;
- }
-
- if (ParseAddress(ta, &rul) != 0)
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. Error in adress.\n", rulesFileName.c_str(), lineNumber);
- WriteServLog("Error in file %s. Error in adress. Line %d.",
- rulesFileName.c_str(), lineNumber);
- fclose(f);
- return true;
- }
- if (!test)
- rules.push_back(rul);
- }
-
-fclose(f);
-
-// Adding lastest rule: ALL 0.0.0.0/0 NULL
-rul.dir = DIR_NUM; //NULL
-rul.ip = 0; //0.0.0.0
-rul.mask = 0;
-rul.port1 = 0;
-rul.port2 = 65535;
-rul.proto = all;
-
-if (!test)
- rules.push_back(rul);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int TRAFFCOUNTER_IMPL::Reload()
-{
-STG_LOCKER lock(&mutex);
-
-if (ReadRules(true))
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() - Failed to reload rules.\n");
- WriteServLog("TRAFFCOUNTER: Cannot reload rules. Errors found.");
- return -1;
- }
-
-FreeRules();
-ReadRules();
-printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() - Reloaded rules successfully.\n");
-WriteServLog("TRAFFCOUNTER: Reloaded rules successfully.");
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool TRAFFCOUNTER_IMPL::ParseAddress(const char * ta, RULE * rule) const
-{
-char addr[50], mask[20], port1[20], port2[20], ports[40];
-
-size_t len = strlen(ta);
-char n = 0;
-size_t i, p;
-memset(addr, 0, sizeof(addr));
-for (i = 0; i < len; i++)
- {
- if (ta[i] == '/' || ta[i] == ':')
- {
- addr[i] = 0;
- n = ta[i];
- break;
- }
- addr[i] = ta[i];
- n = 0;
- }
-addr[i + 1] = 0;
-p = i + 1;
-
-if (n == '/')
- {
- // mask
- for (; i < len; i++)
- {
- if (ta[i] == ':')
- {
- mask[i - p] = 0;
- n = ':';
- break;
- }
- mask[i - p] = ta[i];
- }
- mask[i - p] = 0;
- }
-else
- {
- strcpy(mask, "32");
- }
-
-p = i + 1;
-i++;
-
-if (n == ':')
- {
- // port
- if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - No ports specified for this protocol.\n");
- WriteServLog("No ports specified for this protocol.");
- return true;
- }
-
- for (; i < len; i++)
- ports[i - p] = ta[i];
-
- ports[i - p] = 0;
- }
-else
- {
- strcpy(ports, "0-65535");
- }
-
-char *sss;
-char pts[100];
-strcpy(pts, ports);
-
-if ((sss = strchr(ports, '-')) != NULL)
- {
- strncpy(port1, ports, int(sss-ports));
- port1[int(sss - ports)] = 0;
- strcpy(port2, sss + 1);
- }
-else
- {
- strcpy(port1, ports);
- strcpy(port2, ports);
- }
-
-// Convert strings to mask, ports and IP
-uint16_t prt1, prt2, msk;
-struct in_addr ipaddr;
-char *res;
-
-msk = static_cast<uint16_t>(strtol(mask, &res, 10));
-if (*res != 0)
- return true;
-
-prt1 = static_cast<uint16_t>(strtol(port1, &res, 10));
-if (*res != 0)
- return true;
-
-prt2 = static_cast<uint16_t>(strtol(port2, &res, 10));
-if (*res != 0)
- return true;
-
-int r = inet_aton(addr, &ipaddr);
-if (r == 0)
- return true;
-
-rule->ip = ipaddr.s_addr;
-rule->mask = CalcMask(msk);
-
-if ((ipaddr.s_addr & rule->mask) != ipaddr.s_addr)
- {
- printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - Address does'n match mask.\n");
- WriteServLog("Address does'n match mask.");
- return true;
- }
-
-rule->port1 = prt1;
-rule->port2 = prt2;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-uint32_t TRAFFCOUNTER_IMPL::CalcMask(uint32_t msk) const
-{
-if (msk >= 32) return 0xFFffFFff;
-if (msk == 0) return 0;
-return htonl(0xFFffFFff << (32 - msk));
-}
-//---------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::FreeRules()
-{
-rules.clear();
-}
-//-----------------------------------------------------------------------------
-void TRAFFCOUNTER_IMPL::SetMonitorDir(const std::string & dir)
-{
-monitorDir = dir;
-monitoring = !monitorDir.empty();
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.23 $
- $Date: 2010/04/22 12:57:46 $
- $Author: faust $
- */
-
-
-#ifndef TRAFFCOUNTER_IMPL_H
-#define TRAFFCOUNTER_IMPL_H
-
-#include "stg/traffcounter.h"
-#include "stg/os_int.h"
-#include "stg/logger.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/noncopyable.h"
-#include "stg/notifer.h"
-#include "actions.h"
-#include "eventloop.h"
-#include "user_impl.h"
-
-#include <ctime>
-#include <list>
-#include <map>
-#include <string>
-
-#include <pthread.h>
-
-#define PROTOMAX (5)
-
-class USERS_IMPL;
-
-//-----------------------------------------------------------------------------
-struct RULE {
-uint32_t ip; // IP
-uint32_t mask; // Network mask
-uint16_t port1; // Min port
-uint16_t port2; // Max port
-uint8_t proto; // Protocol
-uint32_t dir; // Direction
-};
-//-----------------------------------------------------------------------------
-struct PACKET_EXTRA_DATA {
-PACKET_EXTRA_DATA()
- : flushTime(0),
- updateTime(0),
- userU(NULL),
- userUPresent(false),
- userD(NULL),
- userDPresent(false),
- dirU(DIR_NUM),
- dirD(DIR_NUM),
- lenU(0),
- lenD(0)
-{}
-
-time_t flushTime; // Last flush time
-time_t updateTime; // Last update time
-USER_IMPL * userU; // Uploader
-bool userUPresent; // Uploader is registered user
-USER_IMPL * userD; // Downloader
-bool userDPresent; // Downloader is registered user
-int dirU; // Upload direction
-int dirD; // Download direction
-uint32_t lenU; // Upload length
-uint32_t lenD; // Download length
-};
-//-----------------------------------------------------------------------------
-class TRAFFCOUNTER_IMPL;
-//-----------------------------------------------------------------------------
-class TRF_IP_BEFORE: public PROPERTY_NOTIFIER_BASE<uint32_t> {
-public:
- TRF_IP_BEFORE(TRAFFCOUNTER_IMPL & t, USER_IMPL * u)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(),
- traffCnt(t),
- user(u)
- {}
- TRF_IP_BEFORE(const TRF_IP_BEFORE & rvalue)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(),
- traffCnt(rvalue.traffCnt),
- user(rvalue.user)
- {}
- void Notify(const uint32_t & oldValue, const uint32_t & newValue);
- void SetUser(USER_IMPL * u) { user = u; }
- USER_IMPL * GetUser() const { return user; }
-
-private:
- TRF_IP_BEFORE & operator=(const TRF_IP_BEFORE & rvalue);
-
- TRAFFCOUNTER_IMPL & traffCnt;
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class TRF_IP_AFTER: public PROPERTY_NOTIFIER_BASE<uint32_t> {
-public:
- TRF_IP_AFTER(TRAFFCOUNTER_IMPL & t, USER_IMPL * u)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(),
- traffCnt(t),
- user(u)
- {}
- TRF_IP_AFTER(const TRF_IP_AFTER & rvalue)
- : PROPERTY_NOTIFIER_BASE<uint32_t>(),
- traffCnt(rvalue.traffCnt),
- user(rvalue.user)
- {}
- void Notify(const uint32_t & oldValue, const uint32_t & newValue);
- void SetUser(USER_IMPL * u) { user = u; }
- USER_IMPL * GetUser() const { return user; }
-private:
- TRF_IP_AFTER & operator=(const TRF_IP_AFTER & rvalue);
-
- TRAFFCOUNTER_IMPL & traffCnt;
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_IMPL_PTR> {
-public:
- explicit ADD_USER_NONIFIER(TRAFFCOUNTER_IMPL & t) :
- NOTIFIER_BASE<USER_IMPL_PTR>(),
- traffCnt(t)
- {}
- virtual ~ADD_USER_NONIFIER() {}
- void Notify(const USER_IMPL_PTR & user);
-
-private:
- ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
- ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
-
- TRAFFCOUNTER_IMPL & traffCnt;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_IMPL_PTR> {
-public:
- explicit DEL_USER_NONIFIER(TRAFFCOUNTER_IMPL & t) :
- NOTIFIER_BASE<USER_IMPL_PTR>(),
- traffCnt(t)
- {}
- virtual ~DEL_USER_NONIFIER() {}
- void Notify(const USER_IMPL_PTR & user);
-
-private:
- DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
- DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
-
- TRAFFCOUNTER_IMPL & traffCnt;
-};
-//-----------------------------------------------------------------------------
-class TRAFFCOUNTER_IMPL : public TRAFFCOUNTER, private NONCOPYABLE {
-friend class ADD_USER_NONIFIER;
-friend class DEL_USER_NONIFIER;
-friend class TRF_IP_BEFORE;
-friend class TRF_IP_AFTER;
-public:
- TRAFFCOUNTER_IMPL(USERS_IMPL * users, const std::string & rulesFileName);
- ~TRAFFCOUNTER_IMPL();
-
- int Reload();
- int Start();
- int Stop();
-
- void Process(const RAW_PACKET & rawPacket);
- void SetMonitorDir(const std::string & monitorDir);
-
- size_t RulesCount() const { return rules.size(); }
-
-private:
- TRAFFCOUNTER_IMPL(const TRAFFCOUNTER_IMPL &);
- TRAFFCOUNTER_IMPL & operator=(const TRAFFCOUNTER_IMPL &);
-
- bool ParseAddress(const char * ta, RULE * rule) const;
- uint32_t CalcMask(uint32_t msk) const;
- void FreeRules();
- bool ReadRules(bool test = false);
-
- static void * Run(void * data);
-
- void DeterminateDir(const RAW_PACKET & packet,
- int * dirU, // Direction for upload
- int * dirD) const; // Direction for download
-
- void FlushAndRemove();
-
- void AddUser(USER_IMPL * user);
- void DelUser(uint32_t uip);
- void SetUserNotifiers(USER_IMPL * user);
- void UnSetUserNotifiers(USER_IMPL * user);
-
- typedef std::list<RULE>::iterator rule_iter;
-
- std::list<RULE> rules;
-
- typedef std::map<RAW_PACKET, PACKET_EXTRA_DATA> Packets;
- typedef Packets::iterator pp_iter;
- typedef std::multimap<uint32_t, pp_iter> Index;
- typedef Index::iterator ip2p_iter;
- typedef Index::const_iterator ip2p_citer;
-
- Packets packets; // Packets tree
-
- Index ip2packets; // IP-to-Packet index
-
- std::string dirName[DIR_NUM + 1];
-
- STG_LOGGER & WriteServLog;
- std::string rulesFileName;
-
- std::string monitorDir;
- bool monitoring;
- time_t touchTimeP;
-
- USERS_IMPL * users;
-
- bool running;
- bool stopped;
- pthread_mutex_t mutex;
- pthread_t thread;
-
- std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
- std::list<TRF_IP_AFTER> ipAfterNotifiers;
-
- ADD_USER_NONIFIER addUserNotifier;
- DEL_USER_NONIFIER delUserNotifier;
-};
-//-----------------------------------------------------------------------------
-inline
-void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &)
-{
-// User changes his address. Remove old IP
-if (!oldValue)
- return;
-
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::DelUser, oldValue);
-}
-//-----------------------------------------------------------------------------
-inline
-void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue)
-{
-// User changes his address. Add new IP
-if (!newValue)
- return;
-
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::AddUser, user);
-}
-//-----------------------------------------------------------------------------
-inline
-void ADD_USER_NONIFIER::Notify(const USER_IMPL_PTR & user)
-{
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::SetUserNotifiers, user);
-}
-//-----------------------------------------------------------------------------
-inline
-void DEL_USER_NONIFIER::Notify(const USER_IMPL_PTR & user)
-{
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::UnSetUserNotifiers, user);
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::DelUser, user->GetCurrIP());
-}
-//-----------------------------------------------------------------------------
-#endif //TRAFFCOUNTER_H
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.101 $
- $Date: 2010/11/03 10:50:03 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "user_impl.h"
-#include "settings_impl.h"
-#include "stg_timer.h"
-
-#include "stg/users.h"
-#include "stg/common.h"
-#include "stg/scriptexecuter.h"
-#include "stg/tariff.h"
-#include "stg/tariffs.h"
-#include "stg/admin.h"
-
-#include <algorithm>
-#include <functional>
-
-#include <cassert>
-#include <cstdlib>
-#include <cmath>
-
-#include <pthread.h>
-#include <unistd.h> // access
-
-namespace
-{
-
-std::string dirsToString(const bool * dirs)
-{
-std::string res;
-for (size_t i = 0; i < DIR_NUM; i++)
- res += dirs[i] ? '1' : '0';
-return res;
-}
-
-void dirsFromBits(bool * dirs, uint32_t bits)
-{
-for (size_t i = 0; i < DIR_NUM; i++)
- dirs[i] = bits & (1 << i);
-}
-
-}
-
-#ifdef USE_ABSTRACT_SETTINGS
-USER_IMPL::USER_IMPL(const SETTINGS * s,
- const STORE * st,
- const TARIFFS * t,
- const ADMIN * a,
- const USERS * u,
- const SERVICES & svcs)
- : users(u),
- property(*s),
- WriteServLog(GetStgLogger()),
- lastScanMessages(0),
- id(0),
- __connected(0),
- connected(__connected),
- __currIP(0),
- currIP(__currIP),
- lastIPForDisconnect(0),
- pingTime(0),
- sysAdmin(a),
- store(st),
- tariffs(t),
- tariff(NULL),
- m_services(svcs),
- settings(s),
- authorizedModificationTime(0),
- deleted(false),
- lastWriteStat(0),
- lastWriteDetailedStat(0),
- cash(property.cash),
- up(property.up),
- down(property.down),
- lastCashAdd(property.lastCashAdd),
- passiveTime(property.passiveTime),
- lastCashAddTime(property.lastCashAddTime),
- freeMb(property.freeMb),
- lastActivityTime(property.lastActivityTime),
- password(property.password),
- passive(property.passive),
- disabled(property.disabled),
- disabledDetailStat(property.disabledDetailStat),
- alwaysOnline(property.alwaysOnline),
- tariffName(property.tariffName),
- nextTariff(property.nextTariff),
- address(property.address),
- note(property.note),
- group(property.group),
- email(property.email),
- phone(property.phone),
- realName(property.realName),
- credit(property.credit),
- creditExpire(property.creditExpire),
- ips(property.ips),
- userdata0(property.userdata0),
- userdata1(property.userdata1),
- userdata2(property.userdata2),
- userdata3(property.userdata3),
- userdata4(property.userdata4),
- userdata5(property.userdata5),
- userdata6(property.userdata6),
- userdata7(property.userdata7),
- userdata8(property.userdata8),
- userdata9(property.userdata9),
- sessionUploadModTime(stgTime),
- sessionDownloadModTime(stgTime),
- passiveNotifier(this),
- disabledNotifier(this),
- tariffNotifier(this),
- cashNotifier(this),
- ipNotifier(this)
-{
-Init();
-}
-#else
-USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
- const STORE * st,
- const TARIFFS * t,
- const ADMIN * a,
- const USERS * u,
- const SERVICES & svcs)
- : users(u),
- property(*s),
- WriteServLog(GetStgLogger()),
- lastScanMessages(0),
- id(0),
- __connected(0),
- connected(__connected),
- __currIP(0),
- currIP(__currIP),
- lastIPForDisconnect(0),
- pingTime(0),
- sysAdmin(a),
- store(st),
- tariffs(t),
- tariff(NULL),
- m_services(svcs),
- settings(s),
- authorizedModificationTime(0),
- deleted(false),
- lastWriteStat(0),
- lastWriteDetailedStat(0),
- cash(property.cash),
- up(property.up),
- down(property.down),
- lastCashAdd(property.lastCashAdd),
- passiveTime(property.passiveTime),
- lastCashAddTime(property.lastCashAddTime),
- freeMb(property.freeMb),
- lastActivityTime(property.lastActivityTime),
- password(property.password),
- passive(property.passive),
- disabled(property.disabled),
- disabledDetailStat(property.disabledDetailStat),
- alwaysOnline(property.alwaysOnline),
- tariffName(property.tariffName),
- nextTariff(property.nextTariff),
- address(property.address),
- note(property.note),
- group(property.group),
- email(property.email),
- phone(property.phone),
- realName(property.realName),
- credit(property.credit),
- creditExpire(property.creditExpire),
- ips(property.ips),
- userdata0(property.userdata0),
- userdata1(property.userdata1),
- userdata2(property.userdata2),
- userdata3(property.userdata3),
- userdata4(property.userdata4),
- userdata5(property.userdata5),
- userdata6(property.userdata6),
- userdata7(property.userdata7),
- userdata8(property.userdata8),
- userdata9(property.userdata9),
- sessionUploadModTime(stgTime),
- sessionDownloadModTime(stgTime),
- passiveNotifier(this),
- disabledNotifier(this),
- tariffNotifier(this),
- cashNotifier(this),
- ipNotifier(this)
-{
-Init();
-}
-#endif
-//-----------------------------------------------------------------------------
-void USER_IMPL::Init()
-{
-password = "*_EMPTY_PASSWORD_*";
-tariffName = NO_TARIFF_NAME;
-tariff = tariffs->FindByName(tariffName);
-ips = StrToIPS("*");
-lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
-lastWriteDetailedStat = stgTime;
-
-property.tariffName.AddBeforeNotifier(&tariffNotifier);
-property.passive.AddBeforeNotifier(&passiveNotifier);
-property.disabled.AddAfterNotifier(&disabledNotifier);
-property.cash.AddBeforeNotifier(&cashNotifier);
-ips.AddAfterNotifier(&ipNotifier);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-USER_IMPL::USER_IMPL(const USER_IMPL & u)
- : USER(),
- users(u.users),
- property(*u.settings),
- WriteServLog(GetStgLogger()),
- lastScanMessages(0),
- login(u.login),
- id(u.id),
- __connected(0),
- connected(__connected),
- userIDGenerator(u.userIDGenerator),
- __currIP(u.__currIP),
- currIP(__currIP),
- lastIPForDisconnect(0),
- pingTime(u.pingTime),
- sysAdmin(u.sysAdmin),
- store(u.store),
- tariffs(u.tariffs),
- tariff(u.tariff),
- m_services(u.m_services),
- traffStat(u.traffStat),
- traffStatSaved(u.traffStatSaved),
- settings(u.settings),
- authorizedModificationTime(u.authorizedModificationTime),
- messages(u.messages),
- deleted(u.deleted),
- lastWriteStat(u.lastWriteStat),
- lastWriteDetailedStat(u.lastWriteDetailedStat),
- cash(property.cash),
- up(property.up),
- down(property.down),
- lastCashAdd(property.lastCashAdd),
- passiveTime(property.passiveTime),
- lastCashAddTime(property.lastCashAddTime),
- freeMb(property.freeMb),
- lastActivityTime(property.lastActivityTime),
- password(property.password),
- passive(property.passive),
- disabled(property.disabled),
- disabledDetailStat(property.disabledDetailStat),
- alwaysOnline(property.alwaysOnline),
- tariffName(property.tariffName),
- nextTariff(property.nextTariff),
- address(property.address),
- note(property.note),
- group(property.group),
- email(property.email),
- phone(property.phone),
- realName(property.realName),
- credit(property.credit),
- creditExpire(property.creditExpire),
- ips(property.ips),
- userdata0(property.userdata0),
- userdata1(property.userdata1),
- userdata2(property.userdata2),
- userdata3(property.userdata3),
- userdata4(property.userdata4),
- userdata5(property.userdata5),
- userdata6(property.userdata6),
- userdata7(property.userdata7),
- userdata8(property.userdata8),
- userdata9(property.userdata9),
- sessionUpload(),
- sessionDownload(),
- sessionUploadModTime(stgTime),
- sessionDownloadModTime(stgTime),
- passiveNotifier(this),
- disabledNotifier(this),
- tariffNotifier(this),
- cashNotifier(this),
- ipNotifier(this)
-{
-if (&u == this)
- return;
-
-property.tariffName.AddBeforeNotifier(&tariffNotifier);
-property.passive.AddBeforeNotifier(&passiveNotifier);
-property.disabled.AddAfterNotifier(&disabledNotifier);
-property.cash.AddBeforeNotifier(&cashNotifier);
-ips.AddAfterNotifier(&ipNotifier);
-
-property.SetProperties(u.property);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-USER_IMPL::~USER_IMPL()
-{
-property.tariffName.DelBeforeNotifier(&tariffNotifier);
-property.passive.DelBeforeNotifier(&passiveNotifier);
-property.disabled.DelAfterNotifier(&disabledNotifier);
-property.cash.DelBeforeNotifier(&cashNotifier);
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::SetLogin(const std::string & l)
-{
-STG_LOCKER lock(&mutex);
-assert(login.empty() && "Login is already set");
-login = l;
-id = userIDGenerator.GetNextID();
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::ReadConf()
-{
-STG_LOCKER lock(&mutex);
-USER_CONF conf;
-
-if (store->RestoreUserConf(&conf, login))
- {
- WriteServLog("Cannot read conf for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
- printfd(__FILE__, "%s\n", store->GetStrError().c_str());
- return -1;
- }
-
-property.SetConf(conf);
-
-tariff = tariffs->FindByName(tariffName);
-if (tariff == NULL)
- {
- WriteServLog("Cannot read user %s. Tariff %s not exist.",
- login.c_str(), property.tariffName.Get().c_str());
- return -1;
- }
-
-std::vector<STG_MSG_HDR> hdrsList;
-
-if (store->GetMessageHdrs(&hdrsList, login))
- {
- printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
- WriteServLog("Cannot read user %s. Error reading message headers: %s.",
- login.c_str(),
- store->GetStrError().c_str());
- return -1;
- }
-
-std::vector<STG_MSG_HDR>::const_iterator it;
-for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
- {
- STG_MSG msg;
- if (store->GetMessage(it->id, &msg, login) == 0)
- {
- messages.push_back(msg);
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::ReadStat()
-{
-STG_LOCKER lock(&mutex);
-USER_STAT stat;
-
-if (store->RestoreUserStat(&stat, login))
- {
- WriteServLog("Cannot read stat for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
- printfd(__FILE__, "%s\n", store->GetStrError().c_str());
- return -1;
- }
-
-property.SetStat(stat);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::WriteConf()
-{
-STG_LOCKER lock(&mutex);
-USER_CONF conf(property.GetConf());
-
-printfd(__FILE__, "USER::WriteConf()\n");
-
-if (store->SaveUserConf(conf, login))
- {
- WriteServLog("Cannot write conf for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
- printfd(__FILE__, "%s\n", store->GetStrError().c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::WriteStat()
-{
-STG_LOCKER lock(&mutex);
-USER_STAT stat(property.GetStat());
-
-if (store->SaveUserStat(stat, login))
- {
- WriteServLog("Cannot write stat for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
- printfd(__FILE__, "%s\n", store->GetStrError().c_str());
- return -1;
- }
-
-lastWriteStat = stgTime;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::WriteMonthStat()
-{
-STG_LOCKER lock(&mutex);
-time_t tt = stgTime - 3600;
-struct tm t1;
-localtime_r(&tt, &t1);
-
-USER_STAT stat(property.GetStat());
-if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
- {
- WriteServLog("Cannot write month stat for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
- printfd(__FILE__, "%s\n", store->GetStrError().c_str());
- return -1;
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
-{
-STG_LOCKER lock(&mutex);
-/*
- * Authorize user. It only means that user will be authorized. Nothing more.
- * User can be connected or disconnected while authorized.
- * Example: user is authorized but disconnected due to 0 money or blocking
- */
-
-/*
- * TODO: in fact "authorization" means allowing access to a service. What we
- * call "authorization" here, int STG, is "authentication". So this should be
- * fixed in future.
- */
-
-/*
- * Prevent double authorization by identical authorizers
- */
-if (authorizedBy.find(auth) != authorizedBy.end())
- return 0;
-
-if (!ip)
- return -1;
-
-dirsFromBits(enabledDirs, dirs);
-
-if (!authorizedBy.empty())
- {
- if (currIP != ip)
- {
- // We are already authorized, but with different IP address
- errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
- return -1;
- }
-
- USER * u = NULL;
- if (!users->FindByIPIdx(ip, &u))
- {
- // Address presents in IP-index.
- // If it's not our IP - report it.
- if (u != this)
- {
- errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
- return -1;
- }
- }
- }
-else
- {
- if (users->IsIPInIndex(ip))
- {
- // Address is already present in IP-index.
- errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
- return -1;
- }
-
- if (ips.ConstData().IsIPInIPS(ip))
- {
- currIP = ip;
- lastIPForDisconnect = currIP;
- }
- else
- {
- printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
- errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
- return -1;
- }
- }
-
-if (authorizedBy.empty())
- authorizedModificationTime = stgTime;
-authorizedBy.insert(auth);
-
-ScanMessage();
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
-{
-STG_LOCKER lock(&mutex);
-/*
- * Authorizer tries to unauthorize user, that was not authorized by it
- */
-if (!authorizedBy.erase(auth))
- return;
-
-authorizedModificationTime = stgTime;
-
-if (authorizedBy.empty())
- {
- lastDisconnectReason = reason;
- lastIPForDisconnect = currIP;
- currIP = 0; // DelUser in traffcounter
- if (connected)
- Disconnect(false, "not authorized");
- return;
- }
-}
-//-----------------------------------------------------------------------------
-bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
-{
-STG_LOCKER lock(&mutex);
-// Is this user authorized by specified authorizer?
-return authorizedBy.find(auth) != authorizedBy.end();
-}
-//-----------------------------------------------------------------------------
-std::vector<std::string> USER_IMPL::GetAuthorizers() const
-{
- STG_LOCKER lock(&mutex);
- std::vector<std::string> list;
- std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
- return list;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::Connect(bool fakeConnect)
-{
-/*
- * Connect user to Internet. This function is differ from Authorize() !!!
- */
-
-STG_LOCKER lock(&mutex);
-
-if (!fakeConnect)
- {
- std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
-
- if (access(scriptOnConnect.c_str(), X_OK) == 0)
- {
- std::string dirs = dirsToString(enabledDirs);
-
- std::string scriptOnConnectParams;
- strprintf(&scriptOnConnectParams,
- "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
- scriptOnConnect.c_str(),
- login.c_str(),
- inet_ntostring(currIP).c_str(),
- cash.ConstData(),
- id,
- dirs.c_str());
-
- std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
- while (it != settings->GetScriptParams().end())
- {
- scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
- ++it;
- }
-
- ScriptExec(scriptOnConnectParams.c_str());
- }
- else
- {
- WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
- }
-
- connected = true;
- }
-
-if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
- {
- WriteServLog("Cannot write connect for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- }
-
-if (!fakeConnect)
- lastIPForDisconnect = currIP;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
-{
-/*
- * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
- */
-
-STG_LOCKER lock(&mutex);
-
-if (!lastIPForDisconnect)
- {
- printfd(__FILE__, "lastIPForDisconnect\n");
- return;
- }
-
-if (!fakeDisconnect)
- {
- lastDisconnectReason = reason;
- std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
-
- if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
- {
- std::string dirs = dirsToString(enabledDirs);
-
- std::string scriptOnDisonnectParams;
- strprintf(&scriptOnDisonnectParams,
- "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
- scriptOnDisonnect.c_str(),
- login.c_str(),
- inet_ntostring(lastIPForDisconnect).c_str(),
- cash.ConstData(),
- id,
- dirs.c_str());
-
- std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
- while (it != settings->GetScriptParams().end())
- {
- scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
- ++it;
- }
-
- ScriptExec(scriptOnDisonnectParams.c_str());
- }
- else
- {
- WriteServLog("Script OnDisconnect cannot be executed. File not found.");
- }
-
- connected = false;
- }
-
-std::string reasonMessage(reason);
-if (!lastDisconnectReason.empty())
- reasonMessage += ": " + lastDisconnectReason;
-
-if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
- cash, freeMb, reasonMessage))
- {
- WriteServLog("Cannot write disconnect for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- }
-
-if (!fakeDisconnect)
- lastIPForDisconnect = 0;
-
-sessionUpload.Reset();
-sessionDownload.Reset();
-sessionUploadModTime = stgTime;
-sessionDownloadModTime = stgTime;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::Run()
-{
-STG_LOCKER lock(&mutex);
-
-if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
- {
- printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
- WriteStat();
- }
-if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
- {
- WriteServLog("User: %s. Credit expired.", login.c_str());
- credit = 0;
- creditExpire = 0;
- WriteConf();
- }
-
-if (passive.ConstData()
- && (stgTime % 30 == 0)
- && (passiveTime.ModificationTime() != stgTime))
- {
- passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
- printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
- }
-
-if (!authorizedBy.empty())
- {
- if (connected)
- property.Stat().lastActivityTime = stgTime;
-
- if (!connected && IsInetable())
- Connect();
-
- if (connected && !IsInetable())
- {
- if (disabled)
- Disconnect(false, "disabled");
- else if (passive)
- Disconnect(false, "passive");
- else
- Disconnect(false, "no cash");
- }
-
- if (stgTime - lastScanMessages > 10)
- {
- ScanMessage();
- lastScanMessages = stgTime;
- }
- }
-else
- {
- if (connected)
- Disconnect(false, "not authorized");
- }
-
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::UpdatePingTime(time_t t)
-{
-STG_LOCKER lock(&mutex);
-if (t)
- pingTime = t;
-else
- pingTime = stgTime;
-}
-//-----------------------------------------------------------------------------
-bool USER_IMPL::IsInetable()
-{
-if (disabled || passive)
- return false;
-
-if (settings->GetFreeMbAllowInet())
- {
- if (freeMb >= 0)
- return true;
- }
-
-if (settings->GetShowFeeInCash() || tariff == NULL)
- return (cash >= -credit);
-
-return (cash - tariff->GetFee() >= -credit);
-}
-//-----------------------------------------------------------------------------
-std::string USER_IMPL::GetEnabledDirs() const
-{
-return dirsToString(enabledDirs);
-}
-//-----------------------------------------------------------------------------
-#ifdef TRAFF_STAT_WITH_PORTS
-void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
-#else
-void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
-#endif
-{
-STG_LOCKER lock(&mutex);
-
-if (!connected || tariff == NULL)
- return;
-
-double cost = 0;
-DIR_TRAFF dt(up);
-
-int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
-int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
-
-dt[dir] += len;
-
-int tt = tariff->GetTraffType();
-if (tt == TARIFF::TRAFF_UP ||
- tt == TARIFF::TRAFF_UP_DOWN ||
- // Check NEW traff data
- (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
- {
- double dc = 0;
- if (traff < threshold &&
- traff + len >= threshold)
- {
- // cash = partBeforeThreshold * priceBeforeThreshold +
- // partAfterThreshold * priceAfterThreshold
- int64_t before = threshold - traff; // Chunk part before threshold
- int64_t after = len - before; // Chunk part after threshold
- dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
- down.ConstData()[dir],
- dir,
- stgTime) * before +
- tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
- down.ConstData()[dir],
- dir,
- stgTime) * after;
- }
- else
- {
- dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
- down.ConstData()[dir],
- dir,
- stgTime) * len;
- }
-
- if (freeMb.ConstData() <= 0) // FreeMb is exhausted
- cost = dc;
- else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
- cost = dc - freeMb.ConstData();
-
- // Direct access to internal data structures via friend-specifier
- property.Stat().freeMb -= dc;
- property.Stat().cash -= cost;
- cash.ModifyTime();
- freeMb.ModifyTime();
- }
-
-up = dt;
-sessionUpload[dir] += len;
-sessionUploadModTime = stgTime;
-
-//Add detailed stat
-
-if (!settings->GetWriteFreeMbTraffCost() &&
- freeMb.ConstData() >= 0)
- cost = 0;
-
-#ifdef TRAFF_STAT_WITH_PORTS
-IP_DIR_PAIR idp(ip, dir, port);
-#else
-IP_DIR_PAIR idp(ip, dir);
-#endif
-
-std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
-lb = traffStat.lower_bound(idp);
-if (lb == traffStat.end() || lb->first != idp)
- {
- traffStat.insert(lb,
- std::make_pair(idp,
- STAT_NODE(len, 0, cost)));
- }
-else
- {
- lb->second.cash += cost;
- lb->second.up += len;
- }
-}
-//-----------------------------------------------------------------------------
-#ifdef TRAFF_STAT_WITH_PORTS
-void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
-#else
-void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
-#endif
-{
-STG_LOCKER lock(&mutex);
-
-if (!connected || tariff == NULL)
- return;
-
-double cost = 0;
-DIR_TRAFF dt(down);
-
-int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
-int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
-
-dt[dir] += len;
-
-int tt = tariff->GetTraffType();
-if (tt == TARIFF::TRAFF_DOWN ||
- tt == TARIFF::TRAFF_UP_DOWN ||
- // Check NEW traff data
- (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
- {
- double dc = 0;
- if (traff < threshold &&
- traff + len >= threshold)
- {
- // cash = partBeforeThreshold * priceBeforeThreshold +
- // partAfterThreshold * priceAfterThreshold
- int64_t before = threshold - traff; // Chunk part before threshold
- int64_t after = len - before; // Chunk part after threshold
- dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
- down.ConstData()[dir], // Traff before chunk
- dir,
- stgTime) * before +
- tariff->GetPriceWithTraffType(up.ConstData()[dir],
- dt[dir], // Traff after chunk
- dir,
- stgTime) * after;
- }
- else
- {
- dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
- down.ConstData()[dir],
- dir,
- stgTime) * len;
- }
-
- if (freeMb.ConstData() <= 0) // FreeMb is exhausted
- cost = dc;
- else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
- cost = dc - freeMb.ConstData();
-
- property.Stat().freeMb -= dc;
- property.Stat().cash -= cost;
- cash.ModifyTime();
- freeMb.ModifyTime();
- }
-
-down = dt;
-sessionDownload[dir] += len;
-sessionDownloadModTime = stgTime;
-
-//Add detailed stat
-
-if (!settings->GetWriteFreeMbTraffCost() &&
- freeMb.ConstData() >= 0)
- cost = 0;
-
-#ifdef TRAFF_STAT_WITH_PORTS
-IP_DIR_PAIR idp(ip, dir, port);
-#else
-IP_DIR_PAIR idp(ip, dir);
-#endif
-
-std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
-lb = traffStat.lower_bound(idp);
-if (lb == traffStat.end() || lb->first != idp)
- {
- traffStat.insert(lb,
- std::make_pair(idp,
- STAT_NODE(0, len, cost)));
- }
-else
- {
- lb->second.cash += cost;
- lb->second.down += len;
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.AddBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.DelBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.AddAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.DelAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.AddBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.DelBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.AddAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.DelAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::OnAdd()
-{
-STG_LOCKER lock(&mutex);
-
-std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
-
-if (access(scriptOnAdd.c_str(), X_OK) == 0)
- {
- std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
-
- ScriptExec(scriptOnAddParams.c_str());
- }
-else
- {
- WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::OnDelete()
-{
-STG_LOCKER lock(&mutex);
-
-std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
-
-if (access(scriptOnDel.c_str(), X_OK) == 0)
- {
- std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
-
- ScriptExec(scriptOnDelParams.c_str());
- }
-else
- {
- WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
- }
-
-Run();
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::WriteDetailStat(bool hard)
-{
-printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
-
-if (!traffStatSaved.second.empty())
- {
- if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
- {
- printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
- WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- return -1;
- }
- traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
- }
-
-TRAFF_STAT ts;
-
- {
- STG_LOCKER lock(&mutex);
- ts.swap(traffStat);
- }
-
-printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
-
-if (ts.size() && !disabledDetailStat)
- {
- if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
- {
- printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
- WriteServLog("Cannot write detail stat for user %s.", login.c_str());
- WriteServLog("%s", store->GetStrError().c_str());
- if (!hard)
- {
- printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
- STG_LOCKER lock(&mutex);
- traffStatSaved.second.swap(ts);
- traffStatSaved.first = lastWriteDetailedStat;
- }
- return -1;
- }
- }
-lastWriteDetailedStat = stgTime;
-return 0;
-}
-//-----------------------------------------------------------------------------
-double USER_IMPL::GetPassiveTimePart() const
-{
-STG_LOCKER lock(&mutex);
-
-static int daysInMonth[12] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-struct tm tms;
-time_t t = stgTime;
-localtime_r(&t, &tms);
-
-time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
-
-if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
- {
- // Leap year
- secMonth += 24 * 3600;
- }
-
-time_t dt = secMonth - passiveTime;
-
-if (dt < 0)
- dt = 0;
-
-return static_cast<double>(dt) / secMonth;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::SetPassiveTimeAsNewUser()
-{
-STG_LOCKER lock(&mutex);
-
-time_t t = stgTime;
-struct tm tm;
-localtime_r(&t, &tm);
-int daysCurrMon = DaysInCurrentMonth();
-double pt = tm.tm_mday - 1;
-pt /= daysCurrMon;
-
-passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::MidnightResetSessionStat()
-{
-STG_LOCKER lock(&mutex);
-
-if (connected)
- {
- Disconnect(true, "fake");
- Connect(true);
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ProcessNewMonth()
-{
-STG_LOCKER lock(&mutex);
-// Reset traff
-if (connected)
- Disconnect(true, "fake");
-
-WriteMonthStat();
-
-property.Stat().monthUp.Reset();
-property.Stat().monthDown.Reset();
-
-if (connected)
- Connect(true);
-
-// Set new tariff
-if (nextTariff.ConstData() != "")
- {
- const TARIFF * nt = tariffs->FindByName(nextTariff);
- if (nt == NULL)
- {
- WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
- login.c_str(), property.tariffName.Get().c_str());
- }
- else
- {
- std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
- if (message.empty())
- {
- property.tariffName.Set(nextTariff, sysAdmin, login, store);
- }
- else
- {
- WriteServLog("Tariff change is prohibited for user %s. %s",
- login.c_str(),
- message.c_str());
- }
- }
- ResetNextTariff();
- WriteConf();
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ProcessDayFeeSpread()
-{
-STG_LOCKER lock(&mutex);
-
-if (passive.ConstData() || tariff == NULL)
- return;
-
-if (tariff->GetPeriod() != TARIFF::MONTH)
- return;
-
-double fee = tariff->GetFee() / DaysInCurrentMonth();
-
-if (std::fabs(fee) < 1.0e-3)
- return;
-
-double c = cash;
-switch (settings->GetFeeChargeType())
- {
- case 0:
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- case 1:
- if (c + credit >= 0)
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- case 2:
- if (c + credit >= fee)
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- case 3:
- if (c >= 0)
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- }
-ResetPassiveTime();
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ProcessDayFee()
-{
-STG_LOCKER lock(&mutex);
-
-if (tariff == NULL)
- return;
-
-if (tariff->GetPeriod() != TARIFF::MONTH)
- return;
-
-double passiveTimePart = 1.0;
-if (!settings->GetFullFee())
- {
- passiveTimePart = GetPassiveTimePart();
- }
-else
- {
- if (passive.ConstData())
- {
- printfd(__FILE__, "Don't charge fee `cause we are passive\n");
- return;
- }
- }
-double fee = tariff->GetFee() * passiveTimePart;
-
-ResetPassiveTime();
-
-if (std::fabs(fee) < 1.0e-3)
- {
- SetPrepaidTraff();
- return;
- }
-
-double c = cash;
-printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
- login.c_str(),
- cash.ConstData(),
- credit.ConstData(),
- tariff->GetFee(),
- passiveTimePart,
- fee);
-switch (settings->GetFeeChargeType())
- {
- case 0:
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- break;
- case 1:
- if (c + credit >= 0)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- case 2:
- if (c + credit >= fee)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- case 3:
- if (c >= 0)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ProcessDailyFee()
-{
-STG_LOCKER lock(&mutex);
-
-if (passive.ConstData() || tariff == NULL)
- return;
-
-if (tariff->GetPeriod() != TARIFF::DAY)
- return;
-
-double fee = tariff->GetFee();
-
-if (fee == 0.0)
- return;
-
-double c = cash;
-switch (settings->GetFeeChargeType())
- {
- case 0:
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- case 1:
- if (c + credit >= 0)
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- case 2:
- if (c + credit >= fee)
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- break;
- }
-ResetPassiveTime();
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ProcessServices()
-{
-struct tm tms;
-time_t t = stgTime;
-localtime_r(&t, &tms);
-
-double passiveTimePart = 1.0;
-if (!settings->GetFullFee())
- {
- passiveTimePart = GetPassiveTimePart();
- }
-else
- {
- if (passive.ConstData())
- {
- printfd(__FILE__, "Don't charge fee `cause we are passive\n");
- return;
- }
- }
-
-for (size_t i = 0; i < property.Conf().services.size(); ++i)
- {
- SERVICE_CONF conf;
- if (m_services.Find(property.Conf().services[i], &conf))
- continue;
- if (conf.payDay == tms.tm_mday ||
- (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
- {
- double c = cash;
- double fee = conf.cost * passiveTimePart;
- printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
- login.c_str(),
- cash.ConstData(),
- credit.ConstData(),
- tariff->GetFee(),
- passiveTimePart,
- fee);
- switch (settings->GetFeeChargeType())
- {
- case 0:
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- break;
- case 1:
- if (c + credit >= 0)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- case 2:
- if (c + credit >= fee)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- case 3:
- if (c >= 0)
- {
- property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
- SetPrepaidTraff();
- }
- break;
- }
- }
- }
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::SetPrepaidTraff()
-{
-if (tariff != NULL)
- property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::AddMessage(STG_MSG * msg)
-{
-STG_LOCKER lock(&mutex);
-
-if (SendMessage(*msg))
- {
- if (store->AddMessage(msg, login))
- {
- errorStr = store->GetStrError();
- WriteServLog("Error adding message: '%s'", errorStr.c_str());
- printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
- return -1;
- }
- messages.push_back(*msg);
- }
-else
- {
- if (msg->header.repeat > 0)
- {
- msg->header.repeat--;
- #ifndef DEBUG
- //TODO: gcc v. 4.x generate ICE on x86_64
- msg->header.lastSendTime = static_cast<int>(time(NULL));
- #else
- msg->header.lastSendTime = static_cast<int>(stgTime);
- #endif
- if (store->AddMessage(msg, login))
- {
- errorStr = store->GetStrError();
- WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
- printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
- return -1;
- }
- messages.push_back(*msg);
- }
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER_IMPL::SendMessage(STG_MSG & msg) const
-{
-// No lock `cause we are already locked from caller
-int ret = -1;
-std::set<const AUTH*>::iterator it(authorizedBy.begin());
-while (it != authorizedBy.end())
- {
- if (!(*it++)->SendMessage(msg, currIP))
- ret = 0;
- }
-if (!ret)
- {
-#ifndef DEBUG
- //TODO: gcc v. 4.x generate ICE on x86_64
- msg.header.lastSendTime = static_cast<int>(time(NULL));
-#else
- msg.header.lastSendTime = static_cast<int>(stgTime);
-#endif
- msg.header.repeat--;
- }
-return ret;
-}
-//-----------------------------------------------------------------------------
-void USER_IMPL::ScanMessage()
-{
-// No lock `cause we are already locked from caller
-// We need not check for the authorizedBy `cause it has already checked by caller
-
-std::list<STG_MSG>::iterator it(messages.begin());
-while (it != messages.end())
- {
- if (settings->GetMessageTimeout() > 0 &&
- difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
- {
- // Timeout exceeded
- if (store->DelMessage(it->header.id, login))
- {
- WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
- printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
- }
- messages.erase(it++);
- continue;
- }
- if (it->GetNextSendTime() <= stgTime)
- {
- if (SendMessage(*it))
- {
- // We need to check all messages in queue for timeout
- ++it;
- continue;
- }
- if (it->header.repeat < 0)
- {
- if (store->DelMessage(it->header.id, login))
- {
- WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
- printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
- }
- messages.erase(it++);
- }
- else
- {
- if (store->EditMessage(*it, login))
- {
- WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
- printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
- }
- ++it;
- }
- }
- else
- {
- ++it;
- }
- }
-}
-//-----------------------------------------------------------------------------
-std::string USER_IMPL::GetParamValue(const std::string & name) const
-{
- std::string lowerName = ToLower(name);
- if (lowerName == "id")
- {
- std::ostringstream stream;
- stream << id;
- return stream.str();
- }
- if (lowerName == "login") return login;
- if (lowerName == "currip") return currIP.ToString();
- if (lowerName == "enableddirs") return GetEnabledDirs();
- if (lowerName == "tariff") return property.tariffName;
- if (property.Exists(lowerName))
- return property.GetPropertyValue(lowerName);
- else
- {
- WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
- return "";
- }
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
-{
-if (newPassive && !oldPassive && user->tariff != NULL)
- user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
- user->sysAdmin,
- user->login,
- user->store,
- "Freeze");
-}
-//-----------------------------------------------------------------------------
-void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
-{
-if (oldValue && !newValue && user->GetConnected())
- user->Disconnect(false, "disabled");
-else if (!oldValue && newValue && user->IsInetable())
- user->Connect(false);
-}
-//-----------------------------------------------------------------------------
-void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
-{
-STG_LOCKER lock(&user->mutex);
-if (user->settings->GetReconnectOnTariffChange() && user->connected)
- user->Disconnect(false, "Change tariff");
-user->tariff = user->tariffs->FindByName(newTariff);
-if (user->settings->GetReconnectOnTariffChange() &&
- !user->authorizedBy.empty() &&
- user->IsInetable())
- {
- // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
- user->property.Conf().tariffName = newTariff;
- user->Connect(false);
- }
-}
-//-----------------------------------------------------------------------------
-void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
-{
-user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
-user->lastCashAdd = newCash - oldCash;
-}
-//-----------------------------------------------------------------------------
-void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
-{
-printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
-if (user->connected)
- user->Disconnect(false, "Change IP");
-if (!user->authorizedBy.empty() && user->IsInetable())
- user->Connect(false);
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.48 $
- $Date: 2010/11/03 10:50:03 $
- $Author: faust $
- */
-
-#ifndef USER_IMPL_H
-#define USER_IMPL_H
-
-#include "stg/user.h"
-#include "stg/user_stat.h"
-#include "stg/user_conf.h"
-#include "stg/user_ips.h"
-#include "stg/user_property.h"
-#include "stg/auth.h"
-#include "stg/message.h"
-#include "stg/noncopyable.h"
-#include "stg/os_int.h"
-#include "stg/const.h"
-
-#include <list>
-#include <vector>
-#include <string>
-#include <set>
-
-#include <ctime>
-
-//-----------------------------------------------------------------------------
-class TARIFF;
-class TARIFFS;
-class ADMIN;
-class USER_IMPL;
-#ifdef USE_ABSTRACT_SETTINGS
-class SETTINGS;
-#else
-class SETTINGS_IMPL;
-#endif
-//-----------------------------------------------------------------------------
-class USER_ID_GENERATOR {
-friend class USER_IMPL;
-private:
- USER_ID_GENERATOR() {}
- int GetNextID() { static int id = 0; return id++; }
-};
-//-----------------------------------------------------------------------------
-class CHG_PASSIVE_NOTIFIER : public PROPERTY_NOTIFIER_BASE<int>,
- private NONCOPYABLE {
-public:
- explicit CHG_PASSIVE_NOTIFIER(USER_IMPL * u) : user(u) {}
- void Notify(const int & oldPassive, const int & newPassive);
-
-private:
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_DISABLED_NOTIFIER : public PROPERTY_NOTIFIER_BASE<int>,
- private NONCOPYABLE {
-public:
- explicit CHG_DISABLED_NOTIFIER(USER_IMPL * u) : user(u) {}
- void Notify(const int & oldValue, const int & newValue);
-
-private:
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_TARIFF_NOTIFIER : public PROPERTY_NOTIFIER_BASE<std::string>,
- private NONCOPYABLE {
-public:
- explicit CHG_TARIFF_NOTIFIER(USER_IMPL * u) : user(u) {}
- void Notify(const std::string & oldTariff, const std::string & newTariff);
-
-private:
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_CASH_NOTIFIER : public PROPERTY_NOTIFIER_BASE<double>,
- private NONCOPYABLE {
-public:
- explicit CHG_CASH_NOTIFIER(USER_IMPL * u) : user(u) {}
- void Notify(const double & oldCash, const double & newCash);
-
-private:
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_IPS_NOTIFIER : public PROPERTY_NOTIFIER_BASE<USER_IPS>,
- private NONCOPYABLE {
-public:
- explicit CHG_IPS_NOTIFIER(USER_IMPL * u) : user(u) {}
- void Notify(const USER_IPS & oldIPs, const USER_IPS & newIPs);
-
-private:
- USER_IMPL * user;
-};
-//-----------------------------------------------------------------------------
-class USER_IMPL : public USER {
-friend class CHG_PASSIVE_NOTIFIER;
-friend class CHG_DISABLED_NOTIFIER;
-friend class CHG_TARIFF_NOTIFIER;
-friend class CHG_CASH_NOTIFIER;
-friend class CHG_IPS_NOTIFIER;
-public:
-#ifdef USE_ABSTRACT_SETTINGS
- USER_IMPL(const SETTINGS * settings,
- const STORE * store,
- const TARIFFS * tariffs,
- const ADMIN * sysAdmin,
- const USERS * u,
- const SERVICES & svcs);
-#else
- USER_IMPL(const SETTINGS_IMPL * settings,
- const STORE * store,
- const TARIFFS * tariffs,
- const ADMIN * sysAdmin,
- const USERS * u,
- const SERVICES & svcs);
-#endif
- USER_IMPL(const USER_IMPL & u);
- virtual ~USER_IMPL();
-
- int ReadConf();
- int ReadStat();
- int WriteConf();
- int WriteStat();
- int WriteMonthStat();
-
- const std::string & GetLogin() const { return login; }
- void SetLogin(std::string const & l);
-
- uint32_t GetCurrIP() const { return currIP; }
- time_t GetCurrIPModificationTime() const { return currIP.ModificationTime(); }
-
- void AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier);
- void DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier);
-
- void AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier);
- void DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier);
-
- void AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier);
- void DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier);
-
- void AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier);
- void DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier);
-
- int GetID() const { return id; }
-
- double GetPassiveTimePart() const;
- void ResetPassiveTime() { passiveTime = 0; }
- void SetPassiveTimeAsNewUser();
-
- int WriteDetailStat(bool hard = false);
-
- const TARIFF * GetTariff() const { return tariff; }
- void ResetNextTariff() { nextTariff = ""; }
-
- #ifdef TRAFF_STAT_WITH_PORTS
- void AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len);
- void AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len);
- #else
- void AddTraffStatU(int dir, uint32_t ip, uint32_t len);
- void AddTraffStatD(int dir, uint32_t ip, uint32_t len);
- #endif
-
- const DIR_TRAFF & GetSessionUpload() const { return sessionUpload; }
- const DIR_TRAFF & GetSessionDownload() const { return sessionDownload; }
- time_t GetSessionUploadModificationTime() const { return sessionUploadModTime; }
- time_t GetSessionDownloadModificationTime() const { return sessionDownloadModTime; }
-
- bool GetConnected() const { return connected; }
- time_t GetConnectedModificationTime() const { return connected.ModificationTime(); }
- const std::string & GetLastDisconnectReason() const { return lastDisconnectReason; }
- int GetAuthorized() const { return static_cast<int>(authorizedBy.size()); }
- time_t GetAuthorizedModificationTime() const { return authorizedModificationTime; }
- int Authorize(uint32_t ip, uint32_t enabledDirs, const AUTH * auth);
- void Unauthorize(const AUTH * auth,
- const std::string & reason = std::string());
- bool IsAuthorizedBy(const AUTH * auth) const;
- std::vector<std::string> GetAuthorizers() const;
-
- int AddMessage(STG_MSG * msg);
-
- void UpdatePingTime(time_t t = 0);
- time_t GetPingTime() const { return pingTime; }
-
- void Run();
-
- const std::string & GetStrError() const { return errorStr; }
-
- USER_PROPERTIES & GetProperty() { return property; }
- const USER_PROPERTIES & GetProperty() const { return property; }
-
- void SetDeleted() { deleted = true; }
- bool GetDeleted() const { return deleted; }
-
- time_t GetLastWriteStatTime() const { return lastWriteStat; }
-
- void MidnightResetSessionStat();
- void ProcessDayFee();
- void ProcessDayFeeSpread();
- void ProcessNewMonth();
- void ProcessDailyFee();
- void ProcessServices();
-
- bool IsInetable();
- std::string GetEnabledDirs() const;
-
- void OnAdd();
- void OnDelete();
-
- virtual std::string GetParamValue(const std::string & name) const;
-
-private:
- USER_IMPL & operator=(const USER_IMPL & rvalue);
-
- void Init();
-
- const USERS * users;
- USER_PROPERTIES property;
- STG_LOGGER & WriteServLog;
-
- void Connect(bool fakeConnect = false);
- void Disconnect(bool fakeDisconnect, const std::string & reason);
- int SaveMonthStat(int month, int year);
-
- void SetPrepaidTraff();
-
- int SendMessage(STG_MSG & msg) const;
- void ScanMessage();
-
- time_t lastScanMessages;
-
- std::string login;
- int id;
- bool __connected;
- USER_PROPERTY<bool> connected;
-
- bool enabledDirs[DIR_NUM];
-
- USER_ID_GENERATOR userIDGenerator;
-
- uint32_t __currIP; // Current user's ip
- USER_PROPERTY<uint32_t> currIP;
-
- uint32_t lastIPForDisconnect; // User's ip after unauth but before disconnect
- std::string lastDisconnectReason;
-
- time_t pingTime;
-
- const ADMIN * sysAdmin;
- const STORE * store;
-
- const TARIFFS * tariffs;
- const TARIFF * tariff;
-
- const SERVICES & m_services;
-
- TRAFF_STAT traffStat;
- std::pair<time_t, TRAFF_STAT> traffStatSaved;
-
-#ifdef USE_ABSTRACT_SETTINGS
- const SETTINGS * settings;
-#else
- const SETTINGS_IMPL * settings;
-#endif
-
- std::set<const AUTH *> authorizedBy;
- time_t authorizedModificationTime;
-
- std::list<STG_MSG> messages;
-
- bool deleted;
-
- time_t lastWriteStat;
- time_t lastWriteDetailedStat;
-
- // Properties
- USER_PROPERTY<double> & cash;
- USER_PROPERTY<DIR_TRAFF> & up;
- USER_PROPERTY<DIR_TRAFF> & down;
- USER_PROPERTY<double> & lastCashAdd;
- USER_PROPERTY<time_t> & passiveTime;
- USER_PROPERTY<time_t> & lastCashAddTime;
- USER_PROPERTY<double> & freeMb;
- USER_PROPERTY<time_t> & lastActivityTime;
- USER_PROPERTY<std::string> & password;
- USER_PROPERTY<int> & passive;
- USER_PROPERTY<int> & disabled;
- USER_PROPERTY<int> & disabledDetailStat;
- USER_PROPERTY<int> & alwaysOnline;
- USER_PROPERTY<std::string> & tariffName;
- USER_PROPERTY<std::string> & nextTariff;
- USER_PROPERTY<std::string> & address;
- USER_PROPERTY<std::string> & note;
- USER_PROPERTY<std::string> & group;
- USER_PROPERTY<std::string> & email;
- USER_PROPERTY<std::string> & phone;
- USER_PROPERTY<std::string> & realName;
- USER_PROPERTY<double> & credit;
- USER_PROPERTY<time_t> & creditExpire;
- USER_PROPERTY<USER_IPS> & ips;
- USER_PROPERTY<std::string> & userdata0;
- USER_PROPERTY<std::string> & userdata1;
- USER_PROPERTY<std::string> & userdata2;
- USER_PROPERTY<std::string> & userdata3;
- USER_PROPERTY<std::string> & userdata4;
- USER_PROPERTY<std::string> & userdata5;
- USER_PROPERTY<std::string> & userdata6;
- USER_PROPERTY<std::string> & userdata7;
- USER_PROPERTY<std::string> & userdata8;
- USER_PROPERTY<std::string> & userdata9;
-
- // End properties
-
- DIR_TRAFF sessionUpload;
- DIR_TRAFF sessionDownload;
- time_t sessionUploadModTime;
- time_t sessionDownloadModTime;
-
- CHG_PASSIVE_NOTIFIER passiveNotifier;
- CHG_DISABLED_NOTIFIER disabledNotifier;
- CHG_TARIFF_NOTIFIER tariffNotifier;
- CHG_CASH_NOTIFIER cashNotifier;
- CHG_IPS_NOTIFIER ipNotifier;
-
- mutable pthread_mutex_t mutex;
-
- std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-
-typedef USER_IMPL * USER_IMPL_PTR;
-
-#endif //USER_H
+++ /dev/null
-#include "stg/user_property.h"
-
-USER_PROPERTIES::USER_PROPERTIES(const SETTINGS& s)
- : stat(),
- conf(),
- cash (stat.cash, "cash", false, true, GetStgLogger(), s, properties),
- up (stat.monthUp, "upload", false, true, GetStgLogger(), s, properties),
- down (stat.monthDown, "download", false, true, GetStgLogger(), s, properties),
- lastCashAdd (stat.lastCashAdd, "lastCashAdd", false, true, GetStgLogger(), s, properties),
- passiveTime (stat.passiveTime, "passiveTime", false, true, GetStgLogger(), s, properties),
- lastCashAddTime (stat.lastCashAddTime, "lastCashAddTime", false, true, GetStgLogger(), s, properties),
- freeMb (stat.freeMb, "freeMb", false, true, GetStgLogger(), s, properties),
- lastActivityTime(stat.lastActivityTime, "lastActivityTime", false, true, GetStgLogger(), s, properties),
-
- password (conf.password, "password", true, false, GetStgLogger(), s, properties),
- passive (conf.passive, "passive", false, false, GetStgLogger(), s, properties),
- disabled (conf.disabled, "disabled", false, false, GetStgLogger(), s, properties),
- disabledDetailStat(conf.disabledDetailStat, "DisabledDetailStat", false, false, GetStgLogger(), s, properties),
- alwaysOnline(conf.alwaysOnline, "alwaysOnline", false, false, GetStgLogger(), s, properties),
- tariffName (conf.tariffName, "tariffName", false, false, GetStgLogger(), s, properties),
- nextTariff (conf.nextTariff, "nextTariff", false, false, GetStgLogger(), s, properties),
- address (conf.address, "address", false, false, GetStgLogger(), s, properties),
- note (conf.note, "note", false, false, GetStgLogger(), s, properties),
- group (conf.group, "group", false, false, GetStgLogger(), s, properties),
- email (conf.email, "email", false, false, GetStgLogger(), s, properties),
- phone (conf.phone, "phone", false, false, GetStgLogger(), s, properties),
- realName (conf.realName, "realName", false, false, GetStgLogger(), s, properties),
- credit (conf.credit, "credit", false, false, GetStgLogger(), s, properties),
- creditExpire(conf.creditExpire, "creditExpire", false, false, GetStgLogger(), s, properties),
- ips (conf.ips, "ips", false, false, GetStgLogger(), s, properties),
- userdata0 (conf.userdata[0], "userdata0", false, false, GetStgLogger(), s, properties),
- userdata1 (conf.userdata[1], "userdata1", false, false, GetStgLogger(), s, properties),
- userdata2 (conf.userdata[2], "userdata2", false, false, GetStgLogger(), s, properties),
- userdata3 (conf.userdata[3], "userdata3", false, false, GetStgLogger(), s, properties),
- userdata4 (conf.userdata[4], "userdata4", false, false, GetStgLogger(), s, properties),
- userdata5 (conf.userdata[5], "userdata5", false, false, GetStgLogger(), s, properties),
- userdata6 (conf.userdata[6], "userdata6", false, false, GetStgLogger(), s, properties),
- userdata7 (conf.userdata[7], "userdata7", false, false, GetStgLogger(), s, properties),
- userdata8 (conf.userdata[8], "userdata8", false, false, GetStgLogger(), s, properties),
- userdata9 (conf.userdata[9], "userdata9", false, false, GetStgLogger(), s, properties)
-{}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.61 $
- $Date: 2010/09/13 05:56:42 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <pthread.h>
-
-#include <csignal>
-#include <cassert>
-#include <algorithm>
-#include <utility>
-#include <string>
-#include <vector>
-
-#include "stg/settings.h"
-#include "stg/common.h"
-#include "users_impl.h"
-#include "stg_timer.h"
-
-extern volatile time_t stgTime;
-
-//#define USERS_DEBUG 1
-
-//-----------------------------------------------------------------------------
-USERS_IMPL::USERS_IMPL(SETTINGS_IMPL * s, STORE * st,
- TARIFFS * t, SERVICES & svcs,
- const ADMIN * sa)
- : settings(s),
- tariffs(t),
- m_services(svcs),
- store(st),
- sysAdmin(sa),
- WriteServLog(GetStgLogger()),
- nonstop(false),
- isRunning(false),
- handle(0)
-{
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-USERS_IMPL::~USERS_IMPL()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByNameNonLock(const std::string & login, user_iter * user)
-{
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-if (iter == loginIndex.end())
- return -1;
-if (user)
- *user = iter->second;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByNameNonLock(const std::string & login, const_user_iter * user) const
-{
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-if (iter == loginIndex.end())
- return -1;
-if (user)
- *user = iter->second;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByName(const std::string & login, USER_PTR * user)
-{
-STG_LOCKER lock(&mutex);
-user_iter u;
-if (FindByNameNonLock(login, &u))
- return -1;
-*user = &(*u);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByName(const std::string & login, CONST_USER_PTR * user) const
-{
-STG_LOCKER lock(&mutex);
-const_user_iter u;
-if (FindByNameNonLock(login, &u))
- return -1;
-*user = &(*u);
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::Exists(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-return iter != loginIndex.end();
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::TariffInUse(const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-std::list<USER_IMPL>::const_iterator iter;
-iter = users.begin();
-while (iter != users.end())
- {
- if (iter->GetProperty().tariffName.Get() == tariffName)
- return true;
- ++iter;
- }
-return false;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::Add(const std::string & login, const ADMIN * admin)
-{
-STG_LOCKER lock(&mutex);
-const PRIV * priv = admin->GetPriv();
-
-if (!priv->userAddDel)
- {
- WriteServLog("%s tried to add user \'%s\'. Access denied.",
- admin->GetLogStr().c_str(), login.c_str());
- /*errorStr = "Admin \'" + admin->GetLogin() +
- "\': tried to add user \'" + ud->login + "\'. Access denied.";*/
- return -1;
- }
-
-//////
-if (store->AddUser(login))
- {
- //TODO
- //WriteServLog("Admin \'%s\': tried to add user \'%s\'. Access denied.",
- // admin->GetLogin().c_str(), ud->login.c_str());
- return -1;
- }
-//////
-
-USER_IMPL u(settings, store, tariffs, sysAdmin, this, m_services);
-
-/*struct tm * tms;
-time_t t = stgTime;
-
-tms = localtime(&t);
-
-tms->tm_hour = 0;
-tms->tm_min = 0;
-tms->tm_sec = 0;
-
-if (settings->GetDayResetTraff() > tms->tm_mday)
- tms->tm_mon -= 1;
-
-tms->tm_mday = settings->GetDayResetTraff();*/
-
-u.SetLogin(login);
-
-u.SetPassiveTimeAsNewUser();
-
-u.WriteConf();
-u.WriteStat();
-
-WriteServLog("%s User \'%s\' added.",
- admin->GetLogStr().c_str(), login.c_str());
-
-u.OnAdd();
-
-users.push_front(u);
-
-AddUserIntoIndexes(users.begin());
-
- {
- // Fire all "on add" notifiers
- std::set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onAddNotifiers.begin();
- while (ni != onAddNotifiers.end())
- {
- (*ni)->Notify(&users.front());
- ++ni;
- }
- }
-
- {
- // Fire all "on add" implementation notifiers
- std::set<NOTIFIER_BASE<USER_IMPL_PTR> *>::iterator ni = onAddNotifiersImpl.begin();
- while (ni != onAddNotifiersImpl.end())
- {
- (*ni)->Notify(&users.front());
- ++ni;
- }
- }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::Del(const std::string & login, const ADMIN * admin)
-{
-const PRIV * priv = admin->GetPriv();
-user_iter u;
-
-if (!priv->userAddDel)
- {
- WriteServLog("%s tried to remove user \'%s\'. Access denied.",
- admin->GetLogStr().c_str(), login.c_str());
- return;
- }
-
-
- {
- STG_LOCKER lock(&mutex);
-
- if (FindByNameNonLock(login, &u))
- {
- WriteServLog("%s tried to delete user \'%s\': not found.",
- admin->GetLogStr().c_str(),
- login.c_str());
- return;
- }
-
- u->SetDeleted();
- }
-
- {
- std::set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onDelNotifiers.begin();
- while (ni != onDelNotifiers.end())
- {
- (*ni)->Notify(&(*u));
- ++ni;
- }
- }
-
- {
- std::set<NOTIFIER_BASE<USER_IMPL_PTR> *>::iterator ni = onDelNotifiersImpl.begin();
- while (ni != onDelNotifiersImpl.end())
- {
- (*ni)->Notify(&(*u));
- ++ni;
- }
- }
-
- {
- STG_LOCKER lock(&mutex);
-
- u->OnDelete();
-
- USER_TO_DEL utd;
- utd.iter = u;
- utd.delTime = stgTime;
- usersToDelete.push_back(utd);
-
- DelUserFromIndexes(u);
-
- WriteServLog("%s User \'%s\' deleted.",
- admin->GetLogStr().c_str(), login.c_str());
-
- }
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::Authorize(const std::string & login, uint32_t ip,
- uint32_t enabledDirs, const AUTH * auth)
-{
-user_iter iter;
-STG_LOCKER lock(&mutex);
-if (FindByNameNonLock(login, &iter))
- {
- WriteServLog("Attempt to authorize non-existant user '%s'", login.c_str());
- return false;
- }
-
-if (FindByIPIdx(ip, iter))
- {
- if (iter->GetLogin() != login)
- {
- WriteServLog("Attempt to authorize user '%s' from ip %s which already occupied by '%s'",
- login.c_str(), inet_ntostring(ip).c_str(),
- iter->GetLogin().c_str());
- return false;
- }
- if (iter->Authorize(ip, enabledDirs, auth))
- return false;
- return true;
- }
-
-if (iter->Authorize(ip, enabledDirs, auth))
- return false;
-
-AddToIPIdx(iter);
-return true;
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::Unauthorize(const std::string & login,
- const AUTH * auth,
- const std::string & reason)
-{
-user_iter iter;
-STG_LOCKER lock(&mutex);
-if (FindByNameNonLock(login, &iter))
- {
- WriteServLog("Attempt to unauthorize non-existant user '%s'", login.c_str());
- printfd(__FILE__, "Attempt to unauthorize non-existant user '%s'", login.c_str());
- return false;
- }
-
-uint32_t ip = iter->GetCurrIP();
-
-iter->Unauthorize(auth, reason);
-
-if (!iter->GetAuthorized())
- DelFromIPIdx(ip);
-
-return true;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::ReadUsers()
-{
-std::vector<std::string> usersList;
-usersList.clear();
-if (store->GetUsersList(&usersList) < 0)
- {
- WriteServLog(store->GetStrError().c_str());
- return -1;
- }
-
-user_iter ui;
-
-unsigned errors = 0;
-for (unsigned int i = 0; i < usersList.size(); i++)
- {
- USER_IMPL u(settings, store, tariffs, sysAdmin, this, m_services);
-
- u.SetLogin(usersList[i]);
- users.push_front(u);
- ui = users.begin();
-
- AddUserIntoIndexes(ui);
-
- if (settings->GetStopOnError())
- {
- if (ui->ReadConf() < 0)
- return -1;
-
- if (ui->ReadStat() < 0)
- return -1;
- }
- else
- {
- if (ui->ReadConf() < 0)
- errors++;
-
- if (ui->ReadStat() < 0)
- errors++;
- }
- }
-
-if (errors > 0)
- return -1;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * USERS_IMPL::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-USERS_IMPL * us = static_cast<USERS_IMPL *>(d);
-
-struct tm t;
-time_t tt = stgTime;
-localtime_r(&tt, &t);
-
-int min = t.tm_min;
-int day = t.tm_mday;
-
-printfd(__FILE__,"Day = %d Min = %d\n", day, min);
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-std::string monFile = us->settings->GetMonitorDir() + "/users_r";
-printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
-
-us->isRunning = true;
-while (us->nonstop)
- {
- //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
- //printfd(__FILE__,"New Day. old = %2d current = %2d\n", day, t->tm_mday);
-
- for_each(us->users.begin(), us->users.end(), std::mem_fun_ref(&USER_IMPL::Run));
-
- tt = stgTime;
- localtime_r(&tt, &t);
-
- if (min != t.tm_min)
- {
- printfd(__FILE__,"Sec = %d\n", stgTime);
- printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
- min = t.tm_min;
-
- us->NewMinute(t);
- }
-
- if (day != t.tm_mday)
- {
- printfd(__FILE__,"Sec = %d\n", stgTime);
- printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
- day = t.tm_mday;
- us->NewDay(t);
- }
-
- if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
- {
- //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
- touchTime = stgTime;
- TouchFile(monFile);
- }
-
- stgUsleep(100000);
- } //while (us->nonstop)
-
-std::list<USER_TO_DEL>::iterator iter(us->usersToDelete.begin());
-while (iter != us->usersToDelete.end())
- {
- iter->delTime -= 2 * userDeleteDelayTime;
- ++iter;
- }
-us->RealDelUser();
-
-us->isRunning = false;
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::NewMinute(const struct tm & t)
-{
-//Write traff, reset session traff. Fake disconnect-connect
-if (t.tm_hour == 23 && t.tm_min == 59)
- {
- printfd(__FILE__,"MidnightResetSessionStat\n");
- for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::MidnightResetSessionStat));
- }
-
-if (TimeToWriteDetailStat(t))
- {
- //printfd(__FILE__, "USER::WriteInetStat\n");
- int usersCnt = 0;
-
- // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
- std::list<USER_IMPL>::iterator usr = users.begin();
- while (usr != users.end())
- {
- usersCnt++;
- usr->WriteDetailStat();
- ++usr;
- if (usersCnt % 10 == 0)
- for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::Run));
- }
- }
-
-RealDelUser();
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::NewDay(const struct tm & t)
-{
-struct tm t1;
-time_t tt = stgTime;
-localtime_r(&tt, &t1);
-int dayFee = settings->GetDayFee();
-
-if (dayFee == 0)
- dayFee = DaysInCurrentMonth();
-
-printfd(__FILE__, "DayFee = %d\n", dayFee);
-printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1.tm_mday, settings->GetDayResetTraff());
-printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
-
-if (!settings->GetDayFeeIsLastDay())
- {
- printfd(__FILE__, "DayResetTraff - 1 -\n");
- DayResetTraff(t1);
- //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
- }
-
-if (settings->GetSpreadFee())
- {
- printfd(__FILE__, "Spread DayFee\n");
- for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDayFeeSpread));
- }
-else
- {
- if (t.tm_mday == dayFee)
- {
- printfd(__FILE__, "DayFee\n");
- for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDayFee));
- }
- }
-
-std::for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDailyFee));
-std::for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessServices));
-
-if (settings->GetDayFeeIsLastDay())
- {
- printfd(__FILE__, "DayResetTraff - 2 -\n");
- DayResetTraff(t1);
- }
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DayResetTraff(const struct tm & t1)
-{
-int dayResetTraff = settings->GetDayResetTraff();
-if (dayResetTraff == 0)
- dayResetTraff = DaysInCurrentMonth();
-if (t1.tm_mday == dayResetTraff)
- {
- printfd(__FILE__, "ResetTraff\n");
- for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessNewMonth));
- //for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::SetPrepaidTraff));
- }
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::Start()
-{
-if (ReadUsers())
- {
- WriteServLog("USERS: Error: Cannot read users!");
- return -1;
- }
-
-nonstop = true;
-if (pthread_create(&thread, NULL, Run, this))
- {
- WriteServLog("USERS: Error: Cannot start thread!");
- return -1;
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::Stop()
-{
-printfd(__FILE__, "USERS::Stop()\n");
-
-if (!isRunning)
- {
- //printfd(__FILE__, "Alredy stopped\n");
- return 0;
- }
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (size_t i = 0; i < 25 * (users.size() / 50 + 1); i++)
- {
- if (!isRunning)
- break;
-
- nanosleep(&ts, NULL);
- }
-
-//after 5 seconds waiting thread still running. now kill it
-if (isRunning)
- {
- printfd(__FILE__, "kill USERS thread.\n");
- //TODO pthread_cancel()
- if (pthread_kill(thread, SIGINT))
- {
- //errorStr = "Cannot kill USERS thread.";
- //printfd(__FILE__, "Cannot kill USERS thread.\n");
- //return 0;
- }
- printfd(__FILE__, "USERS killed\n");
- }
-
-printfd(__FILE__, "Before USERS::Run()\n");
-for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::Run));
-
-// 'cause bind2st accepts only constant first param
-for (std::list<USER_IMPL>::iterator it = users.begin();
- it != users.end();
- ++it)
- it->WriteDetailStat(true);
-
-for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::WriteStat));
-//for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::WriteConf));
-
-printfd(__FILE__, "USERS::Stop()\n");
-return 0;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::RealDelUser()
-{
-STG_LOCKER lock(&mutex);
-
-printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
-
-std::list<USER_TO_DEL>::iterator iter;
-iter = usersToDelete.begin();
-while (iter != usersToDelete.end())
- {
- printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
- if (iter->delTime + userDeleteDelayTime < stgTime)
- {
- printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
- if (store->DelUser(iter->iter->GetLogin()))
- {
- WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
- }
- users.erase(iter->iter);
- usersToDelete.erase(iter++);
- }
- else
- {
- ++iter;
- }
- }
-return;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddToIPIdx(user_iter user)
-{
-printfd(__FILE__, "USERS: Add IP Idx\n");
-uint32_t ip = user->GetCurrIP();
-//assert(ip && "User has non-null ip");
-if (!ip)
- return; // User has disconnected
-
-STG_LOCKER lock(&mutex);
-
-const std::map<uint32_t, user_iter>::iterator it(
- ipIndex.lower_bound(ip)
-);
-
-assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
-
-ipIndex.insert(it, std::make_pair(ip, user));
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelFromIPIdx(uint32_t ip)
-{
-printfd(__FILE__, "USERS: Del IP Idx\n");
-assert(ip && "User has non-null ip");
-
-STG_LOCKER lock(&mutex);
-
-const std::map<uint32_t, user_iter>::iterator it(
- ipIndex.find(ip)
-);
-
-if (it == ipIndex.end())
- return;
-
-ipIndex.erase(it);
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::FindByIPIdx(uint32_t ip, user_iter & iter) const
-{
-std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
-if (it == ipIndex.end())
- return false;
-iter = it->second;
-return true;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByIPIdx(uint32_t ip, USER_PTR * usr) const
-{
-STG_LOCKER lock(&mutex);
-
-user_iter iter;
-if (FindByIPIdx(ip, iter))
- {
- *usr = &(*iter);
- return 0;
- }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::FindByIPIdx(uint32_t ip, USER_IMPL ** usr) const
-{
-STG_LOCKER lock(&mutex);
-
-user_iter iter;
-if (FindByIPIdx(ip, iter))
- {
- *usr = &(*iter);
- return 0;
- }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::IsIPInIndex(uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
-
-return it != ipIndex.end();
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::IsIPInUse(uint32_t ip, const std::string & login, CONST_USER_PTR * user) const
-{
-STG_LOCKER lock(&mutex);
-std::list<USER_IMPL>::const_iterator iter;
-iter = users.begin();
-while (iter != users.end())
- {
- if (iter->GetLogin() != login &&
- !iter->GetProperty().ips.Get().IsAnyIP() &&
- iter->GetProperty().ips.Get().IsIPInIPS(ip))
- {
- if (user != NULL)
- *user = &(*iter);
- return true;
- }
- ++iter;
- }
-return false;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiersImpl.insert(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiersImpl.erase(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiersImpl.insert(n);
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiersImpl.erase(n);
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::OpenSearch()
-{
-STG_LOCKER lock(&mutex);
-handle++;
-searchDescriptors[handle] = users.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::SearchNext(int h, USER_PTR * user)
-{
- USER_IMPL * ptr = NULL;
- if (SearchNext(h, &ptr))
- return -1;
- *user = ptr;
- return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::SearchNext(int h, USER_IMPL ** user)
-{
-STG_LOCKER lock(&mutex);
-
-if (searchDescriptors.find(h) == searchDescriptors.end())
- {
- WriteServLog("USERS. Incorrect search handle.");
- return -1;
- }
-
-if (searchDescriptors[h] == users.end())
- return -1;
-
-while (searchDescriptors[h]->GetDeleted())
- {
- ++searchDescriptors[h];
- if (searchDescriptors[h] == users.end())
- {
- return -1;
- }
- }
-
-*user = &(*searchDescriptors[h]);
-
-++searchDescriptors[h];
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USERS_IMPL::CloseSearch(int h)
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
- {
- searchDescriptors.erase(searchDescriptors.find(h));
- return 0;
- }
-
-WriteServLog("USERS. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::AddUserIntoIndexes(user_iter user)
-{
-STG_LOCKER lock(&mutex);
-loginIndex.insert(make_pair(user->GetLogin(), user));
-}
-//-----------------------------------------------------------------------------
-void USERS_IMPL::DelUserFromIndexes(user_iter user)
-{
-STG_LOCKER lock(&mutex);
-loginIndex.erase(user->GetLogin());
-}
-//-----------------------------------------------------------------------------
-bool USERS_IMPL::TimeToWriteDetailStat(const struct tm & t)
-{
-int statTime = settings->GetDetailStatWritePeriod();
-
-switch (statTime)
- {
- case dsPeriod_1:
- if (t.tm_min == 0)
- return true;
- break;
- case dsPeriod_1_2:
- if (t.tm_min % 30 == 0)
- return true;
- break;
- case dsPeriod_1_4:
- if (t.tm_min % 15 == 0)
- return true;
- break;
- case dsPeriod_1_6:
- if (t.tm_min % 10 == 0)
- return true;
- break;
- }
-return false;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-/*
-$Revision: 1.31 $
-$Date: 2010/10/07 20:04:48 $
-$Author: faust $
-*/
-
-
-#ifndef USERS_IMPL_H
-#define USERS_IMPL_H
-
-#include <pthread.h>
-
-#include <ctime>
-#include <string>
-#include <map>
-#include <list>
-#include <set>
-
-#include "stg/os_int.h"
-#include "stg/store.h"
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/tariffs.h"
-#include "stg/logger.h"
-#include "stg/notifer.h"
-#include "stg/noncopyable.h"
-#include "actions.h"
-#include "eventloop.h"
-#include "settings_impl.h"
-#include "user_impl.h"
-
-const int userDeleteDelayTime = 120;
-
-typedef std::list<USER_IMPL>::iterator user_iter;
-typedef std::list<USER_IMPL>::const_iterator const_user_iter;
-
-class USERS_IMPL;
-//-----------------------------------------------------------------------------
-struct USER_TO_DEL {
-USER_TO_DEL()
- : iter(),
- delTime(0)
-{}
-
-std::list<USER_IMPL>::iterator iter;
-time_t delTime;
-};
-//-----------------------------------------------------------------------------
-class USERS_IMPL : private NONCOPYABLE, public USERS {
- friend class PROPERTY_NOTIFER_IP_BEFORE;
- friend class PROPERTY_NOTIFER_IP_AFTER;
-
-public:
- USERS_IMPL(SETTINGS_IMPL * s, STORE * store,
- TARIFFS * tariffs, SERVICES & svcs,
- const ADMIN * sysAdmin);
- virtual ~USERS_IMPL();
-
- int FindByName(const std::string & login, USER_PTR * user);
- int FindByName(const std::string & login, CONST_USER_PTR * user) const;
-
- bool Exists(const std::string & login) const;
-
- bool TariffInUse(const std::string & tariffName) const;
-
- void AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> *);
- void DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> *);
-
- void AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> *);
- void DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> *);
-
- void AddNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> *);
- void DelNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> *);
-
- void AddNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> *);
- void DelNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> *);
-
- int Add(const std::string & login, const ADMIN * admin);
- void Del(const std::string & login, const ADMIN * admin);
-
- bool Authorize(const std::string & login, uint32_t ip,
- uint32_t enabledDirs, const AUTH * auth);
- bool Unauthorize(const std::string & login,
- const AUTH * auth,
- const std::string & reason = std::string());
-
- int ReadUsers();
- size_t Count() const { return users.size(); }
-
- int FindByIPIdx(uint32_t ip, USER_PTR * user) const;
- int FindByIPIdx(uint32_t ip, USER_IMPL ** user) const;
- bool IsIPInIndex(uint32_t ip) const;
- bool IsIPInUse(uint32_t ip, const std::string & login, CONST_USER_PTR * user) const;
-
- int OpenSearch();
- int SearchNext(int handler, USER_PTR * user);
- int SearchNext(int handler, USER_IMPL ** user);
- int CloseSearch(int handler);
-
- int Start();
- int Stop();
-
-private:
- USERS_IMPL(const USERS_IMPL & rvalue);
- USERS_IMPL & operator=(const USERS_IMPL & rvalue);
-
- void AddToIPIdx(user_iter user);
- void DelFromIPIdx(uint32_t ip);
- bool FindByIPIdx(uint32_t ip, user_iter & iter) const;
-
- int FindByNameNonLock(const std::string & login, user_iter * user);
- int FindByNameNonLock(const std::string & login, const_user_iter * user) const;
-
- void RealDelUser();
- void ProcessActions();
-
- void AddUserIntoIndexes(user_iter user);
- void DelUserFromIndexes(user_iter user);
-
- static void * Run(void *);
- void NewMinute(const struct tm & t);
- void NewDay(const struct tm & t);
- void DayResetTraff(const struct tm & t);
-
- bool TimeToWriteDetailStat(const struct tm & t);
-
- std::list<USER_IMPL> users;
- std::list<USER_TO_DEL> usersToDelete;
-
- std::map<uint32_t, user_iter> ipIndex;
- std::map<std::string, user_iter> loginIndex;
-
- SETTINGS_IMPL * settings;
- TARIFFS * tariffs;
- SERVICES & m_services;
- STORE * store;
- const ADMIN * sysAdmin;
- STG_LOGGER & WriteServLog;
-
- bool nonstop;
- bool isRunning;
-
- mutable pthread_mutex_t mutex;
- pthread_t thread;
- mutable unsigned int handle;
-
- mutable std::map<int, user_iter> searchDescriptors;
-
- std::set<NOTIFIER_BASE<USER_PTR>*> onAddNotifiers;
- std::set<NOTIFIER_BASE<USER_PTR>*> onDelNotifiers;
- std::set<NOTIFIER_BASE<USER_IMPL_PTR>*> onAddNotifiersImpl;
- std::set<NOTIFIER_BASE<USER_IMPL_PTR>*> onDelNotifiersImpl;
-};
-//-----------------------------------------------------------------------------
-/*inline
-void PROPERTY_NOTIFER_IP_BEFORE::Notify(const uint32_t & oldValue,
- const uint32_t &)
-{
-if (!oldValue)
- return;
-
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::DelFromIPIdx, oldValue);
-// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
-users.DelFromIPIdx(oldValue);
-}
-//-----------------------------------------------------------------------------
-inline
-void PROPERTY_NOTIFER_IP_AFTER::Notify(const uint32_t &,
- const uint32_t & newValue)
-{
-if (!newValue)
- return;
-
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::AddToIPIdx, user);
-// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
-users.AddToIPIdx(user);
-}*/
-//-----------------------------------------------------------------------------
-#endif
--- /dev/null
+find_package ( YAJL REQUIRED )
+
+set ( CPP_FILES conn.cpp iface.cpp stg_client.cpp )
+set ( C_FILES rlm_stg.c radlog.c )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_library ( rlm_stg MODULE ${CPP_FILES} ${C_FILES} )
+
+target_link_libraries ( rlm_stg crypto common json dl YAJL::YAJL )
+
+# TODO: install
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#!/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 <iconv.h>\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 <stdio.h>\n" > build_check.c
+ printf "#include <yajl/yajl_version.h>\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 <boost/scoped_ptr.hpp>\nint main() { boost::scoped_ptr<int> 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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "conn.h"
+
+#include "radlog.h"
+#include "stgpair.h"
+
+#include "stg/json_parser.h"
+#include "stg/json_generator.h"
+#include "stg/locker.h"
+
+#include <cerrno>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h> // UNIX
+#include <netinet/in.h> // IP
+#include <netinet/tcp.h> // TCP
+#include <netdb.h>
+
+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<std::string, Packet> packetCodes;
+std::map<std::string, bool> resultCodes;
+std::map<std::string, int> returnCodes;
+
+class PacketParser : public EnumParser<Packet>
+{
+ 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<bool>
+{
+ 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<int>
+{
+ 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<struct sockaddr*>(&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<char> 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<Impl*>(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<Conn::Impl*>(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<Impl*>(data);
+ impl.runImpl();
+ return NULL;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_RLM_CONN_H__
+#define __STG_RLM_CONN_H__
+
+#include "types.h"
+
+#include <boost/scoped_ptr.hpp>
+
+#include <string>
+#include <stdexcept>
+#include <cstdint>
+
+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<Impl> m_impl;
+};
+
+}
+}
+
+#endif
--- /dev/null
+#include "iface.h"
+
+#include "stg_client.h"
+#include "types.h"
+#include "radlog.h"
+
+#include <stdexcept>
+#include <cstring>
+
+#include <strings.h>
+
+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<std::string, std::string>(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);
+}
--- /dev/null
+#ifndef __STG_IFACE_H__
+#define __STG_IFACE_H__
+
+#include <stdint.h>
+
+#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
--- /dev/null
+#include "radlog.h"
+
+//#ifndef NDEBUG
+//#define NDEBUG
+#include <freeradius/ident.h>
+#include <freeradius/radiusd.h>
+#include <freeradius/modules.h>
+//#undef NDEBUG
+//#endif
+
+#include <stdarg.h>
+
+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);
+}
--- /dev/null
+#ifndef __STG_RADLOG_H__
+#define __STG_RADLOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void RadLog(const char* format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * FreeRADIUS module for data access via Stargazer
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/08/14 04:15:08 $
+ *
+ */
+
+#include "iface.h"
+#include "stgpair.h"
+
+#include <freeradius/ident.h>
+#include <freeradius/radiusd.h>
+#include <freeradius/modules.h>
+
+#include <stddef.h> // 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 */
+ },
+};
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "stg_client.h"
+
+#include "conn.h"
+#include "radlog.h"
+
+#include "stg/locker.h"
+#include "stg/common.h"
+
+#include <map>
+#include <utility>
+
+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<Conn> 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<Impl*>(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;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_RLM_CLIENT_H__
+#define __STG_RLM_CLIENT_H__
+
+#include "types.h"
+
+#include <boost/scoped_ptr.hpp>
+
+#include <string>
+#include <cstdint>
+
+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<Impl> m_impl;
+};
+
+} // namespace RLM
+} // namespace STG
+
+#endif
--- /dev/null
+#ifndef __STG_STGPAIR_H__
+#define __STG_STGPAIR_H__
+
+#include <stddef.h>
+
+#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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_RLM_CLIENT_CONN_H__
+#define __STG_RLM_CLIENT_CONN_H__
+
+#include <vector>
+#include <string>
+
+namespace STG
+{
+namespace RLM
+{
+
+typedef std::vector<std::pair<std::string, std::string> > PAIRS;
+
+struct RESULT
+{
+ PAIRS modify;
+ PAIRS reply;
+ int returnCode;
+};
+
+enum REQUEST_TYPE {
+ AUTHORIZE,
+ AUTHENTICATE,
+ POST_AUTH,
+ PRE_ACCT,
+ ACCOUNT
+};
+
+} // namespace RLM
+} // namespace STG
+
+#endif
--- /dev/null
+set ( CPP_FILES main.cpp listener.cpp pidfile.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( rscriptd ${CPP_FILES} )
+
+target_link_libraries ( rscriptd scriptexecuter conffiles logger crypto common Threads::Threads )
+
+# TODO: install
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#!/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 <iconv.h>\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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <arpa/inet.h>
+#include <sys/uio.h> // readv
+#include <sys/types.h> // for historical versions of BSD
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <csignal>
+#include <cerrno>
+#include <ctime>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+#include "stg/scriptexecuter.h"
+#include "stg/locker.h"
+#include "stg/common.h"
+#include "stg/const.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<LISTENER *>(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<LISTENER *>(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<char *>(&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<PendingData>::iterator it(pending.begin());
+size_t count = 0;
+printfd(__FILE__, "Pending: %d\n", pending.size());
+while (it != pending.end() && count < 256)
+ {
+ std::vector<AliveData>::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<UserData>(*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<AliveData>::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));
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <pthread.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <functional>
+#include <cstdint>
+
+#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<const AliveData &, bool> {
+ 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<AliveData> users;
+ std::list<PendingData> 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<const UserData &, void> {
+ public:
+ explicit DisconnectUser(LISTENER & l) : listener(l) {};
+ void operator()(const UserData & data)
+ {
+ listener.Disconnect(data);
+ };
+ private:
+ LISTENER & listener;
+};
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.19 $
+ $Author: faust $
+ $Date: 2010/09/10 06:37:45 $
+ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h> // creat
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <csignal>
+#include <cerrno>
+#include <cstring> // strerror
+#include <set>
+
+#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<pid_t> executersPid;
+volatile time_t stgTime = time(NULL);
+
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+std::set<pid_t>::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;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2010/02/11 12:32:25 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#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());
+ }
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * 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 <string>
+
+class PIDFile {
+public:
+ explicit PIDFile(const std::string & fn);
+ ~PIDFile();
+private:
+ std::string fileName;
+};
+
+#endif
--- /dev/null
+################################################################################
+# 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
+
+################################################################################
--- /dev/null
+css.h
+sgauth
--- /dev/null
+set ( CPP_FILES main.cpp settings_impl.cpp web.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( sgauth ${CPP_FILES} )
+
+target_link_libraries ( sgauth conffiles ia crypto common Threads::Threads )
+
+# TODO: install
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+#!/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 <iconv.h>\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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.13 $
+ $Date: 2010/04/14 09:01:29 $
+ $Author: faust $
+ */
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <csignal>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#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 <path_to_config>\n");
+}
+//-----------------------------------------------------------------------------
+void SetDirName(const std::vector<std::string> & 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;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+#!/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
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include <iostream>
+#include <cstring>
+
+#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;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef SETTINGS_IMPL_H
+#define SETTINGS_IMPL_H
+
+#include <string>
+#include <cstdint>
+
+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
--- /dev/null
+################################################################################
+# 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
+
+################################################################################
--- /dev/null
+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;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.7 $
+ $Date: 2010/03/15 12:58:17 $
+ */
+
+#include <libintl.h>
+
+#include <csignal>
+#include <cstdio>
+#include <cstring>
+#include <ctime>
+
+#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"
+ "<html>\n"
+ "<head>\n"
+ "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
+ "</head>\n"
+ "<body>\n"
+ "</body></html>\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"
+ "<html>\n"
+ "<head>\n"
+ "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
+ "<title>sgauth</title>\n"
+ "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
+ "</head>\n"
+ "<body>\n"
+ "<H3>Stargazer</H3><p>\n";
+
+const char * replyFooter = "</body></html>\n\n";
+
+char replyHeaderBuffer[2000];
+sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
+
+send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
+
+char str[512];
+
+int st = clnp->GetAuthorized();
+
+sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
+ gettext("PrepaidTraffic"),
+ ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<TABLE id=\"TraffTable\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, " <TR id=\"TraffTableCaptionRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, " <TD id=\"TraffTableCaptionCellC\"> </TD>\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, " <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str," <TR id=\"TraffTableUMRow\">\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str," <TD id=\"TraffTableUMCellC\">%s</TD>\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," <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TR id=\"TraffTableDMRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableDMCellC\">%s</TD>\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," <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+
+sprintf(str," <TR id=\"TraffTableUSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableUSCellC\">%s</TD>\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," <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TR id=\"TraffTableDSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableDSCellC\">%s</TD>\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," <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str,"</TABLE>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+if (!messages.empty())
+ {
+ sprintf(str," <TABLE id=\"MessagesTable\">\n");
+ res = send(outerSocket, str, strlen(str), 0);
+
+ sprintf(str," <TR id=\"MessagesTableRowC\">\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>Date</TD>\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>Text</TD>\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," </TR>\n");
+ send(outerSocket, str, strlen(str), 0);
+
+ std::list<STG_MESSAGE>::reverse_iterator it;
+ it = messages.rbegin();
+ while (it != messages.rend())
+ {
+ sprintf(str," <TR id=\"MessagesTableRow%d\">\n", rowNum);
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>%s</TD>\n", it->recvTime.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>%s</TD>\n", it->msg.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," </TR>\n");
+ send(outerSocket, str, strlen(str), 0);
+ ++it;
+ ++rowNum;
+ }
+
+ sprintf(str," </TABLE>\n");
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+time_t t = time(NULL);
+sprintf(str,"Îáíîâëåíî: %s</b>" , 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));
+}
+//---------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2007/12/17 08:39:08 $
+ */
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <string>
+#include <list>
+
+#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<STG_MESSAGE> messages;
+};
+//-----------------------------------------------------------------------------
--- /dev/null
+find_package ( EXPAT REQUIRED )
+
+set ( CPP_FILES main.cpp options.cpp api_action.cpp actions.cpp admins.cpp tariffs.cpp users.cpp services.cpp corps.cpp info.cpp xml.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( sgconf ${CPP_FILES} )
+
+target_link_libraries ( sgconf srvconf crypto common EXPAT::EXPAT )
+
+# TODO: install
--- /dev/null
+###############################################################################
+# $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
--- /dev/null
+Compiling:
+> ./build
+
+
--- /dev/null
+1. No default value for server.
+2. No default value for port.
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_ACTION_H__
+#define __STG_SGCONF_ACTION_H__
+
+#include <string>
+#include <map>
+#include <stdexcept>
+
+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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+
+#include <cassert>
+
+namespace SGCONF
+{
+
+typedef void (* FUNC0)();
+
+template <typename F>
+class FUNC0_ACTION : public ACTION
+{
+ public:
+ FUNC0_ACTION(const F & func) : m_func(func) {}
+
+ virtual ACTION * Clone() const { return new FUNC0_ACTION<F>(*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 <typename F>
+inline
+FUNC0_ACTION<F> * MakeFunc0Action(F func)
+{
+return new FUNC0_ACTION<F>(func);
+}
+
+template <typename T>
+class PARAM_ACTION : public ACTION
+{
+ public:
+ PARAM_ACTION(RESETABLE<T> & param,
+ const T & defaultValue,
+ const std::string & paramDescription)
+ : m_param(param),
+ m_defaltValue(defaultValue),
+ m_description(paramDescription),
+ m_hasDefault(true)
+ {}
+ PARAM_ACTION(RESETABLE<T> & param)
+ : m_param(param),
+ m_hasDefault(false)
+ {}
+ PARAM_ACTION(RESETABLE<T> & param,
+ const std::string & paramDescription)
+ : m_param(param),
+ m_description(paramDescription),
+ m_hasDefault(false)
+ {}
+
+ virtual ACTION * Clone() const { return new PARAM_ACTION<T>(*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<T> & m_param;
+ T m_defaltValue;
+ std::string m_description;
+ bool m_hasDefault;
+ OPTION_BLOCK m_suboptions;
+};
+
+template <typename T>
+inline
+std::string PARAM_ACTION<T>::DefaultDescription() const
+{
+return m_hasDefault ? " (default: '" + x2str(m_defaltValue) + "')"
+ : "";
+}
+
+template <>
+inline
+std::string PARAM_ACTION<std::string>::DefaultDescription() const
+{
+return m_hasDefault ? " (default: '" + m_defaltValue + "')"
+ : "";
+}
+
+template <typename T>
+inline
+PARSER_STATE PARAM_ACTION<T>::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<bool>::Parse(int argc, char ** argv, void * /*data*/)
+{
+m_param = true;
+return PARSER_STATE(false, argc, argv);
+}
+
+template <typename T>
+inline
+void PARAM_ACTION<T>::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<std::string>::ParseValue(const std::string & stringValue)
+{
+m_param = stringValue;
+}
+
+template <>
+inline
+PARSER_STATE PARAM_ACTION<std::string>::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 <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param,
+ const T & defaultValue,
+ const std::string & paramDescription)
+{
+return new PARAM_ACTION<T>(param, defaultValue, paramDescription);
+}
+
+template <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param)
+{
+return new PARAM_ACTION<T>(param);
+}
+
+template <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(RESETABLE<T> & param,
+ const std::string & paramDescription)
+{
+return new PARAM_ACTION<T>(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<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(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
--- /dev/null
+#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 <iostream>
+#include <string>
+#include <map>
+#include <cstdint>
+#include <cassert>
+
+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<SGCONF::API_ACTION::PARAM> GetAdminParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
+params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
+return params;
+}
+
+void ConvPriv(const std::string & value, RESETABLE<PRIV> & 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<STG::GET_ADMIN::INFO> & 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<STG::GET_ADMIN::INFO> & info,
+ void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the admin's login.");
+const std::string & login = *static_cast<const std::string *>(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<std::string, std::string> & /*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<std::string, std::string> & /*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 <GetAdmin login="..."/>.
+// 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<std::string, std::string> & /*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<std::string, std::string> & 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<std::string, std::string> & 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<API_ACTION::PARAM> params(GetAdminParams());
+blocks.Add("Admin management options")
+ .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list")
+ .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", GetAdminFunction), "get admin")
+ .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", params, AddAdminFunction), "add admin")
+ .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", DelAdminFunction), "del admin")
+ .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", params, ChgAdminFunction), "change admin");
+}
--- /dev/null
+#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
--- /dev/null
+#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<PARAM> & params,
+ API_FUNCTION funPtr)
+ : m_commands(commands),
+ m_description(paramDescription),
+ m_argument(needArgument ? "1" : ""), // Hack
+ m_funPtr(funPtr)
+{
+std::vector<PARAM>::const_iterator it(params.begin());
+while (it != params.end())
+ {
+ m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
+ ++it;
+ }
+}
--- /dev/null
+#ifndef __STG_SGCONF_API_ACTION_H__
+#define __STG_SGCONF_API_ACTION_H__
+
+#include "action.h"
+
+#include "options.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+namespace SGCONF
+{
+
+typedef bool (* API_FUNCTION) (const CONFIG &,
+ const std::string &,
+ const std::map<std::string, std::string> &);
+
+class COMMAND
+{
+ public:
+ COMMAND(API_FUNCTION funPtr,
+ const std::string & arg,
+ const std::map<std::string, std::string> & 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<std::string, std::string> m_options;
+};
+
+class COMMANDS
+{
+ public:
+ void Add(API_FUNCTION funPtr,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
+ bool Execute(const SGCONF::CONFIG & config) const
+ {
+ std::vector<COMMAND>::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<COMMAND> 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<PARAM> & 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<std::string, std::string> m_params;
+ API_FUNCTION m_funPtr;
+};
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ const std::string & paramDescription,
+ const std::vector<API_ACTION::PARAM> & params,
+ API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, paramDescription, true, params, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ const std::vector<API_ACTION::PARAM> & 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
--- /dev/null
+#!/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 <iconv.h>\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
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_CONFIG_H__
+#define __STG_SGCONF_CONFIG_H__
+
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+#include <cstdint>
+
+namespace SGCONF
+{
+
+struct CONFIG
+{
+ RESETABLE<std::string> configFile;
+ RESETABLE<std::string> server;
+ RESETABLE<uint16_t> port;
+ RESETABLE<std::string> localAddress;
+ RESETABLE<uint16_t> localPort;
+ RESETABLE<std::string> userName;
+ RESETABLE<std::string> userPass;
+ RESETABLE<bool> 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
--- /dev/null
+#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 <iostream>
+#include <string>
+#include <map>
+
+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<SGCONF::API_ACTION::PARAM> GetCorpParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cash", "<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<STG::GET_CORP::INFO> & 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<std::string, std::string> & /*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<std::string, std::string> & /*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<std::string, std::string> & /*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<std::string, std::string> & 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<std::string, std::string> & 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<API_ACTION::PARAM> params(GetCorpParams());
+blocks.Add("Corporation management options")
+ .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list")
+ .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", GetCorpFunction), "get corporation")
+ .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", params, AddCorpFunction), "add corporation")
+ .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", DelCorpFunction), "delete corporation")
+ .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", params, ChgCorpFunction), "change corporation");
+}
--- /dev/null
+#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
--- /dev/null
+#include "info.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <expat.h>
+
+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<std::string, std::string> & /*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");
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#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
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#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 <string>
+#include <iostream>
+
+#include <cstdlib> // getenv
+#include <cstring> // str*
+
+#include <unistd.h> // access
+#include <libgen.h> // basename
+
+namespace
+{
+
+template <typename T>
+struct nullary_function
+{
+typedef T result_type;
+};
+
+template <typename F>
+class binder0 : public nullary_function<typename F::result_type>
+{
+ 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 <typename F>
+inline
+binder0<F> bind0(const F & func, const typename F::argument_type & arg)
+{
+return binder0<F>(func, arg);
+}
+
+template <typename A, typename R>
+class FUNC1_ADAPTER : public std::unary_function<A, R>
+{
+ 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 <typename C, typename A, typename R>
+class METHOD1_ADAPTER : public std::unary_function<A, R>
+{
+ 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 <typename C, typename A, typename R>
+class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
+{
+ 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 <typename A, typename R>
+FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
+{
+return FUNC1_ADAPTER<A, R>(func);
+}
+
+template <typename C, typename A, typename R>
+METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
+{
+return METHOD1_ADAPTER<C, A, R>(func, obj);
+}
+
+template <typename C, typename A, typename R>
+CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
+{
+return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
+}
+
+void Version(const std::string & self)
+{
+std::cout << self << ", version: 2.0.0.\n";
+}
+
+void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
+{
+std::vector<std::string> 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<std::string>::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"), "<config file>"), "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"), "<address>"), "\t\thost to connect")
+ .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
+ .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "<address>"), "\tlocal address to bind")
+ .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), "<port>"), "\t\tlocal port to bind")
+ .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
+ .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
+ .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
+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 <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 <name>\t\t\tname of the tariff to add\n"
+ << "\t\t--fee <fee>\t\t\tstariff's fee\n"
+ << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
+ << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
+ << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
+ << "\t\t--times <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 <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
+ << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
+ << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
+ << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
+ << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
+ << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
+ << "\t\t--thresholds <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 <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 <name>\t\t\tname of the tariff to change\n"
+ << "\t\t--fee <fee>\t\t\tstariff's fee\n"
+ << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
+ << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
+ << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
+ << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
+ << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
+ << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
+ << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
+ << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
+ << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
+ << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
+ << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
+ << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageUsers(bool full)
+{
+std::cout << "Users management options:\n"
+ << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--get-user\t\t\t\tget the information about user\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--add-user\t\t\t\tadd a new user\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
+if (full)
+ std::cout << "\n\n";
+std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
+if (full)
+ std::cout << "\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageServices(bool full)
+{
+std::cout << "Services management options:\n"
+ << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
+if (full)
+ std::cout << "\t\t--name\t\t\t\tshow service's name\n"
+ << "\t\t--comment\t\t\tshow a comment to the service\n"
+ << "\t\t--cost\t\t\t\tshow service's cost\n"
+ << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
+std::cout << "\t--get-service\t\t\t\tget the information about service\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
+ << "\t\t--comment\t\t\tshow a comment to the service\n"
+ << "\t\t--cost\t\t\t\tshow service's cost\n"
+ << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
+std::cout << "\t--add-service\t\t\t\tadd a new service\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
+ << "\t\t--comment <comment>\t\ta comment to the service\n"
+ << "\t\t--cost <cost>\t\t\tservice's cost\n"
+ << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
+std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
+std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
+ << "\t\t--comment <comment>\t\ta comment to the service\n"
+ << "\t\t--cost <cost>\t\t\tservice's cost\n"
+ << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageCorporations(bool full)
+{
+std::cout << "Corporations management options:\n"
+ << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
+if (full)
+ std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
+ << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
+std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
+ << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
+std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
+ << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
+std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
+std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
+if (full)
+ std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
+ << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
+ << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
+}*/
+
+} // namespace anonymous
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "options.h"
+
+#include "action.h"
+#include "parser_state.h"
+
+#include "stg/common.h"
+
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <functional>
+#include <algorithm>
+
+#include <unistd.h>
+
+namespace
+{
+
+template <class C>
+void ReadConfigFile(const std::string & filePath, void (C::* callback)(const std::string&, const std::string&), C * obj)
+{
+std::ifstream stream(filePath.c_str());
+std::string line;
+size_t num = 0;
+while (std::getline(stream, line))
+ {
+ ++num;
+ line = Trim(line);
+ std::string::size_type pos = line.find_first_of('#');
+ if (pos != std::string::npos)
+ line = line.substr(0, pos);
+ if (line.empty())
+ continue;
+ pos = line.find_first_of('=');
+ if (pos == std::string::npos)
+ {
+ std::ostringstream error;
+ error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'.";
+ throw std::runtime_error(error.str().c_str());
+ }
+ (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1)));
+ }
+}
+
+} // namespace anonymous
+
+using SGCONF::OPTION;
+using SGCONF::OPTION_BLOCK;
+using SGCONF::OPTION_BLOCKS;
+using SGCONF::ACTION;
+using SGCONF::PARSER_STATE;
+
+OPTION::OPTION(const std::string & shortName,
+ const std::string & longName,
+ ACTION * action,
+ const std::string & description)
+ : m_shortName(shortName),
+ m_longName(longName),
+ m_action(action),
+ m_description(description)
+{
+}
+
+OPTION::OPTION(const std::string & longName,
+ ACTION * action,
+ const std::string & description)
+ : m_longName(longName),
+ m_action(action),
+ m_description(description)
+{
+}
+
+OPTION::OPTION(const OPTION & rhs)
+ : m_shortName(rhs.m_shortName),
+ m_longName(rhs.m_longName),
+ m_action(rhs.m_action->Clone()),
+ m_description(rhs.m_description)
+{
+}
+
+OPTION::~OPTION()
+{
+delete m_action;
+}
+
+OPTION & OPTION::operator=(const OPTION & rhs)
+{
+m_shortName = rhs.m_shortName;
+m_longName = rhs.m_longName;
+m_action = rhs.m_action->Clone();
+m_description = rhs.m_description;
+return *this;
+}
+
+void OPTION::Help(size_t level) const
+{
+if (!m_action)
+ throw ERROR("Option is not defined.");
+std::string indent(level, '\t');
+std::cout << indent;
+if (!m_shortName.empty())
+ std::cout << "-" << m_shortName << ", ";
+std::cout << "--" << m_longName << " " << m_action->ParamDescription()
+ << "\t" << m_description << m_action->DefaultDescription() << "\n";
+m_action->Suboptions().Help(level);
+}
+
+bool OPTION::Check(const char * arg) const
+{
+if (arg == NULL)
+ return false;
+
+if (*arg++ != '-')
+ return false;
+
+if (*arg == '-')
+{
+ return m_longName == arg + 1;
+}
+
+return m_shortName == arg;
+}
+
+PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
+{
+if (!m_action)
+ throw ERROR("Option is not defined.");
+try
+ {
+ return m_action->Parse(argc, argv, data);
+ }
+catch (const ACTION::ERROR & ex)
+ {
+ if (m_longName.empty())
+ throw ERROR("-" + m_shortName + ": " + ex.what());
+ else
+ throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what())
+ : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
+ }
+}
+
+void OPTION::ParseValue(const std::string & value)
+{
+if (!m_action)
+ throw ERROR("Option is not defined.");
+try
+ {
+ return m_action->ParseValue(value);
+ }
+catch (const ACTION::ERROR & ex)
+ {
+ throw ERROR(m_longName + ": " + ex.what());
+ }
+}
+
+OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & shortName,
+ const std::string & longName,
+ ACTION * action,
+ const std::string & description)
+{
+m_options.push_back(OPTION(shortName, longName, action, description));
+return *this;
+}
+
+OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & longName,
+ ACTION * action,
+ const std::string & description)
+{
+m_options.push_back(OPTION(longName, action, description));
+return *this;
+}
+
+void OPTION_BLOCK::Help(size_t level) const
+{
+if (m_options.empty())
+ return;
+if (!m_description.empty())
+ std::cout << m_description << ":\n";
+std::for_each(m_options.begin(),
+ m_options.end(),
+ std::bind2nd(std::mem_fun_ref(&OPTION::Help), level + 1));
+}
+
+PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
+{
+PARSER_STATE state(false, argc, argv);
+if (state.argc == 0)
+ return state;
+while (state.argc > 0 && !state.stop)
+ {
+ std::vector<OPTION>::iterator it = std::find_if(m_options.begin(), m_options.end(), std::bind2nd(std::mem_fun_ref(&OPTION::Check), *state.argv));
+ if (it != m_options.end())
+ state = it->Parse(--state.argc, ++state.argv, data);
+ else
+ break;
+ ++it;
+ }
+return state;
+}
+
+void OPTION_BLOCK::ParseFile(const std::string & filePath)
+{
+if (access(filePath.c_str(), R_OK))
+ throw ERROR("File '" + filePath + "' does not exists.");
+ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this);
+}
+
+void OPTION_BLOCK::OptionCallback(const std::string & key, const std::string & value)
+{
+for (std::vector<OPTION>::iterator it = m_options.begin(); it != m_options.end(); ++it)
+ if (it->Name() == key)
+ it->ParseValue(value);
+}
+
+void OPTION_BLOCKS::Help(size_t level) const
+{
+std::list<OPTION_BLOCK>::const_iterator it(m_blocks.begin());
+while (it != m_blocks.end())
+ {
+ it->Help(level);
+ std::cout << "\n";
+ ++it;
+ }
+}
+
+PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv)
+{
+PARSER_STATE state(false, argc, argv);
+std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
+while (state.argc > 0 && !state.stop && it != m_blocks.end())
+ {
+ state = it->Parse(state.argc, state.argv);
+ ++it;
+ }
+return state;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_OPTIONS_H__
+#define __STG_SGCONF_OPTIONS_H__
+
+#include <string>
+#include <vector>
+#include <list>
+#include <utility>
+#include <stdexcept>
+#include <cstddef> // size_t
+
+namespace SGCONF
+{
+
+class ACTION;
+struct PARSER_STATE;
+
+class OPTION
+{
+ public:
+ OPTION(const std::string & shortName,
+ const std::string & longName,
+ ACTION * action,
+ const std::string & description);
+ OPTION(const std::string & longName,
+ ACTION * action,
+ const std::string & description);
+ OPTION(const OPTION & rhs);
+ ~OPTION();
+
+ OPTION & operator=(const OPTION & rhs);
+
+ void Help(size_t level = 0) const;
+ PARSER_STATE Parse(int argc, char ** argv, void * data);
+ void ParseValue(const std::string & value);
+ bool Check(const char * arg) const;
+ const std::string & Name() const { return m_longName; }
+
+ class ERROR : public std::runtime_error
+ {
+ public:
+ ERROR(const std::string & message)
+ : std::runtime_error(message.c_str()) {}
+ };
+
+ private:
+ std::string m_shortName;
+ std::string m_longName;
+ ACTION * m_action;
+ std::string m_description;
+};
+
+class OPTION_BLOCK
+{
+ public:
+ OPTION_BLOCK() {}
+ OPTION_BLOCK(const std::string & description)
+ : m_description(description) {}
+ OPTION_BLOCK & Add(const std::string & shortName,
+ const std::string & longName,
+ ACTION * action,
+ const std::string & description);
+ OPTION_BLOCK & Add(const std::string & longName,
+ ACTION * action,
+ const std::string & description);
+
+ void Help(size_t level) const;
+
+ PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
+ void ParseFile(const std::string & filePath);
+
+ class ERROR : public std::runtime_error
+ {
+ public:
+ ERROR(const std::string & message)
+ : std::runtime_error(message.c_str()) {}
+ };
+
+ private:
+ std::vector<OPTION> m_options;
+ std::string m_description;
+
+ void OptionCallback(const std::string & key, const std::string & value);
+};
+
+class OPTION_BLOCKS
+{
+ public:
+ OPTION_BLOCK & Add(const std::string & description)
+ { m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); }
+ void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); }
+ void Help(size_t level) const;
+ PARSER_STATE Parse(int argc, char ** argv);
+
+ private:
+ std::list<OPTION_BLOCK> m_blocks;
+};
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_PARSER_STATE_H__
+#define __STG_SGCONF_PARSER_STATE_H__
+
+namespace SGCONF
+{
+
+struct PARSER_STATE
+{
+ PARSER_STATE(bool s, int c, char ** v) : stop(s), argc(c), argv(v) {}
+ bool stop;
+ int argc;
+ char ** argv;
+};
+
+}
+
+#endif
--- /dev/null
+#include "services.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/service_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+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 PrintService(const STG::GET_SERVICE::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "name: " << info.name << "\n"
+ << Indent(level) << "cost: " << info.cost << "\n"
+ << Indent(level) << "payment day: " << static_cast<unsigned>(info.payDay) << "\n"
+ << Indent(level) << "comment: " << info.comment << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
+params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
+params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
+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 GetServicesCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_SERVICE::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get service list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Services:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintService(info[i], 1);
+}
+
+void GetServiceCallback(bool result,
+ const std::string & reason,
+ const STG::GET_SERVICE::INFO & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get service. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintService(info);
+}
+
+bool GetServicesFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetServices(GetServicesCallback, NULL) == STG::st_ok;
+}
+
+bool GetServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetService(arg, GetServiceCallback, NULL) == STG::st_ok;
+}
+
+bool DelServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelService(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+SERVICE_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddService(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+SERVICE_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgService(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetServiceParams());
+blocks.Add("Service management options")
+ .Add("get-services", SGCONF::MakeAPIAction(commands, GetServicesFunction), "\tget service list")
+ .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", GetServiceFunction), "get service")
+ .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", params, AddServiceFunction), "add service")
+ .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", DelServiceFunction), "delete service")
+ .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", params, ChgServiceFunction), "change service");
+}
--- /dev/null
+#ifndef __STG_SGCONF_SERVICES_H__
+#define __STG_SGCONF_SERVICES_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+#include "tariffs.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/tariff_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <map>
+#include <cstdint>
+#include <cassert>
+
+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 ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy)
+{
+switch (changePolicy)
+ {
+ case TARIFF::ALLOW: return "allow";
+ case TARIFF::TO_CHEAP: return "to_cheap";
+ case TARIFF::TO_EXPENSIVE: return "to_expensive";
+ case TARIFF::DENY: return "deny";
+ }
+return "unknown";
+}
+
+std::string PeriodToString(TARIFF::PERIOD period)
+{
+switch (period)
+ {
+ case TARIFF::DAY:
+ return "daily";
+ case TARIFF::MONTH:
+ return "monthly";
+ }
+return "unknown";
+}
+
+std::string TraffTypeToString(TARIFF::TRAFF_TYPE traffType)
+{
+switch (traffType)
+ {
+ case TARIFF::TRAFF_UP:
+ return "upload";
+ case TARIFF::TRAFF_DOWN:
+ return "download";
+ case TARIFF::TRAFF_UP_DOWN:
+ return "upload + download";
+ case TARIFF::TRAFF_MAX:
+ return "max(upload, download)";
+ }
+return "unknown";
+}
+
+void ConvPeriod(const std::string & value, RESETABLE<TARIFF::PERIOD> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "daily")
+ res = TARIFF::DAY;
+else if (lowered == "monthly")
+ res = TARIFF::MONTH;
+else
+ throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
+}
+
+void ConvChangePolicy(const std::string & value, RESETABLE<TARIFF::CHANGE_POLICY> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "allow")
+ res = TARIFF::ALLOW;
+else if (lowered == "to_cheap")
+ res = TARIFF::TO_CHEAP;
+else if (lowered == "to_expensive")
+ res = TARIFF::TO_EXPENSIVE;
+else if (lowered == "deny")
+ res = TARIFF::DENY;
+else
+ throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'");
+}
+
+void ConvChangePolicyTimeout(const std::string & value, RESETABLE<time_t> & res)
+{
+struct tm brokenTime;
+if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
+ throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
+res = stg_timegm(&brokenTime);
+}
+
+void ConvTraffType(const std::string & value, RESETABLE<TARIFF::TRAFF_TYPE> & res)
+{
+std::string lowered = ToLower(value);
+lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end());
+if (lowered == "upload")
+ res = TARIFF::TRAFF_UP;
+else if (lowered == "download")
+ res = TARIFF::TRAFF_DOWN;
+else if (lowered == "upload+download")
+ res = TARIFF::TRAFF_UP_DOWN;
+else if (lowered.substr(0, 3) == "max")
+ res = TARIFF::TRAFF_MAX;
+else
+ throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'");
+}
+
+DIRPRICE_DATA_RES ConvTimeSpan(const std::string & value)
+{
+size_t dashPos = value.find_first_of('-');
+if (dashPos == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t fromColon = value.find_first_of(':');
+if (fromColon == std::string::npos || fromColon > dashPos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t toColon = value.find_first_of(':', dashPos);
+if (toColon == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+DIRPRICE_DATA_RES res;
+res.hDay = FromString<int>(value.substr(0, fromColon));
+if (res.hDay.data() < 0 || res.hDay.data() > 23)
+ throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'");
+res.mDay = FromString<int>(value.substr(fromColon + 1, dashPos - fromColon - 1));
+if (res.mDay.data() < 0 || res.mDay.data() > 59)
+ throw SGCONF::ACTION::ERROR("Invalid 'from' minutes. Got: '" + value.substr(fromColon + 1, dashPos - fromColon - 1) + "'");
+res.hNight = FromString<int>(value.substr(dashPos + 1, toColon - dashPos - 1));
+if (res.hNight.data() < 0 || res.hNight.data() > 23)
+ throw SGCONF::ACTION::ERROR("Invalid 'to' hours. Got: '" + value.substr(dashPos + 1, toColon - dashPos - 1) + "'");
+res.mNight = FromString<int>(value.substr(toColon + 1, value.length() - toColon));
+if (res.mNight.data() < 0 || res.mNight.data() > 59)
+ throw SGCONF::ACTION::ERROR("Invalid 'to' minutes. Got: '" + value.substr(toColon + 1, value.length() - toColon) + "'");
+return res;
+}
+
+void Splice(std::vector<DIRPRICE_DATA_RES> & lhs, const std::vector<DIRPRICE_DATA_RES> & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+ lhs[i].Splice(rhs[i]);
+}
+
+void ConvTimes(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvTimeSpan));
+}
+
+struct ConvPrice : public std::unary_function<std::string, DIRPRICE_DATA_RES>
+{
+ typedef RESETABLE<double> (DIRPRICE_DATA_RES::* MemPtr);
+ ConvPrice(MemPtr before, MemPtr after)
+ : m_before(before), m_after(after)
+ {}
+
+ DIRPRICE_DATA_RES operator()(const std::string & value)
+ {
+ DIRPRICE_DATA_RES res;
+ size_t slashPos = value.find_first_of('/');
+ if (slashPos == std::string::npos)
+ {
+ double price = 0;
+ if (str2x(value, price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value + "'");
+ (res.*m_before) = (res.*m_after) = price;
+ res.noDiscount = true;
+ }
+ else
+ {
+ double price = 0;
+ if (str2x(value.substr(0, slashPos), price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(0, slashPos) + "'");
+ (res.*m_before) = price;
+ if (str2x(value.substr(slashPos + 1, value.length() - slashPos), price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+ (res.*m_after) = price;
+ res.noDiscount = false;
+ }
+ return res;
+ }
+
+ MemPtr m_before;
+ MemPtr m_after;
+};
+
+void ConvDayPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceDayA, &DIRPRICE_DATA_RES::priceDayB)));
+}
+
+void ConvNightPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceNightA, &DIRPRICE_DATA_RES::priceNightB)));
+}
+
+DIRPRICE_DATA_RES ConvThreshold(std::string value)
+{
+DIRPRICE_DATA_RES res;
+double threshold = 0;
+if (str2x(value, threshold) < 0)
+ throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'");
+res.threshold = threshold;
+return res;
+}
+
+void ConvThresholds(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvThreshold));
+}
+
+std::string TimeToString(int h, int m)
+{
+std::ostringstream stream;
+stream << (h < 10 ? "0" : "") << h << ":"
+ << (m < 10 ? "0" : "") << m;
+return stream.str();
+}
+
+void PrintDirPriceData(size_t dir, const DIRPRICE_DATA & data, size_t level)
+{
+std::string night = TimeToString(data.hNight, data.mNight);
+std::string day = TimeToString(data.hDay, data.mDay);
+std::cout << Indent(level, true) << "dir: " << dir << "\n"
+ << Indent(level) << "'" << night << "' - '" << day << "': " << data.priceDayA << "/" << data.priceDayB << "\n"
+ << Indent(level) << "'" << day << "' - '" << night << "': " << data.priceNightA << "/" << data.priceNightB << "\n"
+ << Indent(level) << "threshold: " << data.threshold << "\n"
+ << Indent(level) << "single price: " << (data.singlePrice ? "yes" : "no") << "\n"
+ << Indent(level) << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention!
+}
+
+void PrintTariffConf(const TARIFF_CONF & conf, size_t level)
+{
+std::cout << Indent(level, true) << "name: " << conf.name << "\n"
+ << Indent(level) << "fee: " << conf.fee << "\n"
+ << Indent(level) << "free mb: " << conf.free << "\n"
+ << Indent(level) << "passive cost: " << conf.passiveCost << "\n"
+ << Indent(level) << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
+ << Indent(level) << "period: " << PeriodToString(conf.period) << "\n"
+ << Indent(level) << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n"
+ << Indent(level) << "change policy timeout: " << formatTime(conf.changePolicyTimeout) << "\n";
+}
+
+void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0)
+{
+PrintTariffConf(info.tariffConf, level);
+std::cout << Indent(level) << "dir prices:\n";
+for (size_t i = 0; i < info.dirPrice.size(); ++i)
+ PrintDirPriceData(i, info.dirPrice[i], level + 1);
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
+params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
+params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
+params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "<policy>", "tariff change policy (allow, to_cheap, to_expensive, deny)"));
+params.push_back(SGCONF::API_ACTION::PARAM("change-policy-timeout", "<yyyy-mm-dd hh:mm:ss>", "tariff change policy timeout"));
+params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
+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 GetTariffsCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_TARIFF::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get tariff list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Tariffs:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintTariff(info[i], 1);
+}
+
+void GetTariffCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_TARIFF::INFO> & info,
+ void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the tariff's name.");
+const std::string & name = *static_cast<const std::string *>(data);
+if (!result)
+ {
+ std::cerr << "Failed to get tariff. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+for (size_t i = 0; i < info.size(); ++i)
+ if (info[i].tariffConf.name == name)
+ PrintTariff(info[i]);
+}
+
+bool GetTariffsFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetTariffs(GetTariffsCallback, NULL) == STG::st_ok;
+}
+
+bool GetTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*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 <GetTariff name="..."/>.
+// So get a list of tariffs and filter it. 'data' param holds a pointer to 'name'.
+std::string name(arg);
+return proto.GetTariffs(GetTariffCallback, &name) == STG::st_ok;
+}
+
+bool DelTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelTariff(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+TARIFF_DATA_RES conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
+SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+ {
+ if (!conf.dirPrice[i].priceDayA.empty() &&
+ !conf.dirPrice[i].priceNightA.empty() &&
+ !conf.dirPrice[i].priceDayB.empty() &&
+ !conf.dirPrice[i].priceNightB.empty())
+ conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+ conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+ }
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddTariff(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+TARIFF_DATA_RES conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
+SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+ {
+ if (!conf.dirPrice[i].priceDayA.empty() &&
+ !conf.dirPrice[i].priceNightA.empty() &&
+ !conf.dirPrice[i].priceDayB.empty() &&
+ !conf.dirPrice[i].priceNightB.empty())
+ conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+ conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+ }
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgTariff(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetTariffParams());
+blocks.Add("Tariff management options")
+ .Add("get-tariffs", SGCONF::MakeAPIAction(commands, GetTariffsFunction), "\tget tariff list")
+ .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", GetTariffFunction), "get tariff")
+ .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, AddTariffFunction), "add tariff")
+ .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", DelTariffFunction), "delete tariff")
+ .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, ChgTariffFunction), "change tariff");
+}
--- /dev/null
+#ifndef __STG_SGCONF_TARIFFS_H__
+#define __STG_SGCONF_TARIFFS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+#include "users.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/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/user_ips.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <map>
+
+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 PrintUser(const STG::GET_USER::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "login: " << info.login << "\n"
+ << Indent(level) << "password: " << info.password << "\n"
+ << Indent(level) << "cash: " << info.cash << "\n"
+ << Indent(level) << "credit: " << info.credit << "\n"
+ << Indent(level) << "credit expire: " << TimeToString(info.creditExpire) << "\n"
+ << Indent(level) << "last cash add: " << info.lastCashAdd << "\n"
+ << Indent(level) << "last cash add time: " << TimeToString(info.lastCashAddTime) << "\n"
+ << Indent(level) << "prepaid traffic: " << info.prepaidTraff << "\n"
+ << Indent(level) << "disabled: " << (info.disabled ? "t" : "f") << "\n"
+ << Indent(level) << "passive: " << (info.passive ? "t" : "f") << "\n"
+ << Indent(level) << "disabled detail stat: " << (info.disableDetailStat ? "t" : "f") << "\n"
+ << Indent(level) << "connected: " << (info.connected ? "t" : "f") << "\n"
+ << Indent(level) << "always on-line: " << (info.alwaysOnline ? "t" : "f") << "\n"
+ << Indent(level) << "IP: " << inet_ntostring(info.ip) << "\n"
+ << Indent(level) << "IPs: " << info.ips << "\n"
+ << Indent(level) << "tariff: " << info.tariff << "\n"
+ << Indent(level) << "group: " << info.group << "\n"
+ << Indent(level) << "note: " << info.note << "\n"
+ << Indent(level) << "email: " << info.email << "\n"
+ << Indent(level) << "name: " << info.name << "\n"
+ << Indent(level) << "address: " << info.address << "\n"
+ << Indent(level) << "phone: " << info.phone << "\n"
+ << Indent(level) << "corporation: " << info.corp << "\n"
+ << Indent(level) << "last ping time: " << TimeToString(info.pingTime) << "\n"
+ << Indent(level) << "last activity time: " << TimeToString(info.lastActivityTime) << "\n"
+ << Indent(level) << "traffic:\n";
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ std::cout << Indent(level + 1, true) << "dir: " << i << "\n"
+ << Indent(level + 1) << "session upload: " << info.stat.su[i] << "\n"
+ << Indent(level + 1) << "session download: " << info.stat.sd[i] << "\n"
+ << Indent(level + 1) << "month upload: " << info.stat.mu[i] << "\n"
+ << Indent(level + 1) << "month download: " << info.stat.md[i] << "\n";
+ }
+std::cout << Indent(level) << "user data:\n";
+for (size_t i = 0; i < USERDATA_NUM; ++i)
+ std::cout << Indent(level + 1, true) << "user data " << i << ": " << info.userData[i] << "\n";
+if (!info.services.empty())
+ {
+ std::cout << Indent(level) << "services:\n";
+ for (size_t i = 0; i < info.services.size(); ++i)
+ std::cout << Indent(level + 1, true) << info.services[i] << "\n";
+ }
+if (!info.authBy.empty())
+ {
+ std::cout << Indent(level) << "auth by:\n";
+ for (size_t i = 0; i < info.authBy.size(); ++i)
+ std::cout << Indent(level + 1, true) << info.authBy[i] << "\n";
+ }
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-add", "<cash[:message]>", "cash to add (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-set", "<cash[:message]>", "cash to set (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
+params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
+params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
+params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
+params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
+params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
+params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
+params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
+params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
+params.push_back(SGCONF::API_ACTION::PARAM("corp", "<corp name>", "\tcorporation name"));
+params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
+params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
+return params;
+}
+
+void ConvBool(const std::string & value, RESETABLE<int> & res)
+{
+res = !value.empty() && value[0] == 'y';
+}
+
+void Splice(std::vector<RESETABLE<std::string> > & lhs, const std::vector<RESETABLE<std::string> > & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+ lhs[i].splice(rhs[i]);
+}
+
+RESETABLE<std::string> ConvString(const std::string & value)
+{
+return RESETABLE<std::string>(value);
+}
+
+void ConvStringList(std::string value, std::vector<RESETABLE<std::string> > & res)
+{
+Splice(res, Split<std::vector<RESETABLE<std::string> > >(value, ',', ConvString));
+}
+
+void ConvServices(std::string value, RESETABLE<std::vector<std::string> > & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+res = Split<std::vector<std::string> >(value, ',');
+}
+
+void ConvCreditExpire(const std::string & value, RESETABLE<time_t> & res)
+{
+struct tm brokenTime;
+if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
+ throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
+res = stg_timegm(&brokenTime);
+}
+
+void ConvIPs(const std::string & value, RESETABLE<USER_IPS> & res)
+{
+res = StrToIPS(value);
+}
+
+struct TRAFF
+{
+ uint64_t up;
+ uint64_t down;
+};
+
+TRAFF ConvTraff(const std::string & value)
+{
+TRAFF res;
+size_t slashPos = value.find_first_of('/');
+if (slashPos == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Traffic record should be in format 'upload/download'. Got: '" + value + "'");
+
+if (str2x(value.substr(0, slashPos), res.up) < 0)
+ throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(0, slashPos) + "'");
+if (str2x(value.substr(slashPos + 1, value.length() - slashPos), res.down) < 0)
+ throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+return res;
+}
+
+void ConvSessionTraff(std::string value, USER_STAT_RES & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+ throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of session traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ res.sessionUp[i] = traff[i].up;
+ res.sessionDown[i] = traff[i].down;
+ }
+}
+
+void ConvMonthTraff(std::string value, USER_STAT_RES & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+ throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of month traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ res.monthUp[i] = traff[i].up;
+ res.monthDown[i] = traff[i].down;
+ }
+}
+
+void ConvCashInfo(const std::string & value, RESETABLE<CASH_INFO> & res)
+{
+CASH_INFO info;
+size_t pos = value.find_first_of(':');
+if (pos == std::string::npos)
+ {
+ if (str2x(value, info.first) < 0)
+ throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+ }
+else
+ {
+ if (str2x(value.substr(0, pos), info.first) < 0)
+ throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+ info.second = value.substr(pos + 1);
+ }
+res = info;
+}
+
+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 GetUsersCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_USER::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get user list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Users:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintUser(info[i], 1);
+}
+
+void GetUserCallback(bool result,
+ const std::string & reason,
+ const STG::GET_USER::INFO & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get user. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintUser(info);
+}
+
+void AuthByCallback(bool result,
+ const std::string & reason,
+ const std::vector<std::string> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get authorizer list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Authorized by:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ std::cout << Indent(1, true) << info[i] << "\n";
+}
+
+bool GetUsersFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetUsers(GetUsersCallback, NULL) == STG::st_ok;
+}
+
+bool GetUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetUser(arg, GetUserCallback, NULL) == STG::st_ok;
+}
+
+bool DelUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelUser(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+USER_CONF_RES conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+USER_STAT_RES stat;
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+USER_CONF_RES conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+USER_STAT_RES stat;
+SGCONF::MaybeSet(options, "cash-add", stat.cashAdd, ConvCashInfo);
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool CheckUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("password"));
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Password is not specified.");
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.CheckUser(arg, it->second, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool SendMessageFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("logins"));
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Logins are not specified.");
+std::string logins = it->second;
+for (size_t i = 0; i < logins.length(); ++i)
+ if (logins[i] == ',')
+ logins[i] = ':';
+it = options.find("text");
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Message text is not specified.");
+std::string text = it->second;
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.SendMessage(logins, text, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AuthByFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AuthBy(arg, AuthByCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetUserParams());
+blocks.Add("User management options")
+ .Add("get-users", SGCONF::MakeAPIAction(commands, GetUsersFunction), "\tget user list")
+ .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", GetUserFunction), "get user")
+ .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", params, AddUserFunction), "add user")
+ .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", DelUserFunction), "delete user")
+ .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", params, ChgUserFunction), "change user")
+ .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", GetCheckParams(), CheckUserFunction), "check user existance and credentials")
+ .Add("send-message", SGCONF::MakeAPIAction(commands, GetMessageParams(), SendMessageFunction), "send message")
+ .Add("auth-by", SGCONF::MakeAPIAction(commands, "<login>", AuthByFunction), "a list of authorizers user authorized by");
+}
--- /dev/null
+#ifndef __STG_SGCONF_USERS_H__
+#define __STG_SGCONF_USERS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
+
+#endif
--- /dev/null
+#ifndef __STG_SGCONF_UTILS_H__
+#define __STG_SGCONF_UTILS_H__
+
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+#include <map>
+
+namespace SGCONF
+{
+
+template <typename T>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+T value;
+if (str2x(it->second, value) < 0)
+ return;
+res = value;
+}
+
+template <typename T, typename F>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, T & res, F conv)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+conv(it->second, res);
+}
+
+template <>
+inline
+void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<std::string> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+res = it->second;
+}
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+#include "xml.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <expat.h>
+
+namespace
+{
+
+struct ParserState
+{
+size_t level;
+};
+
+std::string Indent(size_t level)
+{
+return std::string(level * 4, ' ');
+}
+
+std::string PrintAttr(const char ** attr)
+{
+std::string res;
+if (attr == NULL)
+ return res;
+while (*attr)
+ {
+ if (*(attr + 1) == NULL)
+ return res;
+ res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
+ ++attr; ++attr;
+ }
+return res;
+}
+
+void Start(void * data, const char * el, const char ** attr)
+{
+ParserState * state = static_cast<ParserState *>(data);
+if (el != NULL)
+ std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
+++state->level;
+}
+
+void End(void * data, const char * el)
+{
+ParserState * state = static_cast<ParserState *>(data);
+--state->level;
+if (el != NULL)
+ std::cout << Indent(state->level) << "</" << el << ">\n";
+}
+
+void PrintXML(const std::string& xml)
+{
+ParserState state = { 0 };
+
+XML_Parser parser = XML_ParserCreate(NULL);
+XML_ParserReset(parser, NULL);
+XML_SetElementHandler(parser, Start, End);
+XML_SetUserData(parser, &state);
+
+if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
+ std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
+ << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
+ << std::endl;
+
+XML_ParserFree(parser);
+}
+
+void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintXML(response);
+}
+
+bool RawXMLFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
+}
+
+}
+
+void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+blocks.Add("Raw XML")
+ .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_XML_H__
+#define __STG_SGCONF_XML_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
+
+#endif
--- /dev/null
+set ( CPP_FILES main.cpp
+ admins_impl.cpp
+ users_impl.cpp
+ tariffs_impl.cpp
+ corps_impl.cpp
+ services_impl.cpp
+ admin_impl.cpp
+ user_impl.cpp
+ tariff_impl.cpp
+ eventloop.cpp
+ pidfile.cpp
+ plugin_runner.cpp
+ plugin_mgr.cpp
+ settings_impl.cpp
+ stg_timer.cpp
+ store_loader.cpp
+ traffcounter_impl.cpp
+ user_property.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( stargazer ${CPP_FILES} )
+
+target_link_libraries ( stargazer scriptexecuter dotconfpp logger common Threads::Threads dl )
+
+add_subdirectory ( plugins )
+
+# TODO: install
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.50 2010/10/07 18:27:27 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = stargazer
+
+SRCS = ./admin_impl.cpp \
+ ./admins_impl.cpp \
+ ./corps_impl.cpp \
+ ./eventloop.cpp \
+ ./main.cpp \
+ ./pidfile.cpp \
+ ./plugin_runner.cpp \
+ ./plugin_mgr.cpp \
+ ./settings_impl.cpp \
+ ./services_impl.cpp \
+ ./stg_timer.cpp \
+ ./store_loader.cpp \
+ ./tariff_impl.cpp \
+ ./tariffs_impl.cpp \
+ ./traffcounter_impl.cpp \
+ ./user_impl.cpp \
+ ./user_property.cpp \
+ ./users_impl.cpp
+
+STGLIBS = scriptexecuter \
+ dotconfpp \
+ logger \
+ 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 += -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)
+
+ifneq ($(OS),darwin)
+LDFLAGS += -Wl,-E
+endif
+
+LDFLAGS += $(STGLIBS_LIBS)
+
+.PHONY: all clean distclean libs plugins install uninstall install-bin install-data
+all: libs plugins $(PROG)
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+plugins: libs
+ $(MAKE) -C $(DIR_PLUGINS)
+
+$(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
+ $(MAKE) -C $(DIR_PLUGINS) clean
+
+distclean: clean
+ rm -f $(DIR_MOD)/*
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin: $(PROG)
+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_INCLUDE) install
+ $(MAKE) -C $(DIR_LIBSRC) install
+ $(MAKE) -C $(DIR_PLUGINS) install
+
+install-data:
+ # Install etc
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer/conf-available.d
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/stargazer/conf-enabled.d
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/stargazer.conf $(PREFIX)/etc/stargazer/stargazer.conf
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/conf-available.d/*.conf $(PREFIX)/etc/stargazer/conf-available.d
+ ln -sf ../conf-available.d/mod_ao.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ao.conf
+ ln -sf ../conf-available.d/mod_ia.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ia.conf
+ ln -sf ../conf-available.d/mod_ping.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_ping.conf
+ ln -sf ../conf-available.d/mod_sg.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_sg.conf
+ ln -sf ../conf-available.d/store_files.conf $(PREFIX)/etc/stargazer/conf-enabled.d/store_files.conf
+
+ifeq ($(OS),linux)
+ ln -sf ../conf-available.d/mod_cap_ether.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_cap_ether.conf
+else
+ ln -sf ../conf-available.d/mod_cap_bpf.conf $(PREFIX)/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf
+endif
+
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/rules $(PREFIX)/etc/stargazer/rules
+ install -m $(BIN_MODE) -o $(OWNER) $(ETC_DIR)/On* $(PREFIX)/etc/stargazer/
+
+ # Install file db
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/admins
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/tariffs
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/var/stargazer/users/test
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/admins/admin.adm $(PREFIX)/var/stargazer/admins/admin.adm
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/tariffs/tariff.tf $(PREFIX)/var/stargazer/tariffs/tariff.tf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/conf $(PREFIX)/var/stargazer/users/test/conf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/stat $(PREFIX)/var/stargazer/users/test/stat
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) uninstall
+ $(MAKE) -C $(DIR_PLUGINS) uninstall
+ rm -rf $(PREFIX)/usr/lib/stg
+
+uninstall-data:
+ # Uninstall etc
+ rm -rf $(PREFIX)/etc/stargazer
+ rm -rf $(PREFIX)/var/stargazer
+
+
+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
--- /dev/null
+Инсталяция и запуск.
+1. > ./build
+2. > make install
+3. Правка конфигурационных файлов
+4. > stargazer
+
--- /dev/null
+#ifndef __ACTIONS_H__
+#define __ACTIONS_H__
+
+// Usage:
+//
+// ACTIONS_LIST actionsList;
+// CLASS myClass;
+// DATA1 myData1;
+// DATA2 myData2;
+//
+// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
+// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
+//
+// actionsList.InvokeAll();
+
+#include <pthread.h>
+#include <list>
+#include <functional>
+
+// Generalized actor type - a method of some class with one argument
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+struct ACTOR
+{
+typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
+};
+
+// Abstract base action class for polymorphic action invocation
+class BASE_ACTION
+{
+public:
+ virtual ~BASE_ACTION() {}
+ virtual void Invoke() = 0;
+};
+
+// Concrete generalized action type - an actor with it's data and owner
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+class ACTION : public BASE_ACTION,
+ public std::unary_function<ACTIVE_CLASS &, void>
+{
+public:
+ ACTION(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+ : activeClass(ac), actor(a), data(d) {}
+ void Invoke();
+private:
+ ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
+ ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
+
+ ACTIVE_CLASS & activeClass;
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
+ DATA_TYPE data;
+};
+
+// A list of an actions
+// All methods are thread-safe
+class ACTIONS_LIST : private std::list<BASE_ACTION *>
+{
+public:
+ // Just a typedef for parent class
+ typedef std::list<BASE_ACTION *> parent;
+
+ // Initialize mutex
+ ACTIONS_LIST();
+ // Delete actions and destroy mutex
+ virtual ~ACTIONS_LIST();
+
+ parent::iterator begin();
+ parent::iterator end();
+ parent::const_iterator begin() const;
+ parent::const_iterator end() const;
+
+ bool empty() const;
+ size_t size() const;
+ void swap(ACTIONS_LIST & list);
+
+ // Add an action to list
+ template <class ACTIVE_CLASS, typename DATA_TYPE>
+ void Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d);
+ // Invoke all actions in the list
+ void InvokeAll();
+private:
+ mutable pthread_mutex_t mutex;
+};
+
+#include "actions.inl.h"
+
+#endif
--- /dev/null
+#ifndef __ACTIONS_INL_H__
+#define __ACTIONS_INL_H__
+
+#include <algorithm>
+
+#include "stg/locker.h"
+
+// Polymorphick action invocation
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
+{
+(activeClass.*actor)(data);
+}
+
+inline
+ACTIONS_LIST::ACTIONS_LIST()
+ : mutex()
+{
+pthread_mutex_init(&mutex, NULL);
+}
+
+// Delete all actions before deleting list
+inline
+ACTIONS_LIST::~ACTIONS_LIST()
+{
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ parent::iterator it(parent::begin());
+ while (it != parent::end())
+ {
+ delete *it++;
+ }
+ }
+
+pthread_mutex_destroy(&mutex);
+}
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
+{
+STG_LOCKER lock(&mutex);
+return parent::begin();
+}
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
+{
+STG_LOCKER lock(&mutex);
+return parent::end();
+}
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
+{
+STG_LOCKER lock(&mutex);
+return parent::begin();
+}
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
+{
+STG_LOCKER lock(&mutex);
+return parent::end();
+}
+
+inline
+bool ACTIONS_LIST::empty() const
+{
+STG_LOCKER lock(&mutex);
+return parent::empty();
+}
+
+inline
+size_t ACTIONS_LIST::size() const
+{
+STG_LOCKER lock(&mutex);
+return parent::size();
+}
+
+inline
+void ACTIONS_LIST::swap(ACTIONS_LIST & list)
+{
+STG_LOCKER lock(&mutex);
+parent::swap(list);
+}
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+{
+STG_LOCKER lock(&mutex);
+push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
+}
+
+inline
+void ACTIONS_LIST::InvokeAll()
+{
+STG_LOCKER lock(&mutex);
+std::for_each(
+ parent::begin(),
+ parent::end(),
+ std::mem_fun(&BASE_ACTION::Invoke)
+);
+}
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.13 $
+ $Date: 2010/10/04 20:16:09 $
+ $Author: faust $
+ */
+
+#include "admin_impl.h"
+
+#include "stg/common.h"
+
+//-----------------------------------------------------------------------------
+ADMIN_IMPL::ADMIN_IMPL()
+ : ip(0)
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN_IMPL::ADMIN_IMPL(const ADMIN_CONF & ac)
+ : conf(ac),
+ ip(0)
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN_IMPL::ADMIN_IMPL(const PRIV & priv,
+ const std::string & login,
+ const std::string & password)
+ : conf(priv, login, password),
+ ip(0)
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN_IMPL & ADMIN_IMPL::operator=(const ADMIN_CONF & ac)
+{
+conf = ac;
+return *this;
+}
+//-----------------------------------------------------------------------------
+bool ADMIN_IMPL::operator==(const ADMIN_IMPL & rhs) const
+{
+return conf.login == rhs.conf.login;
+}
+//-----------------------------------------------------------------------------
+bool ADMIN_IMPL::operator!=(const ADMIN_IMPL & rhs) const
+{
+return conf.login != rhs.conf.login;
+}
+//-----------------------------------------------------------------------------
+bool ADMIN_IMPL::operator<(const ADMIN_IMPL & rhs) const
+{
+return conf.login < rhs.conf.login;
+}
+//-----------------------------------------------------------------------------
+bool ADMIN_IMPL::operator<=(const ADMIN_IMPL & rhs) const
+{
+return conf.login <= rhs.conf.login;
+}
+//-----------------------------------------------------------------------------
+std::string ADMIN_IMPL::GetIPStr() const
+{
+return inet_ntostring(ip);
+}
+//-----------------------------------------------------------------------------
+void ADMIN_IMPL::Print() const
+{
+printfd(__FILE__, "=======================================\n");
+printfd(__FILE__, "login %s\n", conf.login.c_str());
+printfd(__FILE__, "password %s\n", conf.password.c_str());
+printfd(__FILE__, "ChgConf %d\n", conf.priv.userConf);
+printfd(__FILE__, "ChgStat %d\n", conf.priv.userStat);
+printfd(__FILE__, "ChgCash %d\n", conf.priv.userCash);
+printfd(__FILE__, "UsrAddDel %d\n", conf.priv.userAddDel);
+printfd(__FILE__, "ChgAdmin %d\n", conf.priv.adminChg);
+printfd(__FILE__, "ChgTariff %d\n", conf.priv.tariffChg);
+printfd(__FILE__, "=======================================\n");
+}
+//-----------------------------------------------------------------------------
+const std::string ADMIN_IMPL::GetLogStr() const
+{
+return "Admin \'" + conf.login + "\', " + GetIPStr() + ":";
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.14 $
+ $Date: 2010/10/04 20:15:43 $
+ $Author: faust $
+ */
+
+#ifndef ADMIN_IMPL_H
+#define ADMIN_IMPL_H
+
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+
+#include <string>
+#include <cstdint>
+
+class ADMIN_IMPL : public ADMIN {
+public:
+ ADMIN_IMPL();
+ explicit ADMIN_IMPL(const ADMIN_CONF & ac);
+ ADMIN_IMPL(const PRIV & priv,
+ const std::string & login,
+ const std::string & password);
+ virtual ~ADMIN_IMPL() {}
+
+ ADMIN_IMPL & operator=(const ADMIN_CONF &);
+ bool operator==(const ADMIN_IMPL & rhs) const;
+ bool operator!=(const ADMIN_IMPL & rhs) const;
+ bool operator<(const ADMIN_IMPL & rhs) const;
+ bool operator<=(const ADMIN_IMPL & rhs) const;
+
+ const std::string & GetPassword() const { return conf.password; }
+ const std::string & GetLogin() const { return conf.login; }
+ PRIV const * GetPriv() const { return &conf.priv; }
+ uint32_t GetPrivAsInt() const { return conf.priv.ToInt(); }
+ const ADMIN_CONF & GetConf() const { return conf; }
+ void Print() const;
+ uint32_t GetIP() const { return ip; }
+ std::string GetIPStr() const;
+ void SetIP(uint32_t v) { ip = v; }
+ const std::string GetLogStr() const;
+
+private:
+ ADMIN_CONF conf;
+ uint32_t ip;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.15 $
+ $Date: 2010/10/04 20:17:12 $
+ $Author: faust $
+ */
+
+#include "stg/common.h"
+#include "admins_impl.h"
+#include "admin_impl.h"
+
+#include <cerrno>
+#include <cassert>
+#include <algorithm>
+
+//-----------------------------------------------------------------------------
+ADMINS_IMPL::ADMINS_IMPL(STORE * st)
+ : ADMINS(),
+ stg(PRIV(0xFFFF), "@stargazer", ""),
+ noAdmin(PRIV(0xFFFF), "NO-ADMIN", ""),
+ data(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ searchDescriptors(),
+ handle(0),
+ mutex(),
+ strError()
+{
+pthread_mutex_init(&mutex, NULL);
+Read();
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::Add(const std::string & login, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->adminChg)
+ {
+ std::string s = admin->GetLogStr() + " Add administrator \'" + login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+ADMIN_IMPL adm(PRIV(0), login, "");
+admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai != data.end())
+ {
+ strError = "Administrator \'" + login + "\' cannot not be added. Administrator already exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+data.push_back(adm);
+
+if (store->AddAdmin(login) == 0)
+ {
+ WriteServLog("%s Administrator \'%s\' added.",
+ admin->GetLogStr().c_str(), login.c_str());
+ return 0;
+ }
+
+strError = "Administrator \'" + login + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::Del(const std::string & login, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->adminChg)
+ {
+ std::string s = admin->GetLogStr() + " Delete administrator \'" + login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
+
+if (ai == data.end())
+ {
+ strError = "Administrator \'" + login + "\' cannot be deleted. Administrator does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+std::map<int, const_admin_iter>::iterator si;
+si = searchDescriptors.begin();
+while (si != searchDescriptors.end())
+ {
+ if (si->second == ai)
+ (si->second)++;
+ ++si;
+ }
+
+data.remove(*ai);
+if (store->DelAdmin(login) < 0)
+ {
+ strError = "Administrator \'" + login + "\' was not deleted. Error: " + store->GetStrError();
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+WriteServLog("%s Administrator \'%s\' deleted.", admin->GetLogStr().c_str(), login.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::Change(const ADMIN_CONF & ac, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->adminChg)
+ {
+ std::string s = admin->GetLogStr() + " Change administrator \'" + ac.login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), ac.login, "")));
+
+if (ai == data.end())
+ {
+ strError = "Administrator \'" + ac.login + "\' cannot be changed " + ". Administrator does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+*ai = ac;
+if (store->SaveAdmin(ac))
+ {
+ WriteServLog("Cannot write admin %s.", ac.login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+WriteServLog("%s Administrator \'%s\' changed.",
+ admin->GetLogStr().c_str(), ac.login.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::Read()
+{
+STG_LOCKER lock(&mutex);
+std::vector<std::string> adminsList;
+if (store->GetAdminsList(&adminsList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return -1;
+ }
+
+for (unsigned int i = 0; i < adminsList.size(); i++)
+ {
+ ADMIN_CONF ac(PRIV(0), adminsList[i], "");
+
+ if (store->RestoreAdmin(&ac, adminsList[i]))
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return -1;
+ }
+
+ data.push_back(ADMIN_IMPL(ac));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool ADMINS_IMPL::Find(const std::string & l, ADMIN ** admin)
+{
+assert(admin != NULL && "Pointer to admin is not null");
+
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ {
+ printfd(__FILE__, "No admin in system!\n");
+ *admin = &noAdmin;
+ return false;
+ }
+
+admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), l, "")));
+
+if (ai != data.end())
+ {
+ *admin = &(*ai);
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool ADMINS_IMPL::Exists(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ return true;
+ }
+
+const_admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
+
+if (ai != data.end())
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool ADMINS_IMPL::Correct(const std::string & login, const std::string & password, ADMIN ** admin)
+{
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ return true;
+ }
+
+admin_iter ai(find(data.begin(), data.end(), ADMIN_IMPL(PRIV(0), login, "")));
+
+if (ai == data.end())
+ {
+ return false;
+ }
+
+if (ai->GetPassword() != password)
+ {
+ return false;
+ }
+
+*admin = &(*ai);
+
+return true;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::OpenSearch() const
+{
+STG_LOCKER lock(&mutex);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::SearchNext(int h, ADMIN_CONF * ac) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("ADMINS. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == data.end())
+ return -1;
+
+ADMIN_IMPL a = *searchDescriptors[h]++;
+
+*ac = a.GetConf();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS_IMPL::CloseSearch(int h) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("ADMINS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.10 $
+ $Date: 2010/10/04 20:17:12 $
+ $Author: faust $
+ */
+
+#ifndef ADMINS_IMPL_H
+#define ADMINS_IMPL_H
+
+#include "admin_impl.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/locker.h"
+#include "stg/store.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <pthread.h>
+
+class ADMINS_IMPL : private NONCOPYABLE, public ADMINS {
+public:
+ explicit ADMINS_IMPL(STORE * st);
+ virtual ~ADMINS_IMPL() {}
+
+ int Add(const std::string & login, const ADMIN * admin);
+ int Del(const std::string & login, const ADMIN * admin);
+ int Change(const ADMIN_CONF & ac, const ADMIN * admin);
+ const ADMIN * GetSysAdmin() const { return &stg; }
+ const ADMIN * GetNoAdmin() const { return &noAdmin; }
+ bool Find(const std::string & l, ADMIN ** admin);
+ bool Exists(const std::string & login) const;
+ bool Correct(const std::string & login,
+ const std::string & password,
+ ADMIN ** admin);
+ const std::string & GetStrError() const { return strError; }
+
+ size_t Count() const { return data.size(); }
+
+ int OpenSearch() const;
+ int SearchNext(int, ADMIN_CONF * ac) const;
+ int CloseSearch(int) const;
+
+private:
+ ADMINS_IMPL(const ADMINS_IMPL & rvalue);
+ ADMINS_IMPL & operator=(const ADMINS_IMPL & rvalue);
+
+ typedef std::list<ADMIN_IMPL>::iterator admin_iter;
+ typedef std::list<ADMIN_IMPL>::const_iterator const_admin_iter;
+
+ int Read();
+
+ ADMIN_IMPL stg;
+ ADMIN_IMPL noAdmin;
+ std::list<ADMIN_IMPL> data;
+ STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable std::map<int, const_admin_iter> searchDescriptors;
+ mutable unsigned int handle;
+ mutable pthread_mutex_t mutex;
+ std::string strError;
+};
+
+#endif
--- /dev/null
+#!/bin/sh
+
+# $Revision: 1.57 $
+# $Author: faust $
+# $Date: 2010/05/09 12:39:01 $
+######################################################
+
+# 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"
+VAR_DIR="./inst/var/stargazer"
+MIN_XMLRPCC_VERSION="1.06.27"
+XMLRPC_FEATURES="c++2 abyss-server"
+
+
+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
+ ETC_DIR="./inst/linux/etc/stargazer"
+ 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
+ ETC_DIR="./inst/freebsd/etc/stargazer"
+ 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 stargazer is currently supported by Linux, FreeBSD and Darwin. #\n"
+ printf "#############################################################################\n"
+ exit 1
+fi
+
+printf "#############################################################################\n"
+printf " Building STG 2.4 for $sys $release\n"
+printf "#############################################################################\n"
+
+STG_LIBS="logger.lib
+ crypto.lib
+ common.lib
+ scriptexecuter.lib
+ conffiles.lib
+ pinger.lib
+ dotconfpp.lib
+ smux.lib"
+
+PLUGINS="authorization/ao
+ authorization/inetaccess
+ configuration/sgconfig
+ other/ping
+ other/rscript
+ other/smux
+ store/files
+ capture/cap_nf"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ PLUGINS="$PLUGINS
+ capture/ether_linux"
+ LIB_THREAD=-lpthread
+else
+ LIBICONV="-liconv"
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ LIB_THREAD=-lc_r
+ 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
+ PLUGINS="$PLUGINS
+ capture/ether_freebsd
+ capture/divert_freebsd"
+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 <expat.h>\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 <iconv.h>\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
+
+
+printf "Checking for mysql_config... "
+printf "#include <mysql.h>\nint main() { return 0; }\n" > build_check.c
+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
+ MYSQL_CFLAGS=""
+ MYSQL_LDFLAGS="-lmysqlclient_r"
+ 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 <libpq-fe.h>\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
+
+printf "Checking for xmlrpc-c-config... "
+printf "#include <xmlrpc-c/base.hpp>\nint main() { return 0; }\n" > build_check.c
+XMLRPCC_VERSION=`xmlrpc-c-config $XMLRPC_FEATURES --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ printf "no\n";
+ printf "Checking for -lxmlrpc... "
+ $CC $CFLAGS $LDFLAGS build_check.c -lxmlrpc $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ printf "no\n"
+ else
+ CHECK_XMLRPC=yes
+ printf "yes\n"
+ fi
+ rm -f fake
+elif [ "$XMLRPCC_VERSION" \< "$MIN_XMLRPCC_VERSION" ]
+then
+ printf "no (need at least $MIN_XMLRPCC_VERSION, actual $XMLRPCC_VERSION)\n";
+ CHECK_XMLRPC=no
+else
+ printf "yes (version $XMLRPCC_VERSION)\n";
+ printf "Checking for xmlrpc-c-config --cflags... "
+ XMLRPC_CFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --cflags 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ printf "no\n"
+ else
+ printf "[$XMLRPC_CFLAGS]\n"
+ printf "Checking for xmlrpc-c-config --libs... "
+ XMLRPC_LDFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --libs 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ printf "no\n"
+ else
+ CHECK_XMLRPC=yes
+ printf "[$XMLRPC_LDFLAGS]\n"
+ fi
+ fi
+fi
+
+printf "Checking for -lpcap... "
+printf "#include <pcap.h>\nint main() { return 0; }\n" > build_check.c
+$CC $CFLAGS $LDFLAGS build_check.c -lpcap -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_PCAP=no
+ printf "no\n"
+else
+ CHECK_PCAP=yes
+ printf "yes\n"
+fi
+rm -f fake
+
+printf "Checking for -lnfnetlink... "
+printf "#include <stdint.h>\n#include <netinet/in.h>\n#include <linux/netfilter.h>\nint main() { return 0; }\n" > build_check.c
+$CC $CFLAGS $LDFLAGS build_check.c -lnfnetlink -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_NFNETLINK=no
+ printf "no\n"
+else
+ CHECK_NFNETLINK=yes
+ NETLINK_LDFLAGS="-lnfnetlink"
+ printf "yes\n"
+fi
+rm -f fake
+
+printf "Checking for -lnetfilter_queue... "
+printf "#include <stdint.h>\n#include <libnetfilter_queue/libnetfilter_queue.h>\nint main() { return 0; }\n" > build_check.c
+$CC $CFLAGS $LDFLAGS build_check.c -lnetfilter_queue -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_NFQ=no
+ printf "no\n"
+else
+ CHECK_NFQ=yes
+ NFQ_LDFLAGS="-lnetfilter_queue"
+ printf "yes\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"
+ else
+ CHECK_YAJL=yes
+ printf `pkg-config --modversion yajl`"\n"
+ fi
+else
+ printf "#include <stdio.h>\n" > build_check.c
+ printf "#include <yajl/yajl_version.h>\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"
+ 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"
+ fi
+ fi
+ rm -f fake
+fi
+
+printf "Checking for boost::scoped_ptr... "
+printf "#include <boost/scoped_ptr.hpp>\nint main() { boost::scoped_ptr<int> 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"
+else
+ CHECK_BOOST_SCOPED_PTR=yes
+ printf "yes\n"
+fi
+rm -f fake
+
+if [ "$OS" = "linux" ]
+then
+ printf "Checking for linux/netfilter_ipv4/ip_queue.h... "
+ printf "#include <linux/types.h>\n" > build_check.c
+ printf "#include <linux/netfilter_ipv4/ip_queue.h>\n" >> build_check.c
+ printf "int main() { return 0; }\n" >> build_check.c
+ $CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_IP_QUEUE_H=no
+ printf "no\n"
+ else
+ CHECK_IP_QUEUE_H=yes
+ DEFS="$DEFS -DHAS_IP_QUEUE_H"
+ PLUGINS="$PLUGINS
+ capture/ipq_linux"
+ printf "yes\n"
+ fi
+ rm -f fake
+fi
+
+rm -f build_check.c
+rm -f build_check.cpp
+
+if [ "$CHECK_EXPAT" != "yes" ]
+then
+ printf -- "-lexpat not found!\n"
+ exit 1
+fi
+
+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
+
+if [ "$CHECK_XMLRPC" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ configuration/rpcconfig"
+fi
+
+if [ "$CHECK_PCAP" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ capture/pcap"
+fi
+
+if [ "$CHECK_NFNETLINK" = "yes" -a "$CHECK_NFQ" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ capture/nfqueue"
+fi
+
+if [ "$CHECK_YAJL" = "yes" -a "$CHECK_BOOST_SCOPED_PTR" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ other/radius"
+ 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 "DIR_MOD=\$(DIR_BUILD)/modules\n" >> $CONFFILE
+printf "DIR_PLUGINS=\$(DIR_BUILD)/plugins\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 "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 "CHECK_XMLRPC=$CHECK_XMLRPC\n" >> $CONFFILE
+if [ "$CHECK_XMLRPC" = "yes" ]
+then
+ printf "XMLRPC_CFLAGS=$XMLRPC_CFLAGS\n" >> $CONFFILE
+ printf "XMLRPC_LDFLAGS=$XMLRPC_LDFLAGS\n" >> $CONFFILE
+fi
+printf "CHECK_PCAP=$CHECK_PCAP\n" >> $CONFFILE
+printf "CHECK_NFNETLINK=$CHECK_NFNETLINK\n" >> $CONFFILE
+if [ "$CHECK_NFNETLINK" = "yes" ]
+then
+ printf "NETLINK_LDFLAGS=$NETLINK_LDFLAGS\n" >> $CONFFILE
+fi
+printf "CHECK_NFQ=$CHECK_NFQ\n" >> $CONFFILE
+if [ "$CHECK_NFQ" = "yes" ]
+then
+ printf "NFQ_LDFLAGS=$NFQ_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 "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
+printf "VAR_DIR=$VAR_DIR\n" >> $CONFFILE
+printf "ETC_DIR=$ETC_DIR\n" >> $CONFFILE
+
+mkdir -p modules
+
+if [ "$1" != "debug" ]
+then
+ $MAKE $MAKEOPTS
+else
+ printf "\n\n\nDebug build. Type $MAKE explicitly\n"
+fi
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "corps_impl.h"
+
+#include "stg/admin.h"
+#include "stg/common.h"
+
+#include <cerrno>
+#include <cassert>
+#include <algorithm>
+
+//-----------------------------------------------------------------------------
+CORPORATIONS_IMPL::CORPORATIONS_IMPL(STORE * st)
+ : CORPORATIONS(),
+ data(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ searchDescriptors(),
+ handle(0),
+ mutex(),
+ strError()
+{
+pthread_mutex_init(&mutex, NULL);
+Read();
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::Add(const CORP_CONF & corp, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->corpChg)
+ {
+ std::string s = admin->GetLogStr() + " Add corporation \'" + corp.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+crp_iter si(find(data.begin(), data.end(), corp));
+
+if (si != data.end())
+ {
+ strError = "Corporation \'" + corp.name + "\' cannot not be added. Corporation already exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+data.push_back(corp);
+
+if (store->AddCorp(corp.name) == 0)
+ {
+ WriteServLog("%s Corporation \'%s\' added.",
+ admin->GetLogStr().c_str(), corp.name.c_str());
+ return 0;
+ }
+
+strError = "Corporation \'" + corp.name + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::Del(const std::string & name, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->corpChg)
+ {
+ std::string s = admin->GetLogStr() + " Delete corporation \'" + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
+
+if (si == data.end())
+ {
+ strError = "Corporation \'" + name + "\' cannot be deleted. Corporation does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+std::map<int, const_crp_iter>::iterator csi;
+csi = searchDescriptors.begin();
+while (csi != searchDescriptors.end())
+ {
+ if (csi->second == si)
+ (csi->second)++;
+ ++csi;
+ }
+
+data.remove(*si);
+if (store->DelCorp(name) < 0)
+ {
+ strError = "Corporation \'" + name + "\' was not deleted. Error: " + store->GetStrError();
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+WriteServLog("%s Corporation \'%s\' deleted.", admin->GetLogStr().c_str(), name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::Change(const CORP_CONF & corp, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->corpChg)
+ {
+ std::string s = admin->GetLogStr() + " Change corporation \'" + corp.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+crp_iter si(find(data.begin(), data.end(), corp));
+
+if (si == data.end())
+ {
+ strError = "Corporation \'" + corp.name + "\' cannot be changed " + ". Corporation does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+*si = corp;
+if (store->SaveCorp(corp))
+ {
+ WriteServLog("Cannot write corporation %s.", corp.name.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+WriteServLog("%s Corporation \'%s\' changed.",
+ admin->GetLogStr().c_str(), corp.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool CORPORATIONS_IMPL::Read()
+{
+STG_LOCKER lock(&mutex);
+std::vector<std::string> corpsList;
+if (store->GetCorpsList(&corpsList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return true;
+ }
+
+for (size_t i = 0; i < corpsList.size(); i++)
+ {
+ CORP_CONF corp;
+
+ if (store->RestoreCorp(&corp, corpsList[i]))
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return true;
+ }
+
+ data.push_back(corp);
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool CORPORATIONS_IMPL::Find(const std::string & name, CORP_CONF * corp)
+{
+assert(corp != NULL && "Pointer to corporation is not null");
+
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ return false;
+
+crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
+
+if (si != data.end())
+ {
+ *corp = *si;
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool CORPORATIONS_IMPL::Exists(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ return true;
+ }
+
+const_crp_iter si(find(data.begin(), data.end(), CORP_CONF(name)));
+
+if (si != data.end())
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::OpenSearch() const
+{
+STG_LOCKER lock(&mutex);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::SearchNext(int h, CORP_CONF * corp) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("CORPORATIONS. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == data.end())
+ return -1;
+
+*corp = *searchDescriptors[h]++;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CORPORATIONS_IMPL::CloseSearch(int h) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("CORPORATIONS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef CORPORATIONS_IMPL_H
+#define CORPORATIONS_IMPL_H
+
+#include "stg/corporations.h"
+#include "stg/corp_conf.h"
+#include "stg/locker.h"
+#include "stg/store.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <pthread.h>
+
+class ADMIN;
+
+class CORPORATIONS_IMPL : private NONCOPYABLE, public CORPORATIONS {
+public:
+ explicit CORPORATIONS_IMPL(STORE * st);
+ virtual ~CORPORATIONS_IMPL() {}
+
+ int Add(const CORP_CONF & corp, const ADMIN * admin);
+ int Del(const std::string & name, const ADMIN * admin);
+ int Change(const CORP_CONF & corp, const ADMIN * admin);
+ bool Find(const std::string & name, CORP_CONF * corp);
+ bool Exists(const std::string & name) const;
+ const std::string & GetStrError() const { return strError; }
+
+ size_t Count() const { return data.size(); }
+
+ int OpenSearch() const;
+ int SearchNext(int, CORP_CONF * corp) const;
+ int CloseSearch(int) const;
+
+private:
+ CORPORATIONS_IMPL(const CORPORATIONS_IMPL & rvalue);
+ CORPORATIONS_IMPL & operator=(const CORPORATIONS_IMPL & rvalue);
+
+ typedef std::list<CORP_CONF>::iterator crp_iter;
+ typedef std::list<CORP_CONF>::const_iterator const_crp_iter;
+
+ bool Read();
+
+ std::list<CORP_CONF> data;
+ STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable std::map<int, const_crp_iter> searchDescriptors;
+ mutable unsigned int handle;
+ mutable pthread_mutex_t mutex;
+ std::string strError;
+};
+
+#endif
--- /dev/null
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include "stg/locker.h"
+#include "stg/common.h"
+#include "eventloop.h"
+
+EVENT_LOOP::EVENT_LOOP()
+ : ACTIONS_LIST(),
+ _running(false),
+ _stopped(true),
+ _tid(),
+ _mutex(),
+ _condition()
+{
+pthread_mutex_init(&_mutex, NULL);
+pthread_cond_init(&_condition, NULL);
+}
+
+EVENT_LOOP::~EVENT_LOOP()
+{
+pthread_cond_destroy(&_condition);
+pthread_mutex_destroy(&_mutex);
+}
+
+bool EVENT_LOOP::Start()
+{
+_running = true;
+if (pthread_create(&_tid, NULL, Run, this))
+ {
+ printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
+ return true;
+ }
+return false;
+}
+
+bool EVENT_LOOP::Stop()
+{
+_running = false;
+// Wake up thread
+pthread_cond_signal(&_condition);
+// Wait until thread exit
+pthread_join(_tid, NULL);
+return false;
+}
+
+void * EVENT_LOOP::Run(void * self)
+{
+EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
+ev->Runner();
+return NULL;
+}
+
+void EVENT_LOOP::Runner()
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+_stopped = false;
+printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
+while (_running)
+ {
+ {
+ STG_LOCKER lock(&_mutex);
+ // Check for any actions...
+ if (empty())
+ {
+ // ... and sleep until new actions added
+ printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
+ pthread_cond_wait(&_condition, &_mutex);
+ }
+ // Check for running after wake up
+ if (!_running)
+ {
+ // Don't process any actions if stopping
+ break;
+ }
+ }
+ // Create new empty actions list
+ ACTIONS_LIST local;
+ // Fast swap with current
+ swap(local);
+ // Invoke all current actions
+ printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
+ local.InvokeAll();
+ }
+printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
+_stopped = true;
+}
+
+namespace {
+
+pthread_mutex_t singletonMutex;
+
+}
+
+EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
+{
+// Double-checking technique
+if (!_instance)
+ {
+ STG_LOCKER lock(&singletonMutex);
+ if (!_instance)
+ {
+ CreateInstance();
+ }
+ }
+return *_instance;
+}
+
+void EVENT_LOOP_SINGLETON::CreateInstance()
+{
+static EVENT_LOOP loop;
+_instance = &loop;
+}
+
+EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;
--- /dev/null
+#ifndef __EVENT_LOOP_H__
+#define __EVENT_LOOP_H__
+
+#include <pthread.h>
+
+#include "stg/noncopyable.h"
+#include "actions.h"
+
+class EVENT_LOOP : private NONCOPYABLE,
+ private ACTIONS_LIST
+{
+ public:
+ bool Start();
+ bool Stop();
+ bool IsRunning() const { return _running; }
+
+ template <class ACTIVE_CLASS, typename DATA_TYPE>
+ void Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d);
+
+ private:
+ bool _running;
+ bool _stopped;
+ pthread_t _tid;
+ pthread_mutex_t _mutex;
+ pthread_cond_t _condition;
+
+ EVENT_LOOP();
+ virtual ~EVENT_LOOP();
+
+ static void * Run(void *);
+ void Runner();
+
+ friend class EVENT_LOOP_SINGLETON;
+};
+
+class EVENT_LOOP_SINGLETON : private NONCOPYABLE
+{
+ public:
+ static EVENT_LOOP & GetInstance();
+
+ private:
+ static EVENT_LOOP * _instance;
+ static void CreateInstance();
+
+ EVENT_LOOP_SINGLETON() {}
+ ~EVENT_LOOP_SINGLETON() {}
+};
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+{
+STG_LOCKER lock(&_mutex);
+// Add new action
+ACTIONS_LIST::Enqueue(ac, a, d);
+// Signal about new action
+pthread_cond_signal(&_condition);
+}
+
+#endif
--- /dev/null
+#! /bin/sh
+
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
--- /dev/null
+#! /bin/sh
+
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$5
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
--- /dev/null
+#! /bin/sh
+
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
--- /dev/null
+#! /bin/sh
+
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
--- /dev/null
+# Enable the authorization module Always Online "mod_auth_ao.so"
+<Module auth_ao>
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the traffic capture module "mod_cap_ipq.so" using Berkeley Packet Filter
+<Module cap_bpf>
+ # Define interface(s) for traffic capture
+ iface = rl0
+ iface = rl1
+ iface = dc0
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the traffic capture module "mod_cap_divert.so" using Divert-sockets
+<Module cap_divert>
+ # Port for traffic
+ # Parameter: optional
+ # Value: 1 ... 65535
+ # Default: 15701
+ Port = 15701
+
+ # Disable packet forwarding
+ # Parameter: optional
+ # Value: yes, no
+ # Default: no
+ DisableForwarding = no
+</Module>
--- /dev/null
+# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
+<Module cap_nf>
+ # Port for TCP connections
+ # Note: Parameters TCPPort and UDPPort can be equal
+ # Parameter: optional
+ # Value: 1 ... 65535
+ # Default: 9996
+ #TCPPort = 9996
+
+ # Port for UDP connections
+ # Note: Parameters TCPPort and UDPPort can be equal
+ # Parameter: optional
+ # Value: 1 ... 65535
+ # Default: 9996
+ UDPPort = 9996
+</Module>
--- /dev/null
+# Enable the authorization module InetAccess "mod_auth_ia.so"
+<Module auth_ia>
+ # Port on which the server interacts with authorizator
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 5555
+ Port = 5555
+
+ # The time interval between sending an alive query to the user
+ # and updating statistics
+ # Parameter: required
+ # Values: 5 ... 600 (seconds)
+ # Default: 60
+ UserDelay = 60
+
+ # User timeout. If authorizer does not respond during this time,
+ # the user will be disconnected
+ # Parameter: required
+ # Values: 5 ... 600
+ # Default: 60
+ UserTimeout = 65
+
+ # Define which information will be transmitted from the server to InetAccess
+ # as a residue of prepaid traffic
+ # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
+ # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+ # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+ # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
+ # ........................
+ # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
+ # FreeMb = cash - amount of money for which the user can download for free
+ # FreeMb = none - no transfer
+ # Default: cash
+ # Parameter: required
+ # Values: different, see above
+ # Default: cash
+ FreeMb = cash
+
+ # Enable protocol errors logging
+ # Parameter: optional
+ # Values: yes, no
+ # Default: no
+ # LogProtocolErrors = no
+</Module>
--- /dev/null
+# Enable the module that pings users "mod_ping.so"
+<Module ping>
+ # The time interval between pings
+ # Parameter: required
+ # Value: 10 ... 3600 (seconds)
+ # Default: 15
+ PingDelay = 15
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the interaction module for FreeRADIUS "mod_radius.so"
+<Module radius>
+ # FreeRADIUS password
+ # Parameter: required
+ # Values: any, supported by software
+ # Default: 123456
+ Password = 123456
+
+ # FreeRADIUS server
+ # Parameter: required
+ # Values: IP address or DNS name
+ # Default: 127.0.0.1
+ ServerIP = 127.0.0.1
+
+ # FreeRADIUS port
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 6666
+ Port = 6666
+
+ # List of services for which will be carried out FreeRADIUS authentication
+ # Note: Parameter can be blank
+ # Parameter: required
+ # Value: any, supported by software
+ # Default: Login-User
+ AuthServices = Login-User
+
+ # List of services for which will be carried out FreeRADIUS Accounting
+ # Note: Parameter can be blank
+ # Parameter: required
+ # Value: any, supported by software
+ # Default: Framed-User
+ AcctServices = Framed-User
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
+<Module remote_script>
+ # The time interval between sending confirmations that the user is online
+ # Parametr: required
+ # Values: 10 ... 600 (seconds)
+ # Default: 60
+ SendPeriod = 15
+
+ # Define mapping between subnet(s) and remote server(s)
+ # File format: <subnet> <Router1> <Router2> ...
+ # Example:
+ # 192.168.1.0/24 192.168.1.7 192.168.1.8
+ # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
+ # 192.168.3.0/24 192.168.3.5
+ # 192.168.4.0/24 192.168.4.5
+ # Parametr: required
+ # Values: file path
+ # Default: subnets
+ SubnetFile = subnets
+
+ # The password to encrypt packets between the stg-server and remote server
+ # Parameter: required
+ # Values: any
+ # Default: 123456
+ Password = 123456
+
+ # Define which user parameters are transferred to a remote server in addition to
+ # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
+ # Note: Parameter can be blank.
+ # Parameter: required
+ # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName,
+ # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs,
+ # Userdata0...Userdata9
+ # Default: Cash Tariff EnabledDirs
+ UserParams = Cash Tariff EnabledDirs
+
+ # Port on which the server interacts with remote server
+ # Parameter: required
+ # Value: 1...65535
+ # Default: 9999
+ Port = 9999
+</Module>
--- /dev/null
+# Enable the configuration module ConfRPC "mod_conf_rpc.so"
+<Module conf_rpc>
+ # Port on which the server interacts with configurator
+ # Parameter: required
+ # Value: 1...65535
+ # Default:
+ Port = 8080
+
+ # Session timeout in seconds
+ # Parameter: required
+ # Value: positive integer
+ # Default: 1800
+ CookieTimeout = 1800
+</Module>
--- /dev/null
+# Enable the configuration module SgConfig "mod_conf_sg.so"
+<Module conf_sg>
+ # Port on which the server interacts with configurator
+ # Parameter: required
+ # Value: 1...65535
+ # Default: 5555
+ Port = 5555
+</Module>
\ No newline at end of file
--- /dev/null
+# Enables SMUX-peer for SNMPd.
+<Module smux>
+ # IP-address of a server to connect to
+ # Parameter: required
+ # Value: X.X.X.X
+ # Default: 127.0.0.1
+ Server = 127.0.0.1
+
+ # Port number on a server to connect to
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 199
+ Port = 199
+
+ # Password for authentication on a server
+ # Parameter: required
+ # Value: any text
+ Password =
+</Module>
--- /dev/null
+# Enables plain file backend.
+<StoreModule store_files>
+
+ # Working server directory, provides data on tariffs, users, administrators.
+ # Parameter: required
+ # Value: directory path
+ WorkDir = /var/stargazer
+
+ # Owner, group and permissions of the files of user statistics (stat)
+ # Parameter: required
+ # Values: any, supported by OS
+ ConfOwner = root
+ ConfGroup = root
+ ConfMode = 640
+
+ # Owner, group and permissions on user configuration files (conf)
+ # Parameter: required
+ # Values: any, supported by OS
+ StatOwner = root
+ StatGroup = root
+ StatMode = 640
+
+ # Owner, group and permissions for user log files (log)
+ # Parameter: required
+ # Values: any, supported by OS
+ UserLogOwner = root
+ UserLogGroup = root
+ UserLogMode = 640
+
+</StoreModule>
--- /dev/null
+# Enables Firebird backend.
+<StoreModule store_firebird>
+ # Database server address
+ # Parameter: optional
+ # Value: IP address or DNS name
+ # Default: localhost
+ # Server = localhost
+
+ # Path to the database on the server or its alias
+ # Parameter: optional
+ # Value: file path
+ # Default: /var/stg/stargazer.fdb
+ # Database = /var/stg/stargazer.fdb
+
+ # Database username
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stg
+ # User = stg
+
+ # Database password
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: 123456
+ # Password = 123456
+
+ # The transaction isolation level
+ # Parameter: optional
+ # Values: concurrency, dirtyread, readcommitted, consistency
+ # Defalt: concurrency
+ # IsolationLevel = concurrency
+
+ # Responding to lock (optional, defaults to wait):
+ # Parameter: optional
+ # Values: wait, nowait
+ # Defalt: wait
+ # LockResolution = wait
+</StoreModule>
--- /dev/null
+# Enables MySQL backend.
+<StoreModule store_mysql>
+ # Database server address
+ # Parameter: required
+ # Value: IP address or DNS name
+ # Default: localhost
+ Server = localhost
+
+ # Database name
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: stg
+ Database = stg
+
+ # Database username
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: stg
+ User = stg
+
+ # Database password
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: 123456
+ Password = 123456
+</StoreModule>
--- /dev/null
+# Enables PostgreSQL backend.
+<StoreModule store_postgresql>
+ # Database server address
+ # Parameter: optional
+ # Value: IP address or DNS name
+ # Default: localhost
+ # Server = localhost
+
+ # Database name
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stargazer
+ # Database = stargazer
+
+ # Database username
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stg
+ # User = stg
+
+ # Database password
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: 123456
+ # Password = 123456
+
+ # Number of tries to reconnect
+ # Parameter: optional
+ # Value: positive integer
+ # Default: 3
+ # Retries = 3
+</StoreModule>
--- /dev/null
+../conf-available.d/mod_ao.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_cap_bpf.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_ia.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_ping.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_sg.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/store_files.conf
\ No newline at end of file
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+################################################################################
+# Stargazer Configuration file #
+################################################################################
+
+# LOG file name
+# Parameter: required
+# Value: file path
+# Default: /var/log/stargazer.log
+LogFile = /var/log/stargazer.log
+
+# PID file name
+# Parameter: optional
+# Value: file path
+# Default: /var/run/stargazer.pid
+PIDFile = /var/run/stargazer.pid
+
+# Traffic classification rules
+# Parameter: required
+# Value: file path
+# Default: /etc/stargazer/rules
+Rules = /etc/stargazer/rules
+
+# The time interval between writing detailed user's statistics into the database
+# Note: With a large number of users this value should be increased,
+# since writting into the database can take a long time.
+# Parameter: required
+# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
+# Default: 1/2
+DetailStatWritePeriod = 1/2
+
+# The time interval between writing summary user's statistics into the database
+# Parameter: optional
+# Value: 1 ... 1440 (minutes)
+# Default: 10
+StatWritePeriod = 10
+
+# Day of charging fee
+# Note: 0 - The last day of the month
+# Parameter: required
+# Value: 0 ... 31
+# Default: 1
+DayFee = 1
+
+# When set to 'no' Stargazer will continue reading database after error and show all of them.
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# StopOnError = yes
+
+# Fee charged at the last (yes) or first (no) day of tariffication period.
+# Defines how the fee will be charged in the transition to the new tariff.
+# User has tariff A with fee 100. Changing it to tariff B with fee 200
+# will result in charging user's account at 100 if DayFeeIsLastDay = yes
+# and at 200, if DayFeeIsLastDay = no
+# Parameter: required
+# Values: yes, no
+# Default: no
+DayFeeIsLastDay = no
+
+# Day of changing delayed tariffs and resetting summary user's statistics.
+# Defines the edge of the tariffication period.
+# Parameter: required
+# Value: 0 ... 31. 0 - The last day of the month
+# Default: 1
+DayResetTraff = 1
+
+# Defines whether to charge fee daily (yes) or monthly (no)
+# Parameter: required
+# Values: yes, no
+# Default: no
+SpreadFee = no
+
+# Defines whether the user can access the internet if it has no cash,
+# but remained prepaid traffic
+# Parameter: required
+# Values: yes, no
+# Default: no
+FreeMbAllowInet = no
+
+# Defines what will be written in the traffic cost in detail_stat.
+# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost willn't be written in detail_stat.
+# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost will be written in detail_stat.
+# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
+# Parameter: required
+# Values: yes, no
+# Default: yes
+WriteFreeMbTraffCost = yes
+
+# Charge a full monthly fee even if user was "frozen" a part
+# of the tariffication period
+# Parameter: optional
+# Values: yes, no
+# Default: no
+FullFee = no
+
+# Allow user to see and use a full cash (yes) or hide a part of it (no)
+# for the next fee charge
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# ShowFeeInCash=yes
+
+# The names of directions. Direction without names will not appear in
+# authorizer and configurator.
+# Note: Names consisting of several words should be quoted
+# Parameter: optional
+# Values:
+<DirNames>
+ DirName0 = Internet
+ DirName1 =
+ DirName2 =
+ DirName3 =
+ DirName4 =
+ DirName5 =
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+# Amount of stg-exec processes.
+# These processes are responsible for the execution of scripts OnConnect,
+# OnDisconnect, etc.
+# 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 stargazer.
+# 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 with server modules
+# Parameter: required
+# Value: directory path
+# Default: /usr/lib/stg
+ModulesPath = /usr/lib/stg
+
+# Directory where the "monitor" files are located.
+# A blank files will be created in this directory. The modification time of such
+# files will be changed about once a minute. If server crashes or some of server
+# component hang, the files will stop refreshing, and on this basis we can define
+# the failure of the server and if necessary restart.
+# If option is omitted or blank, the monitoring is not performed.
+# Parameter: optional
+# Value: file path
+# Default: /var/stargazer/monitor
+#MonitorDir=/var/stargazer/monitor
+
+# Defines message maximum lifetime
+# Note: 0 - unlimited
+# Parameter: optional
+# Value: any numeric
+# Default: 0 (day)
+# MessagesTimeout = 0
+
+# Defines fee charging rules.
+# 0 - classic rules, allow fee charge even cash is negative;
+# 1 - disallow fee charge if cash value is negative;
+# 2 - disallow fee charge if there is not enought cash (cash < fee).
+# Parameter: optional
+# Value: 0 ... 2
+# Default: 0 (classic)
+# FeeChargeType = 0
+
+# Enable or disable reconnect on tariff change
+# Parameter: optional
+# Values: yes, no
+# Default: no
+# ReconnectOnTariffChange = no
+
+# Definest set of parameters passed to OnConnect and OnDisconnect scripts
+# This set is added to the end of the default param list, which are, respectively:
+# login, ip, cash, id, dirs
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive
+# Default:
+# ScriptParams =
+
+# Enable or disable writing session log
+# Parameter: optional
+# Values: yes, no
+# Default: no (session log is enabled)
+# DisableSessionLog = no
+
+# Filter for logging parameter changes
+# Defines which parameters will be logged to parameter log in database. Allows
+# to specify multiuple parameter names or asterisk (*), which means "log all params".
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive, or "*"
+# Default: *
+# FilterParamsLog = *
+
+################################################################################
+# Store module
+# Configure the module that works with the database server
+
+# Warning: Only one store module could be used at the same time!
+
+<IncludeFile "conf-enabled.d/store_*.conf">
+</IncludeFile>
+
+
+################################################################################
+# Other modules
+
+<Modules>
+
+ <IncludeFile "conf-enabled.d/mod_*.conf">
+ </IncludeFile>
+
+</Modules>
+################################################################################
--- /dev/null
+#!/sbin/runscript
+
+extra_commands="reload"
+
+DAEMON=/usr/sbin/stargazer
+STARGAZER_OPTS=""
+PIDFILE=/var/run/stargazer.pid
+
+depend() {
+ need net
+ use postgresql firebird mysql
+ provide stargazer
+}
+
+start() {
+ ebegin "Starting stargazer"
+ start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} -- ${STARGAZER_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping stargazer"
+ start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --retry=INT/120/KILL/5
+ rm -f ${PIDFILE}
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading stargazer rules"
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
+ return 0
+ eend $?
+}
--- /dev/null
+#!/bin/bash
+#
+# processname: stargazer
+# config: /etc/stargazer/stargazer.conf
+# pidfile: /var/run/stargazer.pid
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+# Source stargazer configureation.
+DAEMON=yes
+QUEUE=1h
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -f /sbin/stargazer ] || exit 0
+
+RETVAL=0
+prog="stargazer"
+
+start() {
+ # Start daemons.
+
+ echo -n $"Starting $prog: "
+ /etc/stargazer/first 2> /dev/null
+ daemon /sbin/stargazer
+ RETVAL=$?
+ /etc/stargazer/last 2> /dev/null
+ echo
+ [ $RETVAL -eq 0 ] && touch /var/lock/subsys/stargazer
+ return $RETVAL
+}
+
+stop() {
+ # Stop daemons.
+ echo -n $"Shutting down $prog: "
+ killproc stargazer
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/stargazer
+ return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart|reload)
+ stop
+ start
+ RETVAL=$?
+ ;;
+ status)
+ status stargazer
+ RETVAL=$?
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart|status}"
+ exit 1
+esac
+
+exit $RETVAL
--- /dev/null
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: stargazer
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: S 0 1 6
+# Short-Description: Stargazer initscript
+# Description: This file should be used to start and stop stargazer daemon
+### END INIT INFO
+
+# Author: Boris Mikhailenko <stg34@stg.dp.ua>
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+DESC="Billing system"
+NAME=stargazer
+DAEMON=/usr/sbin/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+ || return 1
+
+ # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+
+ # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon --stop --quiet --retry=INT/60/KILL/5 --pidfile $PIDFILE --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/60/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ reload)
+ # If do_reload() is not implemented then leave this commented out
+ # and leave 'force-reload' as an alias for 'restart'.
+ log_daemon_msg "Reloading $DESC" "$NAME"
+ do_reload
+ log_end_msg $?
+ ;;
+ restart)
+ #
+ # If the "reload" option is implemented then remove the
+ # 'force-reload' alias
+ #
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
--- /dev/null
+#! /bin/sh
+
+# About: This script is called when user account is changed.
+# Common Task: Notify about various events.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# User parameter
+PARAMETER=$2
+
+# User parameter old value
+OLDVALUE=$3
+
+# User parameter new value
+NEWVALUE=$4
+
+# Usage examples:
+#echo "User: '$LOGIN'. Parameter $PARAMETER changed from '$OLDVALUE' to '$NEWVALUE'" >> /var/stargazer/user.change.log
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+
+# About: This script is called when the user successfully authenticated on the server.
+# Common Task: Rebuild firewall to allow user to access the Internet.
+# Priority: required
+
+# User login
+LOGIN=$1
+
+# User IP
+IP=$2
+
+# User cash
+CASH=$3
+
+# User ID
+ID=$4
+
+# Selected DIRs (from rules file) to connect
+DIRS=$5
+
+# Usage examples:
+#echo "Connected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+
+# About: This script is called when the user wants to disconnect or authorization timeout has passed.
+# Common task: Rebuild firewall to disallow user to access the Internet.
+# Priority: required
+
+# User login
+LOGIN=$1
+
+# User IP
+IP=$2
+
+# User cash
+CASH=$3
+
+# User ID
+ID=$4
+
+# Selected DIRs (from rules file) to disconnect
+DIRS=$5
+
+# Usage examples:
+#echo "Disconnected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
--- /dev/null
+#! /bin/sh
+
+# About: This script is called when the user is added to the Stargazer.
+# Common task: Automate typical actions on adding user to the network,
+# such as creating email or IM account.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# Usage examples:
+#echo "Added user $login" >> /var/stargazer/add_del.log
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+
+# About: This script is called when the user is removed from the Stargazer.
+# Common task: Automate typical actions on removing user from the network,
+# such as removing email or IM account.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# Usage examples:
+#echo "Deleted user $LOGIN" >> /var/stargazer/add_del.log
+
--- /dev/null
+# Enable the authorization module Always Online "mod_auth_ao.so"
+<Module auth_ao>
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the traffic capture module "mod_cap_ether.so" using Packet-sockets
+<Module cap_ether>
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the traffic capture module "mod_cap_ipq.so" using mechanism of IP Queueing
+<Module cap_ipq>
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
+<Module cap_nf>
+ # Port for TCP connections
+ # Note: Parameters TCPPort and UDPPort can be equal
+ # Parameter: optional
+ # Value: 1 ... 65535
+ # Default: 9996
+ #TCPPort = 9996
+
+ # Port for UDP connections
+ # Note: Parameters TCPPort and UDPPort can be equal
+ # Parameter: optional
+ # Value: 1 ... 65535
+ # Default: 9996
+ UDPPort = 9996
+</Module>
--- /dev/null
+# Enable the authorization module InetAccess "mod_auth_ia.so"
+<Module auth_ia>
+ # Port on which the server interacts with authorizator
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 5555
+ Port = 5555
+
+ # The time interval between sending an alive query to the user
+ # and updating statistics
+ # Parameter: required
+ # Values: 5 ... 600 (seconds)
+ # Default: 60
+ UserDelay = 60
+
+ # User timeout. If authorizer does not respond during this time,
+ # the user will be disconnected
+ # Parameter: required
+ # Values: 5 ... 600
+ # Default: 60
+ UserTimeout = 65
+
+ # Define which information will be transmitted from the server to InetAccess
+ # as a residue of prepaid traffic
+ # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
+ # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+ # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+ # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
+ # ........................
+ # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
+ # FreeMb = cash - amount of money for which the user can download for free
+ # FreeMb = none - no transfer
+ # Default: cash
+ # Parameter: required
+ # Values: different, see above
+ # Default: cash
+ FreeMb = cash
+
+ # Enable protocol errors logging
+ # Parameter: optional
+ # Values: yes, no
+ # Default: no
+ # LogProtocolErrors = no
+</Module>
--- /dev/null
+# Enable the module that pings users "mod_ping.so"
+<Module ping>
+ # The time interval between pings
+ # Parameter: required
+ # Value: 10 ... 3600 (seconds)
+ # Default: 15
+ PingDelay = 15
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the interaction module for FreeRADIUS "mod_radius.so"
+<Module radius>
+ # FreeRADIUS password
+ # Parameter: required
+ # Values: any, supported by software
+ # Default: 123456
+ Password = 123456
+
+ # FreeRADIUS server
+ # Parameter: required
+ # Values: IP address or DNS name
+ # Default: 127.0.0.1
+ ServerIP = 127.0.0.1
+
+ # FreeRADIUS port
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 6666
+ Port = 6666
+
+ # List of services for which will be carried out FreeRADIUS authentication
+ # Note: Parameter can be blank
+ # Parameter: required
+ # Value: any, supported by software
+ # Default: Login-User
+ AuthServices = Login-User
+
+ # List of services for which will be carried out FreeRADIUS Accounting
+ # Note: Parameter can be blank
+ # Parameter: required
+ # Value: any, supported by software
+ # Default: Framed-User
+ AcctServices = Framed-User
+</Module>
\ No newline at end of file
--- /dev/null
+# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
+<Module remote_script>
+ # The time interval between sending confirmations that the user is online
+ # Parametr: required
+ # Values: 10 ... 600 (seconds)
+ # Default: 60
+ SendPeriod = 15
+
+ # Define mapping between subnet(s) and remote server(s)
+ # File format: <subnet> <Router1> <Router2> ...
+ # Example:
+ # 192.168.1.0/24 192.168.1.7 192.168.1.8
+ # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
+ # 192.168.3.0/24 192.168.3.5
+ # 192.168.4.0/24 192.168.4.5
+ # Parametr: required
+ # Values: file path
+ # Default: subnets
+ SubnetFile = subnets
+
+ # The password to encrypt packets between the stg-server and remote server
+ # Parameter: required
+ # Values: any
+ # Default: 123456
+ Password = 123456
+
+ # Define which user parameters are transferred to a remote server in addition to
+ # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
+ # Note: Parameter can be blank.
+ # Parameter: required
+ # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName,
+ # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs,
+ # Userdata0...Userdata9
+ # Default: Cash Tariff EnabledDirs
+ UserParams = Cash Tariff EnabledDirs
+
+ # Port on which the server interacts with remote server
+ # Parameter: required
+ # Value: 1...65535
+ # Default: 9999
+ Port = 9999
+</Module>
--- /dev/null
+# Enable the configuration module ConfRPC "mod_conf_rpc.so"
+<Module conf_rpc>
+ # Port on which the server interacts with configurator
+ # Parameter: required
+ # Value: 1...65535
+ # Default:
+ Port = 8080
+
+ # Session timeout in seconds
+ # Parameter: required
+ # Value: positive integer
+ # Default: 1800
+ CookieTimeout = 1800
+</Module>
--- /dev/null
+# Enable the configuration module SgConfig "mod_conf_sg.so"
+<Module conf_sg>
+ # Port on which the server interacts with configurator
+ # Parameter: required
+ # Value: 1...65535
+ # Default: 5555
+ Port = 5555
+</Module>
\ No newline at end of file
--- /dev/null
+# Enables SMUX-peer for SNMPd.
+<Module smux>
+ # IP-address of a server to connect to
+ # Parameter: required
+ # Value: X.X.X.X
+ # Default: 127.0.0.1
+ Server = 127.0.0.1
+
+ # Port number on a server to connect to
+ # Parameter: required
+ # Value: 1 ... 65535
+ # Default: 199
+ Port = 199
+
+ # Password for authentication on a server
+ # Parameter: required
+ # Value: any text
+ Password =
+</Module>
--- /dev/null
+# Enables plain file backend.
+<StoreModule store_files>
+
+ # Working server directory, provides data on tariffs, users, administrators.
+ # Parameter: required
+ # Value: directory path
+ WorkDir = /var/stargazer
+
+ # Owner, group and permissions of the files of user statistics (stat)
+ # Parameter: required
+ # Values: any, supported by OS
+ ConfOwner = root
+ ConfGroup = root
+ ConfMode = 640
+
+ # Owner, group and permissions on user configuration files (conf)
+ # Parameter: required
+ # Values: any, supported by OS
+ StatOwner = root
+ StatGroup = root
+ StatMode = 640
+
+ # Owner, group and permissions for user log files (log)
+ # Parameter: required
+ # Values: any, supported by OS
+ UserLogOwner = root
+ UserLogGroup = root
+ UserLogMode = 640
+
+</StoreModule>
--- /dev/null
+# Enables Firebird backend.
+<StoreModule store_firebird>
+ # Database server address
+ # Parameter: optional
+ # Value: IP address or DNS name
+ # Default: localhost
+ # Server = localhost
+
+ # Path to the database on the server or its alias
+ # Parameter: optional
+ # Value: file path
+ # Default: /var/stg/stargazer.fdb
+ # Database = /var/stg/stargazer.fdb
+
+ # Database username
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stg
+ # User = stg
+
+ # Database password
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: 123456
+ # Password = 123456
+
+ # The transaction isolation level
+ # Parameter: optional
+ # Values: concurrency, dirtyread, readcommitted, consistency
+ # Defalt: concurrency
+ # IsolationLevel = concurrency
+
+ # Responding to lock (optional, defaults to wait):
+ # Parameter: optional
+ # Values: wait, nowait
+ # Defalt: wait
+ # LockResolution = wait
+</StoreModule>
--- /dev/null
+# Enables MySQL backend.
+<StoreModule store_mysql>
+ # Database server address
+ # Parameter: required
+ # Value: IP address or DNS name
+ # Default: localhost
+ Server = localhost
+
+ # Database name
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: stg
+ Database = stg
+
+ # Database username
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: stg
+ User = stg
+
+ # Database password
+ # Parameter: required
+ # Value: any, supported by database
+ # Default: 123456
+ Password = 123456
+</StoreModule>
--- /dev/null
+# Enables PostgreSQL backend.
+<StoreModule store_postgresql>
+ # Database server address
+ # Parameter: optional
+ # Value: IP address or DNS name
+ # Default: localhost
+ # Server = localhost
+
+ # Database name
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stargazer
+ # Database = stargazer
+
+ # Database username
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: stg
+ # User = stg
+
+ # Database password
+ # Parameter: optional
+ # Value: any, supported by database
+ # Default: 123456
+ # Password = 123456
+
+ # Number of tries to reconnect
+ # Parameter: optional
+ # Value: positive integer
+ # Default: 3
+ # Retries = 3
+</StoreModule>
--- /dev/null
+../conf-available.d/mod_ao.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_cap_ether.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_ia.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_ping.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/mod_sg.conf
\ No newline at end of file
--- /dev/null
+../conf-available.d/store_files.conf
\ No newline at end of file
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+################################################################################
+# Stargazer Configuration file #
+################################################################################
+
+# LOG file name
+# Parameter: required
+# Value: file path
+# Default: /var/log/stargazer.log
+LogFile = /var/log/stargazer.log
+
+# PID file name
+# Parameter: optional
+# Value: file path
+# Default: /var/run/stargazer.pid
+PIDFile = /var/run/stargazer.pid
+
+# Traffic classification rules
+# Parameter: required
+# Value: file path
+# Default: /etc/stargazer/rules
+Rules = /etc/stargazer/rules
+
+# The time interval between writing detailed user's statistics into the database
+# Note: With a large number of users this value should be increased,
+# since writting into the database can take a long time.
+# Parameter: required
+# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
+# Default: 1/2
+DetailStatWritePeriod = 1/2
+
+# The time interval between writing summary user's statistics into the database
+# Parameter: optional
+# Value: 1 ... 1440 (minutes)
+# Default: 10
+StatWritePeriod = 10
+
+# Day of charging fee
+# Note: 0 - The last day of the month
+# Parameter: required
+# Value: 0 ... 31
+# Default: 1
+DayFee = 1
+
+# When set to 'no' Stargazer will continue reading database after error and show all of them.
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# StopOnError = yes
+
+# Fee charged at the last (yes) or first (no) day of tariffication period.
+# Defines how the fee will be charged in the transition to the new tariff.
+# User has tariff A with fee 100. Changing it to tariff B with fee 200
+# will result in charging user's account at 100 if DayFeeIsLastDay = yes
+# and at 200, if DayFeeIsLastDay = no
+# Parameter: required
+# Values: yes, no
+# Default: no
+DayFeeIsLastDay = no
+
+# Day of changing delayed tariffs and resetting summary user's statistics.
+# Defines the edge of the tariffication period.
+# Parameter: required
+# Value: 0 ... 31. 0 - The last day of the month
+# Default: 1
+DayResetTraff = 1
+
+# Defines whether to charge fee daily (yes) or monthly (no)
+# Parameter: required
+# Values: yes, no
+# Default: no
+SpreadFee = no
+
+# Defines whether the user can access the internet if it has no cash,
+# but remained prepaid traffic
+# Parameter: required
+# Values: yes, no
+# Default: no
+FreeMbAllowInet = no
+
+# Defines what will be written in the traffic cost in detail_stat.
+# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost willn't be written in detail_stat.
+# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost will be written in detail_stat.
+# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
+# Parameter: required
+# Values: yes, no
+# Default: yes
+WriteFreeMbTraffCost = yes
+
+# Charge a full monthly fee even if user was "frozen" a part
+# of the tariffication period
+# Parameter: optional
+# Values: yes, no
+# Default: no
+FullFee = no
+
+# Allow user to see and use a full cash (yes) or hide a part of it (no)
+# for the next fee charge
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# ShowFeeInCash=yes
+
+# The names of directions. Direction without names will not appear in
+# authorizer and configurator.
+# Note: Names consisting of several words should be quoted
+# Parameter: optional
+# Values:
+<DirNames>
+ DirName0 = Internet
+ DirName1 =
+ DirName2 =
+ DirName3 =
+ DirName4 =
+ DirName5 =
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+# Amount of stg-exec processes.
+# These processes are responsible for the execution of scripts OnConnect,
+# OnDisconnect, etc.
+# 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 stargazer.
+# 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 with server modules
+# Parameter: required
+# Value: directory path
+# Default: /usr/lib/stg
+ModulesPath = /usr/lib/stg
+
+# Directory where the "monitor" files are located.
+# A blank files will be created in this directory. The modification time of such
+# files will be changed about once a minute. If server crashes or some of server
+# component hang, the files will stop refreshing, and on this basis we can define
+# the failure of the server and if necessary restart.
+# If option is omitted or blank, the monitoring is not performed.
+# Parameter: optional
+# Value: file path
+# Default: /var/stargazer/monitor
+#MonitorDir=/var/stargazer/monitor
+
+# Defines message maximum lifetime
+# Note: 0 - unlimited
+# Parameter: optional
+# Value: any numeric
+# Default: 0 (day)
+# MessagesTimeout = 0
+
+# Defines fee charging rules.
+# 0 - classic rules, allow fee charge even cash is negative;
+# 1 - disallow fee charge if cash value is negative;
+# 2 - disallow fee charge if there is not enought cash (cash < fee).
+# Parameter: optional
+# Value: 0 ... 2
+# Default: 0 (classic)
+# FeeChargeType = 0
+
+# Enable or disable reconnect on tariff change
+# Parameter: optional
+# Values: yes, no
+# Default: no
+# ReconnectOnTariffChange = no
+
+# Definest set of parameters passed to OnConnect and OnDisconnect scripts
+# This set is added to the end of the default param list, which are, respectively:
+# login, ip, cash, id, dirs
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive
+# Default:
+# ScriptParams =
+
+# Enable or disable writing session log
+# Parameter: optional
+# Values: yes, no
+# Default: no (session log is enabled)
+# DisableSessionLog = no
+
+# Filter for logging parameter changes
+# Defines which parameters will be logged to parameter log in database. Allows
+# to specify multiuple parameter names or asterisk (*), which means "log all params".
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive, or "*"
+# Default: *
+# FilterParamsLog = *
+
+################################################################################
+# Store module
+# Configure the module that works with the database server
+
+# Warning: Only one store module could be used at the same time!
+
+<IncludeFile "conf-enabled.d/store_*.conf">
+</IncludeFile>
+
+
+################################################################################
+# Other modules
+
+<Modules>
+
+ <IncludeFile "conf-enabled.d/mod_*.conf">
+ </IncludeFile>
+
+</Modules>
+################################################################################
--- /dev/null
+/*
+ * DB migration from v00 to v01 (postgres)
+ */
+
+ALTER TABLE tb_sessions_log ADD free_mb dm_money;
+ALTER TABLE tb_sessions_log ADD reason TEXT;
+
+DROP FUNCTION sp_add_session_log_entry ( dm_name, timestamp without time zone, dm_session_event_type, inet, dm_money);
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+ _event_time TIMESTAMP,
+ _event_type dm_session_event_type,
+ _ip INET,
+ _cash dm_money,
+ _free_mb dm_money,
+ _reason TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_session_log INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ INSERT INTO tb_sessions_log
+ (fk_user,
+ event_time,
+ event_type,
+ ip,
+ cash,
+ free_mb,
+ reason)
+ VALUES
+ (_pk_user,
+ _event_time,
+ _event_type,
+ _ip,
+ _cash,
+ _free_mb,
+ _reason);
+
+ SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+ RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+UPDATE tb_info SET version = 6;
--- /dev/null
+/*
+ * DB migration from v00 to v01 (firebird)
+ */
+
+alter table tb_users add disabled_detail_stat dm_bool;
+
+drop procedure sp_add_user;
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)
+as
+declare variable pk_user integer;
+declare variable pk_stat integer;
+begin
+ pk_user = gen_id(gn_pk_user, 1);
+ insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
+ while (dirs > 0) do
+ begin
+ insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+ dirs = dirs - 1;
+ end
+end!!
+set term ; !!
--- /dev/null
+/*
+ * 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
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * Примечание.
+ * * dm_permission_flag. Представляет собой битовую маску - rw.
+ * r - чтение, w - изменение параметра.
+ * 0 - дествие запрещено, 1 - действие разрешено
+ *
+ * * dm_traff_type. Число определяющее тип подсчета трафика:
+ * 0 - up - считается по upload
+ * 1 - down - считается по download
+ * 2 - max - считается по максимальному среди upload/download
+ * 3 - up+down - считается по сумме upload и download
+ *
+ * * dm_session_event_type. Указывает тип записи в логе о сессии.
+ * 'c' - connect, 'd' - disconnect.
+ *
+ *****************************************************************************
+ */
+
+/*
+ * $Revision: 1.12 $
+ * $Date: 2009/08/20 14:58:43 $
+ */
+
+
+/*
+ *****************************************************************************
+ * -= Создание типов и доменов =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(12, 4) NOT NULL DEFAULT 0;
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_day AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 31 )
+ DEFAULT 0;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+ CHECK ( value = 'c' OR value = 'd' );
+
+/*
+ *****************************************************************************
+ * -= Создание таблиц =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_info
+(
+ version INTEGER NOT NULL
+);
+
+CREATE TABLE tb_admins
+(
+ pk_admin SERIAL PRIMARY KEY,
+ login dm_name UNIQUE,
+ passwd dm_password NOT NULL,
+ chg_conf dm_permission_flag,
+ chg_password dm_permission_flag,
+ chg_stat dm_permission_flag,
+ chg_cash dm_permission_flag,
+ usr_add_del dm_permission_flag,
+ chg_tariff dm_permission_flag,
+ chg_admin dm_permission_flag,
+ chg_service dm_permission_flag,
+ chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+ pk_tariff SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ fee dm_money,
+ free dm_money,
+ passive_cost dm_money,
+ traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+ pk_tariff_param SERIAL PRIMARY KEY,
+ fk_tariff INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ price_day_a dm_money,
+ price_day_b dm_money,
+ price_night_a dm_money,
+ price_night_b dm_money,
+ threshold INTEGER NOT NULL,
+ time_day_begins TIME NOT NULL,
+ time_day_ends TIME NOT NULL,
+
+ FOREIGN KEY (fk_tariff)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_corporations
+(
+ pk_corporation SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+ pk_user SERIAL PRIMARY KEY,
+ fk_tariff INTEGER,
+ fk_tariff_change INTEGER,
+ fk_corporation INTEGER,
+ address VARCHAR(256) NOT NULL,
+ always_online BOOLEAN NOT NULL,
+ credit dm_money,
+ credit_expire TIMESTAMP NOT NULL,
+ disabled BOOLEAN NOT NULL,
+ disabled_detail_stat BOOLEAN NOT NULL,
+ email VARCHAR(256) NOT NULL,
+ grp dm_name,
+ note TEXT NOT NULL,
+ passive BOOLEAN NOT NULL,
+ passwd dm_password,
+ phone VARCHAR(256) NOT NULL,
+ name dm_name UNIQUE,
+ real_name VARCHAR(256) NOT NULL,
+ cash dm_money,
+ free_mb dm_money,
+ last_activity_time TIMESTAMP NOT NULL,
+ last_cash_add dm_money,
+ last_cash_add_time TIMESTAMP NOT NULL,
+ passive_time INTEGER NOT NULL,
+
+ FOREIGN KEY (fk_tariff)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_tariff_change)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_corporation)
+ REFERENCES tb_corporations (pk_corporation)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_detail_stats
+(
+ pk_detail_stat BIGSERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ ip INET NOT NULL,
+ download BIGINT NOT NULL,
+ upload BIGINT NOT NULL,
+ cost dm_money,
+ from_time TIMESTAMP NOT NULL,
+ till_time TIMESTAMP NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_services
+(
+ pk_service SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ comment TEXT NOT NULL,
+ cost dm_money,
+ pay_day dm_day
+);
+
+CREATE TABLE tb_users_services
+(
+ pk_user_service SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ fk_service INTEGER NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_service)
+ REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+ pk_message SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ ver SMALLINT NOT NULL,
+ msg_type SMALLINT NOT NULL,
+ last_send_time TIMESTAMP NOT NULL,
+ creation_time TIMESTAMP NOT NULL,
+ show_time INTEGER NOT NULL,
+ repeat SMALLINT NOT NULL,
+ repeat_period INTEGER NOT NULL,
+ msg_text TEXT NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_stats_traffic
+(
+ pk_stat_traffic BIGSERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ stats_date DATE NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ download BIGINT NOT NULL,
+ upload BIGINT NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ UNIQUE (fk_user, stats_date, dir_num)
+);
+
+CREATE TABLE tb_users_data
+(
+ pk_user_data SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ num SMALLINT NOT NULL,
+ data VARCHAR(256) NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_allowed_ip
+(
+ pk_allowed_ip SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ ip INET NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_log
+(
+ pk_session_log SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ event_time TIMESTAMP NOT NULL,
+ event_type dm_session_event_type,
+ ip INET NOT NULL,
+ cash dm_money,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_data
+(
+ pk_session_data SERIAL PRIMARY KEY,
+ fk_session_log INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ session_upload BIGINT NOT NULL,
+ session_download BIGINT NOT NULL,
+ month_upload BIGINT NOT NULL,
+ month_download BIGINT NOT NULL,
+
+ FOREIGN KEY (fk_session_log)
+ REFERENCES tb_sessions_log (pk_session_log)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_parameters
+(
+ pk_parameter SERIAL PRIMARY KEY,
+ name dm_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+ pk_param_log SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ fk_parameter INTEGER NOT NULL,
+ fk_admin INTEGER NOT NULL,
+ ip INET NOT NULL,
+ event_time TIMESTAMP NOT NULL,
+ from_val VARCHAR(256),
+ to_val VARCHAR(256),
+ comment TEXT,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_parameter)
+ REFERENCES tb_parameters (pk_parameter),
+ FOREIGN KEY (fk_admin)
+ REFERENCES tb_admins (pk_admin)
+ ON DELETE CASCADE
+);
+
+/*
+ *****************************************************************************
+ * -= Создание хранимых процедур =-
+ *****************************************************************************
+ */
+
+CREATE FUNCTION sp_add_message(_login dm_name,
+ _ver SMALLINT,
+ _msg_type SMALLINT,
+ _last_send_time TIMESTAMP,
+ _creation_time TIMESTAMP,
+ _show_time INTEGER,
+ _repeat SMALLINT,
+ _repeat_period INTEGER,
+ _msg_text TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+ INSERT INTO tb_messages
+ (fk_user,
+ ver,
+ msg_type,
+ last_send_time,
+ creation_time,
+ show_time,
+ repeat,
+ repeat_period,
+ msg_text)
+ VALUES
+ (_pk_user,
+ _ver,
+ _msg_type,
+ _last_send_time,
+ _creation_time,
+ _show_time,
+ _repeat,
+ _repeat_period,
+ _msg_text);
+ RETURN CURRVAL('tb_messages_pk_message_seq');
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_tariff(_name dm_name, _dirs INTEGER)
+RETURNS INTEGER
+AS $$
+DECLARE
+ pk_tariff INTEGER;
+BEGIN
+ INSERT INTO tb_tariffs
+ (name,
+ fee,
+ free,
+ passive_cost,
+ traff_type)
+ VALUES
+ (_name,
+ 0, 0, 0, 0);
+ SELECT CURRVAL('tb_tariffs_pk_tariff_seq') INTO pk_tariff;
+ FOR i IN 1.._dirs LOOP
+ INSERT INTO tb_tariffs_params
+ (fk_tariff,
+ dir_num,
+ price_day_a,
+ price_day_b,
+ price_night_a,
+ price_night_b,
+ threshold,
+ time_day_begins,
+ time_day_ends)
+ VALUES
+ (pk_tariff,
+ i - 1,
+ 0, 0, 0, 0, 0,
+ CAST('1970-01-01 00:00:00+00' AS TIMESTAMP),
+ CAST('1970-01-01 00:00:00+00' AS TIMESTAMP));
+ END LOOP;
+ RETURN pk_tariff;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_user(_name dm_name)
+RETURNS INTEGER
+AS $$
+DECLARE
+ pk_user INTEGER;
+BEGIN
+ INSERT INTO tb_users
+ (fk_tariff,
+ fk_tariff_change,
+ fk_corporation,
+ address,
+ always_online,
+ credit,
+ credit_expire,
+ disabled,
+ disabled_detail_stat,
+ email,
+ grp,
+ note,
+ passive,
+ passwd,
+ phone,
+ name,
+ real_name,
+ cash,
+ free_mb,
+ last_activity_time,
+ last_cash_add,
+ last_cash_add_time,
+ passive_time)
+ VALUES
+ (NULL, NULL, NULL, '', FALSE, 0, CAST('now' AS TIMESTAMP),
+ FALSE, FALSE, '', '', '', FALSE, '', '', _name, '', 0, 0,
+ CAST('now' AS TIMESTAMP), 0, CAST('now' AS TIMESTAMP), 0);
+ SELECT CURRVAL('tb_users_pk_user_seq') INTO pk_user;
+ RETURN pk_user;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_stats_traffic (_login dm_name,
+ _stats_date DATE,
+ _dir_num SMALLINT,
+ _upload BIGINT,
+ _download BIGINT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ UPDATE tb_stats_traffic SET
+ upload = _upload,
+ download = _download
+ WHERE fk_user = _pk_user AND
+ dir_num = _dir_num AND
+ stats_date = _stats_date;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_stats_traffic
+ (fk_user,
+ dir_num,
+ stats_date,
+ upload,
+ download)
+ VALUES
+ (_pk_user,
+ _dir_num,
+ _stats_date,
+ _upload,
+ _download);
+ END IF;
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_set_user_data (_pk_user INTEGER,
+ _num SMALLINT,
+ _data VARCHAR(256))
+RETURNS INTEGER
+AS $$
+BEGIN
+ UPDATE tb_users_data SET
+ data = _data
+ WHERE fk_user = _pk_user AND num = _num;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_users_data
+ (fk_user,
+ num,
+ data)
+ VALUES
+ (_pk_user,
+ _num,
+ _data);
+ END IF;
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_param_log_entry(_login dm_name,
+ _admin_login dm_name,
+ _ip INET,
+ _param_name dm_name,
+ _event_time TIMESTAMP,
+ _from VARCHAR(256),
+ _to VARCHAR(256),
+ _comment TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_admin INTEGER;
+ _pk_param INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ SELECT pk_admin INTO _pk_admin
+ FROM tb_admins
+ WHERE login = _admin_login;
+ IF _pk_admin IS NULL THEN
+ RAISE EXCEPTION 'Admin % not found', _admin_login;
+ RETURN -1;
+ END IF;
+
+ SELECT pk_parameter INTO _pk_param
+ FROM tb_parameters
+ WHERE name = _param_name;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_parameters (name) VALUES (_param_name);
+ SELECT CURRVAL('tb_parameters_pk_parameter_seq') INTO _pk_param;
+ END IF;
+
+ INSERT INTO tb_params_log
+ (fk_user,
+ fk_parameter,
+ fk_admin,
+ ip,
+ event_time,
+ from_val,
+ to_val,
+ comment)
+ VALUES
+ (_pk_user,
+ _pk_param,
+ _pk_admin,
+ _ip,
+ _event_time,
+ _from,
+ _to,
+ _comment);
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+ _event_time TIMESTAMP,
+ _event_type dm_session_event_type,
+ _ip INET,
+ _cash dm_money)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_session_log INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ INSERT INTO tb_sessions_log
+ (fk_user,
+ event_time,
+ event_type,
+ ip,
+ cash)
+ VALUES
+ (_pk_user,
+ _event_time,
+ _event_type,
+ _ip,
+ _cash);
+
+ SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+ RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *
+ * Двоичные права доступа пока не поддерживаются, по этому используются флаги
+ *****************************************************************************
+ */
+INSERT INTO tb_admins
+ (login, passwd,
+ chg_conf, chg_password, chg_stat,
+ chg_cash, usr_add_del, chg_tariff,
+ chg_admin, chg_service, chg_corporation)
+VALUES
+ ('admin',
+ 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk',
+ 1, 1, 1, 1, 1, 1, 1, 1, 1);
+INSERT INTO tb_admins
+ (login, passwd,
+ chg_conf, chg_password, chg_stat,
+ chg_cash, usr_add_del, chg_tariff,
+ chg_admin, chg_service, chg_corporation)
+VALUES
+ ('@stargazer',
+ '',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+INSERT INTO tb_info
+ (version)
+VALUES
+ (5);
--- /dev/null
+/*
+ * 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
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * $Id: 00-base-00.sql,v 1.7 2010/01/06 14:41:13 faust Exp $
+ *
+ * Примечание.
+ * * dm_permission_flag. Представляет собой битовую маску - rw.
+ * r - чтение, w - изменение параметра.
+ * 0 - дествие запрещено, 1 - действие разрешено
+ *
+ * * dm_traff_type. Число определяющее тип подсчета трафика:
+ * 0 - up - считается по upload
+ * 1 - down - считается по download
+ * 2 - max - считается по максимальному среди upload/download
+ * 3 - up+down - считается по сумме upload и download
+ *
+ * * dm_ip. IP адресс в виде четырех байтового целого числа со знаком.
+ * Выполнять приведение к знаковуму целому при занесении IP в БД!!!
+ *
+ * * dm_period. Задает периодичность показа сообщения пользователю.
+ * Период задается целым числом (int16). Если значение равно 0 то
+ * сообщение показывается только при подключении пользователя.
+ * Также этот домен определяет промежуток времени в течении которого
+ * сообщение показывается пользователю.
+ *
+ * * dm_session_event_type. Указывает тип записи в логе о сессии.
+ * 'c' - connect, 'd' - disconnect.
+ *
+ *****************************************************************************
+ */
+
+/*
+ * CONNECT 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456';
+ * DROP DATABASE;
+ *
+ * CREATE DATABASE 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456' DEFAULT CHARACTER SET UTF8;
+ */
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ДОМЕНОВ =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_id AS INTEGER NOT NULL;
+CREATE DOMAIN dm_null_id AS INTEGER;
+CREATE DOMAIN dm_login AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_tariff_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_group_name AS VARCHAR(32);
+CREATE DOMAIN dm_corporation_name AS VARCHAR(32);
+CREATE DOMAIN dm_parameter_name AS VARCHAR(32);
+
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+/* bitmask - rw => Read, Write */
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(10,6) NOT NULL;
+/* (0, 1, 2, 3) => (up, down, max, up+down) */
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_dir_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_traffic_mb AS INTEGER NOT NULL;
+CREATE DOMAIN dm_traffic_byte AS BIGINT NOT NULL;
+CREATE DOMAIN dm_time AS TIME NOT NULL;
+CREATE DOMAIN dm_moment AS TIMESTAMP NOT NULL;
+CREATE DOMAIN dm_credit_moment AS TIMESTAMP;
+CREATE DOMAIN dm_ip AS INTEGER NOT NULL;
+CREATE DOMAIN dm_mask AS INTEGER NOT NULL;
+CREATE DOMAIN dm_user_address AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_bool AS CHAR(1) NOT NULL
+ CHECK ( VALUE IN ('0', '1', 't', 'f', 'T', 'F') );
+CREATE DOMAIN dm_email AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_note AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_phone AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_user_name AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_comment AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_name AS VARCHAR(32) DEFAULT '';
+
+CREATE DOMAIN dm_pay_day AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 31 );
+CREATE DOMAIN dm_period AS INTEGER NOT NULL;
+CREATE DOMAIN dm_counter AS SMALLINT NOT NULL;
+
+CREATE DOMAIN dm_message_ver AS INTEGER NOT NULL;
+CREATE DOMAIN dm_message_type AS INTEGER NOT NULL;
+
+CREATE DOMAIN dm_message AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_user_data AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+ CHECK ( VALUE IN ('c', 'd') );
+CREATE DOMAIN dm_char_value AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_date AS DATE NOT NULL;
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТАБЛИЦ =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_admins
+(
+ pk_admin dm_id PRIMARY KEY,
+ login dm_login UNIQUE,
+ passwd dm_password,
+ chg_conf dm_permission_flag,
+ chg_password dm_permission_flag,
+ chg_stat dm_permission_flag,
+ chg_cash dm_permission_flag,
+ usr_add_del dm_permission_flag,
+ chg_tariff dm_permission_flag,
+ chg_admin dm_permission_flag,
+ chg_service dm_permission_flag,
+ chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+ pk_tariff dm_id PRIMARY KEY,
+ name dm_tariff_name UNIQUE,
+ fee dm_money,
+ free dm_money,
+ passive_cost dm_money,
+ traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+ pk_tariff_param dm_id PRIMARY KEY,
+ fk_tariff dm_id,
+ dir_num dm_dir_num,
+ price_day_a dm_money,
+ price_day_b dm_money,
+ price_night_a dm_money,
+ price_night_b dm_money,
+ threshold dm_traffic_mb,
+ time_day_begins dm_time,
+ time_day_ends dm_time,
+
+ FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff)
+);
+
+CREATE TABLE tb_corporations
+(
+ pk_corporation dm_id PRIMARY KEY,
+ name dm_corporation_name UNIQUE,
+ cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+ pk_user dm_id PRIMARY KEY,
+ fk_tariff dm_null_id,
+ fk_tariff_change dm_null_id,
+ fk_corporation dm_null_id,
+ address dm_user_address,
+ always_online dm_bool,
+ credit dm_money,
+ credit_expire dm_credit_moment,
+ disabled dm_bool,
+ disabled_detail_stat dm_bool,
+ email dm_email,
+ grp dm_group_name,
+ note dm_note,
+ passive dm_bool,
+ passwd dm_password,
+ phone dm_phone,
+ name dm_login UNIQUE,
+ real_name dm_user_name,
+
+ FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff),
+ FOREIGN KEY (fk_tariff_change) REFERENCES tb_tariffs (pk_tariff),
+ FOREIGN KEY (fk_corporation) REFERENCES tb_corporations (pk_corporation)
+);
+
+CREATE TABLE tb_detail_stats
+(
+ pk_detail_stat dm_id PRIMARY KEY,
+ fk_user dm_id,
+ dir_num dm_dir_num,
+ ip dm_ip,
+ download dm_traffic_byte,
+ upload dm_traffic_byte,
+ cost dm_money,
+ from_time dm_moment,
+ till_time dm_moment,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_services
+(
+ pk_service dm_id PRIMARY KEY,
+ name dm_service_name UNIQUE,
+ comment dm_service_comment,
+ cost dm_money,
+ pay_day dm_pay_day
+);
+
+CREATE TABLE tb_users_services
+(
+ pk_user_service dm_id PRIMARY KEY,
+ fk_user dm_id,
+ fk_service dm_id,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+ FOREIGN KEY (fk_service) REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+ pk_message dm_id PRIMARY KEY,
+ fk_user dm_id,
+ ver dm_message_ver,
+ msg_type dm_message_type,
+ last_send_time dm_period,
+ creation_time dm_period,
+ show_time dm_period,
+ repeat dm_counter,
+ repeat_period dm_period,
+ msg_text dm_message,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats
+(
+ pk_stat dm_id PRIMARY KEY,
+ fk_user dm_id,
+ cash dm_money,
+ free_mb dm_money,
+ last_activity_time dm_moment,
+ last_cash_add dm_money,
+ last_cash_add_time dm_moment,
+ passive_time dm_period,
+ stats_date dm_date,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats_traffic
+(
+ pk_stat_traffic dm_id PRIMARY KEY,
+ fk_stat dm_id,
+ dir_num dm_dir_num,
+ download dm_traffic_byte,
+ upload dm_traffic_byte,
+
+ FOREIGN KEY (fk_stat) REFERENCES tb_stats (pk_stat)
+);
+
+CREATE TABLE tb_users_data
+(
+ pk_user_data dm_id PRIMARY KEY,
+ fk_user dm_id,
+ num dm_num,
+ data dm_user_data,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_allowed_ip
+(
+ pk_allowed_ip dm_id PRIMARY KEY,
+ fk_user dm_id,
+ ip dm_ip,
+ mask dm_mask,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_log
+(
+ pk_session_log dm_id PRIMARY KEY,
+ fk_user dm_id,
+ event_time dm_moment,
+ event_type dm_session_event_type,
+ ip dm_ip,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_data
+(
+ pk_session_data dm_id PRIMARY KEY,
+ fk_session_log dm_id,
+ dir_num dm_dir_num,
+ session_upload dm_traffic_byte,
+ session_download dm_traffic_byte,
+ month_upload dm_traffic_byte,
+ month_download dm_traffic_byte,
+
+ FOREIGN KEY (fk_session_log) REFERENCES tb_sessions_log (pk_session_log)
+);
+
+CREATE TABLE tb_parameters
+(
+ pk_parameter dm_id PRIMARY KEY,
+ name dm_parameter_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+ pk_param_log dm_id PRIMARY KEY,
+ fk_user dm_id,
+ fk_parameter dm_id,
+ event_time dm_moment,
+ from_val dm_char_value,
+ to_val dm_char_value,
+ comment dm_service_comment,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+ FOREIGN KEY (fk_parameter) REFERENCES tb_parameters (pk_parameter)
+);
+
+
+/*
+ *****************************************************************************
+ * -= Создание ИНДЕКСОВ =-
+ *****************************************************************************
+ */
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ГЕНЕРАТОРОВ =-
+ *****************************************************************************
+ */
+
+CREATE GENERATOR gn_pk_admin;
+SET GENERATOR gn_pk_admin TO 0;
+CREATE GENERATOR gn_pk_tariff;
+SET GENERATOR gn_pk_tariff TO 0;
+CREATE GENERATOR gn_pk_tariff_param;
+SET GENERATOR gn_pk_tariff_param TO 0;
+CREATE GENERATOR gn_pk_corporation;
+SET GENERATOR gn_pk_corporation TO 0;
+CREATE GENERATOR gn_pk_user;
+SET GENERATOR gn_pk_user TO 0;
+CREATE GENERATOR gn_pk_detail_stat;
+SET GENERATOR gn_pk_detail_stat TO 0;
+CREATE GENERATOR gn_pk_service;
+SET GENERATOR gn_pk_service TO 0;
+CREATE GENERATOR gn_pk_user_service;
+SET GENERATOR gn_pk_user_service TO 0;
+CREATE GENERATOR gn_pk_message;
+SET GENERATOR gn_pk_message TO 0;
+CREATE GENERATOR gn_pk_stat;
+SET GENERATOR gn_pk_stat TO 0;
+CREATE GENERATOR gn_pk_stat_traffic;
+SET GENERATOR gn_pk_stat_traffic TO 0;
+CREATE GENERATOR gn_pk_user_data;
+SET GENERATOR gn_pk_user_data TO 0;
+CREATE GENERATOR gn_pk_allowed_ip;
+SET GENERATOR gn_pk_allowed_ip TO 0;
+CREATE GENERATOR gn_pk_session;
+SET GENERATOR gn_pk_session TO 0;
+CREATE GENERATOR gn_pk_session_log;
+SET GENERATOR gn_pk_session_log TO 0;
+CREATE GENERATOR gn_pk_session_data;
+SET GENERATOR gn_pk_session_data TO 0;
+CREATE GENERATOR gn_pk_parameter;
+SET GENERATOR gn_pk_parameter TO 0;
+CREATE GENERATOR gn_pk_param_log;
+SET GENERATOR gn_pk_param_log TO 0;
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТРИГГЕРОВ =-
+ *****************************************************************************
+ */
+
+SET TERM !! ;
+CREATE TRIGGER tr_admin_bi FOR tb_admins
+ACTIVE BEFORE INSERT POSITION 0
+AS
+BEGIN
+ IF (new.pk_admin IS NULL)
+ THEN new.pk_admin = GEN_ID(gn_pk_admin, 1);
+END !!
+SET TERM ; !!
+
+set term !! ;
+create trigger tr_tariff_param_bi for tb_tariffs_params active
+before insert position 0
+as
+begin
+ if (new.pk_tariff_param is null)
+ then new.pk_tariff_param = gen_id(gn_pk_tariff_param, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_corporation_bi for tb_corporations active
+before insert position 0
+as
+begin
+ if (new.pk_corporation is null)
+ then new.pk_corporation = gen_id(gn_pk_corporation, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_detail_stat_bi for tb_detail_stats active
+before insert position 0
+as
+begin
+ if (new.pk_detail_stat is null)
+ then new.pk_detail_stat = gen_id(gn_pk_detail_stat, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_service_bi for tb_services active
+before insert position 0
+as
+begin
+ if (new.pk_service is null)
+ then new.pk_service = gen_id(gn_pk_service, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_service_bi for tb_users_services active
+before insert position 0
+as
+begin
+ if (new.pk_user_service is null)
+ then new.pk_user_service = gen_id(gn_pk_user_service, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_stat_traffic_bi for tb_stats_traffic active
+before insert position 0
+as
+begin
+ if (new.pk_stat_traffic is null)
+ then new.pk_stat_traffic = gen_id(gn_pk_stat_traffic, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_data_bi for tb_users_data active
+before insert position 0
+as
+begin
+ if (new.pk_user_data is null)
+ then new.pk_user_data = gen_id(gn_pk_user_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_allowed_ip_bi for tb_allowed_ip active
+before insert position 0
+as
+begin
+ if (new.pk_allowed_ip is null)
+ then new.pk_allowed_ip = gen_id(gn_pk_allowed_ip, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_session_data_bi for tb_sessions_data active
+before insert position 0
+as
+begin
+ if (new.pk_session_data is null)
+ then new.pk_session_data = gen_id(gn_pk_session_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_parameter_bi for tb_parameters active
+before insert position 0
+as
+begin
+ if (new.pk_parameter is null)
+ then new.pk_parameter = gen_id(gn_pk_parameter, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_param_log_bi for tb_params_log active
+before insert position 0
+as
+begin
+ if (new.pk_param_log is null)
+ then new.pk_param_log = gen_id(gn_pk_param_log, 1);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание stored procedure =-
+ *****************************************************************************
+ */
+
+/*
+ * Add a message returning it's ID
+ */
+set term !! ;
+create procedure sp_add_message(pk_message integer, login varchar(32), ver integer, msg_type integer, last_send_time integer, creation_time integer, show_time integer, repeat integer, repeat_period integer, msg_text varchar(256))
+returns(res integer)
+as
+begin
+ if (:pk_message is null) then
+ begin
+ pk_message = gen_id(gn_pk_message, 1);
+ insert into tb_messages values (:pk_message,
+ (select pk_user from tb_users where name = :login),
+ :ver,
+ :msg_type,
+ :last_send_time,
+ :creation_time,
+ :show_time,
+ :repeat,
+ :repeat_period,
+ :msg_text);
+ end
+ else
+ begin
+ update tb_messages set fk_user = (select pk_user from tb_users where name = :login),
+ ver = :ver,
+ msg_type = :msg_type,
+ last_send_time = :last_send_time,
+ creation_time = :creation_time,
+ show_time = :show_time,
+ repeat = :repeat_period,
+ repeat_period = :repeat_period,
+ msg_text = :msg_text
+ where pk_message = :pk_message;
+ end
+ res = :pk_message;
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_service(name varchar(32))
+as
+declare variable pk_service integer;
+begin
+ select pk_service from tb_services where name = :name into pk_service;
+ if (pk_service is not null) then
+ begin
+ delete from tb_users_services where fk_service = :pk_service;
+ delete from tb_services where pk_service = :pk_service;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_tariff(name varchar(32), dirs integer)
+as
+declare variable pk_tariff integer;
+begin
+ pk_tariff = gen_id(gn_pk_tariff, 1);
+ insert into tb_tariffs (pk_tariff, name, fee, free, passive_cost, traff_type) values (:pk_tariff, :name, 0, 0, 0, 0);
+ while (dirs > 0) do
+ begin
+ insert into tb_tariffs_params (fk_tariff, dir_num, price_day_a,
+ price_day_b, price_night_a, price_night_b,
+ threshold, time_day_begins, time_day_ends)
+ values (:pk_tariff, :dirs - 1, 0, 0, 0, 0, 0, '0:0', '0:0');
+ dirs = dirs - 1;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_tariff(name varchar(32))
+as
+declare variable pk_tariff integer;
+begin
+ select pk_tariff from tb_tariffs where name = :name into pk_tariff;
+ if (pk_tariff is not null) then
+ begin
+ delete from tb_tariffs_params where fk_tariff = :pk_tariff;
+ delete from tb_tariffs where pk_tariff = :pk_tariff;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)
+as
+declare variable pk_user integer;
+declare variable pk_stat integer;
+begin
+ pk_user = gen_id(gn_pk_user, 1);
+ insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
+ while (dirs > 0) do
+ begin
+ insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+ dirs = dirs - 1;
+ end
+end!!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_user(name varchar(32))
+as
+declare variable pk_user integer;
+begin
+ select pk_user from tb_users where name = :name into pk_user;
+ if (pk_user is not null) then
+ begin
+ delete from tb_users_services where fk_user = :pk_user;
+ delete from tb_params_log where fk_user = :pk_user;
+ delete from tb_detail_stats where fk_user = :pk_user;
+ delete from tb_stats_traffic where fk_stat in (select pk_stat from tb_stats where fk_user = :pk_user);
+ delete from tb_stats where fk_user = :pk_user;
+ delete from tb_sessions_data where fk_session_log in (select pk_session_log from tb_sessions_log where fk_user = :pk_user);
+ delete from tb_sessions_log where fk_user = :pk_user;
+ delete from tb_allowed_ip where fk_user = :pk_user;
+ delete from tb_users_data where fk_user = :pk_user;
+ delete from tb_messages where fk_user = :pk_user;
+ delete from tb_users where pk_user = :pk_user;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_append_session_log(name varchar(32), event_time timestamp, event_type char(1), ip integer)
+returns(pk_session_log integer)
+as
+begin
+ pk_session_log = gen_id(gn_pk_session_log, 1);
+ insert into tb_sessions_log (pk_session_log, fk_user, event_time, event_type, ip) values (:pk_session_log, (select pk_user from tb_users where name = :name), :event_time, :event_type, :ip);
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_stat(name varchar(32), cash numeric(10,6), free_mb numeric(10,6), last_activity_time timestamp, last_cash_add numeric(10,6), last_cash_add_time timestamp, passive_time integer, stats_date date)
+returns(pk_stat integer)
+as
+begin
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats (pk_stat, fk_user, cash, free_mb, last_activity_time, last_cash_add, last_cash_add_time, passive_time, stats_date) values (:pk_stat, (select pk_user from tb_users where name = :name), :cash, :free_mb, :last_activity_time, :last_cash_add, :last_cash_add_time, :passive_time, :stats_date);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *****************************************************************************
+ */
+
+insert into tb_admins values(0, 'admin', 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk', 1, 1, 1, 1, 1, 1, 1, 1, 1);
+
+/* EOF */
--- /dev/null
+/*
+ * DB migration from v00 to v01 (mysql)
+ */
+
+ALTER TABLE users ADD DisabledDetailStat INT(3) DEFAULT 0;
--- /dev/null
+/*
+ * DB migration from v01 to v02 (mysql)
+ */
+
+ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month';
+
+CREATE TABLE info
+(
+ version INTEGER NOT NULL
+);
+
+INSERT INTO info VALUES (1);
--- /dev/null
+/*
+ * DB migration from v01 to v02 (postgres)
+ */
+BEGIN;
+
+CREATE DOMAIN DM_TARIFF_PERIOD AS TEXT NOT NULL
+ CONSTRAINT valid_value CHECK (VALUE = 'month' OR VALUE = 'day');
+
+ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
+
+UPDATE tb_info SET version = 7;
+
+COMMIT;
--- /dev/null
+/*
+ * DB migration from v01 to v02 (firebird)
+ */
+
+CREATE DOMAIN DM_TARIFF_PERIOD AS VARCHAR(32) NOT NULL
+ CHECK (VALUE = 'month' OR VALUE = 'day');
+
+ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
+
+CREATE TABLE tb_info
+(
+ version INTEGER NOT NULL
+);
+
+INSERT INTO tb_info VALUES (1);
--- /dev/null
+/*
+ * DB migration from v02 to v03 (postgres)
+ */
+BEGIN;
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL
+ CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+ALTER TABLE tb_tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
+
+UPDATE tb_info SET version = 8;
+
+COMMIT;
--- /dev/null
+/*
+ * DB migration from v02 to v03 (firebird)
+ */
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS VARCHAR(32) NOT NULL
+ CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+ALTER TABLE tb_tariffs ADD change_policy_timeout DM_MOMENT DEFAULT '1970-01-01 00:00:00';
+
+UPDATE tb_tariffs SET change_policy = 'allow', change_policy_timeout = '1970-01-01 00:00:00';
+
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
+
+UPDATE tb_info SET version = 2;
--- /dev/null
+password=geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa
+ChgConf=1
+ChgPassword=1
+ChgStat=1
+ChgCash=1
+UsrAddDel=1
+ChgTariff=1
+ChgAdmin=1
--- /dev/null
+Fee=10.000000
+Free=0
+NoDiscount0=1
+NoDiscount1=1
+NoDiscount2=1
+NoDiscount3=1
+NoDiscount4=1
+NoDiscount5=1
+NoDiscount6=1
+NoDiscount7=1
+NoDiscount8=1
+NoDiscount9=1
+PassiveCost=0.000000
+PriceDayA0=0.000000
+PriceDayA1=0.750000
+PriceDayA2=0.000000
+PriceDayA3=0.000000
+PriceDayA4=0.000000
+PriceDayA5=0.000000
+PriceDayA6=0.000000
+PriceDayA7=0.000000
+PriceDayA8=0.000000
+PriceDayA9=0.000000
+PriceDayB0=0.000000
+PriceDayB1=0.750000
+PriceDayB2=0.000000
+PriceDayB3=0.000000
+PriceDayB4=0.000000
+PriceDayB5=0.000000
+PriceDayB6=0.000000
+PriceDayB7=0.000000
+PriceDayB8=0.000000
+PriceDayB9=0.000000
+PriceNightA0=1.000000
+PriceNightA1=0.000000
+PriceNightA2=0.000000
+PriceNightA3=0.000000
+PriceNightA4=0.000000
+PriceNightA5=0.000000
+PriceNightA6=0.000000
+PriceNightA7=0.000000
+PriceNightA8=0.000000
+PriceNightA9=0.000000
+PriceNightB0=1.000000
+PriceNightB1=0.000000
+PriceNightB2=0.000000
+PriceNightB3=0.000000
+PriceNightB4=0.000000
+PriceNightB5=0.000000
+PriceNightB6=0.000000
+PriceNightB7=0.000000
+PriceNightB8=0.000000
+PriceNightB9=0.000000
+SinglePrice0=1
+SinglePrice1=1
+SinglePrice2=0
+SinglePrice3=0
+SinglePrice4=0
+SinglePrice5=0
+SinglePrice6=0
+SinglePrice7=0
+SinglePrice8=0
+SinglePrice9=0
+Threshold0=0
+Threshold1=0
+Threshold2=0
+Threshold3=0
+Threshold4=0
+Threshold5=0
+Threshold6=0
+Threshold7=0
+Threshold8=0
+Threshold9=0
+Time0=0:0-0:0
+Time1=0:0-0:0
+Time2=0:0-0:0
+Time3=0:0-0:0
+Time4=0:0-0:0
+Time5=0:0-0:0
+Time6=0:0-0:0
+Time7=0:0-0:0
+Time8=0:0-0:0
+Time9=0:0-0:0
+TraffType=up+down
--- /dev/null
+Address=
+AlwaysOnline=0
+CreationTime=1123487395
+Credit=0.000000
+CreditExpire=0
+Down=0
+Email=
+Group=
+Iface=eth1
+IP=192.168.1.1
+Note=
+Passive=0
+Password=123456
+Phone=
+RealName=
+Tariff=tariff
+TariffChange=
+Userdata0=
+Userdata1=
--- /dev/null
+Cash=10.000000
+D0=0
+D1=0
+D2=0
+D3=0
+D4=0
+D5=0
+D6=0
+D7=0
+D8=0
+D9=0
+FreeMb=0.000000
+LastActivityTime=0
+LastCashAdd=0
+LastCashAddTime=0
+PassiveTime=0
+U0=0
+U1=0
+U2=0
+U3=0
+U4=0
+U5=0
+U6=0
+U7=0
+U8=0
+U9=0
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#include "store_loader.h"
+#include "plugin_mgr.h"
+#include "plugin_runner.h"
+#include "users_impl.h"
+#include "admins_impl.h"
+#include "tariffs_impl.h"
+#include "services_impl.h"
+#include "corps_impl.h"
+#include "traffcounter_impl.h"
+#include "settings_impl.h"
+#include "pidfile.h"
+#include "eventloop.h"
+#include "stg_timer.h"
+
+#include "stg/user.h"
+#include "stg/common.h"
+#include "stg/plugin.h"
+#include "stg/logger.h"
+#include "stg/scriptexecuter.h"
+#include "stg/version.h"
+
+#include <fstream>
+#include <vector>
+#include <set>
+#include <csignal>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib> // srandom, exit
+
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h> // S_IRUSR
+#include <fcntl.h> // create
+
+#ifdef DEBUG
+ #define NO_DAEMON (1)
+#endif
+
+#define START_FILE "/._ST_ART_ED_"
+
+namespace
+{
+std::set<pid_t> executers;
+
+void StartTimer();
+int StartScriptExecuter(char * procName, int msgKey, int * msgID);
+int ForkAndWait(const std::string & confDir);
+void KillExecuters();
+
+//-----------------------------------------------------------------------------
+void StartTimer()
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+
+if (RunStgTimer())
+ {
+ WriteServLog("Cannot start timer. Fatal.");
+ //printfd(__FILE__, "Cannot start timer. Fatal.\n");
+ exit(1);
+ }
+else
+ {
+ WriteServLog("Timer thread started successfully.");
+ //printfd(__FILE__, "Timer thread started successfully.\n");
+ }
+}
+//-----------------------------------------------------------------------------
+#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 pid = fork();
+
+switch (pid)
+ {
+ case -1:
+ WriteServLog("Fork error!");
+ return -1;
+
+ case 0:
+#if defined(LINUX) || defined(DARWIN)
+ Executer(*msgID, pid, procName);
+#else
+ Executer(*msgID, pid);
+#endif
+ return 1;
+
+ default:
+ if (executers.empty()) {
+#if defined(LINUX) || defined(DARWIN)
+ Executer(*msgID, pid, NULL);
+#else
+ Executer(*msgID, pid);
+#endif
+ }
+ executers.insert(pid);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+#ifndef NO_DAEMON
+int ForkAndWait(const std::string & confDir)
+#else
+int ForkAndWait(const std::string &)
+#endif
+{
+#ifndef NO_DAEMON
+pid_t pid = fork();
+std::string startFile = confDir + START_FILE;
+unlink(startFile.c_str());
+
+switch (pid)
+ {
+ case -1:
+ return -1;
+ break;
+
+ case 0:
+ close(1);
+ close(2);
+ setsid();
+ break;
+
+ default:
+ struct timespec ts = {0, 200000000};
+ for (int i = 0; i < 120 * 5; i++)
+ {
+ if (access(startFile.c_str(), F_OK) == 0)
+ {
+ unlink(startFile.c_str());
+ exit(0);
+ }
+
+ nanosleep(&ts, NULL);
+ }
+ unlink(startFile.c_str());
+ exit(1);
+ break;
+ }
+#endif
+return 0;
+}
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+std::set<pid_t>::iterator pid(executers.begin());
+while (pid != executers.end())
+ {
+ printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
+ kill(*pid, SIGUSR1);
+ ++pid;
+ }
+}
+//-----------------------------------------------------------------------------
+} // namespace anonymous
+//-----------------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+int msgID = -11;
+
+GetStgLogger().SetLogFileName("/var/log/stargazer.log");
+
+if (getuid())
+ {
+ printf("You must be root. Exit.\n");
+ return 1;
+ }
+
+SETTINGS_IMPL settings(argc == 2 ? argv[1] : "");
+
+if (settings.ReadSettings())
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+
+ if (settings.GetLogFileName() != "")
+ WriteServLog.SetLogFileName(settings.GetLogFileName());
+
+ WriteServLog("ReadSettings error. %s", settings.GetStrError().c_str());
+ return -1;
+ }
+
+#ifndef NO_DAEMON
+std::string startFile(settings.GetConfDir() + START_FILE);
+#endif
+
+if (ForkAndWait(settings.GetConfDir()) < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Fork error!");
+ return -1;
+ }
+
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog.SetLogFileName(settings.GetLogFileName());
+WriteServLog("Stg v. %s", SERVER_VERSION);
+
+for (size_t i = 0; i < settings.GetExecutersNum(); i++)
+ {
+ int ret = StartScriptExecuter(argv[0], settings.GetExecMsgKey(), &msgID);
+ if (ret < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Start Script Executer error!");
+ return -1;
+ }
+ if (ret == 1)
+ {
+ // Stopping child
+ return 0;
+ }
+ }
+
+PIDFile pidFile(settings.GetPIDFileName());
+
+struct sigaction sa;
+memset(&sa, 0, sizeof(sa));
+sa.sa_handler = SIG_DFL;
+sigaction(SIGHUP, &sa, NULL); // Apparently FreeBSD ignores SIGHUP by default when launched from rc.d at bot time.
+
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+StartTimer();
+WaitTimer();
+if (!IsStgTimerRunning())
+ {
+ printfd(__FILE__, "Timer thread not started in 1 sec!\n");
+ WriteServLog("Timer thread not started in 1 sec!");
+ return -1;
+ }
+
+EVENT_LOOP & loop(EVENT_LOOP_SINGLETON::GetInstance());
+
+STORE_LOADER storeLoader(settings);
+if (storeLoader.Load())
+ {
+ printfd(__FILE__, "Storage plugin: '%s'\n", storeLoader.GetStrError().c_str());
+ WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
+ return -1;
+ }
+
+if (loop.Start())
+ {
+ printfd(__FILE__, "Event loop not started.\n");
+ WriteServLog("Event loop not started.");
+ return -1;
+ }
+
+STORE & store(storeLoader.GetStore());
+WriteServLog("Storage plugin: %s. Loading successfull.", store.GetVersion().c_str());
+
+ADMINS_IMPL admins(&store);
+TARIFFS_IMPL tariffs(&store);
+SERVICES_IMPL services(&store);
+CORPORATIONS_IMPL corps(&store);
+USERS_IMPL users(&settings, &store, &tariffs, services, admins.GetSysAdmin());
+TRAFFCOUNTER_IMPL traffCnt(&users, settings.GetRulesFileName());
+traffCnt.SetMonitorDir(settings.GetMonitorDir());
+
+if (users.Start())
+ return -1;
+
+WriteServLog("Users started successfully.");
+
+if (traffCnt.Start())
+ return -1;
+
+WriteServLog("Traffcounter started successfully.");
+
+STG::PluginManager manager(settings, store, admins, tariffs, services, corps, users, traffCnt);
+
+srandom(static_cast<unsigned int>(stgTime));
+
+WriteServLog("Stg started successfully.");
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+#ifndef NO_DAEMON
+creat(startFile.c_str(), S_IRUSR);
+#endif
+
+bool running = true;
+while (running)
+ {
+ sigfillset(&signalSet);
+ int sig = 0;
+ sigwait(&signalSet, &sig);
+ int status;
+ switch (sig)
+ {
+ case SIGHUP:
+ {
+ SETTINGS_IMPL newSettings(settings);
+ if (newSettings.ReadSettings())
+ WriteServLog("ReadSettings error. %s", newSettings.GetStrError().c_str());
+ else
+ settings = newSettings;
+ WriteServLog.SetLogFileName(settings.GetLogFileName());
+ traffCnt.Reload();
+ manager.reload(settings);
+ }
+ break;
+ case SIGTERM:
+ running = false;
+ break;
+ case SIGINT:
+ running = false;
+ break;
+ case SIGPIPE:
+ WriteServLog("Broken pipe!");
+ break;
+ case SIGCHLD:
+ executers.erase(waitpid(-1, &status, WNOHANG));
+ if (executers.empty())
+ running = false;
+ break;
+ default:
+ WriteServLog("Ignore signal %d", sig);
+ break;
+ }
+ }
+
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+manager.stop();
+
+if (loop.Stop())
+ WriteServLog("Event loop not stopped.");
+
+if (!traffCnt.Stop())
+ WriteServLog("Traffcounter: Stop successfull.");
+
+if (!users.Stop())
+ WriteServLog("Users: Stop successfull.");
+
+sleep(1);
+int res = msgctl(msgID, IPC_RMID, NULL);
+if (res)
+ WriteServLog("Queue was not removed. id=%d", msgID);
+else
+ WriteServLog("Queue removed successfully.");
+
+KillExecuters();
+
+StopStgTimer();
+WriteServLog("StgTimer: Stop successfull.");
+
+WriteServLog("Stg stopped successfully.");
+WriteServLog("---------------------------------------------");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#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());
+ }
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Header file for RAII pid-file writer
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+#ifndef __PID_FILE_H__
+#define __PID_FILE_H__
+
+#include <string>
+
+class PIDFile {
+public:
+ explicit PIDFile(const std::string & fn);
+ ~PIDFile();
+private:
+ std::string fileName;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "plugin_mgr.h"
+
+#include "plugin_runner.h"
+
+#include "admins_impl.h"
+#include "tariffs_impl.h"
+#include "services_impl.h"
+#include "corps_impl.h"
+#include "users_impl.h"
+#include "traffcounter_impl.h"
+#include "settings_impl.h"
+
+#include "stg/logger.h"
+
+using STG::PluginManager;
+
+namespace
+{
+
+bool StartModCmp(const PLUGIN_RUNNER * lhs, const PLUGIN_RUNNER * rhs)
+{
+ return lhs->GetStartPosition() < rhs->GetStartPosition();
+}
+
+bool StopModCmp(const PLUGIN_RUNNER * lhs, const PLUGIN_RUNNER * rhs)
+{
+ return lhs->GetStopPosition() > rhs->GetStopPosition();
+}
+
+} // namespace anonymous
+
+PluginManager::PluginManager(const SETTINGS_IMPL& settings,
+ STORE& store, ADMINS_IMPL& admins, TARIFFS_IMPL& tariffs,
+ SERVICES_IMPL& services, CORPORATIONS_IMPL& corporations,
+ USERS_IMPL& users, TRAFFCOUNTER_IMPL& traffcounter)
+ : m_log(GetStgLogger())
+{
+ std::string basePath = settings.GetModulesPath();
+ const std::vector<MODULE_SETTINGS> & modSettings(settings.GetModulesSettings());
+ for (size_t i = 0; i < modSettings.size(); i++)
+ {
+ std::string moduleName = modSettings[i].moduleName;
+ std::string modulePath = basePath + "/mod_" + moduleName + ".so";
+ printfd(__FILE__, "Module: %s\n", modulePath.c_str());
+ try
+ {
+ m_modules.push_back(
+ new PLUGIN_RUNNER(modulePath, moduleName, modSettings[i], admins, tariffs,
+ users, services, corporations, traffcounter,
+ store, settings)
+ );
+ }
+ catch (const PLUGIN_RUNNER::Error & ex)
+ {
+ m_log(ex.what());
+ printfd(__FILE__, "%s\n", ex.what());
+ // TODO: React
+ }
+ }
+ std::sort(m_modules.begin(), m_modules.end(), StartModCmp);
+ for (size_t i = 0; i < m_modules.size(); ++i)
+ {
+ PLUGIN & plugin = m_modules[i]->GetPlugin();
+ if (m_modules[i]->Start())
+ {
+ m_log("Failed to start module '%s': '%s'", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ printfd(__FILE__, "Failed to start module '%s': '%s'\n", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ }
+ else
+ {
+ m_log("Module '%s' started successfully.", plugin.GetVersion().c_str());
+ printfd(__FILE__, "Module '%s' started successfully.\n", plugin.GetVersion().c_str());
+ }
+ }
+}
+
+PluginManager::~PluginManager()
+{
+ stop();
+ for (size_t i = 0; i < m_modules.size(); ++i)
+ delete m_modules[i];
+}
+
+void PluginManager::reload(const SETTINGS_IMPL& settings)
+{
+ const std::vector<MODULE_SETTINGS> & modSettings(settings.GetModulesSettings());
+ for (size_t i = 0; i < m_modules.size(); ++i)
+ {
+ for (size_t j = 0; j < modSettings.size(); j++)
+ {
+ if (modSettings[j].moduleName == m_modules[i]->GetName())
+ {
+ PLUGIN & plugin = m_modules[i]->GetPlugin();
+ if (m_modules[i]->Reload(modSettings[j]))
+ {
+ m_log("Error reloading module '%s': '%s'", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ printfd(__FILE__, "Error reloading module '%s': '%s'\n", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ }
+ break;
+ }
+ }
+ }
+}
+
+void PluginManager::stop()
+{
+ std::sort(m_modules.begin(), m_modules.end(), StopModCmp);
+ for (size_t i = 0; i < m_modules.size(); ++i)
+ {
+ if (!m_modules[i]->IsRunning())
+ continue;
+ PLUGIN & plugin = m_modules[i]->GetPlugin();
+ if (m_modules[i]->Stop())
+ {
+ m_log("Failed to stop module '%s': '%s'", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ printfd(__FILE__, "Failed to stop module '%s': '%s'\n", plugin.GetVersion().c_str(),
+ plugin.GetStrError().c_str());
+ }
+ else
+ {
+ m_log("Module '%s' stopped successfully.", plugin.GetVersion().c_str());
+ printfd(__FILE__, "Module '%s' stopped successfully.\n", plugin.GetVersion().c_str());
+ }
+ }
+}
--- /dev/null
+#ifndef __STG_PLUGIN_MGR_H__
+#define __STG_PLUGIN_MGR_H__
+
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "stg/module_settings.h"
+
+#include <vector>
+
+class SETTINGS_IMPL;
+class PLUGIN_RUNNER;
+class STORE;
+class ADMINS_IMPL;
+class TARIFFS_IMPL;
+class SERVICES_IMPL;
+class CORPORATIONS_IMPL;
+class USERS_IMPL;
+class TRAFFCOUNTER_IMPL;
+class STG_LOGGER;
+
+namespace STG
+{
+
+class PluginManager
+{
+ public:
+ PluginManager(const SETTINGS_IMPL& settings,
+ STORE& store, ADMINS_IMPL& admins, TARIFFS_IMPL& tariffs,
+ SERVICES_IMPL& services, CORPORATIONS_IMPL& corporations,
+ USERS_IMPL& users, TRAFFCOUNTER_IMPL& traffcounter);
+ ~PluginManager();
+
+ void reload(const SETTINGS_IMPL& settings);
+ void stop();
+
+ private:
+ std::vector<PLUGIN_RUNNER*> m_modules;
+ STG_LOGGER & m_log;
+};
+
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "plugin_runner.h"
+
+#include "stg/common.h"
+
+#include <dlfcn.h>
+#include <unistd.h>
+
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER::PLUGIN_RUNNER(const std::string & fileName,
+ const std::string & name,
+ const MODULE_SETTINGS & ms,
+ ADMINS & admins,
+ TARIFFS & tariffs,
+ USERS & users,
+ SERVICES & services,
+ CORPORATIONS & corporations,
+ TRAFFCOUNTER & traffcounter,
+ STORE & store,
+ const SETTINGS & settings)
+ : pluginFileName(fileName),
+ pluginName(name),
+ libHandle(NULL),
+ m_plugin(Load(ms, admins, tariffs, users, services, corporations,
+ traffcounter, store, settings))
+{
+}
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER::~PLUGIN_RUNNER()
+{
+delete &m_plugin;
+if (dlclose(libHandle))
+ {
+ errorStr = "Failed to unload plugin '" + pluginFileName + "': " + dlerror();
+ printfd(__FILE__, "PLUGIN_RUNNER::Unload() - %s", errorStr.c_str());
+ }
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Start()
+{
+int res = m_plugin.Start();
+errorStr = m_plugin.GetStrError();
+return res;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Stop()
+{
+int res = m_plugin.Stop();
+errorStr = m_plugin.GetStrError();
+return res;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Reload(const MODULE_SETTINGS & ms)
+{
+int res = m_plugin.Reload(ms);
+errorStr = m_plugin.GetStrError();
+return res;
+}
+//-----------------------------------------------------------------------------
+PLUGIN & PLUGIN_RUNNER::Load(const MODULE_SETTINGS & ms,
+ ADMINS & admins,
+ TARIFFS & tariffs,
+ USERS & users,
+ SERVICES & services,
+ CORPORATIONS & corporations,
+ TRAFFCOUNTER & traffcounter,
+ STORE & store,
+ const SETTINGS & settings)
+{
+if (pluginFileName.empty())
+ {
+ const std::string msg = "Empty plugin file name.";
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+
+if (access(pluginFileName.c_str(), R_OK))
+ {
+ const std::string msg = "Plugin file '" + pluginFileName + "' is missing or inaccessible.";
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+
+libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
+
+if (!libHandle)
+ {
+ std::string msg = "Error loading plugin '" + pluginFileName + "'";
+ const char* error = dlerror();
+ if (error)
+ msg = msg + ": '" + error + "'";
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+
+PLUGIN * (*GetPlugin)();
+GetPlugin = (PLUGIN * (*)())dlsym(libHandle, "GetPlugin");
+if (!GetPlugin)
+ {
+ const std::string msg = "Plugin '" + pluginFileName + "' does not have GetPlugin() function. ";
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+PLUGIN * plugin = GetPlugin();
+
+if (!plugin)
+ {
+ const std::string msg = "Failed to create an instance of plugin '" + pluginFileName + "'.";
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+
+plugin->SetSettings(ms);
+plugin->SetTariffs(&tariffs);
+plugin->SetAdmins(&admins);
+plugin->SetUsers(&users);
+plugin->SetServices(&services);
+plugin->SetCorporations(&corporations);
+plugin->SetTraffcounter(&traffcounter);
+plugin->SetStore(&store);
+plugin->SetStgSettings(&settings);
+
+if (plugin->ParseSettings())
+ {
+ const std::string msg = "Plugin '" + pluginFileName + "' is unable to parse settings. " + plugin->GetStrError();
+ printfd(__FILE__, "PLUGIN_RUNNER::Load() - %s\n", msg.c_str());
+ throw Error(msg);
+ }
+
+return *plugin;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef PLUGIN_RUNNER_H
+#define PLUGIN_RUNNER_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+
+#include <string>
+#include <stdexcept>
+#include <cstdint>
+
+class SETTINGS;
+class ADMINS;
+class TARIFFS;
+class USERS;
+class SERVICES;
+class CORPORATIONS;
+class TRAFFCOUNTER;
+class STORE;
+
+//-----------------------------------------------------------------------------
+class PLUGIN_RUNNER {
+public:
+ struct Error : public std::runtime_error {
+ explicit Error(const std::string & msg) : runtime_error(msg) {}
+ };
+
+ PLUGIN_RUNNER(const std::string & pluginFileName,
+ const std::string & pluginName,
+ const MODULE_SETTINGS & ms,
+ ADMINS & admins,
+ TARIFFS & tariffs,
+ USERS & users,
+ SERVICES & services,
+ CORPORATIONS & corporations,
+ TRAFFCOUNTER & traffcounter,
+ STORE & store,
+ const SETTINGS & settings);
+ ~PLUGIN_RUNNER();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & ms);
+ int Restart();
+ bool IsRunning() { return m_plugin.IsRunning(); }
+
+ const std::string & GetStrError() const { return errorStr; }
+ PLUGIN & GetPlugin() { return m_plugin; }
+ const std::string & GetFileName() const { return pluginFileName; }
+ const std::string & GetName() const { return pluginName; }
+
+ uint16_t GetStartPosition() const { return m_plugin.GetStartPosition(); }
+ uint16_t GetStopPosition() const { return m_plugin.GetStopPosition(); }
+
+private:
+ PLUGIN_RUNNER(const PLUGIN_RUNNER & rvalue);
+ PLUGIN_RUNNER & operator=(const PLUGIN_RUNNER & rvalue);
+
+ PLUGIN & Load(const MODULE_SETTINGS & ms,
+ ADMINS & admins,
+ TARIFFS & tariffs,
+ USERS & users,
+ SERVICES & services,
+ CORPORATIONS & corporations,
+ TRAFFCOUNTER & traffcounter,
+ STORE & store,
+ const SETTINGS & settings);
+
+ std::string pluginFileName;
+ std::string pluginName;
+ void * libHandle;
+
+ PLUGIN & m_plugin;
+ std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+#endif //PLUGIN_RUNNER_H
--- /dev/null
+add_subdirectory ( authorization )
+add_subdirectory ( capture )
+add_subdirectory ( configuration )
+add_subdirectory ( other )
+add_subdirectory ( store )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.1 2007/09/26 13:55:45 faust Exp $
+###############################################################################
+
+include ../../../Makefile.conf
+
+.PHONY: clean install uninstall
+.PHONY: all $(PLUGINS)
+
+all: $(PLUGINS)
+
+$(PLUGINS):
+ $(MAKE) $(MAKECMDGOALS) -C $@
+
+clean: all
+
+install: all
+
+uninstall: all
+
--- /dev/null
+###############################################################################
+# $Id: Makefile.in,v 1.11 2009/03/03 15:49:35 faust Exp $
+###############################################################################
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+LN = ln
+
+STGLIBS_INCS = $(addprefix -I ../../../../../stglibs/,$(addsuffix .lib/include,$(STGLIBS)))
+STGLIBS_PATHS = $(addprefix -L ../../../../../stglibs/,$(addsuffix .lib,$(STGLIBS)))
+
+STGLIBS_LIBS = $(addprefix -lstg,$(STGLIBS))
+
+CXXFLAGS += -fPIC $(DEFS) $(SEARCH_DIRS) $(STGLIBS_INCS)
+CFLAGS += -fPIC $(DEFS) $(SEARCH_DIRS) $(STGLIBS_INCS)
+
+ifneq ($(OS),darwin)
+LDFLAGS += -shared -Wl,-rpath,$(PREFIX)/usr/lib/stg
+else
+LDFLAGS += -dynamiclib -undefined suppress -flat_namespace -Wl,-rpath,$(PREFIX)/usr/lib/stg
+endif
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) $^ $(LDFLAGS) $(STGLIBS_PATHS) $(STGLIBS_LIBS) $(LIBS) -o $(PROG)
+ $(LN) -fs "`pwd`/$(PROG)" $(DIR_MOD)/$(PROG)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~
+
+install: $(PROG)
+ mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/stg
+ifeq ($(DEBUG), yes)
+ install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
+else
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
+endif
+
+uninstall:
+ rm -f $(PREFIX)/usr/lib/stg/$(PROG)
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+
+deps: $(SRCS) ../../../../../Makefile.conf
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "$$file" | grep ".c$$" > /dev/null;\
+ if [ $$? -eq 0 ];\
+ then\
+ echo "`$(CC) $(CFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile ../../../../../Makefile.conf" >> deps ;\
+ printf '%b\n' '\t$$(CC) -c $$< $(CFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ else\
+ echo "`$(CXX) $(CXXFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile ../../../../../Makefile.conf" >> deps ;\
+ printf '%b\n' '\t$$(CXX) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ fi;\
+ done
--- /dev/null
+if ( BUILD_MOD_AO )
+ add_subdirectory ( ao )
+endif ( BUILD_MOD_AO )
+
+if ( BUILD_MOD_IA )
+ add_subdirectory ( inetaccess )
+endif ( BUILD_MOD_IA )
--- /dev/null
+set ( CPP_FILES ao.cpp )
+
+add_library ( mod_auth_ao MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_auth_ao scriptexecuter logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2008/12/04 15:41:03 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_auth_ao.so
+
+SRCS = ./ao.cpp
+
+STGLIBS = scriptexecuter \
+ logger \
+ common
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+$Revision: 1.30 $
+$Date: 2010/03/04 12:29:06 $
+$Author: faust $
+*/
+
+#include <unistd.h>
+
+#include <csignal>
+#include <cassert>
+#include <algorithm> // for_each
+#include <functional> // mem_fun_ref
+
+#include "stg/user.h"
+#include "stg/users.h"
+#include "stg/user_property.h"
+#include "stg/common.h"
+#include "stg/plugin_creator.h"
+#include "ao.h"
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+static PLUGIN_CREATOR<AUTH_AO> aoc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return aoc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename varType>
+class IS_CONTAINS_USER: public std::binary_function<varType, USER_PTR, bool>
+{
+public:
+ bool operator()(const varType& notifier, USER_PTR user) const
+ {
+ return notifier.GetUser() == user;
+ }
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string AUTH_AO::GetVersion() const
+{
+return "Always Online authorizator v.1.0";
+}
+//-----------------------------------------------------------------------------
+AUTH_AO::AUTH_AO()
+ : users(NULL),
+ isRunning(false),
+ onAddUserNotifier(*this),
+ onDelUserNotifier(*this),
+ logger(GetPluginLogger(GetStgLogger(), "auth_ao"))
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Start()
+{
+printfd(__FILE__, "AUTH_AO::Start()\n");
+GetUsers();
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+std::for_each(usersList.begin(), usersList.end(), std::bind1st(std::mem_fun(&AUTH_AO::UpdateUserAuthorization), this));
+
+isRunning = true;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Stop()
+{
+printfd(__FILE__, "AUTH_AO::Stop()\n");
+if (!isRunning)
+ return 0;
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+std::list<USER_PTR>::iterator users_iter;
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ if ((*users_iter)->IsAuthorizedBy(this))
+ users->Unauthorize((*users_iter)->GetLogin(), this);
+ UnSetUserNotifiers(*users_iter);
+ ++users_iter;
+ }
+isRunning = false;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::SetUserNotifiers(USER_PTR u)
+{
+// ---------- AlwaysOnline -------------------
+CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier(*this, u);
+CHG_AFTER_NOTIFIER<int> AfterChgAONotifier(*this, u);
+
+BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
+AfterChgAONotifierList.push_front(AfterChgAONotifier);
+
+u->GetProperty().alwaysOnline.AddBeforeNotifier(&BeforeChgAONotifierList.front());
+u->GetProperty().alwaysOnline.AddAfterNotifier(&AfterChgAONotifierList.front());
+// ---------- AlwaysOnline end ---------------
+
+// ---------- IP -------------------
+CHG_BEFORE_NOTIFIER<USER_IPS> BeforeChgIPNotifier(*this, u);
+CHG_AFTER_NOTIFIER<USER_IPS> AfterChgIPNotifier(*this, u);
+
+BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
+AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
+
+u->GetProperty().ips.AddBeforeNotifier(&BeforeChgIPNotifierList.front());
+u->GetProperty().ips.AddAfterNotifier(&AfterChgIPNotifierList.front());
+// ---------- IP end ---------------
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UnSetUserNotifiers(USER_PTR u)
+{
+// --- AlwaysOnline ---
+IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<int> > IsContainsUserAOB;
+IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<int> > IsContainsUserAOA;
+
+std::list<CHG_BEFORE_NOTIFIER<int> >::iterator aoBIter;
+std::list<CHG_AFTER_NOTIFIER<int> >::iterator aoAIter;
+
+aoBIter = find_if(BeforeChgAONotifierList.begin(),
+ BeforeChgAONotifierList.end(),
+ bind2nd(IsContainsUserAOB, u));
+
+if (aoBIter != BeforeChgAONotifierList.end())
+ {
+ aoBIter->GetUser()->GetProperty().alwaysOnline.DelBeforeNotifier(&(*aoBIter));
+ BeforeChgAONotifierList.erase(aoBIter);
+ }
+
+aoAIter = find_if(AfterChgAONotifierList.begin(),
+ AfterChgAONotifierList.end(),
+ bind2nd(IsContainsUserAOA, u));
+
+if (aoAIter != AfterChgAONotifierList.end())
+ {
+ aoAIter->GetUser()->GetProperty().alwaysOnline.DelAfterNotifier(&(*aoAIter));
+ AfterChgAONotifierList.erase(aoAIter);
+ }
+// --- AlwaysOnline end ---
+
+// --- IP ---
+IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<USER_IPS> > IsContainsUserIPB;
+IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<USER_IPS> > IsContainsUserIPA;
+
+std::list<CHG_BEFORE_NOTIFIER<USER_IPS> >::iterator ipBIter;
+std::list<CHG_AFTER_NOTIFIER<USER_IPS> >::iterator ipAIter;
+
+ipBIter = std::find_if(BeforeChgIPNotifierList.begin(),
+ BeforeChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPB, u));
+
+if (ipBIter != BeforeChgIPNotifierList.end())
+ {
+ ipBIter->GetUser()->GetProperty().ips.DelBeforeNotifier(&(*ipBIter));
+ BeforeChgIPNotifierList.erase(ipBIter);
+ }
+
+ipAIter = find_if(AfterChgIPNotifierList.begin(),
+ AfterChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPA, u));
+
+if (ipAIter != AfterChgIPNotifierList.end())
+ {
+ ipAIter->GetUser()->GetProperty().ips.DelAfterNotifier(&(*ipAIter));
+ AfterChgIPNotifierList.erase(ipAIter);
+ }
+// --- IP end ---
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::GetUsers()
+{
+USER_PTR u;
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (!users->SearchNext(h, &u))
+ {
+ usersList.push_back(u);
+ SetUserNotifiers(u);
+ }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UpdateUserAuthorization(CONST_USER_PTR u) const
+{
+if (u->GetProperty().alwaysOnline)
+ {
+ USER_IPS ips = u->GetProperty().ips;
+ if (ips.OnlyOneIP())
+ {
+ users->Authorize(u->GetLogin(), ips[0].ip, 0xFFffFFff, this);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::AddUser(USER_PTR u)
+{
+SetUserNotifiers(u);
+usersList.push_back(u);
+UpdateUserAuthorization(u);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::DelUser(USER_PTR u)
+{
+if (u->IsAuthorizedBy(this))
+ users->Unauthorize(u->GetLogin(), this);
+UnSetUserNotifiers(u);
+usersList.remove(u);
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::SendMessage(const STG_MSG &, uint32_t) const
+{
+errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
+return -1;
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::Unauthorize, user);
+if (user->IsAuthorizedBy(&auth))
+ auth.users->Unauthorize(user->GetLogin(), &auth);
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::UpdateUserAuthorization, user);
+auth.UpdateUserAuthorization(user);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.21 $
+ $Date: 2010/09/10 06:38:26 $
+ $Author: faust $
+*/
+
+#ifndef AO_H
+#define AO_H
+
+#include <pthread.h>
+
+#include <string>
+#include <list>
+
+#include "stg/auth.h"
+#include "stg/store.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/user.h"
+#include "stg/logger.h"
+
+extern "C" PLUGIN * GetPlugin();
+
+class AUTH_AO;
+class USERS;
+//-----------------------------------------------------------------------------
+template <typename T>
+class CHG_BEFORE_NOTIFIER : public PROPERTY_NOTIFIER_BASE<T> {
+public:
+ CHG_BEFORE_NOTIFIER(AUTH_AO & a, USER_PTR u)
+ : PROPERTY_NOTIFIER_BASE<T>(), user(u), auth(a) {}
+ CHG_BEFORE_NOTIFIER(const CHG_BEFORE_NOTIFIER<T> & rvalue)
+ : PROPERTY_NOTIFIER_BASE<T>(),
+ user(rvalue.user), auth(rvalue.auth) {}
+ void Notify(const T & oldValue, const T & newValue);
+ USER_PTR GetUser() const { return user; }
+
+private:
+ CHG_BEFORE_NOTIFIER<T> & operator=(const CHG_BEFORE_NOTIFIER<T> & rvalue);
+
+ USER_PTR user;
+ const AUTH_AO & auth;
+};
+//-----------------------------------------------------------------------------
+template <typename T>
+class CHG_AFTER_NOTIFIER : public PROPERTY_NOTIFIER_BASE<T> {
+public:
+ CHG_AFTER_NOTIFIER(AUTH_AO & a, USER_PTR u)
+ : PROPERTY_NOTIFIER_BASE<T>(), user(u), auth(a) {}
+ CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER<T> & rvalue)
+ : PROPERTY_NOTIFIER_BASE<T>(),
+ user(rvalue.user), auth(rvalue.auth) {}
+ void Notify(const T & oldValue, const T & newValue);
+ USER_PTR GetUser() const { return user; }
+
+private:
+ CHG_AFTER_NOTIFIER<T> & operator=(const CHG_AFTER_NOTIFIER<T> & rvalue);
+
+ USER_PTR user;
+ const AUTH_AO & auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_AO : public AUTH {
+public:
+ AUTH_AO();
+ virtual ~AUTH_AO(){}
+
+ void SetUsers(USERS * u) { users = u; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+ void SetSettings(const MODULE_SETTINGS &) {}
+ int ParseSettings() { return 0; }
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 30; }
+ uint16_t GetStopPosition() const { return 30; }
+
+ void AddUser(USER_PTR u);
+ void DelUser(USER_PTR u);
+
+ int SendMessage(const STG_MSG & msg, uint32_t ip) const;
+
+private:
+ AUTH_AO(const AUTH_AO & rvalue);
+ AUTH_AO & operator=(const AUTH_AO & rvalue);
+
+ void GetUsers();
+ void SetUserNotifiers(USER_PTR u);
+ void UnSetUserNotifiers(USER_PTR u);
+ void UpdateUserAuthorization(CONST_USER_PTR u) const;
+
+ mutable std::string errorStr;
+ USERS * users;
+ std::list<USER_PTR> usersList;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+
+ std::list<CHG_BEFORE_NOTIFIER<int> > BeforeChgAONotifierList;
+ std::list<CHG_AFTER_NOTIFIER<int> > AfterChgAONotifierList;
+
+ std::list<CHG_BEFORE_NOTIFIER<USER_IPS> > BeforeChgIPNotifierList;
+ std::list<CHG_AFTER_NOTIFIER<USER_IPS> > AfterChgIPNotifierList;
+
+ class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
+ public:
+ explicit ADD_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
+ virtual ~ADD_USER_NONIFIER() {}
+ void Notify(const USER_PTR & user) { auth.AddUser(user); }
+
+ private:
+ ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
+ ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
+
+ AUTH_AO & auth;
+ } onAddUserNotifier;
+
+ class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
+ public:
+ explicit DEL_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
+ virtual ~DEL_USER_NONIFIER() {}
+ void Notify(const USER_PTR & user) { auth.DelUser(user); }
+
+ private:
+ DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
+ DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
+
+ AUTH_AO & auth;
+ } onDelUserNotifier;
+ PLUGIN_LOGGER logger;
+
+ friend class CHG_BEFORE_NOTIFIER<int>;
+ friend class CHG_AFTER_NOTIFIER<int>;
+ friend class CHG_BEFORE_NOTIFIER<USER_IPS>;
+ friend class CHG_AFTER_NOTIFIER<USER_IPS>;
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+set ( CPP_FILES inetaccess.cpp )
+
+add_library ( mod_auth_ia MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_auth_ia scriptexecuter crypto logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2010/02/16 11:41:00 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_auth_ia.so
+
+SRCS = ./inetaccess.cpp
+
+STGLIBS = common \
+ crypto \
+ logger \
+ scriptexecuter
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.79 $
+ $Date: 2010/03/25 15:18:48 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h> // close
+
+#include <csignal>
+#include <cstdlib>
+#include <cstdio> // snprintf
+#include <cerrno>
+#include <cmath>
+#include <algorithm>
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/tariff.h"
+#include "stg/user_property.h"
+#include "stg/settings.h"
+#include "stg/plugin_creator.h"
+#include "inetaccess.h"
+
+extern volatile time_t stgTime;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<AUTH_IA> iac;
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return iac.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA_SETTINGS::AUTH_IA_SETTINGS()
+ : userDelay(0),
+ userTimeout(0),
+ port(0),
+ errorStr(),
+ freeMbShowType(freeMbCash),
+ logProtocolErrors(false)
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = static_cast<uint16_t>(p);
+///////////////////////////
+pv.param = "UserDelay";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'UserDelay\' not found.";
+ printfd(__FILE__, "Parameter 'UserDelay' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &userDelay))
+ {
+ errorStr = "Cannot parse parameter \'UserDelay\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'UserDelay'\n");
+ return -1;
+ }
+///////////////////////////
+pv.param = "UserTimeout";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'UserTimeout\' not found.";
+ printfd(__FILE__, "Parameter 'UserTimeout' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 15, 1200, &userTimeout))
+ {
+ errorStr = "Cannot parse parameter \'UserTimeout\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'UserTimeout'\n");
+ return -1;
+ }
+///////////////////////////
+pv.param = "LogProtocolErrors";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ logProtocolErrors = false;
+else if (ParseYesNo(pvi->value[0], &logProtocolErrors))
+ {
+ errorStr = "Cannot parse parameter \'LogProtocolErrors\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'LogProtocolErrors'\n");
+ return -1;
+ }
+/////////////////////////////////////////////////////////////
+std::string freeMbType;
+int n = 0;
+pv.param = "FreeMb";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'FreeMb\' not found.";
+ printfd(__FILE__, "Parameter 'FreeMb' not found\n");
+ return -1;
+ }
+freeMbType = pvi->value[0];
+
+if (strcasecmp(freeMbType.c_str(), "cash") == 0)
+ {
+ freeMbShowType = freeMbCash;
+ }
+else if (strcasecmp(freeMbType.c_str(), "none") == 0)
+ {
+ freeMbShowType = freeMbNone;
+ }
+else if (!str2x(freeMbType.c_str(), n))
+ {
+ if (n < 0 || n >= DIR_NUM)
+ {
+ errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+ freeMbShowType = (FREEMB)(freeMb0 + n);
+ }
+else
+ {
+ errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+/////////////////////////////////////////////////////////////
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+IA_PHASE::IA_PHASE()
+ : phase(1),
+ flog(NULL)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#else
+IA_PHASE::IA_PHASE()
+ : phase(1)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#endif
+//-----------------------------------------------------------------------------
+IA_PHASE::~IA_PHASE()
+{
+#ifdef IA_PHASE_DEBUG
+flog = fopen(log.c_str(), "at");
+if (flog)
+ {
+ fprintf(flog, "IA %s D\n", login.c_str());
+ fclose(flog);
+ }
+#endif
+}
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+void IA_PHASE::SetLogFileName(const string & logFileName)
+{
+log = logFileName + ".ia.log";
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetUserLogin(const string & login)
+{
+IA_PHASE::login = login;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::WritePhaseChange(int newPhase)
+{
+UTIME newPhaseTime;
+gettimeofday(&newPhaseTime, NULL);
+flog = fopen(log.c_str(), "at");
+if (flog)
+ {
+ string action = newPhase == phase ? "U" : "C";
+ double delta = newPhaseTime.GetSec() - phaseTime.GetSec();
+ delta += (newPhaseTime.GetUSec() - phaseTime.GetUSec()) * 1.0e-6;
+ fprintf(flog, "IA %s %s oldPhase = %d, newPhase = %d. dt = %.6f\n",
+ login.c_str(),
+ action.c_str(),
+ phase,
+ newPhase,
+ delta);
+ fclose(flog);
+ }
+}
+#endif
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase1()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(1);
+#endif
+phase = 1;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase2()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(2);
+#endif
+phase = 2;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase3()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(3);
+#endif
+phase = 3;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase4()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(4);
+#endif
+phase = 4;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+int IA_PHASE::GetPhase() const
+{
+return phase;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::UpdateTime()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(phase);
+#endif
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+const UTIME & IA_PHASE::GetTime() const
+{
+return phaseTime;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA::AUTH_IA()
+ : ctxS(),
+ errorStr(),
+ iaSettings(),
+ settings(),
+ nonstop(false),
+ isRunningRun(false),
+ isRunningRunTimeouter(false),
+ users(NULL),
+ stgSettings(NULL),
+ ip2user(),
+ recvThread(),
+ timeouterThread(),
+ mutex(),
+ listenSocket(-1),
+ connSynAck6(),
+ connSynAck8(),
+ disconnSynAck6(),
+ disconnSynAck8(),
+ aliveSyn6(),
+ aliveSyn8(),
+ fin6(),
+ fin8(),
+ packetTypes(),
+ enabledDirs(0xFFffFFff),
+ onDelUserNotifier(*this),
+ logger(GetPluginLogger(GetStgLogger(), "auth_ia"))
+{
+InitContext("pr7Hhen", 7, &ctxS);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+
+memset(&connSynAck6, 0, sizeof(CONN_SYN_ACK_6));
+memset(&connSynAck8, 0, sizeof(CONN_SYN_ACK_8));
+memset(&disconnSynAck6, 0, sizeof(DISCONN_SYN_ACK_6));
+memset(&disconnSynAck8, 0, sizeof(DISCONN_SYN_ACK_8));
+memset(&aliveSyn6, 0, sizeof(ALIVE_SYN_6));
+memset(&aliveSyn8, 0, sizeof(ALIVE_SYN_8));
+memset(&fin6, 0, sizeof(FIN_6));
+memset(&fin8, 0, sizeof(FIN_8));
+
+printfd(__FILE__, "sizeof(CONN_SYN_6) = %d %d\n", sizeof(CONN_SYN_6), Min8(sizeof(CONN_SYN_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_8) = %d %d\n", sizeof(CONN_SYN_8), Min8(sizeof(CONN_SYN_8)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_6) = %d %d\n", sizeof(CONN_SYN_ACK_6), Min8(sizeof(CONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_8) = %d %d\n", sizeof(CONN_SYN_ACK_8), Min8(sizeof(CONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(CONN_ACK_6) = %d %d\n", sizeof(CONN_ACK_6), Min8(sizeof(CONN_ACK_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_6) = %d %d\n", sizeof(ALIVE_SYN_6), Min8(sizeof(ALIVE_SYN_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_8) = %d %d\n", sizeof(ALIVE_SYN_8), Min8(sizeof(ALIVE_SYN_8)));
+printfd(__FILE__, "sizeof(ALIVE_ACK_6) = %d %d\n", sizeof(ALIVE_ACK_6), Min8(sizeof(ALIVE_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_6) = %d %d\n", sizeof(DISCONN_SYN_6), Min8(sizeof(DISCONN_SYN_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_6) = %d %d\n", sizeof(DISCONN_SYN_ACK_6), Min8(sizeof(DISCONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_8) = %d %d\n", sizeof(DISCONN_SYN_ACK_8), Min8(sizeof(DISCONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(DISCONN_ACK_6) = %d %d\n", sizeof(DISCONN_ACK_6), Min8(sizeof(DISCONN_ACK_6)));
+printfd(__FILE__, "sizeof(FIN_6) = %d %d\n", sizeof(FIN_6), Min8(sizeof(FIN_6)));
+printfd(__FILE__, "sizeof(FIN_8) = %d %d\n", sizeof(FIN_8), Min8(sizeof(FIN_8)));
+printfd(__FILE__, "sizeof(ERR) = %d %d\n", sizeof(ERR), Min8(sizeof(ERR)));
+printfd(__FILE__, "sizeof(INFO_6) = %d %d\n", sizeof(INFO_6), Min8(sizeof(INFO_6)));
+printfd(__FILE__, "sizeof(INFO_7) = %d %d\n", sizeof(INFO_7), Min8(sizeof(INFO_7)));
+printfd(__FILE__, "sizeof(INFO_8) = %d %d\n", sizeof(INFO_8), Min8(sizeof(INFO_8)));
+
+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;
+}
+//-----------------------------------------------------------------------------
+AUTH_IA::~AUTH_IA()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Start()
+{
+users->AddNotifierUserDel(&onDelUserNotifier);
+nonstop = true;
+
+if (PrepareNet())
+ {
+ return -1;
+ }
+
+if (!isRunningRun)
+ {
+ if (pthread_create(&recvThread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create recv thread\n");
+ logger("Cannot create recv thread.");
+ return -1;
+ }
+ }
+
+if (!isRunningRunTimeouter)
+ {
+ if (pthread_create(&timeouterThread, NULL, RunTimeouter, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create timeouter thread\n");
+ logger("Cannot create timeouter thread.");
+ return -1;
+ }
+ }
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Stop()
+{
+if (!IsRunning())
+ return 0;
+
+nonstop = false;
+
+std::for_each(
+ ip2user.begin(),
+ ip2user.end(),
+ UnauthorizeUser(this)
+ );
+
+if (isRunningRun)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunningRun; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ }
+
+FinalizeNet();
+
+if (isRunningRunTimeouter)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunningRunTimeouter; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ }
+
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+if (isRunningRun || isRunningRunTimeouter)
+ return -1;
+
+printfd(__FILE__, "AUTH_IA::Stoped successfully.\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRun = true;
+
+char buffer[512];
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+
+while (ia->nonstop)
+ {
+ ia->RecvData(buffer, sizeof(buffer));
+ if ((touchTime + MONITOR_TIME_DELAY_SEC <= stgTime) && ia->stgSettings->GetMonitoring())
+ {
+ touchTime = stgTime;
+ std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_r";
+ TouchFile(monFile);
+ }
+ }
+
+ia->isRunningRun = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::RunTimeouter(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRunTimeouter = true;
+
+int a = -1;
+std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_t";
+while (ia->nonstop)
+ {
+ struct timespec ts = {0, 20000000};
+ nanosleep(&ts, NULL);
+ ia->Timeouter();
+ // TODO change counter to timer and MONITOR_TIME_DELAY_SEC
+ if (++a % (50 * 60) == 0 && ia->stgSettings->GetMonitoring())
+ {
+ TouchFile(monFile);
+ }
+ }
+
+ia->isRunningRunTimeouter = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::ParseSettings()
+{
+int ret = iaSettings.ParseSettings(settings);
+if (ret)
+ errorStr = iaSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Reload(const MODULE_SETTINGS & ms)
+{
+AUTH_IA_SETTINGS newIaSettings;
+if (newIaSettings.ParseSettings(ms))
+ {
+ printfd(__FILE__, "AUTH_IA::Reload() - Failed to reload InetAccess.\n");
+ logger("AUTH_IA: Cannot reload InetAccess. Errors found.");
+ return -1;
+ }
+
+printfd(__FILE__, "AUTH_IA::Reload() - Reloaded InetAccess successfully.\n");
+logger("AUTH_IA: Reloaded InetAccess successfully.");
+iaSettings = newIaSettings;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PrepareNet()
+{
+struct sockaddr_in listenAddr;
+
+listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Cannot create socket.";
+ logger("Cannot create a socket: %s", strerror(errno));
+ return -1;
+ }
+
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(static_cast<uint16_t>(iaSettings.GetUserPort()));
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
+ {
+ errorStr = "AUTH_IA: Bind failed.";
+ logger("Cannot bind the socket: %s", strerror(errno));
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::FinalizeNet()
+{
+close(listenSocket);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RecvData(char * buffer, int bufferSize)
+{
+if (!WaitPackets(listenSocket)) // Timeout
+ {
+ return 0;
+ }
+
+struct sockaddr_in outerAddr;
+socklen_t outerAddrLen(sizeof(outerAddr));
+ssize_t dataLen = recvfrom(listenSocket, buffer, bufferSize, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
+
+if (!dataLen) // EOF
+ {
+ return 0;
+ }
+
+if (dataLen <= 0) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "recvfrom res=%d, error: '%s'\n", dataLen, strerror(errno));
+ logger("recvfrom error: %s", strerror(errno));
+ return -1;
+ }
+ return 0;
+ }
+
+if (dataLen > 256)
+ return -1;
+
+uint32_t sip = outerAddr.sin_addr.s_addr;
+uint16_t sport = htons(outerAddr.sin_port);
+
+int protoVer;
+if (CheckHeader(buffer, sip, &protoVer))
+ return -1;
+
+char login[PASSWD_LEN]; //TODO why PASSWD_LEN ?
+memset(login, 0, PASSWD_LEN);
+
+DecryptString(login, buffer + 8, PASSWD_LEN, &ctxS);
+
+USER_PTR user;
+if (users->FindByName(login, &user))
+ {
+ logger("User's connect failed: user '%s' not found. IP %s",
+ login,
+ inet_ntostring(sip).c_str());
+ printfd(__FILE__, "User '%s' NOT found!\n", login);
+ SendError(sip, sport, protoVer, IconvString("Неправильный логин.", "utf8", "koi8-ru"));
+ return -1;
+ }
+
+printfd(__FILE__, "User '%s' FOUND!\n", user->GetLogin().c_str());
+
+if (user->GetProperty().disabled.Get())
+ {
+ logger("Cannont authorize '%s', user is disabled.", login);
+ SendError(sip, sport, protoVer, IconvString("Учетная запись заблокирована.", "utf8", "koi8-ru"));
+ return 0;
+ }
+
+if (user->GetProperty().passive.Get())
+ {
+ logger("Cannont authorize '%s', user is passive.", login);
+ SendError(sip, sport, protoVer, IconvString("Учетная запись заморожена.", "utf8", "koi8-ru"));
+ return 0;
+ }
+
+if (!user->GetProperty().ips.Get().IsIPInIPS(sip))
+ {
+ printfd(__FILE__, "User %s. IP address is incorrect. IP %s\n",
+ user->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ logger("User %s. IP address is incorrect. IP %s",
+ user->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ SendError(sip, sport, protoVer, IconvString("Пользователь не опознан. Проверьте IP-адрес.", "utf8", "koi8-ru"));
+ return 0;
+ }
+
+return PacketProcessor(buffer, dataLen, sip, sport, protoVer, user);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::CheckHeader(const char * buffer, uint32_t sip, int * protoVer)
+{
+if (strncmp(IA_ID, buffer, strlen(IA_ID)) != 0)
+ {
+ printfd(__FILE__, "update needed - IA_ID\n");
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. Header: invalid packed signature.", inet_ntostring(sip).c_str());
+ return -1;
+ }
+
+if (buffer[6] != 0) //proto[0] shoud be 0
+ {
+ printfd(__FILE__, "update needed - PROTO major: %d\n", buffer[6]);
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. Header: invalid protocol major version: %d.", inet_ntostring(sip).c_str(), buffer[6]);
+ return -1;
+ }
+
+if (buffer[7] < 6)
+ {
+ // need update
+ printfd(__FILE__, "update needed - PROTO minor: %d\n", buffer[7]);
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. Header: invalid protocol minor version: %d.", inet_ntostring(sip).c_str(), buffer[7]);
+ return -1;
+ }
+else
+ {
+ *protoVer = buffer[7];
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Timeouter()
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, IA_USER>::iterator it;
+it = ip2user.begin();
+
+while (it != ip2user.end())
+ {
+ uint32_t sip = it->first;
+
+ static UTIME currTime;
+ gettimeofday(&currTime, NULL);
+
+ if ((it->second.phase.GetPhase() == 2)
+ && (currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay())
+ {
+ if (iaSettings.LogProtocolErrors())
+ logger("User '%s'. Protocol version: %d. Phase 2: connect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
+ it->second.phase.SetPhase1();
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: timeout\n");
+ ip2user.erase(it++);
+ continue;
+ }
+
+ if (it->second.phase.GetPhase() == 3)
+ {
+ if (!it->second.messagesToSend.empty())
+ {
+ if (it->second.protoVer == 6)
+ RealSendMessage6(*it->second.messagesToSend.begin(), sip, it->second);
+
+ if (it->second.protoVer == 7)
+ RealSendMessage7(*it->second.messagesToSend.begin(), sip, it->second);
+
+ if (it->second.protoVer == 8)
+ RealSendMessage8(*it->second.messagesToSend.begin(), sip, it->second);
+
+ it->second.messagesToSend.erase(it->second.messagesToSend.begin());
+ }
+
+ if((currTime - it->second.lastSendAlive) > iaSettings.GetUserDelay())
+ {
+ switch (it->second.protoVer)
+ {
+ case 6:
+ Send_ALIVE_SYN_6(&(it->second), sip);
+ break;
+ case 7:
+ Send_ALIVE_SYN_7(&(it->second), sip);
+ break;
+ case 8:
+ Send_ALIVE_SYN_8(&(it->second), sip);
+ break;
+ }
+
+ gettimeofday(&it->second.lastSendAlive, NULL);
+ }
+
+ if ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserTimeout())
+ {
+ if (iaSettings.LogProtocolErrors())
+ logger("User '%s'. Protocol version: %d. Phase 3: alive timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserTimeout().GetSec());
+ users->Unauthorize(it->second.user->GetLogin(), this);
+ ip2user.erase(it++);
+ continue;
+ }
+ }
+
+ if ((it->second.phase.GetPhase() == 4)
+ && ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay()))
+ {
+ if (iaSettings.LogProtocolErrors())
+ logger("User '%s'. Protocol version: %d. Phase 4: disconnect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
+ it->second.phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 4 to 3. Reason: timeout\n");
+ }
+
+ ++it;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, USER_PTR user)
+{
+std::string login(user->GetLogin());
+const size_t offset = LOGIN_LEN + 2 + 6; // LOGIN_LEN + sizeOfMagic + sizeOfVer;
+
+STG_LOCKER lock(&mutex);
+std::map<uint32_t, IA_USER>::iterator it(ip2user.find(sip));
+
+if (it == ip2user.end())
+ {
+ USER_PTR userPtr;
+ if (!users->FindByIPIdx(sip, &userPtr))
+ {
+ if (userPtr->GetID() != user->GetID())
+ {
+ printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
+ userPtr->GetLogin().c_str(),
+ inet_ntostring(sip).c_str(),
+ login.c_str());
+ logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
+ userPtr->GetLogin().c_str(),
+ inet_ntostring(sip).c_str(),
+ login.c_str());
+ SendError(sip, sport, protoVer, IconvString("IP-адрес уже сипользуется.", "utf8", "koi8-ru"));
+ return 0;
+ }
+ }
+
+ printfd(__FILE__, "Add new user '%s' from ip %s\n",
+ login.c_str(), inet_ntostring(sip).c_str());
+ std::pair<std::map<uint32_t, IA_USER>::iterator, bool> res;
+ res = ip2user.insert(std::make_pair(sip, IA_USER(login, user, sport, protoVer)));
+ it = res.first;
+ #ifdef IA_PHASE_DEBUG
+ it->second.phase.SetLogFileName(stgSettings->GetLogFileName());
+ it->second.phase.SetUserLogin(login);
+ #endif
+ }
+else if (user->GetID() != it->second.user->GetID())
+ {
+ printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
+ it->second.user->GetLogin().c_str(),
+ inet_ntostring(sip).c_str(),
+ user->GetLogin().c_str());
+ logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
+ it->second.user->GetLogin().c_str(),
+ inet_ntostring(sip).c_str(),
+ user->GetLogin().c_str());
+ SendError(sip, sport, protoVer, IconvString("IP-адрес уже используется.", "utf8", "koi8-ru"));
+ return 0;
+ }
+
+IA_USER * iaUser = &(it->second);
+
+if (iaUser->password != user->GetProperty().password.Get())
+ {
+ const std::string & password = user->GetProperty().password.Get();
+ InitContext(password.c_str(), password.length(), &iaUser->ctx);
+ iaUser->password = user->GetProperty().password.Get();
+ }
+
+DecryptString(static_cast<char *>(buff) + offset, static_cast<char *>(buff) + offset, (dataLen - offset), &iaUser->ctx);
+
+char packetName[IA_MAX_TYPE_LEN];
+strncpy(packetName, static_cast<char *>(buff) + offset + 4, IA_MAX_TYPE_LEN);
+packetName[IA_MAX_TYPE_LEN - 1] = 0;
+
+std::map<std::string, int>::iterator pi(packetTypes.find(packetName));
+if (pi == packetTypes.end())
+ {
+ SendError(sip, sport, protoVer, IconvString("Неправильный логин или пароль.", "utf8", "koi8-ru"));
+ printfd(__FILE__, "Login or password is wrong!\n");
+ logger("User's connect failed. User: '%s', ip %s. Wrong login or password",
+ login.c_str(),
+ inet_ntostring(sip).c_str());
+ ip2user.erase(it);
+ return 0;
+ }
+
+if (user->IsAuthorizedBy(this) && user->GetCurrIP() != sip)
+ {
+ printfd(__FILE__, "Login %s already in use from ip %s. IP %s\n",
+ login.c_str(), inet_ntostring(user->GetCurrIP()).c_str(),
+ inet_ntostring(sip).c_str());
+ logger("Login '%s' is already in use from ip %s. IP %s",
+ login.c_str(),
+ inet_ntostring(user->GetCurrIP()).c_str(),
+ inet_ntostring(sip).c_str());
+ SendError(sip, sport, protoVer, IconvString("Логин уже используется.", "utf8", "koi8-ru"));
+ ip2user.erase(it);
+ return 0;
+ }
+
+switch (pi->second)
+ {
+ case CONN_SYN_N:
+ switch (protoVer)
+ {
+ case 6:
+ if (Process_CONN_SYN_6(static_cast<CONN_SYN_6 *>(buff), &(it->second), sip))
+ return -1;
+ return Send_CONN_SYN_ACK_6(iaUser, sip);
+ case 7:
+ if (Process_CONN_SYN_7(static_cast<CONN_SYN_7 *>(buff), &(it->second), sip))
+ return -1;
+ return Send_CONN_SYN_ACK_7(iaUser, sip);
+ case 8:
+ if (Process_CONN_SYN_8(static_cast<CONN_SYN_8 *>(buff), &(it->second), sip))
+ return -1;
+ return Send_CONN_SYN_ACK_8(iaUser, sip);
+ }
+ break;
+
+ case CONN_ACK_N:
+ switch (protoVer)
+ {
+ case 6:
+ if (Process_CONN_ACK_6(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
+ return -1;
+ return Send_ALIVE_SYN_6(iaUser, sip);
+ case 7:
+ if (Process_CONN_ACK_7(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
+ return -1;
+ return Send_ALIVE_SYN_7(iaUser, sip);
+ case 8:
+ if (Process_CONN_ACK_8(static_cast<CONN_ACK_8 *>(buff), iaUser, sip))
+ return -1;
+ return Send_ALIVE_SYN_8(iaUser, sip);
+ }
+ break;
+
+ case ALIVE_ACK_N:
+ switch (protoVer)
+ {
+ case 6:
+ return Process_ALIVE_ACK_6(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
+ case 7:
+ return Process_ALIVE_ACK_7(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
+ case 8:
+ return Process_ALIVE_ACK_8(static_cast<ALIVE_ACK_8 *>(buff), iaUser, sip);
+ }
+ break;
+
+ case DISCONN_SYN_N:
+ switch (protoVer)
+ {
+ case 6:
+ if (Process_DISCONN_SYN_6(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
+ return -1;
+ return Send_DISCONN_SYN_ACK_6(iaUser, sip);
+ case 7:
+ if (Process_DISCONN_SYN_7(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
+ return -1;
+ return Send_DISCONN_SYN_ACK_7(iaUser, sip);
+ case 8:
+ if (Process_DISCONN_SYN_8(static_cast<DISCONN_SYN_8 *>(buff), iaUser, sip))
+ return -1;
+ return Send_DISCONN_SYN_ACK_8(iaUser, sip);
+ }
+ break;
+
+ case DISCONN_ACK_N:
+ switch (protoVer)
+ {
+ case 6:
+ if (Process_DISCONN_ACK_6(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
+ return -1;
+ return Send_FIN_6(iaUser, sip, it);
+ case 7:
+ if (Process_DISCONN_ACK_7(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
+ return -1;
+ return Send_FIN_7(iaUser, sip, it);
+ case 8:
+ if (Process_DISCONN_ACK_8(static_cast<DISCONN_ACK_8 *>(buff), iaUser, sip, it))
+ return -1;
+ return Send_FIN_8(iaUser, sip, it);
+ }
+ break;
+ }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::DelUser(USER_PTR u)
+{
+
+uint32_t ip = u->GetCurrIP();
+
+if (!ip)
+ return;
+
+std::map<uint32_t, IA_USER>::iterator it;
+
+STG_LOCKER lock(&mutex);
+it = ip2user.find(ip);
+if (it == ip2user.end())
+ {
+ //Nothing to delete
+ printfd(__FILE__, "Nothing to delete\n");
+ return;
+ }
+
+if (it->second.user == u)
+ {
+ printfd(__FILE__, "User removed!\n");
+ users->Unauthorize(u->GetLogin(), this);
+ ip2user.erase(it);
+ }
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text)
+{
+struct sockaddr_in sendAddr;
+ssize_t res;
+switch (protoVer)
+ {
+ case 6:
+ case 7:
+ ERR err;
+ memset(&err, 0, sizeof(ERR));
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = htons(port);
+ sendAddr.sin_addr.s_addr = ip;
+
+ err.len = 1;
+ strncpy((char*)err.type, "ERR", 16);
+ strncpy((char*)err.text, text.c_str(), MAX_MSG_LEN);
+
+ #ifdef ARCH_BE
+ SwapBytes(err.len);
+ #endif
+
+ res = sendto(listenSocket, &err, sizeof(err), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ printfd(__FILE__, "SendError %d bytes sent\n", res);
+ break;
+
+ case 8:
+ ERR_8 err8;
+ memset(&err8, 0, sizeof(ERR_8));
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = htons(port);
+ sendAddr.sin_addr.s_addr = ip;
+
+ err8.len = 256;
+ strncpy((char*)err8.type, "ERR", 16);
+ strncpy((char*)err8.text, text.c_str(), MAX_MSG_LEN);
+
+ #ifdef ARCH_BE
+ SwapBytes(err8.len);
+ #endif
+
+ res = sendto(listenSocket, &err8, sizeof(err8), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ printfd(__FILE__, "SendError_8 %d bytes sent\n", res);
+ break;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send(uint32_t ip, uint16_t port, const char * buffer, size_t len)
+{
+struct sockaddr_in sendAddr;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = htons(port);
+sendAddr.sin_addr.s_addr = ip;
+
+if (sendto(listenSocket, buffer, len, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr)) == static_cast<ssize_t>(len))
+ return 0;
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendMessage(const STG_MSG & msg, uint32_t ip) const
+{
+printfd(__FILE__, "SendMessage userIP=%s\n", inet_ntostring(ip).c_str());
+
+std::map<uint32_t, IA_USER>::iterator it;
+
+STG_LOCKER lock(&mutex);
+it = ip2user.find(ip);
+if (it == ip2user.end())
+ {
+ errorStr = "Unknown user.";
+ return -1;
+ }
+it->second.messagesToSend.push_back(msg);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 6 user=%s\n", user.login.c_str());
+
+INFO_6 info;
+memset(&info, 0, sizeof(INFO_6));
+
+info.len = 256;
+strncpy((char*)info.type, "INFO", 16);
+info.infoType = 'I';
+strncpy((char*)info.text, msg.text.c_str(), 235);
+info.text[234] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+#endif
+
+char buffer[256];
+memcpy(buffer, &info, sizeof(INFO_6));
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, iaSettings.GetUserPort(), buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 7 user=%s\n", user.login.c_str());
+
+INFO_7 info;
+memset(&info, 0, sizeof(INFO_7));
+
+info.len = 264;
+strncpy((char*)info.type, "INFO_7", 16);
+info.infoType = static_cast<int8_t>(msg.header.type);
+info.showTime = static_cast<int8_t>(msg.header.showTime);
+info.sendTime = msg.header.creationTime;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+strncpy((char*)info.text, msg.text.c_str(), MAX_MSG_LEN - 1);
+info.text[MAX_MSG_LEN - 1] = 0;
+
+char buffer[300];
+memcpy(buffer, &info, sizeof(INFO_7));
+
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, iaSettings.GetUserPort(), buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 8 user=%s\n", user.login.c_str());
+
+INFO_8 info;
+memset(&info, 0, sizeof(INFO_8));
+
+info.len = 1056;
+strncpy((char*)info.type, "INFO_8", 16);
+info.infoType = static_cast<int8_t>(msg.header.type);
+info.showTime = static_cast<int8_t>(msg.header.showTime);
+info.sendTime = msg.header.creationTime;
+
+strncpy((char*)info.text, msg.text.c_str(), IA_MAX_MSG_LEN_8 - 1);
+info.text[IA_MAX_MSG_LEN_8 - 1] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+char buffer[1500];
+memcpy(buffer, &info, sizeof(INFO_8));
+
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, user.port, buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_6(CONN_SYN_6 *, IA_USER * iaUser, uint32_t)
+{
+if (!(iaUser->phase.GetPhase() == 1 || iaUser->phase.GetPhase() == 3))
+ return -1;
+
+enabledDirs = 0xFFffFFff;
+
+iaUser->phase.SetPhase2();
+printfd(__FILE__, "Phase changed from %d to 2. Reason: CONN_SYN_6\n", iaUser->phase.GetPhase());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip)
+{
+return Process_CONN_SYN_6(connSyn, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connSyn->dirs);
+#endif
+int ret = Process_CONN_SYN_6(reinterpret_cast<CONN_SYN_6 *>(connSyn), iaUser, sip);
+enabledDirs = connSyn->dirs;
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_6 %s\n", connAck->type);
+
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+
+ iaUser->lastSendAlive = iaUser->phase.GetTime();
+ if (users->Authorize(iaUser->login, sip, enabledDirs, this))
+ {
+ iaUser->phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_6\n");
+ return 0;
+ }
+ else
+ {
+ errorStr = iaUser->user->GetStrError();
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
+ iaUser->phase.SetPhase1();
+ ip2user.erase(sip);
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+ return -1;
+ }
+ }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
+if (iaSettings.LogProtocolErrors())
+ {
+ if (iaUser->phase.GetPhase() != 2)
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ if (connAck->rnd != iaUser->rnd + 1)
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+return Process_CONN_ACK_6(connAck, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_8 %s\n", connAck->type);
+
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ iaUser->lastSendAlive = iaUser->phase.GetTime();
+ if (users->Authorize(iaUser->login, sip, enabledDirs, this))
+ {
+ iaUser->phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_8\n");
+ return 0;
+ }
+ else
+ {
+ errorStr = iaUser->user->GetStrError();
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
+ iaUser->phase.SetPhase1();
+ ip2user.erase(sip);
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+ return -1;
+ }
+ }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
+if (iaSettings.LogProtocolErrors())
+ {
+ if (iaUser->phase.GetPhase() != 2)
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ if (connAck->rnd != iaUser->rnd + 1)
+ logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_6\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ #ifdef IA_DEBUG
+ iaUser->aliveSent = false;
+ #endif
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip)
+{
+return Process_ALIVE_ACK_6(aliveAck, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_8\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ #ifdef IA_DEBUG
+ iaUser->aliveSent = false;
+ #endif
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_6(DISCONN_SYN_6 *, IA_USER * iaUser, uint32_t sip)
+{
+printfd(__FILE__, "DISCONN_SYN_6\n");
+if (iaUser->phase.GetPhase() != 3)
+ {
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+ errorStr = "Incorrect request DISCONN_SYN";
+ return -1;
+ }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip)
+{
+return Process_DISCONN_SYN_6(disconnSyn, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_8(DISCONN_SYN_8 *, IA_USER * iaUser, uint32_t sip)
+{
+if (iaUser->phase.GetPhase() != 3)
+ {
+ if (iaSettings.LogProtocolErrors())
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ errorStr = "Incorrect request DISCONN_SYN";
+ printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+ return -1;
+ }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnAck,
+ IA_USER * iaUser,
+ uint32_t sip,
+ std::map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_6\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+ {
+ if (iaSettings.LogProtocolErrors())
+ {
+ if (iaUser->phase.GetPhase() != 4)
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ if (disconnAck->rnd != iaUser->rnd + 1)
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
+ }
+ printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+return Process_DISCONN_ACK_6(disconnAck, iaUser, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_8\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+ {
+ if (iaSettings.LogProtocolErrors())
+ {
+ if (iaUser->phase.GetPhase() != 4)
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+ if (disconnAck->rnd != iaUser->rnd + 1)
+ logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
+ }
+ printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
+{
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck6.len = Min8(sizeof(CONN_SYN_ACK_6));
+strcpy((char*)connSynAck6.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ strncpy((char*)connSynAck6.dirName[j],
+ stgSettings->GetDirName(j).c_str(),
+ sizeof(string16));
+
+ connSynAck6.dirName[j][sizeof(string16) - 1] = 0;
+ }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = static_cast<uint32_t>(random());
+connSynAck6.rnd = iaUser->rnd;
+
+printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
+
+connSynAck6.userTimeOut = iaSettings.GetUserTimeout().GetSec();
+connSynAck6.aliveDelay = iaSettings.GetUserDelay().GetSec();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck6.len);
+SwapBytes(connSynAck6.rnd);
+SwapBytes(connSynAck6.userTimeOut);
+SwapBytes(connSynAck6.aliveDelay);
+#endif
+
+EncryptString((char*)&connSynAck6, (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)));;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_CONN_SYN_ACK_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)connSynAck8.hdr.magic, IA_ID);
+connSynAck8.hdr.protoVer[0] = 0;
+connSynAck8.hdr.protoVer[1] = 8;
+
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck8.len = Min8(sizeof(CONN_SYN_ACK_8));
+strcpy((char*)connSynAck8.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ strncpy((char*)connSynAck8.dirName[j],
+ stgSettings->GetDirName(j).c_str(),
+ sizeof(string16));
+
+ connSynAck8.dirName[j][sizeof(string16) - 1] = 0;
+ }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = static_cast<uint32_t>(random());
+connSynAck8.rnd = iaUser->rnd;
+
+printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
+
+connSynAck8.userTimeOut = iaSettings.GetUserTimeout().GetSec();
+connSynAck8.aliveDelay = iaSettings.GetUserDelay().GetSec();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck8.len);
+SwapBytes(connSynAck8.rnd);
+SwapBytes(connSynAck8.userTimeOut);
+SwapBytes(connSynAck8.aliveDelay);
+#endif
+
+EncryptString((char*)&connSynAck8, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip)
+{
+aliveSyn6.len = Min8(sizeof(ALIVE_SYN_6));
+aliveSyn6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+strcpy((char*)aliveSyn6.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ aliveSyn6.md[i] = iaUser->user->GetProperty().down.Get()[i];
+ aliveSyn6.mu[i] = iaUser->user->GetProperty().up.Get()[i];
+
+ aliveSyn6.sd[i] = iaUser->user->GetSessionDownload()[i];
+ aliveSyn6.su[i] = iaUser->user->GetSessionUpload()[i];
+ }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+const TARIFF * tf = iaUser->user->GetTariff();
+
+if (dn < DIR_NUM)
+ {
+ double p = tf->GetPriceWithTraffType(aliveSyn6.mu[dn],
+ aliveSyn6.md[dn],
+ dn,
+ stgTime);
+ p *= 1024 * 1024;
+ if (std::fabs(p) < 1.0e-3)
+ {
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "---");
+ }
+ else
+ {
+ double fmb = iaUser->user->GetProperty().freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+ }
+ }
+else
+ {
+ if (freeMbNone == iaSettings.GetFreeMbShowType())
+ {
+ aliveSyn6.freeMb[0] = 0;
+ }
+ else
+ {
+ double fmb = iaUser->user->GetProperty().freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+ }
+ }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+ {
+ printfd(__FILE__, "========= ALIVE_ACK_6(7) TIMEOUT !!! %s =========\n", iaUser->login.c_str());
+ }
+iaUser->aliveSent = true;
+#endif
+
+aliveSyn6.cash =(int64_t) (iaUser->user->GetProperty().cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+ aliveSyn6.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn6.len);
+SwapBytes(aliveSyn6.rnd);
+SwapBytes(aliveSyn6.cash);
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ SwapBytes(aliveSyn6.mu[i]);
+ SwapBytes(aliveSyn6.md[i]);
+ SwapBytes(aliveSyn6.su[i]);
+ SwapBytes(aliveSyn6.sd[i]);
+ }
+#endif
+
+EncryptString((char*)&aliveSyn6, (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_ALIVE_SYN_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)aliveSyn8.hdr.magic, IA_ID);
+aliveSyn8.hdr.protoVer[0] = 0;
+aliveSyn8.hdr.protoVer[1] = 8;
+
+aliveSyn8.len = Min8(sizeof(ALIVE_SYN_8));
+aliveSyn8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+strcpy((char*)aliveSyn8.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ aliveSyn8.md[i] = iaUser->user->GetProperty().down.Get()[i];
+ aliveSyn8.mu[i] = iaUser->user->GetProperty().up.Get()[i];
+
+ aliveSyn8.sd[i] = iaUser->user->GetSessionDownload()[i];
+ aliveSyn8.su[i] = iaUser->user->GetSessionUpload()[i];
+ }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+
+if (dn < DIR_NUM)
+ {
+ const TARIFF * tf = iaUser->user->GetTariff();
+ double p = tf->GetPriceWithTraffType(aliveSyn8.mu[dn],
+ aliveSyn8.md[dn],
+ dn,
+ stgTime);
+ p *= 1024 * 1024;
+ if (std::fabs(p) < 1.0e-3)
+ {
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "---");
+ }
+ else
+ {
+ double fmb = iaUser->user->GetProperty().freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+ }
+ }
+else
+ {
+ if (freeMbNone == iaSettings.GetFreeMbShowType())
+ {
+ aliveSyn8.freeMb[0] = 0;
+ }
+ else
+ {
+ double fmb = iaUser->user->GetProperty().freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+ }
+ }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+ {
+ printfd(__FILE__, "========= ALIVE_ACK_8 TIMEOUT !!! =========\n");
+ }
+iaUser->aliveSent = true;
+#endif
+
+const TARIFF * tf = iaUser->user->GetTariff();
+
+aliveSyn8.cash =(int64_t) (iaUser->user->GetProperty().cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+ aliveSyn8.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#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
+
+EncryptString((char*)&aliveSyn8, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
+{
+disconnSynAck6.len = Min8(sizeof(DISCONN_SYN_ACK_6));
+strcpy((char*)disconnSynAck6.type, "DISCONN_SYN_ACK");
+disconnSynAck6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck6.len);
+SwapBytes(disconnSynAck6.rnd);
+#endif
+
+EncryptString((char*)&disconnSynAck6, (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_DISCONN_SYN_ACK_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)disconnSynAck8.hdr.magic, IA_ID);
+disconnSynAck8.hdr.protoVer[0] = 0;
+disconnSynAck8.hdr.protoVer[1] = 8;
+
+disconnSynAck8.len = Min8(sizeof(DISCONN_SYN_ACK_8));
+strcpy((char*)disconnSynAck8.type, "DISCONN_SYN_ACK");
+disconnSynAck8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck8.len);
+SwapBytes(disconnSynAck8.rnd);
+#endif
+
+EncryptString((char*)&disconnSynAck8, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+fin6.len = Min8(sizeof(FIN_6));
+strcpy((char*)fin6.type, "FIN");
+strcpy((char*)fin6.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin6.len);
+#endif
+
+EncryptString((char*)&fin6, (char*)&fin6, Min8(sizeof(fin6)), &iaUser->ctx);
+
+users->Unauthorize(iaUser->login, this);
+
+int res = Send(sip, iaSettings.GetUserPort(), (char*)&fin6, Min8(sizeof(fin6)));
+
+ip2user.erase(it);
+
+return res;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+return Send_FIN_6(iaUser, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+strcpy((char*)fin8.hdr.magic, IA_ID);
+fin8.hdr.protoVer[0] = 0;
+fin8.hdr.protoVer[1] = 8;
+
+fin8.len = Min8(sizeof(FIN_8));
+strcpy((char*)fin8.type, "FIN");
+strcpy((char*)fin8.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin8.len);
+#endif
+
+EncryptString((char*)&fin8, (char*)&fin8, Min8(sizeof(fin8)), &iaUser->ctx);
+
+users->Unauthorize(iaUser->login, this);
+
+int res = Send(sip, iaUser->port, (char*)&fin8, Min8(sizeof(fin8)));
+
+ip2user.erase(it);
+
+return res;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.34 $
+ $Date: 2010/09/10 06:39:19 $
+ $Author: faust $
+ */
+
+#ifndef INETACCESS_H
+#define INETACCESS_H
+
+#include "stg/auth.h"
+#include "stg/store.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/user.h"
+#include "stg/users.h"
+#include "stg/ia_packets.h"
+#include "stg/blowfish.h"
+#include "stg/logger.h"
+#include "stg/utime.h"
+#include "stg/logger.h"
+
+#include <cstring>
+#include <ctime>
+#include <cstdint>
+#include <string>
+#include <map>
+#include <list>
+#include <functional>
+#include <utility>
+
+#include <sys/time.h>
+#include <pthread.h>
+
+#define IA_PROTO_VER (6)
+
+//#define IA_DEBUG (1)
+//#define IA_PHASE_DEBUG (1)
+
+class AUTH_IA;
+//-----------------------------------------------------------------------------
+enum FREEMB {
+ freeMb0 = 0,
+ freeMb1,
+ freeMb2,
+ freeMb3,
+ freeMb4,
+ freeMb5,
+ freeMb6,
+ freeMb7,
+ freeMb8,
+ freeMb9,
+ freeMb10,
+ freeMb11,
+ freeMb12,
+ freeMb13,
+ freeMb14,
+ freeMb15,
+ freeMb16,
+ freeMb17,
+ freeMb18,
+ freeMb19,
+ freeMbCash = 100,
+ freeMbNone = 101
+};
+//-----------------------------------------------------------------------------
+class IA_PHASE {
+public:
+ IA_PHASE();
+ ~IA_PHASE();
+
+ void SetPhase1();
+ void SetPhase2();
+ void SetPhase3();
+ void SetPhase4();
+ int GetPhase() const;
+
+ void UpdateTime();
+ const UTIME & GetTime() const;
+
+ #ifdef IA_PHASE_DEBUG
+ void SetUserLogin(const std::string & login);
+ void SetLogFileName(const std::string & logFileName);
+ #endif
+
+private:
+ int phase;
+ UTIME phaseTime;
+
+ #ifdef IA_PHASE_DEBUG
+ void WritePhaseChange(int newPhase);
+ std::string log;
+ std::string login;
+ FILE * flog;
+ #endif
+};
+//-----------------------------------------------------------------------------
+struct IA_USER {
+ IA_USER()
+ : login(),
+ user(NULL),
+ phase(),
+ lastSendAlive(0),
+ rnd(static_cast<uint32_t>(random())),
+ port(0),
+ ctx(),
+ messagesToSend(),
+ protoVer(0),
+ password("NO 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);
+
+ #ifdef IA_DEBUG
+ aliveSent = false;
+ #endif
+ }
+
+ IA_USER(const IA_USER & u)
+ : login(u.login),
+ user(u.user),
+ phase(u.phase),
+ lastSendAlive(u.lastSendAlive),
+ rnd(u.rnd),
+ port(u.port),
+ ctx(),
+ messagesToSend(u.messagesToSend),
+ protoVer(u.protoVer),
+ password(u.password)
+ {
+ #ifdef IA_DEBUG
+ aliveSent = u.aliveSent;
+ #endif
+ memcpy(&ctx, &u.ctx, sizeof(BLOWFISH_CTX));
+ }
+
+ IA_USER(const std::string & l,
+ CONST_USER_PTR u,
+ uint16_t p,
+ int ver)
+ : login(l),
+ user(u),
+ phase(),
+ lastSendAlive(0),
+ rnd(static_cast<uint32_t>(random())),
+ port(p),
+ ctx(),
+ messagesToSend(),
+ protoVer(ver),
+ password(user->GetProperty().password.Get())
+ {
+ unsigned char keyL[PASSWD_LEN];
+ memset(keyL, 0, PASSWD_LEN);
+ strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+ Blowfish_Init(&ctx, keyL, PASSWD_LEN);
+
+ #ifdef IA_DEBUG
+ aliveSent = false;
+ #endif
+ }
+
+ std::string login;
+ CONST_USER_PTR user;
+ IA_PHASE phase;
+ UTIME lastSendAlive;
+ uint32_t rnd;
+ uint16_t port;
+ BLOWFISH_CTX ctx;
+ std::list<STG_MSG> messagesToSend;
+ int protoVer;
+ std::string password;
+ #ifdef IA_DEBUG
+ bool aliveSent;
+ #endif
+
+private:
+ IA_USER & operator=(const IA_USER & rvalue);
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA_SETTINGS {
+public:
+ AUTH_IA_SETTINGS();
+ virtual ~AUTH_IA_SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ UTIME GetUserDelay() const { return UTIME(userDelay); }
+ UTIME GetUserTimeout() const { return UTIME(userTimeout); }
+ uint16_t GetUserPort() const { return port; }
+ FREEMB GetFreeMbShowType() const { return freeMbShowType; }
+ bool LogProtocolErrors() const { return logProtocolErrors; }
+
+private:
+ int userDelay;
+ int userTimeout;
+ uint16_t port;
+ std::string errorStr;
+ FREEMB freeMbShowType;
+ bool logProtocolErrors;
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA;
+//-----------------------------------------------------------------------------
+class DEL_USER_NOTIFIER: public NOTIFIER_BASE<USER_PTR> {
+public:
+ explicit DEL_USER_NOTIFIER(AUTH_IA & a) : auth(a) {}
+ virtual ~DEL_USER_NOTIFIER() {}
+
+ void Notify(const USER_PTR & user);
+private:
+ DEL_USER_NOTIFIER(const DEL_USER_NOTIFIER & rvalue);
+ DEL_USER_NOTIFIER & operator=(const DEL_USER_NOTIFIER & rvalue);
+
+ AUTH_IA & auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA :public AUTH {
+friend class DEL_USER_NOTIFIER;
+public:
+ AUTH_IA();
+ virtual ~AUTH_IA();
+
+ void SetUsers(USERS * u) { users = u; }
+ void SetStgSettings(const SETTINGS * s) { stgSettings = s; }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & ms);
+ bool IsRunning() { return isRunningRunTimeouter || isRunningRun; }
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return "InetAccess authorization plugin v.1.4"; }
+ uint16_t GetStartPosition() const { return 30; }
+ uint16_t GetStopPosition() const { return 30; }
+
+ int SendMessage(const STG_MSG & msg, uint32_t ip) const;
+
+private:
+ AUTH_IA(const AUTH_IA & rvalue);
+ AUTH_IA & operator=(const AUTH_IA & rvalue);
+
+ static void * Run(void *);
+ static void * RunTimeouter(void * d);
+ int PrepareNet();
+ int FinalizeNet();
+ void DelUser(USER_PTR u);
+ int RecvData(char * buffer, int bufferSize);
+ int CheckHeader(const char * buffer, uint32_t sip, int * protoVer);
+ int PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, USER_PTR user);
+
+ int Process_CONN_SYN_6(CONN_SYN_6 * connSyn, IA_USER * iaUser, uint32_t sip);
+ int Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip);
+ int Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip);
+
+ int Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip);
+ int Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip);
+ int Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip);
+
+ int Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t sip);
+ int Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip);
+ int Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t sip);
+
+ int Process_DISCONN_SYN_6(DISCONN_SYN_6 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+ int Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+ int Process_DISCONN_SYN_8(DISCONN_SYN_8 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+
+ int Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnSyn,
+ IA_USER * iaUser,
+ uint32_t sip,
+ std::map<uint32_t, IA_USER>::iterator it);
+ int Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnSyn,
+ IA_USER * iaUser,
+ uint32_t sip,
+ std::map<uint32_t, IA_USER>::iterator it);
+ int Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnSyn,
+ IA_USER * iaUser,
+ uint32_t sip,
+ std::map<uint32_t, IA_USER>::iterator it);
+
+ int Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
+ int Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
+ int Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
+
+ int Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip);
+ int Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip);
+ int Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip);
+
+ int Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
+ int Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
+ int Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
+
+ int Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+ int Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+ int Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+
+ int Timeouter();
+
+ int SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text);
+ int Send(uint32_t ip, uint16_t port, const char * buffer, size_t len);
+ int RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+ int RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+ int RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+
+ BLOWFISH_CTX ctxS; //for loginS
+
+ mutable std::string errorStr;
+ AUTH_IA_SETTINGS iaSettings;
+ MODULE_SETTINGS settings;
+
+ bool nonstop;
+
+ bool isRunningRun;
+ bool isRunningRunTimeouter;
+
+ USERS * users;
+ const SETTINGS * stgSettings;
+
+ mutable std::map<uint32_t, IA_USER> ip2user;
+
+ pthread_t recvThread;
+ pthread_t timeouterThread;
+ mutable pthread_mutex_t mutex;
+
+ int listenSocket;
+
+ CONN_SYN_ACK_6 connSynAck6;
+ CONN_SYN_ACK_8 connSynAck8;
+
+ DISCONN_SYN_ACK_6 disconnSynAck6;
+ DISCONN_SYN_ACK_8 disconnSynAck8;
+
+ ALIVE_SYN_6 aliveSyn6;
+ ALIVE_SYN_8 aliveSyn8;
+ FIN_6 fin6;
+ FIN_8 fin8;
+
+ std::map<std::string, int> packetTypes;
+
+ uint32_t enabledDirs;
+
+ DEL_USER_NOTIFIER onDelUserNotifier;
+
+ PLUGIN_LOGGER logger;
+
+ friend class UnauthorizeUser;
+};
+//-----------------------------------------------------------------------------
+class UnauthorizeUser : std::unary_function<const std::pair<uint32_t, IA_USER> &, void> {
+ public:
+ explicit UnauthorizeUser(AUTH_IA * a) : auth(a) {}
+ UnauthorizeUser(const UnauthorizeUser & rvalue) : auth(rvalue.auth) {}
+ void operator()(const std::pair<uint32_t, IA_USER> & p)
+ {
+ auth->users->Unauthorize(p.second.user->GetLogin(), auth);
+ }
+ private:
+ UnauthorizeUser & operator=(const UnauthorizeUser & rvalue);
+
+ AUTH_IA * auth;
+};
+//-----------------------------------------------------------------------------
+inline
+void DEL_USER_NOTIFIER::Notify(const USER_PTR & user)
+{
+ auth.DelUser(user);
+}
+
+#endif
--- /dev/null
+if ( BUILD_MOD_CAP_NF )
+ add_subdirectory ( cap_nf )
+endif ( BUILD_MOD_CAP_NF )
+
+if ( BUILD_MOD_CAP_ETHER_LINUX )
+ add_subdirectory ( ether_linux )
+endif ( BUILD_MOD_CAP_ETHER_LINUX )
+
+if ( BUILD_MOD_CAP_ETHER_FREEBSD )
+ add_subdirectory ( ether_freebsd )
+endif ( BUILD_MOD_CAP_ETHER_FREEBSD )
+
+if ( BUILD_MOD_CAP_DIVERT )
+ add_subdirectory ( divert_freebsd )
+endif ( BUILD_MOD_CAP_DIVERT )
+
+if ( BUILD_MOD_CAP_PCAP )
+ add_subdirectory ( pcap )
+endif ( BUILD_MOD_CAP_PCAP )
+
+if ( BUILD_MOD_CAP_NFQUEUE )
+ add_subdirectory ( nfqueue )
+endif ( BUILD_MOD_CAP_NFQUEUE )
--- /dev/null
+set ( CPP_FILES cap_nf.cpp )
+
+add_library ( mod_cap_nf MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_nf logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.2 2008/12/04 17:04:41 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_nf.so
+
+SRCS = ./cap_nf.cpp
+
+LIBS += $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.11 $
+$Date: 2010/09/10 06:41:06 $
+$Author: faust $
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include <vector>
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "cap_nf.h"
+
+namespace
+{
+PLUGIN_CREATOR<NF_CAP> cnc;
+}
+
+extern "C" PLUGIN * GetPlugin();
+
+PLUGIN * GetPlugin()
+{
+return cnc.GetPlugin();
+}
+
+NF_CAP::NF_CAP()
+ : traffCnt(NULL),
+ runningTCP(false),
+ runningUDP(false),
+ stoppedTCP(true),
+ stoppedUDP(true),
+ portT(0),
+ portU(0),
+ sockTCP(-1),
+ sockUDP(-1),
+ logger(GetPluginLogger(GetStgLogger(), "cap_nf"))
+{
+}
+
+NF_CAP::~NF_CAP()
+{
+}
+
+int NF_CAP::ParseSettings()
+{
+std::vector<PARAM_VALUE>::iterator it;
+for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
+ {
+ if (it->param == "TCPPort" && !it->value.empty())
+ {
+ if (str2x(it->value[0], portT))
+ {
+ errorStr = "Invalid TCPPort value";
+ printfd(__FILE__, "Error: Invalid TCPPort value\n");
+ return -1;
+ }
+ continue;
+ }
+ if (it->param == "UDPPort" && !it->value.empty())
+ {
+ if (str2x(it->value[0], portU))
+ {
+ errorStr = "Invalid UDPPort value";
+ printfd(__FILE__, "Error: Invalid UDPPort value\n");
+ return -1;
+ }
+ continue;
+ }
+ printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
+ }
+return 0;
+}
+
+int NF_CAP::Start()
+{
+if (portU > 0)
+ {
+ if (OpenUDP())
+ {
+ return -1;
+ }
+ runningUDP = true;
+ if (pthread_create(&tidUDP, NULL, RunUDP, this))
+ {
+ runningUDP = false;
+ CloseUDP();
+ errorStr = "Cannot create UDP thread";
+ logger("Cannot create UDP thread.");
+ printfd(__FILE__, "Error: Cannot create UDP thread\n");
+ return -1;
+ }
+ }
+if (portT > 0)
+ {
+ if (OpenTCP())
+ {
+ return -1;
+ }
+ runningTCP = true;
+ if (pthread_create(&tidTCP, NULL, RunTCP, this))
+ {
+ runningTCP = false;
+ CloseTCP();
+ logger("Cannot create TCP thread.");
+ errorStr = "Cannot create TCP thread";
+ printfd(__FILE__, "Error: Cannot create TCP thread\n");
+ return -1;
+ }
+ }
+return 0;
+}
+
+int NF_CAP::Stop()
+{
+runningTCP = runningUDP = false;
+if (portU && !stoppedUDP)
+ {
+ CloseUDP();
+ for (int i = 0; i < 25 && !stoppedUDP; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (stoppedUDP)
+ {
+ pthread_join(tidUDP, NULL);
+ }
+ else
+ {
+ if (pthread_kill(tidUDP, SIGUSR1))
+ {
+ errorStr = "Error sending signal to UDP thread";
+ logger("Error sending sugnal to UDP thread.");
+ printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "UDP thread NOT stopped\n");
+ logger("Cannot stop UDP thread.");
+ }
+ }
+if (portT && !stoppedTCP)
+ {
+ CloseTCP();
+ for (int i = 0; i < 25 && !stoppedTCP; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (stoppedTCP)
+ {
+ pthread_join(tidTCP, NULL);
+ }
+ else
+ {
+ if (pthread_kill(tidTCP, SIGUSR1))
+ {
+ errorStr = "Error sending signal to TCP thread";
+ logger("Error sending signal to TCP thread.");
+ printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "TCP thread NOT stopped\n");
+ logger("Cannot stop TCP thread.");
+ }
+ }
+return 0;
+}
+
+bool NF_CAP::OpenUDP()
+{
+struct sockaddr_in sin;
+sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
+if (sockUDP <= 0)
+ {
+ errorStr = "Error opening UDP socket";
+ logger("Cannot create UDP socket: %s", strerror(errno));
+ printfd(__FILE__, "Error: Error opening UDP socket\n");
+ return true;
+ }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portU);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
+ {
+ errorStr = "Error binding UDP socket";
+ logger("Cannot bind UDP socket: %s", strerror(errno));
+ printfd(__FILE__, "Error: Error binding UDP socket\n");
+ return true;
+ }
+return false;
+}
+
+bool NF_CAP::OpenTCP()
+{
+struct sockaddr_in sin;
+sockTCP = socket(PF_INET, SOCK_STREAM, 0);
+if (sockTCP <= 0)
+ {
+ errorStr = "Error opening TCP socket";
+ logger("Cannot create TCP socket: %s", strerror(errno));
+ printfd(__FILE__, "Error: Error opening TCP socket\n");
+ return true;
+ }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portT);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
+ {
+ errorStr = "Error binding TCP socket";
+ logger("Cannot bind TCP socket: %s", strerror(errno));
+ printfd(__FILE__, "Error: Error binding TCP socket\n");
+ return true;
+ }
+if (listen(sockTCP, 1))
+ {
+ errorStr = "Error listening on TCP socket";
+ logger("Cannot listen on TCP socket: %s", strerror(errno));
+ printfd(__FILE__, "Error: Error listening TCP socket\n");
+ return true;
+ }
+return false;
+}
+
+void * NF_CAP::RunUDP(void * c)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+cap->stoppedUDP = false;
+while (cap->runningUDP)
+ {
+ if (!WaitPackets(cap->sockUDP))
+ {
+ continue;
+ }
+
+ // Data
+ struct sockaddr_in sin;
+ socklen_t slen = sizeof(sin);
+ uint8_t buf[BUF_SIZE];
+ ssize_t res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (!cap->runningUDP)
+ break;
+
+ if (res < 0)
+ {
+ cap->logger("recvfrom error: %s", strerror(errno));
+ continue;
+ }
+
+ if (res == 0) // EOF
+ {
+ continue;
+ }
+
+ if (res < 24)
+ {
+ if (errno != EINTR)
+ {
+ cap->errorStr = "Invalid data received";
+ printfd(__FILE__, "Error: Invalid data received through UDP\n");
+ }
+ continue;
+ }
+
+ cap->ParseBuffer(buf, res);
+ }
+cap->stoppedUDP = true;
+return NULL;
+}
+
+void * NF_CAP::RunTCP(void * c)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+cap->stoppedTCP = false;
+while (cap->runningTCP)
+ {
+ if (!WaitPackets(cap->sockTCP))
+ {
+ continue;
+ }
+
+ // Data
+ struct sockaddr_in sin;
+ socklen_t slen = sizeof(sin);
+ int sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (!cap->runningTCP)
+ break;
+
+ if (sd <= 0)
+ {
+ if (sd < 0)
+ cap->logger("accept error: %s", strerror(errno));
+ continue;
+ }
+
+ if (!WaitPackets(sd))
+ {
+ close(sd);
+ continue;
+ }
+
+ uint8_t buf[BUF_SIZE];
+ ssize_t res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
+
+ if (res < 0)
+ cap->logger("recv error: %s", strerror(errno));
+
+ close(sd);
+
+ if (!cap->runningTCP)
+ break;
+
+ if (res == 0) // EOF
+ {
+ continue;
+ }
+
+ // Wrong logic!
+ // Need to check actual data length and wait all data to receive
+ if (res < 24)
+ {
+ continue;
+ }
+
+ cap->ParseBuffer(buf, res);
+ }
+cap->stoppedTCP = true;
+return NULL;
+}
+
+void NF_CAP::ParseBuffer(uint8_t * buf, ssize_t size)
+{
+RAW_PACKET ip;
+NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
+if (htons(hdr->version) != 5)
+ {
+ return;
+ }
+
+int packets = htons(hdr->count);
+
+if (packets < 0 || packets > 30)
+ {
+ return;
+ }
+
+if (24 + 48 * packets != size)
+ {
+ // See 'wrong logic' upper
+ return;
+ }
+
+for (int i = 0; i < packets; ++i)
+ {
+ NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
+
+ ip.rawPacket.header.ipHeader.ip_v = 4;
+ ip.rawPacket.header.ipHeader.ip_hl = 5;
+ ip.rawPacket.header.ipHeader.ip_p = data->proto;
+ ip.dataLen = ntohl(data->octets);
+ ip.rawPacket.header.ipHeader.ip_src.s_addr = data->srcAddr;
+ ip.rawPacket.header.ipHeader.ip_dst.s_addr = data->dstAddr;
+ ip.rawPacket.header.sPort = data->srcPort;
+ ip.rawPacket.header.dPort = data->dstPort;
+
+ traffCnt->Process(ip);
+ }
+}
--- /dev/null
+/*
+ * 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: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.5 $
+$Date: 2009/12/13 12:56:07 $
+$Author: faust $
+*/
+#ifndef __CAP_NF_H__
+#define __CAP_NF_H__
+
+#include <pthread.h>
+
+#include <string>
+#include <cstdint>
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#define VERSION "cap_nf v. 0.4"
+#define START_POS 40
+#define STOP_POS 40
+
+class USERS;
+class USER;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class STORE;
+class SETTINGS;
+
+struct NF_HEADER {
+ uint16_t version; // Protocol version
+ uint16_t count; // Flows count
+ uint32_t uptime; // System uptime
+ uint32_t timestamp; // UNIX timestamp
+ uint32_t nsecs; // Residual nanoseconds
+ uint32_t flowSeq; // Sequence counter
+ uint8_t eType; // Engine type
+ uint8_t eID; // Engine ID
+ uint16_t sInterval; // Sampling mode and interval
+};
+
+struct NF_DATA {
+ uint32_t srcAddr; // Flow source address
+ uint32_t dstAddr; // Flow destination address
+ uint32_t nextHop; // IP addres on next hop router
+ uint16_t inSNMP; // SNMP index of input iface
+ uint16_t outSNMP; // SNMP index of output iface
+ uint32_t packets; // Packets in flow
+ uint32_t octets; // Total number of bytes in flow
+ uint32_t timeStart; // Uptime on first packet in flow
+ uint32_t timeFinish;// Uptime on last packet in flow
+ uint16_t srcPort; // Flow source port
+ uint16_t dstPort; // Flow destination port
+ uint8_t pad1; // 1-byte padding
+ uint8_t TCPFlags; // Cumulative OR of TCP flags
+ uint8_t proto; // IP protocol type (tcp, udp, etc.)
+ uint8_t tos; // IP Type of Service (ToS)
+ uint16_t srcAS; // Source BGP autonomous system number
+ uint16_t dstAS; // Destination BGP autonomus system number
+ uint8_t srcMask; // Source address mask in "slash" notation
+ uint8_t dstMask; // Destination address mask in "slash" notation
+ uint16_t pad2; // 2-byte padding
+};
+
+#define BUF_SIZE (sizeof(NF_HEADER) + 30 * sizeof(NF_DATA))
+
+class NF_CAP : public PLUGIN {
+public:
+ NF_CAP();
+ ~NF_CAP();
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return runningTCP || runningUDP; }
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return VERSION; }
+ uint16_t GetStartPosition() const { return START_POS; }
+ uint16_t GetStopPosition() const { return STOP_POS; }
+
+private:
+ NF_CAP(const NF_CAP & rvalue);
+ NF_CAP & operator=(const NF_CAP & rvalue);
+
+ TRAFFCOUNTER * traffCnt;
+ MODULE_SETTINGS settings;
+ pthread_t tidTCP;
+ pthread_t tidUDP;
+ bool runningTCP;
+ bool runningUDP;
+ bool stoppedTCP;
+ bool stoppedUDP;
+ uint16_t portT;
+ uint16_t portU;
+ int sockTCP;
+ int sockUDP;
+ mutable std::string errorStr;
+ PLUGIN_LOGGER logger;
+
+ static void * RunUDP(void *);
+ static void * RunTCP(void *);
+ void ParseBuffer(uint8_t * buf, ssize_t size);
+
+ bool OpenTCP();
+ bool OpenUDP();
+ void CloseTCP() { close(sockTCP); }
+ void CloseUDP() { close(sockUDP); }
+};
+
+#endif
--- /dev/null
+set ( CPP_FILES divert_cap.cpp )
+
+add_library ( mod_cap_divert MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_divert logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2008/12/04 17:05:21 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_divert.so
+
+SRCS = ./divert_cap.cpp
+
+LIBS += $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.13 $
+$Date: 2010/09/10 06:43:03 $
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cstdlib>
+#include <csignal>
+
+#include <algorithm>
+#include <vector>
+
+#include "stg/common.h"
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "divert_cap.h"
+
+#define BUFF_LEN (16384) /* max mtu -> lo=16436 TODO why?*/
+
+//-----------------------------------------------------------------------------
+struct DIVERT_DATA {
+int sock;
+short int port;
+char iface[10];
+};
+//-----------------------------------------------------------------------------
+pollfd pollddiv;
+DIVERT_DATA cddiv; //capture data
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<DIVERT_CAP> dcc;
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return dcc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string DIVERT_CAP::GetVersion() const
+{
+return "cap_divert v.1.0";
+}
+//-----------------------------------------------------------------------------
+DIVERT_CAP::DIVERT_CAP()
+ : port(0),
+ disableForwarding(false),
+ nonstop(false),
+ isRunning(false),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "cap_divert"))
+{
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (DivertCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ printfd(__FILE__, "Cannot open socket\n");
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+DivertCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * DIVERT_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
+dc->isRunning = true;
+
+char buffer[pcktSize + 14];
+while (dc->nonstop)
+ {
+ RAW_PACKET rp;
+ dc->DivertCapRead(buffer, sizeof(buffer), NULL);
+
+ if (buffer[12] != 0x8)
+ continue;
+
+ memcpy(rp.rawPacket.pckt, &buffer[14], pcktSize);
+
+ dc->traffCnt->Process(rp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen()
+{
+memset(&pollddiv, 0, sizeof(pollddiv));
+memset(&cddiv, 0, sizeof(DIVERT_DATA));
+
+strcpy(cddiv.iface, "foo");
+cddiv.port = port;
+
+DivertCapOpen(0);
+pollddiv.events = POLLIN;
+pollddiv.fd = cddiv.sock;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen(int)
+{
+int ret;
+cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+if (cddiv.sock < 0)
+ {
+ errorStr = "Create divert socket error.";
+ logger("Cannot create a socket: %s", strerror(errno));
+ printfd(__FILE__, "Cannot create divert socket\n");
+ return -1;
+ }
+
+struct sockaddr_in divAddr;
+
+memset(&divAddr, 0, sizeof(divAddr));
+
+divAddr.sin_family = AF_INET;
+divAddr.sin_port = htons(cddiv.port);
+divAddr.sin_addr.s_addr = INADDR_ANY;
+
+ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
+
+if (ret < 0)
+ {
+ errorStr = "Bind divert socket error.";
+ logger("Cannot bind the scoket: %s", strerror(errno));
+ printfd(__FILE__, "Cannot bind divert socket\n");
+ return -1;
+ }
+
+return cddiv.sock;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
+{
+poll(&pollddiv, 1, -1);
+
+if (pollddiv.revents & POLLIN)
+ {
+ DivertCapRead(b, blen, iface, 0);
+ pollddiv.revents = 0;
+ return 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
+{
+static char buf[BUFF_LEN];
+static struct sockaddr_in divertaddr;
+static int bytes;
+static socklen_t divertaddrSize = sizeof(divertaddr);
+
+if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
+ 0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
+ {
+ memcpy(b + 14, buf, blen - 14);
+ b[12] = 0x8;
+
+ if (iface)
+ *iface = cddiv.iface;
+
+ if (!disableForwarding)
+ {
+ if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
+ logger("sendto error: %s", strerror(errno));
+ }
+ }
+else
+ {
+ if (bytes < 0)
+ logger("recvfrom error: %s", strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapClose()
+{
+close(cddiv.sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::ParseSettings()
+{
+int p;
+PARAM_VALUE pv;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+ {
+ p = 15701;
+ }
+else if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+
+port = p;
+
+bool d = false;
+pv.param = "DisableForwarding";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+ {
+ disableForwarding = false;
+ }
+else if (ParseYesNo(pvi->value[0], &d))
+ {
+ errorStr = "Cannot parse parameter \'DisableForwarding\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'DisableForwarding'\n");
+ return -1;
+ }
+
+disableForwarding = d;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.6 $
+$Date: 2009/06/23 11:32:27 $
+*/
+
+#ifndef DIVERT_CAP_H
+#define DIVERT_CAP_H
+
+#include <pthread.h>
+
+#include <string>
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+
+//-----------------------------------------------------------------------------
+class DIVERT_CAP : public PLUGIN {
+public:
+ DIVERT_CAP();
+ virtual ~DIVERT_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+private:
+ DIVERT_CAP(const DIVERT_CAP & rvalue);
+ DIVERT_CAP & operator=(const DIVERT_CAP & rvalue);
+
+ static void * Run(void *);
+
+ int DivertCapOpen();
+ int DivertCapOpen(int n);
+ int DivertCapRead(char * buffer, int blen, char ** iface);
+ int DivertCapRead(char * buffer, int blen, char ** iface, int n);
+ int DivertCapClose();
+
+ MODULE_SETTINGS settings;
+
+ int port;
+ bool disableForwarding;
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+
+ bool nonstop;
+ bool isRunning;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+set ( CPP_FILES ether_cap.cpp )
+
+add_library ( mod_cap_bpf MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_bpf logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.7 2008/12/04 17:06:56 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_bpf.so
+
+SRCS = ./ether_cap.cpp
+
+LIBS += $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.19 $
+$Date: 2009/03/24 11:20:15 $
+$Author: faust $
+*/
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <csignal>
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+
+#include "ether_cap.h"
+
+//#define CAP_DEBUG 1
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<BPF_CAP> bcc;
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return bcc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int BPF_CAP_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+iface.erase(iface.begin(), iface.end());
+
+if (s.moduleParams.empty())
+ {
+ errorStr = "Parameter \'iface\' not found.";
+ printfd(__FILE__, "Parameter 'iface' not found\n");
+ return -1;
+ }
+
+for (unsigned i = 0; i < s.moduleParams.size(); i++)
+ {
+ if (s.moduleParams[i].param != "iface")
+ {
+ errorStr = "Parameter \'" + s.moduleParams[i].param + "\' unrecognized.";
+ printfd(__FILE__, "Invalid parameter: '%s'\n", s.moduleParams[i].param.c_str());
+ return -1;
+ }
+ for (unsigned j = 0; j < s.moduleParams[i].value.size(); j++)
+ {
+ iface.push_back(s.moduleParams[i].value[j]);
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+std::string BPF_CAP_SETTINGS::GetIface(unsigned int num)
+{
+if (num >= iface.size())
+ {
+ return "";
+ }
+return iface[num];
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string BPF_CAP::GetVersion() const
+{
+return "cap_bpf v.1.0";
+}
+//-----------------------------------------------------------------------------
+BPF_CAP::BPF_CAP()
+ : nonstop(false),
+ isRunning(false),
+ capSock(-1),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "cap_bpf"))
+{
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::ParseSettings()
+{
+int ret = capSettings.ParseSettings(settings);
+if (ret)
+ {
+ errorStr = capSettings.GetStrError();
+ return ret;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (BPFCapOpen() < 0)
+ {
+ //errorStr = "Cannot open bpf device!";
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+BPFCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * BPF_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+BPF_CAP * dc = static_cast<BPF_CAP *>(d);
+dc->isRunning = true;
+
+uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96
+
+RAW_PACKET * rpp = (RAW_PACKET *)&hdr[14];
+memset(hdr, 0, sizeof(hdr));
+
+rpp->dataLen = -1;
+char * iface;
+
+while (dc->nonstop)
+ {
+ if (dc->BPFCapRead((char*)&hdr, 68 + 14, &iface))
+ continue;
+
+ if (!(hdr[12] == 0x8 && hdr[13] == 0x0))
+ continue;
+
+ dc->traffCnt->Process(*rpp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapOpen()
+{
+int i = 0;
+BPF_DATA bd;
+pollfd pd;
+
+while ((bd.iface = capSettings.GetIface(i)) != "")
+ {
+ bpfData.push_back(bd);
+ if (BPFCapOpen(&bpfData[i]) < 0)
+ {
+ return -1;
+ }
+
+ pd.events = POLLIN;
+ pd.fd = bpfData[i].fd;
+ polld.push_back(pd);
+ i++;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapOpen(BPF_DATA * bd)
+{
+char devbpf[20];
+int i = 0;
+int l = BUFF_LEN;
+int im = 1;
+struct ifreq ifr;
+
+do
+ {
+ sprintf(devbpf, "/dev/bpf%d", i);
+ i++;
+ bd->fd = open(devbpf, O_RDONLY);
+ } while(bd->fd < 0 && errno == EBUSY);
+
+if (bd->fd < 0)
+ {
+ errorStr = "Can't capture packets. Open bpf device for " + bd->iface + " error.";
+ logger("Cannot open device for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+ printfd(__FILE__, "Cannot open BPF device\n");
+ return -1;
+ }
+
+strncpy(ifr.ifr_name, bd->iface.c_str(), sizeof(ifr.ifr_name));
+
+if (ioctl(bd->fd, BIOCSBLEN, (caddr_t)&l) < 0)
+ {
+ errorStr = bd->iface + " BIOCSBLEN " + std::string(strerror(errno));
+ logger("ioctl (BIOCSBLEN) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+if (ioctl(bd->fd, BIOCSETIF, (caddr_t)&ifr) < 0)
+ {
+ errorStr = bd->iface + " BIOCSETIF " + std::string(strerror(errno));
+ logger("ioctl (BIOCSETIF) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+if (ioctl(bd->fd, BIOCIMMEDIATE, &im) < 0)
+ {
+ errorStr = bd->iface + " BIOCIMMEDIATE " + std::string(strerror(errno));
+ logger("ioctl (BIOCIMMEDIATE) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+return bd->fd;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapClose()
+{
+for (unsigned int i = 0; i < bpfData.size(); i++)
+ close(bpfData[i].fd);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char ** capIface)
+{
+poll(&polld[0], polld.size(), -1);
+
+for (unsigned int i = 0; i < polld.size(); i++)
+ {
+ if (polld[i].revents & POLLIN)
+ {
+ if (BPFCapRead(buffer, blen, capIface, &bpfData[i]))
+ {
+ polld[i].revents = 0;
+ continue;
+ }
+ polld[i].revents = 0;
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char **, BPF_DATA * bd)
+{
+if (bd->canRead)
+ {
+ bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
+ if (bd->r < 0)
+ {
+ logger("read error: %s", strerror(errno));
+ struct timespec ts = {0, 20000000};
+ nanosleep(&ts, NULL);
+ return -1;
+ }
+
+ bd->p = bd->buffer;
+ bd->bh = (struct bpf_hdr*)bd->p;
+ bd->canRead = 0;
+ }
+
+if(bd->r > bd->sum)
+ {
+ memcpy(buffer, (char*)(bd->p) + bd->bh->bh_hdrlen, blen);
+
+ bd->sum += BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+ bd->p = bd->p + BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+ bd->bh = (struct bpf_hdr*)bd->p;
+ }
+
+if(bd->r <= bd->sum)
+ {
+ bd->canRead = 1;
+ bd->sum = 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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
+ */
+
+ /*
+ $Revision: 1.11 $
+ $Date: 2009/06/23 11:32:27 $
+ $Author: faust $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#ifndef ETHER_CAP_H
+#define ETHER_CAP_H
+
+#include <pthread.h>
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#define BUFF_LEN (128)
+
+class TRAFFCOUNTER;
+
+//-----------------------------------------------------------------------------
+struct BPF_DATA {
+ BPF_DATA()
+ {
+ fd = 0;
+ p = NULL;
+ r = 0;
+ sum = 0;
+ memset(buffer, 0, BUFF_LEN);
+ bh = NULL;
+ canRead = 1;
+ iface = "";
+ };
+
+ BPF_DATA(const BPF_DATA & bd)
+ {
+ fd = bd.fd;
+ p = bd.p;
+ r = bd.r;
+ sum = bd.sum;
+ memcpy(buffer, bd.buffer, BUFF_LEN);
+ bh = bd.bh;
+ canRead = bd.canRead;
+ iface = bd.iface;
+ };
+
+int fd;
+uint8_t * p;
+int r;
+int sum;
+uint8_t buffer[BUFF_LEN];
+struct bpf_hdr * bh;
+int canRead;
+std::string iface;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP_SETTINGS {
+public:
+ virtual ~BPF_CAP_SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ std::string GetIface(unsigned int num);
+
+private:
+ std::vector<std::string> iface;
+ mutable std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP : public PLUGIN {
+public:
+ BPF_CAP();
+ virtual ~BPF_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+private:
+ BPF_CAP(const BPF_CAP & rvalue);
+ BPF_CAP & operator=(const BPF_CAP & rvalue);
+
+ static void * Run(void *);
+ int BPFCapOpen();
+ int BPFCapOpen(BPF_DATA * bd);
+ int BPFCapClose();
+ int BPFCapRead(char * buffer, int blen, char ** iface);
+ int BPFCapRead(char * buffer, int blen, char ** iface, BPF_DATA * bd);
+
+ BPF_CAP_SETTINGS capSettings;
+
+ mutable std::string errorStr;
+
+ std::vector<BPF_DATA> bpfData;
+ std::vector<pollfd> polld;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ int capSock;
+ MODULE_SETTINGS settings;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+set ( CPP_FILES ether_cap.cpp )
+
+add_library ( mod_cap_ether MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_ether logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:07:37 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_ether.so
+
+SRCS = ./ether_cap.cpp
+
+LIBS += $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+/*
+$Revision: 1.23 $
+$Date: 2009/12/13 13:45:13 $
+*/
+
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <csignal>
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+
+#include "ether_cap.h"
+
+//#define CAP_DEBUG 1
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<ETHER_CAP> ecc;
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return ecc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string ETHER_CAP::GetVersion() const
+{
+return "cap_ether v.1.2";
+}
+//-----------------------------------------------------------------------------
+ETHER_CAP::ETHER_CAP()
+ : nonstop(false),
+ isRunning(false),
+ capSock(-1),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "cap_ether"))
+{
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (EthCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ printfd(__FILE__, "Cannot open socket\n");
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (isRunning)
+ {
+ errorStr = "ETHER_CAP not stopped.";
+ logger("Cannot stop thread.");
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ else
+ {
+ pthread_join(thread, NULL);
+ }
+ }
+
+EthCapClose();
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * ETHER_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+ETHER_CAP * dc = static_cast<ETHER_CAP *>(d);
+dc->isRunning = true;
+
+struct ETH_IP
+{
+uint16_t ethHdr[8];
+RAW_PACKET rp;
+char padding[4];
+char padding1[8];
+};
+
+char ethip[sizeof(ETH_IP)];
+
+memset(ðip, 0, sizeof(ETH_IP));
+
+ETH_IP * ethIP = static_cast<ETH_IP *>(static_cast<void *>(ðip));
+ethIP->rp.dataLen = -1;
+
+char * iface = NULL;
+
+while (dc->nonstop)
+ {
+ if (dc->EthCapRead(ðip, 68 + 14, &iface))
+ {
+ continue;
+ }
+
+ if (ethIP->ethHdr[7] != 0x8)
+ continue;
+
+ dc->traffCnt->Process(ethIP->rp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapOpen()
+{
+capSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+if (capSock < 0)
+ logger("Cannot create socket: %s", strerror(errno));
+return capSock;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapClose()
+{
+close(capSock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapRead(void * buffer, int blen, char **)
+{
+struct sockaddr_ll addr;
+int addrLen;
+
+if (!WaitPackets(capSock))
+ {
+ return ENODATA;
+ }
+
+addrLen = sizeof(addr);
+
+if (recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen) < 0)
+ {
+ logger("recvfrom error: %s", strerror(errno));
+ return ENODATA;
+ }
+
+return 0;
+}
--- /dev/null
+/*
+ * 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
+ */
+
+ /*
+ $Revision: 1.12 $
+ $Date: 2009/12/13 13:45:13 $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#ifndef ETHER_CAP_H
+#define ETHER_CAP_H
+
+#include <pthread.h>
+
+#include <string>
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+
+class TRAFFCOUNTER;
+
+//-----------------------------------------------------------------------------
+class ETHER_CAP : public PLUGIN {
+public:
+ ETHER_CAP();
+ virtual ~ETHER_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ int ParseSettings() { return 0; }
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+private:
+ ETHER_CAP(const ETHER_CAP & rvalue);
+ ETHER_CAP & operator=(const ETHER_CAP & rvalue);
+
+ static void * Run(void *);
+ int EthCapOpen();
+ int EthCapClose();
+ int EthCapRead(void * buffer, int blen, char ** iface);
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ int capSock;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+find_package ( NFQueue REQUIRED )
+find_package ( NFNetLink REQUIRED )
+find_package ( MNL REQUIRED )
+
+set ( CPP_FILES nfqueue.cpp )
+
+add_library ( mod_cap_nfqueue MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_nfqueue logger common NF::Queue NF::NetLink MNL::MNL )
--- /dev/null
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_nfqueue.so
+
+SRCS = ./nfqueue.cpp
+
+LIBS += $(NFQ_LDFLAGS) $(NETLINK_LDFLAGS) $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+*/
+
+#include "nfqueue.h"
+
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+extern "C" {
+
+#include <linux/netfilter.h> /* Defines verdicts (NF_ACCEPT, etc) */
+#include <libnetfilter_queue/libnetfilter_queue.h>
+
+}
+
+#include <cerrno>
+#include <csignal>
+
+#include <arpa/inet.h> // ntohl
+
+#include <unistd.h> // read
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+
+PLUGIN_CREATOR<NFQ_CAP> ncc;
+
+int Callback(struct nfq_q_handle * queueHandle, struct nfgenmsg * /*msg*/,
+ struct nfq_data * nfqData, void *data)
+{
+int id = 0;
+
+struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
+if (packetHeader == NULL)
+ return 0;
+
+id = ntohl(packetHeader->packet_id);
+
+unsigned char * payload = NULL;
+
+if (nfq_get_payload(nfqData, &payload) < 0 || payload == NULL)
+ return id;
+
+RAW_PACKET packet;
+
+memcpy(&packet.rawPacket, payload, sizeof(packet.rawPacket));
+
+NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
+
+cap->Process(packet);
+
+return nfq_set_verdict(queueHandle, id, NF_ACCEPT, 0, NULL);
+}
+
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return ncc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string NFQ_CAP::GetVersion() const
+{
+return "cap_nfqueue v.1.0";
+}
+//-----------------------------------------------------------------------------
+NFQ_CAP::NFQ_CAP()
+ : nonstop(false),
+ isRunning(false),
+ queueNumber(0),
+ nfqHandle(NULL),
+ queueHandle(NULL),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "cap_nfqueue"))
+{
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::ParseSettings()
+{
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "queueNumber" && !settings.moduleParams[i].value.empty())
+ if (str2x(settings.moduleParams[i].value[0], queueNumber) < 0)
+ {
+ errorStr = "Queue number should be a number. Got: '" + settings.moduleParams[i].param + "'";
+ logger(errorStr);
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+nfqHandle = nfq_open();
+if (nfqHandle == NULL)
+ {
+ errorStr = "Failed to initialize netfilter queue.";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
+ {
+ errorStr = "Failed to unbind netfilter queue from IP handling.";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
+ {
+ errorStr = "Failed to bind netfilter queue to IP handling.";
+ logger(errorStr);
+ return -1;
+ }
+
+queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
+if (queueHandle == NULL)
+ {
+ errorStr = "Failed to create queue " + x2str(queueNumber) + ".";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
+ {
+ errorStr = "Failed to set queue " + x2str(queueNumber) + " mode.";
+ logger(errorStr);
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (isRunning)
+ {
+ errorStr = "NFQ_CAP not stopped.";
+ logger("Cannot stop thread.");
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ }
+
+pthread_join(thread, NULL);
+
+nfq_destroy_queue(queueHandle);
+nfq_close(nfqHandle);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * NFQ_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
+dc->isRunning = true;
+
+int fd = nfq_fd(dc->nfqHandle);
+char buf[4096];
+
+while (dc->nonstop)
+ {
+ if (!WaitPackets(fd))
+ continue;
+
+ int rv = read(fd, buf, sizeof(buf));
+ if (rv < 0)
+ {
+ dc->errorStr = std::string("Read error: ") + strerror(errno);
+ dc->logger(dc->errorStr);
+ break;
+ }
+ nfq_handle_packet(dc->nfqHandle, buf, rv);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void NFQ_CAP::Process(const RAW_PACKET & packet)
+{
+traffCnt->Process(packet);
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+*/
+
+#ifndef NFQ_CAP_H
+#define NFQ_CAP_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pthread.h>
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+struct RAW_PACKET;
+
+class TRAFFCOUNTER;
+
+struct nfq_handle;
+struct nfq_q_handle;
+
+class NFQ_CAP : public PLUGIN {
+public:
+ NFQ_CAP();
+ virtual ~NFQ_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+ void Process(const RAW_PACKET & packet);
+
+private:
+ NFQ_CAP(const NFQ_CAP & rvalue);
+ NFQ_CAP & operator=(const NFQ_CAP & rvalue);
+
+ static void * Run(void *);
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+
+ size_t queueNumber;
+
+ struct nfq_handle * nfqHandle;
+ struct nfq_q_handle * queueHandle;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+find_package ( PCap REQUIRED )
+
+set ( CPP_FILES pcap_cap.cpp )
+
+add_library ( mod_cap_pcap MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_cap_pcap logger common PCap::PCap )
--- /dev/null
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_pcap.so
+
+SRCS = ./pcap_cap.cpp
+
+LIBS += -lpcap $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+*/
+
+#include "pcap_cap.h"
+
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+#include <signal.h>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<PCAP_CAP> pcc;
+
+const size_t SNAP_LEN = 1518;
+const size_t ETHER_ADDR_LEN = 6;
+
+struct ETH
+{
+u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
+u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
+u_short ether_type; /* IP? ARP? RARP? etc */
+};
+
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return pcc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string PCAP_CAP::GetVersion() const
+{
+return "pcap_cap v.1.0";
+}
+//-----------------------------------------------------------------------------
+PCAP_CAP::PCAP_CAP()
+ : nonstop(false),
+ isRunning(false),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "pcap_cap"))
+{
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::ParseSettings()
+{
+devices.erase(devices.begin(), devices.end());
+
+if (settings.moduleParams.empty())
+ {
+ devices.push_back(DEV());
+ logger("Defaulting to pseudo-device 'any'.");
+ return 0;
+ }
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "interfaces")
+ for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+ devices.push_back(DEV(settings.moduleParams[i].value[j]));
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "filters")
+ for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+ if (j < devices.size())
+ devices[j].filterExpression = settings.moduleParams[i].value[j];
+
+if (devices.empty())
+ {
+ devices.push_back(DEV());
+ logger("Defaulting to pseudo-device 'all'.");
+ return 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+DEV_MAP::iterator it(devices.begin());
+while (it != devices.end())
+ {
+ bpf_u_int32 mask;
+ bpf_u_int32 net;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /* get network number and mask associated with capture device */
+ if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1)
+ {
+ errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* open capture device */
+ it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf);
+ if (it->handle == NULL)
+ {
+ errorStr = "Couldn't open device " + it->device + ": " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ if (pcap_setnonblock(it->handle, true, errbuf) == -1)
+ {
+ errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* make sure we're capturing on an Ethernet device [2] */
+ if (pcap_datalink(it->handle) != DLT_EN10MB)
+ {
+ errorStr = it->device + " is not an Ethernet";
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* compile the filter expression */
+ if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1)
+ {
+ errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* apply the compiled filter */
+ if (pcap_setfilter(it->handle, &it->filter) == -1)
+ {
+ errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ it->fd = pcap_get_selectable_fd(it->handle);
+ if (it->fd == -1)
+ {
+ errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ ++it;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (isRunning)
+ {
+ errorStr = "PCAP_CAP not stopped.";
+ logger("Cannot stop thread.");
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ }
+
+pthread_join(thread, NULL);
+
+for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it)
+ {
+ pcap_freecode(&it->filter);
+ pcap_close(it->handle);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * PCAP_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+PCAP_CAP * dc = static_cast<PCAP_CAP *>(d);
+dc->isRunning = true;
+
+fd_set fds;
+FD_ZERO(&fds);
+int maxFd = 0;
+for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it)
+ {
+ FD_SET(it->fd, &fds);
+ maxFd = std::max(maxFd, it->fd);
+ }
+
+while (dc->nonstop)
+ {
+ fd_set rfds = fds;
+ struct timeval tv = {0, 500000};
+
+ if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0)
+ dc->TryRead(rfds);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+
+void PCAP_CAP::TryRead(const fd_set & set)
+{
+for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it)
+ if (FD_ISSET(it->fd, &set))
+ TryReadDev(*it);
+}
+
+void PCAP_CAP::TryReadDev(const DEV & dev)
+{
+struct pcap_pkthdr * header;
+const u_char * packet;
+if (pcap_next_ex(dev.handle, &header, &packet) == -1)
+ {
+ printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle));
+ return;
+ }
+
+const ETH * eth = reinterpret_cast<const ETH *>(packet);
+if (eth->ether_type != 0x8)
+ return;
+
+RAW_PACKET ip;
+memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket));
+traffCnt->Process(ip);
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+*/
+
+#ifndef PCAP_CAP_H
+#define PCAP_CAP_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pcap.h>
+#include <pthread.h>
+#include <sys/select.h>
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+
+class TRAFFCOUNTER;
+
+struct DEV
+{
+ DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {}
+ DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {}
+ DEV(const std::string & d, const std::string & f)
+ : device(d), filterExpression(f), handle(NULL), fd(-1) {}
+
+ std::string device;
+ std::string filterExpression;
+ pcap_t * handle;
+ struct bpf_program filter;
+ int fd;
+};
+
+typedef std::vector<DEV> DEV_MAP;
+
+class PCAP_CAP : public PLUGIN {
+public:
+ PCAP_CAP();
+ virtual ~PCAP_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+private:
+ PCAP_CAP(const PCAP_CAP & rvalue);
+ PCAP_CAP & operator=(const PCAP_CAP & rvalue);
+
+ void TryRead(const fd_set & set);
+ void TryReadDev(const DEV & dev);
+
+ static void * Run(void *);
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+ DEV_MAP devices;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+if ( BUILD_MOD_SGCONFIG )
+ add_subdirectory ( sgconfig )
+endif ( BUILD_MOD_SGCONFIG )
+
+if ( BUILD_MOD_RPCCONFIG )
+ add_subdirectory ( rpcconfig )
+endif ( BUILD_MOD_RPCCONFIG )
--- /dev/null
+find_package ( XMLRPC REQUIRED c++ abyss-server )
+
+set ( CPP_FILES rpcconfig.cpp
+ user_helper.cpp
+ tariff_helper.cpp
+ info_methods.cpp
+ users_methods.cpp
+ tariffs_methods.cpp
+ admins_methods.cpp
+ messages_methods.cpp )
+
+add_library ( mod_conf_rpc MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_conf_rpc scriptexecuter logger common xmlrpc_server_abyss++ )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2009/08/03 10:25:40 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_rpc.so
+
+SRCS = ./rpcconfig.cpp \
+ ./user_helper.cpp \
+ ./tariff_helper.cpp \
+ ./info_methods.cpp \
+ ./users_methods.cpp \
+ ./tariffs_methods.cpp \
+ ./admins_methods.cpp \
+ ./messages_methods.cpp
+
+LIBS += $(XMLRPC_LDFLAGS) \
+ $(LIB_THREAD) \
+ $(LIBICONV)
+
+STGLIBS = common \
+ logger \
+ scriptexecuter
+
+include ../../Makefile.in
+
--- /dev/null
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "stg/common.h"
+#include "admins_methods.h"
+#include "rpcconfig.h"
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(login, &admin))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(admin->GetLogin());
+structVal["password"] = xmlrpc_c::value_string(admin->GetPassword());
+
+const PRIV * priv = admin->GetPriv();
+
+structVal["user_stat"] = xmlrpc_c::value_boolean(priv->userStat);
+structVal["user_conf"] = xmlrpc_c::value_boolean(priv->userConf);
+structVal["user_cash"] = xmlrpc_c::value_boolean(priv->userCash);
+structVal["user_passwd"] = xmlrpc_c::value_boolean(priv->userPasswd);
+structVal["user_add_del"] = xmlrpc_c::value_boolean(priv->userAddDel);
+structVal["admin_chg"] = xmlrpc_c::value_boolean(priv->adminChg);
+structVal["tariff_chg"] = xmlrpc_c::value_boolean(priv->tariffChg);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Not logged or cookie timeout'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Invalid admin (logged)'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (admins->Add(login, admin))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Failed to add admin'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (admins->Del(login, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * loggedAdmin;
+
+if (admins->Find(adminInfo.admin, &loggedAdmin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(login, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN_CONF conf;
+
+conf.priv = *admin->GetPriv();
+conf.password = admin->GetPassword();
+conf.login = login;
+
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("password")) != structVal.end())
+ {
+ conf.password = xmlrpc_c::value_string(it->second);
+ }
+
+if ((it = structVal.find("user_stat")) != structVal.end())
+ {
+ conf.priv.userStat = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_conf")) != structVal.end())
+ {
+ conf.priv.userConf = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_cash")) != structVal.end())
+ {
+ conf.priv.userCash = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_passwd")) != structVal.end())
+ {
+ conf.priv.userPasswd = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_add_del")) != structVal.end())
+ {
+ conf.priv.userAddDel = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("admin_chg")) != structVal.end())
+ {
+ conf.priv.adminChg = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("tariff_chg")) != structVal.end())
+ {
+ conf.priv.tariffChg = xmlrpc_c::value_boolean(it->second);
+ }
+
+if (admins->Change(conf, loggedAdmin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMINS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> mainStructVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ mainStructVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(mainStructVal);
+ return;
+ }
+
+ADMIN_CONF ac;
+int h = admins->OpenSearch();
+
+while (admins->SearchNext(h, &ac) == 0)
+ {
+ std::map<std::string, xmlrpc_c::value> structVal;
+ structVal["result"] = xmlrpc_c::value_boolean(true);
+ structVal["login"] = xmlrpc_c::value_string(ac.login);
+ structVal["password"] = xmlrpc_c::value_string(ac.password);
+ structVal["user_stat"] = xmlrpc_c::value_boolean(ac.priv.userStat);
+ structVal["user_conf"] = xmlrpc_c::value_boolean(ac.priv.userConf);
+ structVal["user_cash"] = xmlrpc_c::value_boolean(ac.priv.userCash);
+ structVal["user_passwd"] = xmlrpc_c::value_boolean(ac.priv.userPasswd);
+ structVal["user_add_del"] = xmlrpc_c::value_boolean(ac.priv.userAddDel);
+ structVal["admin_chg"] = xmlrpc_c::value_boolean(ac.priv.adminChg);
+ structVal["tariff_chg"] = xmlrpc_c::value_boolean(ac.priv.tariffChg);
+
+ retval.push_back(xmlrpc_c::value_struct(structVal));
+ }
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
--- /dev/null
+#ifndef __ADMINS_METHODS_H__
+#define __ADMINS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+
+class RPC_CONFIG;
+
+class METHOD_ADMIN_GET : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_GET(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_ADMIN_GET(const METHOD_ADMIN_GET & rvalue);
+ METHOD_ADMIN_GET & operator=(const METHOD_ADMIN_GET & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_ADD : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_ADD(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_ADMIN_ADD(const METHOD_ADMIN_ADD & rvalue);
+ METHOD_ADMIN_ADD & operator=(const METHOD_ADMIN_ADD & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_DEL : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_DEL(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_ADMIN_DEL(const METHOD_ADMIN_DEL & rvalue);
+ METHOD_ADMIN_DEL & operator=(const METHOD_ADMIN_DEL & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_CHG : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_CHG(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_ADMIN_CHG(const METHOD_ADMIN_CHG & rvalue);
+ METHOD_ADMIN_CHG & operator=(const METHOD_ADMIN_CHG & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMINS_GET : public xmlrpc_c::method {
+public:
+ METHOD_ADMINS_GET(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_ADMINS_GET(const METHOD_ADMINS_GET & rvalue);
+ METHOD_ADMINS_GET & operator=(const METHOD_ADMINS_GET & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+#endif
--- /dev/null
+#include <sys/utsname.h>
+
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "stg/version.h"
+#include "stg/common.h"
+#include "info_methods.h"
+#include "rpcconfig.h"
+
+void METHOD_INFO::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+paramList.verifyEnd(0);
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string un;
+struct utsname utsn;
+
+uname(&utsn);
+un[0] = 0;
+
+un += utsn.sysname;
+un += " ";
+un += utsn.release;
+un += " ";
+un += utsn.machine;
+un += " ";
+un += utsn.nodename;
+
+structVal["version"] = xmlrpc_c::value_string(SERVER_VERSION);
+structVal["tariff_num"] = xmlrpc_c::value_int(static_cast<int>(tariffs->Count()));
+structVal["tariff"] = xmlrpc_c::value_int(2);
+structVal["users_num"] = xmlrpc_c::value_int(static_cast<int>(users->Count()));
+structVal["uname"] = xmlrpc_c::value_string(un);
+structVal["dir_num"] = xmlrpc_c::value_int(DIR_NUM);
+structVal["day_fee"] = xmlrpc_c::value_int(static_cast<int>(dayFee));
+
+std::vector<xmlrpc_c::value> dirnameVal;
+
+for (int i = 0; i< DIR_NUM; i++)
+ {
+ dirnameVal.push_back(xmlrpc_c::value_string(IconvString(dirNames[i], "KOI8-RU", "UTF-8")));
+ }
+
+structVal["dir_names"] = xmlrpc_c::value_array(dirnameVal);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGIN::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string login = paramList.getString(0);
+std::string password = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string cookie;
+if (config->CheckAdmin(login, password, &cookie))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ structVal["cookie"] = xmlrpc_c::value_string("");
+ }
+else
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(true);
+ structVal["cookie"] = xmlrpc_c::value_string(cookie);
+ }
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGOUT::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+if (config->LogoutAdmin(cookie))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ }
+else
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ }
+}
--- /dev/null
+#ifndef __INFO_METHODS_H__
+#define __INFO_METHODS_H__
+
+#include <string>
+#include <vector>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "stg/users.h"
+#include "stg/tariffs.h"
+
+// Forward declaration
+class RPC_CONFIG;
+class SETTINGS;
+
+class METHOD_INFO : public xmlrpc_c::method
+{
+public:
+ METHOD_INFO(TARIFFS * t,
+ USERS * u,
+ size_t df,
+ const std::vector<std::string> & dn)
+ : tariffs(t),
+ users(u),
+ dayFee(df),
+ dirNames(dn)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_INFO(const METHOD_INFO & rvalue);
+ METHOD_INFO & operator=(const METHOD_INFO & rvalue);
+
+ TARIFFS * tariffs;
+ USERS * users;
+ size_t dayFee;
+ const std::vector<std::string> & dirNames;
+};
+
+class METHOD_LOGIN : public xmlrpc_c::method
+{
+public:
+ explicit METHOD_LOGIN(RPC_CONFIG * c)
+ : config(c)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_LOGIN(const METHOD_LOGIN & rvalue);
+ METHOD_LOGIN & operator=(const METHOD_LOGIN & rvalue);
+
+ RPC_CONFIG * config;
+};
+
+class METHOD_LOGOUT : public xmlrpc_c::method
+{
+public:
+ explicit METHOD_LOGOUT(RPC_CONFIG * c)
+ : config(c)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_LOGOUT(const METHOD_LOGOUT & rvalue);
+ METHOD_LOGOUT & operator=(const METHOD_LOGOUT & rvalue);
+
+ RPC_CONFIG * config;
+};
+
+#endif
--- /dev/null
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "stg/message.h"
+#include "stg/common.h"
+#include "messages_methods.h"
+#include "rpcconfig.h"
+
+extern volatile time_t stgTime;
+
+//------------------------------------------------------------------------------
+
+void METHOD_MESSAGE_SEND::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::vector<xmlrpc_c::value> logins(paramList.getArray(1));
+std::map<std::string, xmlrpc_c::value> msgInfo(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+STG_MSG message;
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = msgInfo.find("version")) == msgInfo.end())
+ {
+ message.header.ver = 1; // Default value
+ }
+else
+ {
+ message.header.ver = xmlrpc_c::value_int(it->second);
+ }
+
+if ((it = msgInfo.find("type")) == msgInfo.end())
+ {
+ message.header.type = 1; // default value
+ }
+else
+ {
+ message.header.type = xmlrpc_c::value_int(it->second);
+ }
+
+if ((it = msgInfo.find("repeat")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.repeat = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("repeat_period")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.repeatPeriod = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("show_time")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.showTime = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("text")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.text = IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "CP1251");
+
+message.header.creationTime = static_cast<int>(stgTime);
+message.header.lastSendTime = 0;
+
+std::vector<xmlrpc_c::value>::iterator lit;
+for (lit = logins.begin(); lit != logins.end(); ++lit)
+ {
+ USER_PTR ui;
+ if (users->FindByName(xmlrpc_c::value_string(*lit), &ui))
+ {
+ printfd(__FILE__, "METHOD_MESSAGE_SEND::execute(): 'User '%s' not found'\n", std::string(xmlrpc_c::value_string(*lit)).c_str());
+ }
+ else
+ {
+ ui->AddMessage(&message);
+ }
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
--- /dev/null
+#ifndef __MESSAGES_METHODS_H__
+#define __MESSAGES_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "stg/users.h"
+
+class RPC_CONFIG;
+
+class METHOD_MESSAGE_SEND : public xmlrpc_c::method {
+public:
+ METHOD_MESSAGE_SEND(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_MESSAGE_SEND(const METHOD_MESSAGE_SEND & rvalue);
+ METHOD_MESSAGE_SEND & operator=(const METHOD_MESSAGE_SEND & rvalue);
+
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+#endif
--- /dev/null
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+#include <vector>
+#include <algorithm>
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "stg/common.h"
+#include "stg/admin.h"
+#include "stg/module_settings.h"
+#include "stg/settings.h"
+#include "stg/plugin_creator.h"
+
+#include "rpcconfig.h"
+#include "info_methods.h"
+#include "users_methods.h"
+#include "tariffs_methods.h"
+#include "admins_methods.h"
+#include "messages_methods.h"
+
+namespace
+{
+PLUGIN_CREATOR<RPC_CONFIG> rpcc;
+}
+
+extern "C" PLUGIN * GetPlugin();
+
+RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
+ : port(0),
+ cookieTimeout(0)
+{
+}
+
+int RPC_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+PARAM_VALUE pv;
+pv.param = "Port";
+std::vector<PARAM_VALUE>::const_iterator pvi;
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+int p;
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = static_cast<uint16_t>(p);
+
+pv.param = "CookieTimeout";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ cookieTimeout = 1800; // 30 * 60
+ }
+else
+ {
+ if (str2x(pvi->value[0], cookieTimeout))
+ {
+ errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+
+PLUGIN * GetPlugin()
+{
+return rpcc.GetPlugin();
+}
+
+RPC_CONFIG::RPC_CONFIG()
+ : users(NULL),
+ admins(NULL),
+ tariffs(NULL),
+ store(NULL),
+ fd(-1),
+ rpcServer(NULL),
+ running(false),
+ stopped(true),
+ dayFee(0),
+ logger(GetPluginLogger(GetStgLogger(), "conf_rpc"))
+{
+}
+
+RPC_CONFIG::~RPC_CONFIG()
+{
+// delete server
+delete rpcServer;
+}
+
+int RPC_CONFIG::ParseSettings()
+{
+int ret = rpcConfigSettings.ParseSettings(settings);
+
+if (ret)
+ errorStr = rpcConfigSettings.GetStrError();
+
+return ret;
+}
+
+void RPC_CONFIG::SetStgSettings(const SETTINGS * s)
+{
+ dayFee = s->GetDayFee();
+ dirNames.erase(dirNames.begin(), dirNames.end());
+ for (size_t i = 0; i < DIR_NUM; ++i) {
+ dirNames.push_back(s->GetDirName(i));
+ }
+}
+
+int RPC_CONFIG::Start()
+{
+InitiateRegistry();
+running = true;
+
+fd = socket(AF_INET, SOCK_STREAM, 0);
+if (fd < 0)
+ {
+ errorStr = "Failed to create socket";
+ logger("Cannot create a socket: %s", strerror(errno));
+ printfd(__FILE__, "Failed to create listening socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+int flag = 1;
+
+if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))
+ {
+ errorStr = "Setsockopt failed.";
+ logger("setsockopt error: %s", strerror(errno));
+ printfd(__FILE__, "Setsockopt failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+struct sockaddr_in addr;
+addr.sin_family = AF_INET;
+addr.sin_port = htons(rpcConfigSettings.GetPort());
+addr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
+ {
+ logger("Cannot bind the socket: %s", strerror(errno));
+ errorStr = "Failed to bind socket";
+ printfd(__FILE__, "Failed to bind listening socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+if (listen(fd, 10))
+ {
+ logger("Cannot listen the socket: %s", strerror(errno));
+ errorStr = "Failed to listen socket";
+ printfd(__FILE__, "Failed to listen listening socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+rpcServer = new xmlrpc_c::serverAbyss(
+ xmlrpc_c::serverAbyss::constrOpt()
+ .registryP(&rpcRegistry)
+ .logFileName("/var/log/stargazer_rpc.log")
+ .socketFd(fd)
+ );
+
+if (pthread_create(&tid, NULL, Run, this))
+ {
+ errorStr = "Failed to create RPC thread";
+ logger("Cannot create RPC thread.");
+ printfd(__FILE__, "Failed to crate RPC thread\n");
+ return -1;
+ }
+
+return 0;
+}
+
+int RPC_CONFIG::Stop()
+{
+running = false;
+for (int i = 0; i < 5 && !stopped; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+
+if (!stopped)
+ {
+ running = true;
+ logger("Cannot stop RPC thread.");
+ printfd(__FILE__, "Failed to stop RPC thread\n");
+ errorStr = "Failed to stop RPC thread";
+ return -1;
+ }
+else
+ {
+ pthread_join(tid, NULL);
+ }
+
+close(fd);
+
+return 0;
+}
+
+void * RPC_CONFIG::Run(void * rc)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
+
+config->stopped = false;
+while (config->running)
+ {
+ if (WaitPackets(config->fd))
+ config->rpcServer->runOnce();
+ }
+config->stopped = true;
+
+return NULL;
+}
+
+bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
+ ADMIN_INFO * info)
+{
+std::map<std::string,
+ ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+ {
+ return true;
+ }
+
+if (difftime(it->second.accessTime, time(NULL)) >
+ rpcConfigSettings.GetCookieTimeout())
+ {
+ cookies.erase(it);
+ return true;
+ }
+
+// Update access time
+time(&it->second.accessTime);
+*info = it->second;
+return false;
+}
+
+bool RPC_CONFIG::CheckAdmin(const std::string & login,
+ const std::string & password,
+ std::string * cookie)
+{
+ADMIN * admin = NULL;
+
+if (!admins->Correct(login, password, &admin))
+ {
+ logger("Attempt to connect with invalid credentials. Login: %s", login.c_str());
+ return true;
+ }
+
+ADMIN_INFO info;
+time(&info.accessTime);
+info.admin = login;
+info.priviledges = *admin->GetPriv();
+*cookie = GetCookie();
+cookies[*cookie] = info;
+
+return false;
+}
+
+bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
+{
+std::map<std::string,
+ ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+ {
+ return true;
+ }
+
+cookies.erase(it);
+
+return false;
+}
+
+std::string RPC_CONFIG::GetCookie() const
+{
+std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+std::string cookie;
+
+for (int i = 0; i < 64; ++i)
+ {
+ cookie += charset[rand() % charset.length()];
+ };
+
+return cookie;
+}
+
+void RPC_CONFIG::InitiateRegistry()
+{
+// manage registry
+xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
+ tariffs,
+ users,
+ dayFee,
+ dirNames
+ ));
+rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
+
+xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
+ this
+ ));
+rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
+
+xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
+ this
+ ));
+rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
+
+xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
+
+xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
+ this,
+ admins,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
+
+xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
+ this,
+ admins,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
+
+xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
+
+xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
+ this,
+ admins,
+ tariffs,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
+
+xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
+ this,
+ admins,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.add_user_cash", methodAddCashPtr);
+
+xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
+ this,
+ admins,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.set_user_cash", methodSetCashPtr);
+
+xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
+ this,
+ admins,
+ tariffs,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.chg_user_tariff", methodTariffChangePtr);
+
+xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
+ this,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
+
+xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
+ this,
+ admins,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
+ this,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
+
+xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
+ this,
+ admins,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
+
+xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
+ this,
+ admins,
+ tariffs,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
+
+xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
+
+xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
+
+xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
+
+xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.send_user_message", methodSendMessagePtr);
+
+xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
+
+xmlrpc_c::methodPtr const methodGetUserAuthByPtr(new METHOD_GET_USER_AUTH_BY(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_user_auth_by", methodGetUserAuthByPtr);
+}
+
--- /dev/null
+#ifndef __RPC_CONFIG_H__
+#define __RPC_CONFIG_H__
+
+#include <pthread.h>
+
+#include <ctime>
+#include <cstdint>
+#include <string>
+#include <map>
+#include <vector>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+#include "stg/plugin.h"
+#include "stg/admin_conf.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#define RPC_CONFIG_VERSION "Stargazer RPC v. 0.2"
+
+class ADMINS;
+class TARIFFS;
+class USERS;
+class STORE;
+
+class RPC_CONFIG_SETTINGS
+{
+public:
+ RPC_CONFIG_SETTINGS();
+ virtual ~RPC_CONFIG_SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort() const { return port; }
+ double GetCookieTimeout() const { return cookieTimeout; }
+
+private:
+ std::string errorStr;
+ uint16_t port;
+ double cookieTimeout;
+};
+
+struct ADMIN_INFO
+{
+ ADMIN_INFO()
+ : admin(),
+ accessTime(0),
+ priviledges()
+ {}
+
+ std::string admin;
+ time_t accessTime;
+ PRIV priviledges;
+};
+
+class RPC_CONFIG : public PLUGIN
+{
+public:
+ RPC_CONFIG();
+ virtual ~RPC_CONFIG();
+
+ void SetUsers(USERS * u) { users = u; }
+ void SetTariffs(TARIFFS * t) { tariffs = t; }
+ void SetAdmins(ADMINS * a) { admins = a; }
+ void SetStore(STORE * s) { store = s; }
+ void SetStgSettings(const SETTINGS * s);
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return running && !stopped; }
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return RPC_CONFIG_VERSION; }
+ uint16_t GetStartPosition() const { return 20; }
+ uint16_t GetStopPosition() const { return 20; }
+
+ bool GetAdminInfo(const std::string & cookie,
+ ADMIN_INFO * info);
+ bool CheckAdmin(const std::string & login,
+ const std::string & password,
+ std::string * cookie);
+ bool LogoutAdmin(const std::string & cookie);
+
+private:
+ RPC_CONFIG(const RPC_CONFIG & rvalue);
+ RPC_CONFIG & operator=(const RPC_CONFIG & rvalue);
+
+ static void * Run(void *);
+ std::string GetCookie() const;
+ void InitiateRegistry();
+
+ mutable std::string errorStr;
+ RPC_CONFIG_SETTINGS rpcConfigSettings;
+ USERS * users;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ STORE * store;
+ MODULE_SETTINGS settings;
+ int fd;
+ xmlrpc_c::registry rpcRegistry;
+ xmlrpc_c::serverAbyss * rpcServer;
+ bool running;
+ bool stopped;
+ pthread_t tid;
+ std::map<std::string,
+ ADMIN_INFO> cookies;
+ size_t dayFee;
+ std::vector<std::string> dirNames;
+ PLUGIN_LOGGER logger;
+};
+
+#endif
--- /dev/null
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "tariff_helper.h"
+#include "stg/common.h"
+
+void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const
+{
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["name"] = xmlrpc_c::value_string(data.tariffConf.name);
+structVal["fee"] = xmlrpc_c::value_double(data.tariffConf.fee);
+structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free);
+structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
+structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
+structVal["period"] = xmlrpc_c::value_string(TARIFF::PeriodToString(data.tariffConf.period));
+structVal["changePolicy"] = xmlrpc_c::value_string(TARIFF::ChangePolicyToString(data.tariffConf.changePolicy));
+structVal["changePolicyTimeout"] = xmlrpc_c::value_string(formatTime(data.tariffConf.changePolicyTimeout));
+
+std::vector<xmlrpc_c::value> prices(DIR_NUM);
+
+for (unsigned i = 0; i < DIR_NUM; ++i)
+ {
+ std::map<std::string, xmlrpc_c::value> dirPrice;
+ dirPrice["hday"] = xmlrpc_c::value_int(data.dirPrice[i].hDay);
+ dirPrice["mday"] = xmlrpc_c::value_int(data.dirPrice[i].mDay);
+ dirPrice["hnight"] = xmlrpc_c::value_int(data.dirPrice[i].hNight);
+ dirPrice["mnight"] = xmlrpc_c::value_int(data.dirPrice[i].mNight);
+ dirPrice["pricedaya"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayA * 1024 * 1024);
+ dirPrice["pricedayb"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayB * 1024 * 1024);
+ dirPrice["pricenighta"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightA * 1024 * 1024);
+ dirPrice["pricenightb"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightB * 1024 * 1024);
+ dirPrice["threshold"] = xmlrpc_c::value_int(data.dirPrice[i].threshold);
+ dirPrice["singleprice"] = xmlrpc_c::value_boolean(data.dirPrice[i].singlePrice);
+ dirPrice["nodiscount"] = xmlrpc_c::value_boolean(data.dirPrice[i].noDiscount);
+ prices[i] = xmlrpc_c::value_struct(dirPrice);
+ }
+
+structVal["dirprices"] = xmlrpc_c::value_array(prices);
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+bool TARIFF_HELPER::SetTariffInfo(const xmlrpc_c::value & info)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("fee")) != structVal.end())
+ {
+ data.tariffConf.fee = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+ {
+ data.tariffConf.free = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("passivecost")) != structVal.end())
+ {
+ data.tariffConf.passiveCost = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("traffType")) != structVal.end())
+ {
+ data.tariffConf.traffType = static_cast<TARIFF::TRAFF_TYPE>(xmlrpc_c::value_int(it->second).cvalue());
+ }
+
+if ((it = structVal.find("period")) != structVal.end())
+ {
+ data.tariffConf.period = TARIFF::StringToPeriod(xmlrpc_c::value_string(it->second));
+ }
+
+if ((it = structVal.find("changePolicy")) != structVal.end())
+ {
+ data.tariffConf.changePolicy = TARIFF::StringToChangePolicy(xmlrpc_c::value_string(it->second));
+ }
+
+if ((it = structVal.find("changePolicyTimeout")) != structVal.end())
+ {
+ data.tariffConf.changePolicyTimeout = readTime(xmlrpc_c::value_string(it->second));
+ }
+
+if ((it = structVal.find("dirprices")) != structVal.end())
+ {
+ std::vector<xmlrpc_c::value> prices(
+ xmlrpc_c::value_array(it->second).vectorValueValue()
+ );
+
+ for (unsigned i = 0; i < DIR_NUM; ++i)
+ {
+ std::map<std::string, xmlrpc_c::value> dirPrice(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(prices[i]))
+ );
+ data.dirPrice[i].mDay = xmlrpc_c::value_int(dirPrice["mday"]);
+ data.dirPrice[i].hDay = xmlrpc_c::value_int(dirPrice["hday"]);
+ data.dirPrice[i].mNight = xmlrpc_c::value_int(dirPrice["mnight"]);
+ data.dirPrice[i].hNight = xmlrpc_c::value_int(dirPrice["hnight"]);
+ data.dirPrice[i].priceDayA = xmlrpc_c::value_double(dirPrice["pricedaya"]) / 1024 / 1024;
+ data.dirPrice[i].priceDayB = xmlrpc_c::value_double(dirPrice["pricedayb"]) / 1024 / 1024;
+ data.dirPrice[i].priceNightA = xmlrpc_c::value_double(dirPrice["pricenighta"]) / 1024 / 1024;
+ data.dirPrice[i].priceNightB = xmlrpc_c::value_double(dirPrice["pricenightb"]) / 1024 / 1024;
+ data.dirPrice[i].threshold = xmlrpc_c::value_int(dirPrice["threshold"]);
+ data.dirPrice[i].singlePrice = xmlrpc_c::value_boolean(dirPrice["singleprice"]);
+ data.dirPrice[i].noDiscount = xmlrpc_c::value_boolean(dirPrice["nodiscount"]);
+ }
+ }
+
+return false;
+}
--- /dev/null
+#ifndef __TARIFF_HELPER_H__
+#define __TARIFF_HELPER_H__
+
+#include <xmlrpc-c/base.hpp>
+#include "stg/tariff_conf.h"
+
+class TARIFF_HELPER
+{
+public:
+ explicit TARIFF_HELPER(TARIFF_DATA & td)
+ : data(td)
+ {}
+
+ void GetTariffInfo(xmlrpc_c::value * info) const;
+ bool SetTariffInfo(const xmlrpc_c::value & info);
+private:
+ TARIFF_DATA & data;
+};
+
+#endif
+
+
--- /dev/null
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "tariffs_methods.h"
+#include "rpcconfig.h"
+#include "tariff_helper.h"
+#include "stg/tariffs.h"
+#include "stg/users.h"
+#include "stg/admins.h"
+#include "stg/admin.h"
+
+void METHOD_TARIFF_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+const TARIFF * tariff = tariffs->FindByName(name);
+
+if (!tariff)
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+TARIFF_DATA td(tariff->GetTariffData());
+
+TARIFF_HELPER helper(td);
+
+helper.GetTariffInfo(retvalPtr);
+}
+
+void METHOD_TARIFF_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+const TARIFF * tariff = tariffs->FindByName(name);
+
+if (!tariff)
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+TARIFF_DATA td(tariff->GetTariffData());
+
+TARIFF_HELPER helper(td);
+
+helper.SetTariffInfo(info);
+
+if (tariffs->Chg(td, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFFS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+std::vector<xmlrpc_c::value> tariffsInfo;
+
+
+std::list<TARIFF_DATA> dataList;
+tariffs->GetTariffsData(&dataList);
+std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
+for (; it != dataList.end(); ++it)
+ {
+ xmlrpc_c::value info;
+ TARIFF_DATA td(*it); // 'cause TARIFF_HELPER work in both ways and take not const referense
+ TARIFF_HELPER helper(td);
+ helper.GetTariffInfo(&info);
+ tariffsInfo.push_back(info);
+ }
+
+*retvalPtr = xmlrpc_c::value_array(tariffsInfo);
+}
+
+void METHOD_TARIFF_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->Add(tariff, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFF_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (users->TariffInUse(tariff))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->Del(tariff, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
--- /dev/null
+#ifndef __TARIFFS_METHODS_H__
+#define __TARIFFS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+class RPC_CONFIG;
+class TARIFFS;
+class USERS;
+class ADMINS;
+
+class METHOD_TARIFF_GET : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_GET(RPC_CONFIG * c,
+ TARIFFS * t)
+ : config(c),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_TARIFF_GET(const METHOD_TARIFF_GET & rvalue);
+ METHOD_TARIFF_GET & operator=(const METHOD_TARIFF_GET & rvalue);
+
+ RPC_CONFIG * config;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_CHG : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_CHG(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t)
+ : config(c),
+ admins(a),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_TARIFF_CHG(const METHOD_TARIFF_CHG & rvalue);
+ METHOD_TARIFF_CHG & operator=(const METHOD_TARIFF_CHG & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFFS_GET : public xmlrpc_c::method {
+public:
+ METHOD_TARIFFS_GET(RPC_CONFIG * c,
+ TARIFFS * t)
+ : config(c),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+
+private:
+ METHOD_TARIFFS_GET(const METHOD_TARIFFS_GET & rvalue);
+ METHOD_TARIFFS_GET & operator=(const METHOD_TARIFFS_GET & rvalue);
+
+ RPC_CONFIG * config;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_ADD : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t)
+ : config(c),
+ admins(a),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_TARIFF_ADD(const METHOD_TARIFF_ADD & rvalue);
+ METHOD_TARIFF_ADD & operator=(const METHOD_TARIFF_ADD & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_DEL : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_DEL(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t,
+ USERS * u)
+ : config(c),
+ admins(a),
+ tariffs(t),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_TARIFF_DEL(const METHOD_TARIFF_DEL & rvalue);
+ METHOD_TARIFF_DEL & operator=(const METHOD_TARIFF_DEL & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ USERS * users;
+};
+
+#endif
--- /dev/null
+#include <cmath>
+
+#include "stg/tariffs.h"
+#include "stg/admin.h"
+#include "stg/store.h"
+#include "stg/user_ips.h"
+#include "stg/common.h"
+#include "stg/user_property.h"
+#include "user_helper.h"
+
+//------------------------------------------------------------------------------
+
+void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
+ bool hidePassword)
+{
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(ptr->GetLogin());
+
+if (!hidePassword)
+ {
+ structVal["password"] = xmlrpc_c::value_string(ptr->GetProperty().password.Get());
+ }
+else
+ {
+ structVal["password"] = xmlrpc_c::value_string("++++++++");
+ }
+
+structVal["cash"] = xmlrpc_c::value_double(ptr->GetProperty().cash.Get());
+structVal["freemb"] = xmlrpc_c::value_double(ptr->GetProperty().freeMb.Get());
+structVal["credit"] = xmlrpc_c::value_double(ptr->GetProperty().credit.Get());
+
+if (ptr->GetProperty().nextTariff.Get() != "")
+ {
+ structVal["tariff"] = xmlrpc_c::value_string(
+ ptr->GetProperty().tariffName.Get() +
+ "/" +
+ ptr->GetProperty().nextTariff.Get()
+ );
+ }
+else
+ {
+ structVal["tariff"] = xmlrpc_c::value_string(ptr->GetProperty().tariffName.Get());
+ }
+
+structVal["note"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().note, "KOI8-RU", "UTF-8"));
+
+structVal["phone"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().phone, "KOI8-RU", "UTF-8"));
+
+structVal["address"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().address, "KOI8-RU", "UTF-8"));
+
+structVal["email"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().email, "KOI8-RU", "UTF-8"));
+
+std::vector<xmlrpc_c::value> userdata;
+
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata0.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata1.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata2.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata3.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata4.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata5.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata6.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata7.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata8.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperty().userdata9.Get(), "KOI8-RU", "UTF-8")));
+
+structVal["userdata"] = xmlrpc_c::value_array(userdata);
+
+structVal["name"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().realName, "KOI8-RU", "UTF-8"));
+
+structVal["group"] = xmlrpc_c::value_string(IconvString(ptr->GetProperty().group, "KOI8-RU", "UTF-8"));
+
+structVal["status"] = xmlrpc_c::value_boolean(ptr->GetConnected());
+structVal["aonline"] = xmlrpc_c::value_boolean(ptr->GetProperty().alwaysOnline.Get());
+structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(ptr->GetCurrIP()));
+structVal["pingtime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetPingTime()));
+structVal["ips"] = xmlrpc_c::value_string(ptr->GetProperty().ips.Get().GetIpStr());
+
+std::map<std::string, xmlrpc_c::value> traffInfo;
+std::vector<xmlrpc_c::value> mu(DIR_NUM);
+std::vector<xmlrpc_c::value> md(DIR_NUM);
+std::vector<xmlrpc_c::value> su(DIR_NUM);
+std::vector<xmlrpc_c::value> sd(DIR_NUM);
+
+DIR_TRAFF upload;
+DIR_TRAFF download;
+DIR_TRAFF supload;
+DIR_TRAFF sdownload;
+download = ptr->GetProperty().down.Get();
+upload = ptr->GetProperty().up.Get();
+sdownload = ptr->GetSessionUpload();
+supload = ptr->GetSessionDownload();
+
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ std::string value;
+ x2str(upload[j], value);
+ mu[j] = xmlrpc_c::value_string(value);
+ x2str(download[j], value);
+ md[j] = xmlrpc_c::value_string(value);
+ x2str(supload[j], value);
+ su[j] = xmlrpc_c::value_string(value);
+ x2str(sdownload[j], value);
+ sd[j] = xmlrpc_c::value_string(value);
+ }
+
+traffInfo["mu"] = xmlrpc_c::value_array(mu);
+traffInfo["md"] = xmlrpc_c::value_array(md);
+traffInfo["su"] = xmlrpc_c::value_array(su);
+traffInfo["sd"] = xmlrpc_c::value_array(sd);
+
+structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
+
+structVal["down"] = xmlrpc_c::value_boolean(ptr->GetProperty().disabled.Get());
+structVal["disableddetailstat"] = xmlrpc_c::value_boolean(ptr->GetProperty().disabledDetailStat.Get());
+structVal["passive"] = xmlrpc_c::value_boolean(ptr->GetProperty().passive.Get());
+structVal["lastcash"] = xmlrpc_c::value_double(ptr->GetProperty().lastCashAdd.Get());
+structVal["lasttimecash"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().lastCashAddTime.Get()));
+structVal["lastactivitytime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().lastActivityTime.Get()));
+structVal["creditexpire"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperty().creditExpire.Get()));
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
+ const ADMIN * admin,
+ const std::string & login,
+ const STORE & store,
+ TARIFFS * tariffs)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+bool check = false;
+bool alwaysOnline = ptr->GetProperty().alwaysOnline;
+if ((it = structVal.find("aonline")) != structVal.end())
+ {
+ check = true;
+ alwaysOnline = xmlrpc_c::value_boolean(it->second);
+ }
+bool onlyOneIP = ptr->GetProperty().ips.ConstData().OnlyOneIP();
+if ((it = structVal.find("ips")) != structVal.end())
+ {
+ check = true;
+ onlyOneIP = StrToIPS(xmlrpc_c::value_string(it->second)).OnlyOneIP();
+ }
+
+if (check && alwaysOnline && !onlyOneIP)
+ {
+ printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
+ return true;
+ }
+
+if ((it = structVal.find("ips")) != structVal.end())
+ {
+ USER_IPS ips;
+ ips = StrToIPS(xmlrpc_c::value_string(it->second));
+
+ for (size_t i = 0; i < ips.Count(); ++i)
+ {
+ CONST_USER_PTR user;
+ uint32_t ip = ips[i].ip;
+ if (users.IsIPInUse(ip, login, &user))
+ {
+ printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), login.c_str(), user->GetLogin().c_str());
+ return true;
+ }
+ }
+
+ if (!ptr->GetProperty().ips.Set(ips,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("aonline")) != structVal.end())
+ {
+ bool value(xmlrpc_c::value_boolean(it->second));
+ if (ptr->GetProperty().alwaysOnline.Get() != value)
+ if (!ptr->GetProperty().alwaysOnline.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("password")) != structVal.end())
+ {
+ std::string value(xmlrpc_c::value_string(it->second));
+ if (ptr->GetProperty().password.Get() != value)
+ if (!ptr->GetProperty().password.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("address")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().address.Get() != value)
+ if (!ptr->GetProperty().address.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("phone")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().phone.Get() != value)
+ if (!ptr->GetProperty().phone.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("email")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().email.Get() != value)
+ if (!ptr->GetProperty().email.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("cash")) != structVal.end())
+ {
+ double value(xmlrpc_c::value_double(it->second));
+ if (std::fabs(ptr->GetProperty().cash.Get() - value) > 1.0e-3)
+ if (!ptr->GetProperty().cash.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("creditexpire")) != structVal.end())
+ {
+ time_t value(xmlrpc_c::value_int(it->second));
+ if (ptr->GetProperty().creditExpire.Get() != value)
+ if (!ptr->GetProperty().creditExpire.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("credit")) != structVal.end())
+ {
+ double value(xmlrpc_c::value_double(it->second));
+ if (std::fabs(ptr->GetProperty().credit.Get() - value) > 1.0e-3)
+ if (!ptr->GetProperty().credit.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+ {
+ double value(xmlrpc_c::value_double(it->second));
+ if (std::fabs(ptr->GetProperty().freeMb.Get() - value) > 1.0e-3)
+ if (!ptr->GetProperty().freeMb.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("down")) != structVal.end())
+ {
+ bool value(xmlrpc_c::value_boolean(it->second));
+ if (ptr->GetProperty().disabled.Get() != value)
+ if (!ptr->GetProperty().disabled.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("passive")) != structVal.end())
+ {
+ bool value(xmlrpc_c::value_boolean(it->second));
+ if (ptr->GetProperty().passive.Get() != value)
+ if (!ptr->GetProperty().passive.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("disableddetailstat")) != structVal.end())
+ {
+ bool value(xmlrpc_c::value_boolean(it->second));
+ if (ptr->GetProperty().disabledDetailStat.Get() != value)
+ if (!ptr->GetProperty().disabledDetailStat.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("name")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().realName.Get() != value)
+ if (!ptr->GetProperty().realName.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("group")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().group.Get() != value)
+ if (!ptr->GetProperty().group.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("note")) != structVal.end())
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+ if (ptr->GetProperty().note.Get() != value)
+ if (!ptr->GetProperty().note.Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+if ((it = structVal.find("userdata")) != structVal.end())
+ {
+ std::vector<USER_PROPERTY_LOGGED<std::string> *> userdata;
+ userdata.push_back(ptr->GetProperty().userdata0.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata1.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata2.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata3.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata4.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata5.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata6.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata7.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata8.GetPointer());
+ userdata.push_back(ptr->GetProperty().userdata9.GetPointer());
+
+ std::vector<xmlrpc_c::value> udata(
+ xmlrpc_c::value_array(it->second).vectorValueValue()
+ );
+
+ for (unsigned i = 0; i < userdata.size(); ++i)
+ {
+ std::string value(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-RU"));
+ if (userdata[i]->Get() != value)
+ if (!userdata[i]->Set(value,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+ }
+
+if ((it = structVal.find("traff")) != structVal.end())
+ {
+ std::map<std::string, xmlrpc_c::value> traff(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
+ );
+
+ DIR_TRAFF dtData;
+ dtData = ptr->GetProperty().up.Get();
+ if ((it = traff.find("mu")) != traff.end())
+ {
+ std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
+
+ for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+ {
+ int64_t value;
+ if (str2x(xmlrpc_c::value_string(data[i]), value))
+ printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
+ else
+ dtData[i] = value;
+ }
+ if (!ptr->GetProperty().up.Set(dtData,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+ dtData = ptr->GetProperty().down.Get();
+ if ((it = traff.find("md")) != traff.end())
+ {
+ std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
+
+ for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+ {
+ int64_t value;
+ if (str2x(xmlrpc_c::value_string(data[i]), value))
+ printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
+ else
+ dtData[i] = value;
+ }
+ if (!ptr->GetProperty().down.Set(dtData,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+ }
+
+if ((it = structVal.find("tariff")) != structVal.end())
+ {
+ std::string tariff(xmlrpc_c::value_string(it->second));
+ size_t pos = tariff.find('/');
+ std::string nextTariff;
+ if (pos != std::string::npos)
+ {
+ nextTariff = tariff.substr(pos + 1);
+ tariff = tariff.substr(0, pos);
+ }
+
+ const TARIFF * newTariff = tariffs->FindByName(tariff);
+ if (newTariff)
+ {
+ const TARIFF * currentTariff = ptr->GetTariff();
+ std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
+ if (message.empty())
+ {
+ if (ptr->GetProperty().tariffName.Get() != tariff)
+ {
+ if (!ptr->GetProperty().tariffName.Set(tariff,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+ }
+ else
+ {
+ GetStgLogger()("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str());
+ }
+ }
+
+ if (nextTariff != "" &&
+ tariffs->FindByName(nextTariff))
+ if (ptr->GetProperty().nextTariff.Get() != nextTariff)
+ if (!ptr->GetProperty().nextTariff.Set(tariff,
+ admin,
+ login,
+ &store))
+ return true;
+ }
+
+return false;
+}
--- /dev/null
+#ifndef __USER_HELPER_H__
+#define __USER_HELPER_H__
+
+#include <string>
+
+#include <xmlrpc-c/base.hpp>
+
+#include "stg/users.h"
+
+class ADMIN;
+class STORE;
+class TARIFFS;
+
+class USER_HELPER
+{
+public:
+ USER_HELPER(USER_PTR & p, USERS & us)
+ : ptr(p),
+ users(us)
+ {
+ }
+
+ void GetUserInfo(xmlrpc_c::value * info,
+ bool hidePassword = false);
+ bool SetUserInfo(const xmlrpc_c::value & info,
+ const ADMIN * admin,
+ const std::string & login,
+ const STORE & store,
+ TARIFFS * tariffs);
+private:
+ USER_PTR & ptr;
+ USERS & users;
+};
+
+#endif
--- /dev/null
+#include <cerrno>
+
+#include "stg/users.h"
+#include "stg/admins.h"
+#include "stg/tariffs.h"
+#include "stg/user_ips.h"
+#include "stg/common.h"
+#include "stg/user_property.h"
+
+#include "users_methods.h"
+#include "rpcconfig.h"
+#include "user_helper.h"
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+USER_HELPER uhelper(u, *users);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+ {
+ uhelper.GetUserInfo(retvalPtr, true);
+ return;
+ }
+
+uhelper.GetUserInfo(retvalPtr);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin = NULL;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ if (users->Add(login, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (!users->FindByName(login, &u))
+ {
+ users->Del(login, admin);
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USERS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+bool hidePassword = !adminInfo.priviledges.userConf ||
+ !adminInfo.priviledges.userPasswd;
+
+USER_PTR u;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(h);
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+
+ xmlrpc_c::value info;
+
+ USER_HELPER uhelper(u, *users);
+
+ uhelper.GetUserInfo(&info, hidePassword);
+
+ retval.push_back(info);
+ }
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_HELPER uhelper(u, *users);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+ {
+ uhelper.SetUserInfo(info, admin, login, *store, tariffs);
+ }
+else
+ {
+ uhelper.SetUserInfo(info, admin, login, *store, tariffs);
+ }
+
+u->WriteConf();
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double amount = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+double cash = u->GetProperty().cash.Get();
+cash += amount;
+
+if (!u->GetProperty().cash.Set(cash, admin, login, store, comment))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_SET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double cash = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (!u->GetProperty().cash.Set(cash, admin, login, store, comment))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_TARIFF_CHANGE::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string tariff = paramList.getString(2);
+bool delayed = paramList.getBoolean(3);
+std::string comment = IconvString(paramList.getString(4), "UTF-8", "KOI8-R");
+paramList.verifyEnd(5);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN * admin;
+
+if (admins->Find(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->FindByName(tariff))
+ {
+ if (delayed)
+ {
+ if (u->GetProperty().nextTariff.Set(tariff,
+ admin,
+ login,
+ store,
+ comment))
+ {
+ u->WriteConf();
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+ }
+ else
+ {
+ const TARIFF * newTariff = tariffs->FindByName(tariff);
+ if (newTariff)
+ {
+ const TARIFF * currentTariff = u->GetTariff();
+ std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
+ if (message.empty())
+ {
+ if (u->GetProperty().tariffName.Set(tariff,
+ admin,
+ login,
+ store,
+ comment))
+ {
+ u->ResetNextTariff();
+ u->WriteConf();
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+ }
+ else
+ {
+ GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
+ }
+ }
+ }
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_GET_ONLINE_IPS::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+typedef std::vector<xmlrpc_c::value> ValueVector;
+ValueVector subnetsStr = paramList.getArray(1);
+paramList.verifyEnd(2);
+
+std::vector<IP_MASK> subnets;
+
+for (ValueVector::const_iterator it(subnetsStr.begin()); it != subnetsStr.end(); ++it)
+ {
+ IP_MASK ipm;
+ if (ParseNet(xmlrpc_c::value_string(*it), ipm))
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::execute(): Failed to parse subnet ('%s')\n", std::string(xmlrpc_c::value_string(*it)).c_str());
+ }
+ else
+ {
+ subnets.push_back(ipm);
+ }
+ }
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+ValueVector ips;
+
+USER_PTR u;
+
+int handle = users->OpenSearch();
+if (!handle)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(handle);
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(handle, &u))
+ {
+ break;
+ }
+
+ if (u->GetAuthorized())
+ {
+ uint32_t ip = u->GetCurrIP();
+
+ for (std::vector<IP_MASK>::const_iterator it(subnets.begin()); it != subnets.end(); ++it)
+ {
+ if ((it->ip & it->mask) == (ip & it->mask))
+ {
+ ips.push_back(xmlrpc_c::value_string(inet_ntostring(u->GetCurrIP())));
+ break;
+ }
+ }
+ }
+ }
+
+structVal["ips"] = xmlrpc_c::value_array(ips);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+bool METHOD_GET_ONLINE_IPS::ParseNet(const std::string & net, IP_MASK & ipm) const
+{
+size_t pos = net.find_first_of('/');
+
+if (pos == std::string::npos)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network address is not in CIDR-notation\n");
+ return true;
+ }
+
+int res = inet_pton(AF_INET, net.substr(0, pos).c_str(), &ipm.ip);
+
+if (res < 0)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): '%s'\n", strerror(errno));
+ return true;
+ }
+else if (res == 0)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network address\n", strerror(errno));
+ return true;
+ }
+
+if (str2x(net.substr(pos + 1, net.length() - pos - 1), ipm.mask))
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network mask\n");
+ return true;
+ }
+if (ipm.mask > 32)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network mask is out of range\n");
+ return true;
+ }
+ipm.mask = htonl(0xffFFffFF << (32 - ipm.mask));
+
+return false;
+}
+
+void METHOD_GET_USER_AUTH_BY::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+USER_PTR u;
+
+if (users->FindByName(login, &u))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+std::vector<std::string> list(u->GetAuthorizers());
+std::vector<xmlrpc_c::value> authList;
+for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+ authList.push_back(xmlrpc_c::value_string(*it));
+*retvalPtr = xmlrpc_c::value_array(authList);
+}
--- /dev/null
+#ifndef __USERS_METHODS_H__
+#define __USERS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+class RPC_CONFIG;
+class ADMINS;
+class TARIFFS;
+class USERS;
+class STORE;
+struct IP_MASK;
+
+class METHOD_USER_GET : public xmlrpc_c::method {
+public:
+ METHOD_USER_GET(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_GET(const METHOD_USER_GET & rvalue);
+ METHOD_USER_GET & operator=(const METHOD_USER_GET & rvalue);
+
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+class METHOD_USER_ADD : public xmlrpc_c::method {
+public:
+ METHOD_USER_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ USERS * u)
+ : config(c),
+ admins(a),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_ADD(const METHOD_USER_ADD & rvalue);
+ METHOD_USER_ADD & operator=(const METHOD_USER_ADD & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ USERS * users;
+};
+
+class METHOD_USER_DEL : public xmlrpc_c::method {
+public:
+ METHOD_USER_DEL(RPC_CONFIG * c,
+ ADMINS * a,
+ USERS * u)
+ : config(c),
+ admins(a),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_DEL(const METHOD_USER_DEL & rvalue);
+ METHOD_USER_DEL & operator=(const METHOD_USER_DEL & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ USERS * users;
+};
+
+class METHOD_USERS_GET : public xmlrpc_c::method {
+public:
+ METHOD_USERS_GET(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USERS_GET(const METHOD_USERS_GET & rvalue);
+ METHOD_USERS_GET & operator=(const METHOD_USERS_GET & rvalue);
+
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+class METHOD_USER_CHG : public xmlrpc_c::method {
+public:
+ METHOD_USER_CHG(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t,
+ STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ tariffs(t),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_CHG(const METHOD_USER_CHG & rvalue);
+ METHOD_USER_CHG & operator=(const METHOD_USER_CHG & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_CASH_ADD : public xmlrpc_c::method {
+public:
+ METHOD_USER_CASH_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_CASH_ADD(const METHOD_USER_CASH_ADD & rvalue);
+ METHOD_USER_CASH_ADD & operator=(const METHOD_USER_CASH_ADD & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_CASH_SET : public xmlrpc_c::method {
+public:
+ METHOD_USER_CASH_SET(RPC_CONFIG * c,
+ ADMINS * a,
+ STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_CASH_SET(const METHOD_USER_CASH_SET & rvalue);
+ METHOD_USER_CASH_SET & operator=(const METHOD_USER_CASH_SET & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_TARIFF_CHANGE : public xmlrpc_c::method {
+public:
+ METHOD_USER_TARIFF_CHANGE(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t,
+ STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ tariffs(t),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_USER_TARIFF_CHANGE(const METHOD_USER_TARIFF_CHANGE & rvalue);
+ METHOD_USER_TARIFF_CHANGE & operator=(const METHOD_USER_TARIFF_CHANGE & rvalue);
+
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ STORE * store;
+ USERS * users;
+};
+
+class METHOD_GET_ONLINE_IPS : public xmlrpc_c::method {
+public:
+ METHOD_GET_ONLINE_IPS(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_GET_ONLINE_IPS(const METHOD_GET_ONLINE_IPS & rvalue);
+ METHOD_GET_ONLINE_IPS & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
+
+ RPC_CONFIG * config;
+ USERS * users;
+
+ bool ParseNet(const std::string & net, IP_MASK & ipm) const;
+};
+
+class METHOD_GET_USER_AUTH_BY : public xmlrpc_c::method {
+public:
+ METHOD_GET_USER_AUTH_BY(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+
+private:
+ METHOD_GET_USER_AUTH_BY(const METHOD_GET_ONLINE_IPS & rvalue);
+ METHOD_GET_USER_AUTH_BY & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
+
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+#endif
--- /dev/null
+find_package ( EXPAT REQUIRED )
+
+set ( CPP_FILES stgconfig.cpp
+ conn.cpp
+ configproto.cpp
+ parser.cpp
+ parser_tariffs.cpp
+ parser_admins.cpp
+ parser_users.cpp
+ parser_services.cpp
+ parser_message.cpp
+ parser_auth_by.cpp
+ parser_user_info.cpp
+ parser_server_info.cpp )
+
+add_library ( mod_conf_sg MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_conf_sg scriptexecuter crypto logger common EXPAT::EXPAT )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.11 2010/03/04 10:47:45 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_sg.so
+
+SRCS = ./stgconfig.cpp \
+ ./conn.cpp \
+ ./configproto.cpp \
+ ./parser.cpp \
+ ./parser_tariffs.cpp \
+ ./parser_admins.cpp \
+ ./parser_users.cpp \
+ ./parser_services.cpp \
+ ./parser_message.cpp \
+ ./parser_auth_by.cpp \
+ ./parser_user_info.cpp \
+ ./parser_server_info.cpp
+
+LIBS += -lexpat \
+ $(LIB_THREAD)
+
+STGLIBS = common \
+ logger \
+ crypto \
+ scriptexecuter
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "configproto.h"
+
+#include "conn.h"
+
+#include "parser_server_info.h"
+#include "parser_admins.h"
+#include "parser_tariffs.h"
+#include "parser_users.h"
+#include "parser_services.h"
+#include "parser_message.h"
+#include "parser_user_info.h"
+#include "parser_auth_by.h"
+
+#include "stg/common.h"
+#include "stg/logger.h"
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+#include <csignal>
+#include <cstring>
+#include <cerrno>
+#include <cassert>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+namespace SP = STG::PARSER;
+
+CONFIGPROTO::CONFIGPROTO(PLUGIN_LOGGER & l)
+ : m_settings(NULL),
+ m_admins(NULL),
+ m_tariffs(NULL),
+ m_users(NULL),
+ m_services(NULL),
+ m_corporations(NULL),
+ m_store(NULL),
+ m_port(0),
+ m_bindAddress("0.0.0.0"),
+ m_running(false),
+ m_stopped(true),
+ m_logger(l),
+ m_listenSocket(-1)
+{
+}
+
+CONFIGPROTO::~CONFIGPROTO()
+{
+ {
+ std::deque<STG::Conn *>::iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ delete *it;
+ }
+ {
+ BASE_PARSER::REGISTRY::iterator it;
+ for (it = m_registry.begin(); it != m_registry.end(); ++it)
+ delete it->second;
+ }
+}
+
+int CONFIGPROTO::Prepare()
+{
+ sigset_t sigmask, oldmask;
+ sigemptyset(&sigmask);
+ sigaddset(&sigmask, SIGINT);
+ sigaddset(&sigmask, SIGTERM);
+ sigaddset(&sigmask, SIGUSR1);
+ sigaddset(&sigmask, SIGHUP);
+ pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
+ m_listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+ if (m_listenSocket < 0)
+ {
+ m_errorStr = std::string("Cannot create listen socket: '") + strerror(errno) + "'.";
+ m_logger(m_errorStr);
+ return -1;
+ }
+
+ int dummy = 1;
+
+ if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &dummy, 4) != 0)
+ {
+ m_errorStr = std::string("Failed to set SO_REUSEADDR to the listen socket: '") + strerror(errno) + "'.";
+ m_logger(m_errorStr);
+ return -1;
+ }
+
+ if (!Bind())
+ return -1;
+
+ if (listen(m_listenSocket, 64) == -1) // TODO: backlog length
+ {
+ m_errorStr = std::string("Failed to start listening for connections: '") + strerror(errno) + "'.";
+ m_logger(m_errorStr);
+ return -1;
+ }
+
+ RegisterParsers();
+
+ m_running = true;
+ m_stopped = false;
+ return 0;
+}
+
+int CONFIGPROTO::Stop()
+{
+ m_running = false;
+ for (int i = 0; i < 5 && !m_stopped; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+
+ if (!m_stopped)
+ {
+ m_errorStr = "Cannot stop listenign thread.";
+ m_logger(m_errorStr);
+ return -1;
+ }
+
+ shutdown(m_listenSocket, SHUT_RDWR);
+ close(m_listenSocket);
+ return 0;
+}
+
+void CONFIGPROTO::Run()
+{
+ while (m_running)
+ {
+ fd_set fds;
+
+ BuildFDSet(fds);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ int res = select(MaxFD() + 1, &fds, NULL, NULL, &tv);
+ if (res < 0)
+ {
+ m_errorStr = std::string("'select' is failed: '") + strerror(errno) + "'.";
+ printfd(__FILE__, "%s\n", m_errorStr.c_str());
+ m_logger(m_errorStr);
+ break;
+ }
+ if (!m_running)
+ break;
+ if (res > 0)
+ HandleEvents(fds);
+
+ CleanupConns();
+ }
+ m_stopped = true;
+}
+
+bool CONFIGPROTO::Bind()
+{
+ const hostent * he = gethostbyname(m_bindAddress.c_str());
+ if (he == NULL)
+ {
+ m_errorStr = "Failed to resolve name '" + m_bindAddress + "': '" + hstrerror(h_errno) + "'.";
+ printfd(__FILE__, "%s\n", m_errorStr.c_str());
+ m_logger(m_errorStr);
+ return false;
+ }
+
+ char ** ptr = he->h_addr_list;
+ while (*ptr != NULL)
+ {
+ struct sockaddr_in listenAddr;
+ listenAddr.sin_family = PF_INET;
+ listenAddr.sin_port = htons(m_port);
+ listenAddr.sin_addr.s_addr = *reinterpret_cast<in_addr_t *>(*ptr);
+
+ printfd(__FILE__, "Trying to bind to %s:%d\n", inet_ntostring(listenAddr.sin_addr.s_addr).c_str(), m_port);
+
+ if (bind(m_listenSocket, reinterpret_cast<sockaddr *>(&listenAddr), sizeof(listenAddr)) == 0)
+ return true;
+
+ m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'.";
+ printfd(__FILE__, "%s\n", m_errorStr.c_str());
+ m_logger(m_errorStr);
+
+ ++ptr;
+ }
+
+ return false;
+}
+
+void CONFIGPROTO::RegisterParsers()
+{
+ assert(m_settings != NULL);
+ assert(m_store != NULL);
+ assert(m_admins != NULL);
+ assert(m_users != NULL);
+ assert(m_tariffs != NULL);
+ assert(m_services != NULL);
+ assert(m_corporations != NULL);
+
+ SP::GET_SERVER_INFO::FACTORY::Register(m_registry, *m_settings, *m_users, *m_tariffs);
+
+ SP::GET_ADMINS::FACTORY::Register(m_registry, *m_admins);
+ SP::ADD_ADMIN::FACTORY::Register(m_registry, *m_admins);
+ SP::DEL_ADMIN::FACTORY::Register(m_registry, *m_admins);
+ SP::CHG_ADMIN::FACTORY::Register(m_registry, *m_admins);
+
+ SP::GET_TARIFFS::FACTORY::Register(m_registry, *m_tariffs);
+ SP::ADD_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
+ SP::DEL_TARIFF::FACTORY::Register(m_registry, *m_tariffs, *m_users);
+ SP::CHG_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
+
+ SP::GET_USERS::FACTORY::Register(m_registry, *m_users);
+ SP::GET_USER::FACTORY::Register(m_registry, *m_users);
+ SP::ADD_USER::FACTORY::Register(m_registry, *m_users);
+ SP::DEL_USER::FACTORY::Register(m_registry, *m_users);
+ SP::CHG_USER::FACTORY::Register(m_registry, *m_users, *m_store, *m_tariffs);
+ SP::CHECK_USER::FACTORY::Register(m_registry, *m_users);
+
+ SP::GET_SERVICES::FACTORY::Register(m_registry, *m_services);
+ SP::GET_SERVICE::FACTORY::Register(m_registry, *m_services);
+ SP::ADD_SERVICE::FACTORY::Register(m_registry, *m_services);
+ SP::DEL_SERVICE::FACTORY::Register(m_registry, *m_services);
+ SP::CHG_SERVICE::FACTORY::Register(m_registry, *m_services);
+
+ SP::SEND_MESSAGE::FACTORY::Register(m_registry, *m_users);
+
+ SP::AUTH_BY::FACTORY::Register(m_registry, *m_users);
+
+ SP::USER_INFO::FACTORY::Register(m_registry, *m_users);
+}
+
+int CONFIGPROTO::MaxFD() const
+{
+ int maxFD = m_listenSocket;
+ std::deque<STG::Conn *>::const_iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ if (maxFD < (*it)->Sock())
+ maxFD = (*it)->Sock();
+ return maxFD;
+}
+
+void CONFIGPROTO::BuildFDSet(fd_set & fds) const
+{
+ FD_ZERO(&fds);
+ FD_SET(m_listenSocket, &fds);
+ std::deque<STG::Conn *>::const_iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ FD_SET((*it)->Sock(), &fds);
+}
+
+void CONFIGPROTO::CleanupConns()
+{
+ std::deque<STG::Conn *>::iterator pos;
+ for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
+ if (((*pos)->IsDone() && !(*pos)->IsKeepAlive()) || !(*pos)->IsOk())
+ {
+ delete *pos;
+ *pos = NULL;
+ }
+
+ pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
+ m_conns.erase(pos, m_conns.end());
+}
+
+void CONFIGPROTO::HandleEvents(const fd_set & fds)
+{
+ if (FD_ISSET(m_listenSocket, &fds))
+ AcceptConnection();
+ else
+ {
+ std::deque<STG::Conn *>::iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ if (FD_ISSET((*it)->Sock(), &fds))
+ (*it)->Read();
+ }
+}
+
+void CONFIGPROTO::AcceptConnection()
+{
+ struct sockaddr_in outerAddr;
+ socklen_t outerAddrLen(sizeof(outerAddr));
+ int sock = accept(m_listenSocket, reinterpret_cast<sockaddr *>(&outerAddr), &outerAddrLen);
+
+ if (sock < 0)
+ {
+ m_errorStr = std::string("Failed to accept connection: '") + strerror(errno) + "'.";
+ printfd(__FILE__, "%s\n", m_errorStr.c_str());
+ m_logger(m_errorStr);
+ return;
+ }
+
+ assert(m_admins != NULL);
+
+ try
+ {
+ m_conns.push_back(new STG::Conn(m_registry, *m_admins, sock, outerAddr, m_logger));
+ printfd(__FILE__, "New connection from %s:%d. Total connections: %d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port(), m_conns.size());
+ }
+ catch (const STG::Conn::Error & error)
+ {
+ // Unlikely.
+ m_logger(std::string("Failed to create new client connection: '") + error.what() + "'.");
+ }
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef CONFIGPROTO_H
+#define CONFIGPROTO_H
+
+#include "parser.h"
+
+#include "stg/module_settings.h"
+
+#include <string>
+#include <deque>
+#include <cstdint>
+
+#include <sys/select.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+class SETTINGS;
+class ADMINS;
+class TARIFFS;
+class USERS;
+class SERVICES;
+class CORPORATIONS;
+class STORE;
+class PLUGIN_LOGGER;
+
+namespace STG
+{
+
+class Conn;
+
+}
+
+class CONFIGPROTO {
+public:
+ explicit CONFIGPROTO(PLUGIN_LOGGER & l);
+ ~CONFIGPROTO();
+
+ void SetPort(uint16_t port) { m_port = port; }
+ void SetBindAddress(const std::string & address) { m_bindAddress = address; }
+ void SetSettings(const SETTINGS * settings) { m_settings = settings; }
+ void SetAdmins(ADMINS * admins) { m_admins = admins; }
+ void SetTariffs(TARIFFS * tariffs) { m_tariffs = tariffs; }
+ void SetUsers(USERS * users) { m_users = users; }
+ void SetStore(STORE * store) { m_store = store; }
+ void SetServices(SERVICES * services) { m_services = services; }
+ void SetCorporations(CORPORATIONS * corporations) { m_corporations = corporations; }
+
+ int Prepare();
+ int Stop();
+ const std::string & GetStrError() const { return m_errorStr; }
+ void Run();
+
+private:
+ CONFIGPROTO(const CONFIGPROTO & rvalue);
+ CONFIGPROTO & operator=(const CONFIGPROTO & rvalue);
+
+ const SETTINGS * m_settings;
+ ADMINS * m_admins;
+ TARIFFS * m_tariffs;
+ USERS * m_users;
+ SERVICES * m_services;
+ CORPORATIONS * m_corporations;
+ STORE * m_store;
+
+ uint16_t m_port;
+ std::string m_bindAddress;
+ bool m_running;
+ bool m_stopped;
+ PLUGIN_LOGGER & m_logger;
+ int m_listenSocket;
+
+ std::string m_errorStr;
+
+ BASE_PARSER::REGISTRY m_registry;
+ std::deque<STG::Conn *> m_conns;
+
+ bool Bind();
+
+ void RegisterParsers();
+
+ int MaxFD() const;
+ void BuildFDSet(fd_set & fds) const;
+ void CleanupConns();
+ void HandleEvents(const fd_set & fds);
+ void AcceptConnection();
+};
+
+#endif //CONFIGPROTO_H
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "conn.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/logger.h"
+#include "stg/blowfish.h"
+#include "stg/bfstream.h"
+#include "stg/common.h"
+
+#include <cassert>
+#include <cstring>
+#include <cerrno>
+
+#include <unistd.h>
+#include <sys/socket.h>
+
+using STG::Conn;
+
+const char Conn::STG_HEADER[] = "SG04";
+const char Conn::OK_HEADER[] = "OKHD";
+const char Conn::ERR_HEADER[] = "ERHD";
+const char Conn::OK_LOGIN[] = "OKLG";
+const char Conn::ERR_LOGIN[] = "ERLG";
+const char Conn::OK_LOGINS[] = "OKLS";
+const char Conn::ERR_LOGINS[] = "ERLS";
+
+Conn::Conn(const BASE_PARSER::REGISTRY & registry,
+ ADMINS & admins, int sock, const sockaddr_in& addr,
+ PLUGIN_LOGGER & logger)
+ : m_registry(registry),
+ m_admins(admins),
+ m_admin(NULL),
+ m_sock(sock),
+ m_addr(addr),
+ m_keepAlive(false),
+ m_parser(NULL),
+ m_xmlParser(XML_ParserCreate(NULL)),
+ m_state(HEADER),
+ m_buffer(m_header),
+ m_bufferSize(sizeof(m_header)),
+ m_stream(NULL),
+ m_logger(logger),
+#ifdef DUMPCRYPTO
+ m_dataState(false, *this),
+ m_dumper(endpoint())
+#else
+ m_dataState(false, *this)
+#endif
+{
+ if (m_xmlParser == NULL)
+ throw Error("Failed to create XML parser.");
+
+ XML_ParserReset(m_xmlParser, NULL);
+ XML_SetElementHandler(m_xmlParser, ParseXMLStart, ParseXMLEnd);
+ XML_SetUserData(m_xmlParser, this);
+}
+
+Conn::~Conn()
+{
+ shutdown(m_sock, SHUT_RDWR);
+ close(m_sock);
+
+ XML_ParserFree(m_xmlParser);
+
+ delete m_stream;
+ delete m_parser;
+}
+
+bool Conn::Read()
+{
+ ssize_t res = read(m_sock, m_buffer, m_bufferSize);
+ if (res < 0)
+ {
+ m_state = ERROR;
+ Log(__FILE__, "Failed to read data from " + endpoint() + ". Reason: '" + strerror(errno) + "'");
+ return false;
+ }
+ if (res == 0 && m_state != DATA) // EOF is ok for data.
+ {
+ m_state = ERROR;
+ Log(__FILE__, "Failed to read data from " + endpoint() + ". Unexpected EOF.");
+ return false;
+ }
+#ifdef DUMPCRYPTO
+ m_dumper.write(m_buffer, res);
+#endif
+ m_bufferSize -= res;
+ m_buffer = static_cast<char*>(m_buffer) + res;
+ return HandleBuffer(res);
+}
+
+bool Conn::WriteAnswer(const void* buffer, size_t size)
+{
+ ssize_t res = write(m_sock, buffer, size);
+ if (res < 0)
+ {
+ m_state = ERROR;
+ Log(__FILE__, "Failed to write data to " + endpoint() + ". Reason: '" + strerror(errno) + "'.");
+ return false;
+ }
+ return true;
+}
+
+BASE_PARSER * Conn::GetParser(const std::string & tag) const
+{
+ BASE_PARSER::REGISTRY::const_iterator it = m_registry.find(ToLower(tag));
+ if (it == m_registry.end())
+ return NULL;
+ return it->second->create(*m_admin);
+}
+
+bool Conn::HandleBuffer(size_t size)
+{
+ if (m_state == DATA)
+ return HandleData(size);
+
+ if (m_bufferSize > 0)
+ return true;
+
+ switch (m_state)
+ {
+ case HEADER: return HandleHeader();
+ case LOGIN: return HandleLogin();
+ case CRYPTO_LOGIN: return HandleCryptoLogin();
+ default: return true;
+ }
+
+ return true;
+}
+
+bool Conn::HandleHeader()
+{
+ if (strncmp(m_header, STG_HEADER, sizeof(m_header)) != 0)
+ {
+ Log(__FILE__, "Received invalid header from " + endpoint() + ".");
+ WriteAnswer(ERR_HEADER, sizeof(ERR_HEADER) - 1); // Without \0
+ m_state = ERROR;
+ return false;
+ }
+ m_state = LOGIN;
+ m_buffer = m_login;
+ m_bufferSize = sizeof(m_login);
+ return WriteAnswer(OK_HEADER, sizeof(OK_HEADER) - 1); // Without \0
+}
+
+bool Conn::HandleLogin()
+{
+ if (m_admins.Find(m_login, &m_admin)) // ADMINS::Find returns true on error.
+ {
+ std::string login(m_login, strnlen(m_login, sizeof(m_login)));
+ Log(__FILE__, "Received invalid login '" + ToPrintable(login) + "' from " + endpoint() + ".");
+ WriteAnswer(ERR_LOGIN, sizeof(ERR_LOGIN) - 1); // Without \0
+ m_state = ERROR;
+ return false;
+ }
+ m_admin->SetIP(IP());
+ m_state = CRYPTO_LOGIN;
+ m_buffer = m_cryptoLogin;
+ m_bufferSize = sizeof(m_cryptoLogin);
+ return WriteAnswer(OK_LOGIN, sizeof(OK_LOGIN) - 1); // Without \0
+}
+
+bool Conn::HandleCryptoLogin()
+{
+ char login[ADM_LOGIN_LEN + 1];
+ BLOWFISH_CTX ctx;
+ InitContext(m_admin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+ DecryptString(login, m_cryptoLogin, ADM_LOGIN_LEN, &ctx);
+
+ if (strncmp(m_login, login, sizeof(login)) != 0)
+ {
+ Log(__FILE__, "Attempt to connect with wrong password from " + m_admin->GetLogin() + "@" + endpoint() + ".");
+ WriteAnswer(ERR_LOGINS, sizeof(ERR_LOGINS) - 1); // Without \0
+ m_state = ERROR;
+ return false;
+ }
+
+ m_state = DATA;
+ m_buffer = m_data;
+ m_bufferSize = sizeof(m_data);
+ m_stream = new STG::DECRYPT_STREAM(m_admin->GetPassword(), DataCallback, &m_dataState);
+ return WriteAnswer(OK_LOGINS, sizeof(OK_LOGINS) - 1); // Without \0
+}
+
+bool Conn::HandleData(size_t size)
+{
+ m_stream->Put(m_data, size, size == 0 || memchr(m_data, 0, size) != NULL);
+ m_buffer = m_data;
+ return m_stream->IsOk();
+}
+
+bool Conn::DataCallback(const void * block, size_t size, void * data)
+{
+ assert(data != NULL);
+ DataState& state = *static_cast<DataState *>(data);
+
+ const char * xml = static_cast<const char *>(block);
+ size_t length = strnlen(xml, size);
+
+ state.final = state.final || length < size || size == 0;
+
+ if (XML_Parse(state.conn.m_xmlParser, xml, length, state.final) == XML_STATUS_ERROR)
+ {
+ state.conn.Log(__FILE__, "Received invalid XML from " + state.conn.m_admin->GetLogin() + "@" + state.conn.endpoint() + ".");
+ printfd(__FILE__, "XML parse error at line %d, %d: %s. Is final: %d\n",
+ static_cast<int>(XML_GetCurrentLineNumber(state.conn.m_xmlParser)),
+ static_cast<int>(XML_GetCurrentColumnNumber(state.conn.m_xmlParser)),
+ XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), (int)state.final);
+ printfd(__FILE__, "Data block: '%s' of size %d\n", xml, length);
+ state.conn.m_state = ERROR;
+ return false;
+ }
+
+ if (state.final)
+ {
+ if (!state.conn.WriteResponse())
+ {
+ state.conn.Log(__FILE__, "Failed to write response to " + state.conn.m_admin->GetLogin() + "@" + state.conn.endpoint() + ".");
+ state.conn.m_state = ERROR;
+ return false;
+ }
+ state.conn.m_state = DONE;
+ }
+
+ return true;
+}
+
+void Conn::ParseXMLStart(void * data, const char * el, const char ** attr)
+{
+ assert(data != NULL);
+ Conn & conn = *static_cast<Conn *>(data);
+
+ if (conn.m_parser == NULL)
+ conn.m_parser = conn.GetParser(el);
+
+ if (conn.m_parser == NULL)
+ {
+ conn.Log(__FILE__, "Received unknown command '" + std::string(el) + "' from " + conn.m_admin->GetLogin() + "@" + conn.endpoint() + ".");
+ conn.m_state = ERROR;
+ return;
+ }
+
+ conn.m_parser->Start(data, el, attr);
+}
+
+void Conn::ParseXMLEnd(void * data, const char * el)
+{
+ assert(data != NULL);
+ Conn & conn = *static_cast<Conn *>(data);
+
+ if (conn.m_parser == NULL)
+ {
+ // No need to log it.
+ conn.m_state = ERROR;
+ return;
+ }
+
+ conn.m_parser->End(data, el);
+}
+
+bool Conn::WriteResponse()
+{
+ STG::ENCRYPT_STREAM stream(m_admin->GetPassword(), WriteCallback, this);
+ std::string answer;
+ if (m_parser != NULL)
+ answer = m_parser->GetAnswer();
+ else
+ answer = "<Error result=\"Unknown command.\"/>";
+ delete m_parser;
+ m_parser = NULL;
+ printfd(__FILE__, "Writing %d bytes of answer.\n", answer.length());
+ stream.Put(answer.c_str(), answer.length() + 1 /* including \0 */, true /* final */);
+ return stream.IsOk();
+}
+
+bool Conn::WriteCallback(const void * block, size_t size, void * data)
+{
+ assert(data != NULL);
+ Conn & conn = *static_cast<Conn *>(data);
+ return WriteAll(conn.m_sock, block, size);;
+}
+
+void Conn::Log(const char * file, const std::string & message)
+{
+ printfd(file, "%s\n", message.c_str());
+ m_logger(message);
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_CONN_H__
+#define __STG_SGCONFIG_CONN_H__
+
+#include "parser.h"
+
+#include "dumphelpers.h"
+
+#include "stg/const.h"
+
+#include <stdexcept>
+#include <string>
+#include <cstdint>
+
+#include <expat.h>
+
+#include <netinet/in.h>
+
+class SETTINGS;
+class ADMINS;
+class USERS;
+class TARIFFS;
+class ADMIN;
+class BASE_PARSER;
+class PLUGIN_LOGGER;
+
+namespace STG
+{
+
+class DECRYPT_STREAM;
+
+class Conn
+{
+ public:
+ struct Error : public std::runtime_error
+ {
+ explicit Error(const std::string& message) : runtime_error(message.c_str()) {}
+ };
+
+ Conn(const BASE_PARSER::REGISTRY & registry,
+ ADMINS & admins, int sock, const sockaddr_in& addr,
+ PLUGIN_LOGGER & logger);
+ ~Conn();
+
+ int Sock() const { return m_sock; }
+ uint32_t IP() const { return *(uint32_t *)(&m_addr.sin_addr); }
+ uint16_t Port() const { return ntohs(m_addr.sin_port); }
+
+ std::string endpoint() const { return inet_ntostring(IP()) + ":" + x2str(Port()); }
+
+ bool Read();
+
+ bool IsOk() const { return m_state != ERROR; }
+ bool IsDone() const { return m_state == DONE; }
+ bool IsKeepAlive() const { return m_keepAlive; }
+
+ void SetKeepAlive() { m_keepAlive = true; }
+
+ private:
+
+ static const char STG_HEADER[5];
+ static const char OK_HEADER[5];
+ static const char ERR_HEADER[5];
+ static const char OK_LOGIN[5];
+ static const char ERR_LOGIN[5];
+ static const char OK_LOGINS[5];
+ static const char ERR_LOGINS[5];
+
+ const BASE_PARSER::REGISTRY & m_registry;
+
+ ADMINS & m_admins;
+
+ ADMIN * m_admin;
+
+ int m_sock;
+ sockaddr_in m_addr;
+ bool m_keepAlive;
+
+ BASE_PARSER * m_parser;
+
+ XML_Parser m_xmlParser;
+
+ enum { HEADER, LOGIN, CRYPTO_LOGIN, DATA, DONE, ERROR } m_state;
+
+ void * m_buffer;
+ size_t m_bufferSize;
+ char m_header[sizeof(STG_HEADER) - 1]; // Without \0
+ char m_login[ADM_LOGIN_LEN]; // Without \0
+ char m_cryptoLogin[ADM_LOGIN_LEN]; // Without \0
+ char m_data[1024];
+ STG::DECRYPT_STREAM * m_stream;
+ PLUGIN_LOGGER & m_logger;
+
+ BASE_PARSER * GetParser(const std::string & tag) const;
+
+ bool HandleBuffer(size_t size);
+
+ bool HandleHeader();
+ bool HandleLogin();
+ bool HandleCryptoLogin();
+ bool HandleData(size_t size);
+
+ bool WriteAnswer(const void* buffer, size_t size);
+ bool WriteResponse();
+
+ void Log(const char * file, const std::string & message);
+
+ struct DataState
+ {
+ DataState(bool f, Conn & c) : final(f), conn(c) {}
+ bool final;
+ Conn & conn;
+ } m_dataState;
+
+#ifdef DUMPCRYPTO
+ Dumper m_dumper;
+#endif
+
+ static bool DataCallback(const void * block, size_t size, void * data);
+ static void ParseXMLStart(void * data, const char * el, const char ** attr);
+ static void ParseXMLEnd(void * data, const char * el);
+ static bool WriteCallback(const void * block, size_t size, void * data);
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef __STG_DUMP_HELPERS_H__
+#define __STG_DUMP_HELPERS_H__
+
+#include "stg/common.h"
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+
+#include <cstddef>
+#include <ctime>
+
+namespace STG
+{
+
+class Dumper
+{
+ public:
+ explicit Dumper(const std::string& tag)
+ : m_stream(getName(tag).c_str())
+ {
+ }
+ ~Dumper() {}
+
+ void write(const void* data, size_t size)
+ {
+ writePrefix();
+ m_stream << " ";
+ writeHEX(data, size);
+ }
+
+ private:
+ std::ofstream m_stream;
+
+ tm getTime() const
+ {
+ time_t now = time(NULL);
+ tm localTime;
+ localtime_r(&now, &localTime);
+ return localTime;
+ }
+
+ std::string getName(const std::string& tag) const
+ {
+ tm localTime = getTime();
+
+ std::ostringstream res;
+ res << tag
+ << "-" << (localTime.tm_year + 1900) << twoDigit(localTime.tm_mon + 1) << twoDigit(localTime.tm_mday)
+ << "-" << twoDigit(localTime.tm_hour) << twoDigit(localTime.tm_min) << twoDigit(localTime.tm_sec)
+ << ".data";
+
+ return res.str();
+ }
+
+ void writePrefix()
+ {
+ tm localTime = getTime();
+ m_stream << "[" << (localTime.tm_year + 1900) << "-" << twoDigit(localTime.tm_mon + 1) << "-" << twoDigit(localTime.tm_mday)
+ << " " << twoDigit(localTime.tm_hour) << ":" << twoDigit(localTime.tm_min) << ":" << twoDigit(localTime.tm_sec)
+ << "]";
+ }
+
+ void writeHEX(const void* data, size_t size)
+ {
+ m_stream << "(" << std::setw(4) << std::setfill(' ') << size << ") ";
+ const unsigned char* pos = static_cast<const unsigned char*>(data);
+ for (size_t i = 0; i < size; ++i)
+ m_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*pos++);
+ m_stream << std::dec << "\n";
+ }
+
+ std::string twoDigit(int value) const
+ {
+ std::string res = x2str(value);
+ if (res.length() < 2)
+ res = "0" + res;
+ return res;
+ }
+};
+
+} // namespace Caster
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#include "parser.h"
+
+#include <cstring>
+
+//-----------------------------------------------------------------------------
+// BASE PARSER
+//-----------------------------------------------------------------------------
+int BASE_PARSER::Start(void *, const char * el, const char **)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ return 0;
+
+ return -1;
+}
+//-----------------------------------------------------------------------------
+int BASE_PARSER::End(void *, const char * el)
+{
+ if (m_depth < 2)
+ {
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+ CreateAnswer();
+ }
+
+ --m_depth;
+ return 0;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <string>
+#include <map>
+
+class ADMIN;
+
+class BASE_PARSER
+{
+ public:
+ struct FACTORY
+ {
+ virtual ~FACTORY() {}
+ virtual BASE_PARSER * create(const ADMIN & admin) = 0;
+ };
+ typedef std::map<std::string, FACTORY *> REGISTRY;
+
+ BASE_PARSER(const ADMIN & admin, const std::string & t)
+ : m_currAdmin(admin),
+ m_depth(0),
+ m_tag(t)
+ {}
+ virtual ~BASE_PARSER() {}
+ virtual int Start(void * data, const char * el, const char ** attr);
+ virtual int End(void * data, const char * el);
+
+ const std::string & GetAnswer() const { return m_answer; }
+ const std::string & GetTag() const { return m_tag; }
+ std::string GetOpenTag() const { return "<" + m_tag + ">"; }
+ std::string GetCloseTag() const { return "</" + m_tag + ">"; }
+
+ protected:
+ BASE_PARSER(const BASE_PARSER & rvalue);
+ BASE_PARSER & operator=(const BASE_PARSER & rvalue);
+
+ const ADMIN & m_currAdmin;
+ size_t m_depth;
+ std::string m_answer;
+ std::string m_tag;
+
+ private:
+ virtual void CreateAnswer() = 0;
+};
+
+#endif //PARSER_H
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_admins.h"
+
+#include "stg/admins.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::GET_ADMINS;
+using STG::PARSER::ADD_ADMIN;
+using STG::PARSER::DEL_ADMIN;
+using STG::PARSER::CHG_ADMIN;
+
+const char * GET_ADMINS::tag = "GetAdmins";
+const char * ADD_ADMIN::tag = "AddAdmin";
+const char * DEL_ADMIN::tag = "DelAdmin";
+const char * CHG_ADMIN::tag = "ChgAdmin";
+
+void GET_ADMINS::CreateAnswer()
+{
+ const PRIV * priv = m_currAdmin.GetPriv();
+ if (!priv->adminChg)
+ {
+ m_answer = "<Error Result=\"Error. Access denied.\"/>";
+ return;
+ }
+
+ m_answer = "<Admins>";
+ ADMIN_CONF ac;
+ int h = m_admins.OpenSearch();
+
+ while (m_admins.SearchNext(h, &ac) == 0)
+ {
+ unsigned int p = (ac.priv.userStat << 0) +
+ (ac.priv.userConf << 2) +
+ (ac.priv.userCash << 4) +
+ (ac.priv.userPasswd << 6) +
+ (ac.priv.userAddDel << 8) +
+ (ac.priv.adminChg << 10) +
+ (ac.priv.tariffChg << 12);
+ m_answer += "<admin login=\"" + ac.login + "\" priv=\"" + x2str(p) + "\"/>";
+ }
+ m_admins.CloseSearch(h);
+ m_answer += "</Admins>";
+}
+
+int DEL_ADMIN::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ m_admin = attr[1];
+ return 0;
+ }
+ return -1;
+}
+
+void DEL_ADMIN::CreateAnswer()
+{
+ if (m_admins.Del(m_admin, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.GetStrError() + "\"/>";
+}
+
+int ADD_ADMIN::Start(void *, const char *el, const char **attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ m_admin = attr[1];
+ return 0;
+ }
+ return -1;
+}
+
+void ADD_ADMIN::CreateAnswer()
+{
+ if (m_admins.Add(m_admin, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.GetStrError() + "\"/>";
+}
+
+int CHG_ADMIN::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ for (size_t i = 0; i < 6; i += 2)
+ {
+ printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
+ if (attr[i] == NULL)
+ break;
+
+ if (strcasecmp(attr[i], "Login") == 0)
+ {
+ login = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Priv") == 0)
+ {
+ privAsString = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Password") == 0)
+ {
+ password = attr[i + 1];
+ continue;
+ }
+ }
+
+ return 0;
+ }
+ return -1;
+}
+
+void CHG_ADMIN::CreateAnswer()
+{
+ if (!login.empty())
+ {
+ ADMIN * origAdmin = NULL;
+
+ if (m_admins.Find(login, &origAdmin))
+ {
+ m_answer = "<" + m_tag + " Result = \"Admin '" + login + "' is not found.\"/>";
+ return;
+ }
+
+ ADMIN_CONF conf(origAdmin->GetConf());
+
+ if (!password.empty())
+ conf.password = password.data();
+
+ if (!privAsString.empty())
+ {
+ int p = 0;
+ if (str2x(privAsString.data().c_str(), p) < 0)
+ {
+ m_answer = "<" + m_tag + " Result = \"Incorrect parameter Priv.\"/>";
+ return;
+ }
+
+ conf.priv.FromInt(p);
+ }
+
+ if (m_admins.Change(conf, &m_currAdmin) != 0)
+ m_answer = "<" + m_tag + " Result = \"" + m_admins.GetStrError() + "\"/>";
+ else
+ m_answer = "<" + m_tag + " Result = \"Ok\"/>";
+ }
+ else
+ m_answer = "<" + m_tag + " Result = \"Incorrect parameter login.\"/>";
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_ADMINS_H__
+#define __STG_SGCONFIG_PARSER_ADMINS_H__
+
+#include "parser.h"
+
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+
+class ADMINS;
+class ADMIN;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class GET_ADMINS: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(const ADMINS & admins) : m_admins(admins) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_ADMINS(admin, m_admins); }
+ static void Register(REGISTRY & registry, const ADMINS & admins)
+ { registry[ToLower(tag)] = new FACTORY(admins); }
+ private:
+ const ADMINS & m_admins;
+ };
+
+ static const char * tag;
+
+ GET_ADMINS(const ADMIN & admin, const ADMINS & admins)
+ : BASE_PARSER(admin, tag), m_admins(admins) {}
+
+ private:
+ const ADMINS & m_admins;
+
+ void CreateAnswer();
+};
+
+class ADD_ADMIN: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_ADMIN(admin, m_admins); }
+ static void Register(REGISTRY & registry, ADMINS & admins)
+ { registry[ToLower(tag)] = new FACTORY(admins); }
+ private:
+ ADMINS & m_admins;
+ };
+
+ static const char * tag;
+
+ ADD_ADMIN(const ADMIN & admin, ADMINS & admins)
+ : BASE_PARSER(admin, tag), m_admins(admins) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string m_admin;
+ ADMINS & m_admins;
+
+ void CreateAnswer();
+};
+
+class DEL_ADMIN: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_ADMIN(admin, m_admins); }
+ static void Register(REGISTRY & registry, ADMINS & admins)
+ { registry[ToLower(tag)] = new FACTORY(admins); }
+ private:
+ ADMINS & m_admins;
+ };
+
+ static const char * tag;
+
+ DEL_ADMIN(const ADMIN & admin, ADMINS & admins)
+ : BASE_PARSER(admin, tag), m_admins(admins) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string m_admin;
+ ADMINS & m_admins;
+
+ void CreateAnswer();
+};
+
+class CHG_ADMIN: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(ADMINS & admins) : m_admins(admins) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_ADMIN(admin, m_admins); }
+ static void Register(REGISTRY & registry, ADMINS & admins)
+ { registry[ToLower(tag)] = new FACTORY(admins); }
+ private:
+ ADMINS & m_admins;
+ };
+
+ static const char * tag;
+
+ CHG_ADMIN(const ADMIN & admin, ADMINS & admins)
+ : BASE_PARSER(admin, tag), m_admins(admins) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string login;
+ RESETABLE<std::string> password;
+ RESETABLE<std::string> privAsString;
+ ADMINS & m_admins;
+
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "parser_auth_by.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+
+using STG::PARSER::AUTH_BY;
+
+const char * AUTH_BY::tag = "GetUserAuthBy";
+
+int AUTH_BY::Start(void * /*data*/, const char *el, const char **attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ if (!attr[1])
+ return -1;
+
+ m_login = attr[1];
+ return 0;
+}
+
+void AUTH_BY::CreateAnswer()
+{
+ CONST_USER_PTR u;
+ if (m_users.FindByName(m_login, &u))
+ {
+ m_answer = "<AuthorizedBy result=\"error\" reason=\"User not found.\"/>";
+ return;
+ }
+
+ m_answer = "<AuthorizedBy result=\"ok\">";
+ std::vector<std::string> list(u->GetAuthorizers());
+ for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+ m_answer += "<Auth name=\"" + *it + "\"/>";
+ m_answer += "</AuthorizedBy>";
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_PARSER_AUTH_BY_H__
+#define __STG_PARSER_AUTH_BY_H__
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+class ADMIN;
+class USERS;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class AUTH_BY : public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(const USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new AUTH_BY(admin, m_users); }
+ static void Register(REGISTRY & registry, const USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ const USERS & m_users;
+ };
+
+ static const char * tag;
+
+ AUTH_BY(const ADMIN & admin, const USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ const USERS & m_users;
+ std::string m_login;
+
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_message.h"
+
+#include "stg/users.h"
+
+extern volatile time_t stgTime; // So sad...
+
+using STG::PARSER::SEND_MESSAGE;
+
+const char * SEND_MESSAGE::tag = "Message";
+
+int SEND_MESSAGE::Start(void *, const char *el, const char **attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ for (size_t i = 0; i < 14; i++)
+ if (attr[i] == NULL)
+ {
+ m_result = res_params_error;
+ CreateAnswer();
+ printfd(__FILE__, "To few parameters\n");
+ return 0;
+ }
+
+ for (size_t i = 0; i < 14; i += 2)
+ {
+ if (strcasecmp(attr[i], "login") == 0)
+ ParseLogins(attr[i + 1]);
+
+ if (strcasecmp(attr[i], "MsgVer") == 0)
+ {
+ str2x(attr[i + 1], m_msg.header.ver);
+ if (m_msg.header.ver != 1)
+ m_result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "MsgType") == 0)
+ {
+ str2x(attr[i + 1], m_msg.header.type);
+ if (m_msg.header.type != 1)
+ m_result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "Repeat") == 0)
+ {
+ str2x(attr[i + 1], m_msg.header.repeat);
+ if (m_msg.header.repeat < 0)
+ m_result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "RepeatPeriod") == 0)
+ str2x(attr[i + 1], m_msg.header.repeatPeriod);
+
+ if (strcasecmp(attr[i], "ShowTime") == 0)
+ str2x(attr[i + 1], m_msg.header.showTime);
+
+ if (strcasecmp(attr[i], "Text") == 0)
+ {
+ Decode21str(m_msg.text, attr[i + 1]);
+ m_result = res_ok;
+ }
+ }
+ return 0;
+}
+
+int SEND_MESSAGE::End(void *, const char *el)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ m_result = res_unknown;
+ for (unsigned i = 0; i < m_logins.size(); i++)
+ {
+ if (m_users.FindByName(m_logins[i], &m_user))
+ {
+ printfd(__FILE__, "User not found. %s\n", m_logins[i].c_str());
+ continue;
+ }
+ m_msg.header.creationTime = static_cast<unsigned int>(stgTime);
+ m_user->AddMessage(&m_msg);
+ m_result = res_ok;
+ }
+ CreateAnswer();
+ return 0;
+}
+
+int SEND_MESSAGE::ParseLogins(const char * login)
+{
+ char * p;
+ char * l = new char[strlen(login) + 1];
+ strcpy(l, login);
+ p = strtok(l, ":");
+ m_logins.clear();
+ while (p)
+ {
+ m_logins.push_back(p);
+ p = strtok(NULL, ":");
+ }
+
+ delete[] l;
+ return 0;
+}
+
+void SEND_MESSAGE::CreateAnswer()
+{
+ switch (m_result)
+ {
+ case res_ok:
+ m_answer = "<SendMessageResult value=\"ok\"/>";
+ break;
+ case res_params_error:
+ m_answer = "<SendMessageResult value=\"Parameters error.\"/>";
+ break;
+ case res_unknown:
+ m_answer = "<SendMessageResult value=\"Unknown user.\"/>";
+ break;
+ }
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_SEND_MESSAGE_H__
+#define __STG_SGCONFIG_PARSER_SEND_MESSAGE_H__
+
+#include "parser.h"
+
+#include "stg/message.h"
+#include "stg/common.h"
+
+#include <vector>
+#include <string>
+
+class USERS;
+class USER;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class SEND_MESSAGE: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new SEND_MESSAGE(admin, m_users); }
+ static void Register(REGISTRY & registry, USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ USERS & m_users;
+ };
+
+ static const char * tag;
+
+ SEND_MESSAGE(const ADMIN & admin, USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users), m_result(res_ok), m_user(NULL) {}
+ int Start(void *data, const char *el, const char **attr);
+ int End(void *data, const char *el);
+
+ private:
+ USERS & m_users;
+ std::vector<std::string> m_logins;
+ enum { res_ok, res_params_error, res_unknown } m_result;
+ STG_MSG m_msg;
+ USER * m_user;
+
+ int ParseLogins(const char * logins);
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_server_info.h"
+
+#include "stg/settings.h"
+#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/version.h"
+#include "stg/const.h"
+
+#include <string>
+#include <cstring>
+
+#include <sys/utsname.h>
+
+using STG::PARSER::GET_SERVER_INFO;
+
+const char * GET_SERVER_INFO::tag = "GetServerInfo";
+
+void GET_SERVER_INFO::CreateAnswer()
+{
+ struct utsname utsn;
+ uname(&utsn);
+
+ std::string name = std::string(utsn.sysname) + " " +
+ utsn.release + " " +
+ utsn.machine + " " +
+ utsn.nodename;
+
+ m_answer = std::string("<ServerInfo><version value=\"") + SERVER_VERSION + "\"/>" +
+ "<tariff_num value=\"" + x2str(m_tariffs.Count()) + "\"/>" +
+ "<tariff value=\"2\"/>" +
+ "<user_num value=\"" + x2str(m_users.Count()) + "\"/>" +
+ "<uname value=\"" + name + "\"/>" +
+ "<dir_num value=\"" + x2str(DIR_NUM) + "\"/>" +
+ "<day_fee value=\"" + x2str(m_settings.GetDayFee()) + "\"/>";
+
+ for (size_t i = 0; i< DIR_NUM; i++)
+ m_answer += "<dir_name_" + x2str(i) + " value=\"" + Encode12str(m_settings.GetDirName(i)) + "\"/>";
+
+ m_answer += "</ServerInfo>";
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_SERVER_INFO_H__
+#define __STG_SGCONFIG_PARSER_SERVER_INFO_H__
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+class ADMIN;
+class SETTINGS;
+class USERS;
+class TARIFFS;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class GET_SERVER_INFO: public BASE_PARSER {
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(const SETTINGS & settings, const USERS & users, const TARIFFS & tariffs)
+ : m_settings(settings), m_users(users), m_tariffs(tariffs) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
+ static void Register(REGISTRY & registry, const SETTINGS & settings, const USERS & users, const TARIFFS & tariffs)
+ { registry[ToLower(tag)] = new FACTORY(settings, users, tariffs); }
+ private:
+ const SETTINGS & m_settings;
+ const USERS & m_users;
+ const TARIFFS & m_tariffs;
+ };
+
+ static const char * tag;
+
+ GET_SERVER_INFO(const ADMIN & admin,
+ const SETTINGS & settings,
+ const USERS & users,
+ const TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag),
+ m_settings(settings),
+ m_users(users),
+ m_tariffs(tariffs)
+ {}
+
+ private:
+ const SETTINGS & m_settings;
+ const USERS & m_users;
+ const TARIFFS & m_tariffs;
+
+ void CreateAnswer();
+};
+
+}
+}
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "parser_services.h"
+
+#include "stg/services.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::GET_SERVICES;
+using STG::PARSER::GET_SERVICE;
+using STG::PARSER::ADD_SERVICE;
+using STG::PARSER::DEL_SERVICE;
+using STG::PARSER::CHG_SERVICE;
+
+const char * GET_SERVICES::tag = "GetServices";
+const char * GET_SERVICE::tag = "AddService";
+const char * ADD_SERVICE::tag = "AddService";
+const char * DEL_SERVICE::tag = "DelService";
+const char * CHG_SERVICE::tag = "SetService";
+
+void GET_SERVICES::CreateAnswer()
+{
+ // TODO: no priviledges implemented yet
+ /*const PRIV * priv = m_currAdmin.GetPriv();
+ if (!priv->serviceChg)
+ {
+ m_answer = "<Error Result=\"Error. Access denied.\"/>";
+ return;
+ }*/
+
+ m_answer = "<Services>";
+ SERVICE_CONF conf;
+ int h = m_services.OpenSearch();
+ while (m_services.SearchNext(h, &conf) == 0)
+ {
+ m_answer += "<Service name=\"" + conf.name +
+ "\" comment=\"" + Encode12str(conf.comment) +
+ "\" cost=\"" + x2str(conf.cost) +
+ "\" payDay=\"" + x2str(conf.payDay) + "\"/>";
+ }
+ m_services.CloseSearch(h);
+ m_answer += "</Services>";
+}
+
+int GET_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ m_name = attr[1];
+ return 0;
+ }
+ return -1;
+}
+
+void GET_SERVICE::CreateAnswer()
+{
+ // TODO: no priviledges implemented yet
+ /*const PRIV * priv = m_currAdmin.GetPriv();
+ if (!priv->serviceChg)
+ {
+ m_answer = "<Error Result=\"Error. Access denied.\"/>";
+ return;
+ }*/
+
+ SERVICE_CONF conf;
+ if (!m_services.Find(m_name, &conf))
+ m_answer = "<Error result=\"Service '" + m_name + "' does not exist.\"/>";
+ else
+ m_answer += "<" + m_tag + " name=\"" + conf.name +
+ "\" comment=\"" + Encode12str(conf.comment) +
+ "\" cost=\"" + x2str(conf.cost) +
+ "\" payDay=\"" + x2str(conf.payDay) + "\"/>";
+}
+
+int ADD_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ m_name = attr[1];
+ return 0;
+ }
+ return -1;
+}
+
+void ADD_SERVICE::CreateAnswer()
+{
+ SERVICE_CONF conf(m_name);
+ if (m_services.Add(conf, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
+}
+
+int DEL_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ m_name = attr[1];
+ return 0;
+ }
+ return -1;
+}
+
+void DEL_SERVICE::CreateAnswer()
+{
+ if (m_services.Del(m_name, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
+}
+
+int CHG_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ for (size_t i = 0; i < 8; i += 2)
+ {
+ if (attr[i] == NULL)
+ break;
+
+ if (strcasecmp(attr[i], "name") == 0)
+ {
+ m_service.name = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "comment") == 0)
+ {
+ m_service.comment = Decode21str(attr[i + 1]);
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "cost") == 0)
+ {
+ double cost = 0;
+ if (str2x(attr[i + 1], cost) == 0)
+ m_service.cost = cost;
+ else
+ printfd(__FILE__, "Bad cast from '%s' to double\n", attr[i + 1]);
+ // TODO: log it
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "payDay") == 0)
+ {
+ unsigned payDay;
+ if (str2x(attr[i + 1], payDay) == 0)
+ m_service.payDay = payDay;
+ else
+ printfd(__FILE__, "Bad cast from '%s' to unsigned\n", attr[i + 1]);
+ // TODO: log it
+ continue;
+ }
+ }
+
+ return 0;
+ }
+ return -1;
+}
+
+void CHG_SERVICE::CreateAnswer()
+{
+ if (m_service.name.empty())
+ {
+ m_answer = "<" + m_tag + " result=\"Empty service name.\"/>";
+ return;
+ }
+
+ if (!m_services.Exists(m_service.name.const_data()))
+ {
+ m_answer = "<" + m_tag + " result = \"Service '" + m_service.name.const_data() + "' does not exist.\"/>";
+ return;
+ }
+
+ SERVICE_CONF orig;
+ m_services.Find(m_service.name.const_data(), &orig);
+
+ SERVICE_CONF_RES conf(orig);
+ conf.Splice(m_service);
+
+ if (m_services.Change(conf.GetData(), &m_currAdmin) != 0)
+ m_answer = "<" + m_tag + " result = \"" + m_services.GetStrError() + "\"/>";
+ else
+ m_answer = "<" + m_tag + " result = \"Ok\"/>";
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_SERVICES_H__
+#define __STG_SGCONFIG_PARSER_SERVICES_H__
+
+#include "parser.h"
+
+#include "stg/service_conf.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+class SERVICES;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class GET_SERVICES: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(const SERVICES & services) : m_services(services) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVICES(admin, m_services); }
+ static void Register(REGISTRY & registry, const SERVICES & services)
+ { registry[ToLower(tag)] = new FACTORY(services); }
+ private:
+ const SERVICES & m_services;
+ };
+
+ static const char * tag;
+
+ GET_SERVICES(const ADMIN & admin, const SERVICES & services)
+ : BASE_PARSER(admin, tag), m_services(services) {}
+
+ private:
+ const SERVICES & m_services;
+
+ void CreateAnswer();
+};
+
+class GET_SERVICE: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(const SERVICES & services) : m_services(services) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_SERVICE(admin, m_services); }
+ static void Register(REGISTRY & registry, SERVICES & services)
+ { registry[ToLower(tag)] = new FACTORY(services); }
+ private:
+ const SERVICES & m_services;
+ };
+
+ static const char * tag;
+
+ GET_SERVICE(const ADMIN & admin, const SERVICES & services)
+ : BASE_PARSER(admin, tag), m_services(services) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string m_name;
+ const SERVICES & m_services;
+
+ void CreateAnswer();
+};
+
+class ADD_SERVICE: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(SERVICES & services) : m_services(services) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_SERVICE(admin, m_services); }
+ static void Register(REGISTRY & registry, SERVICES & services)
+ { registry[ToLower(tag)] = new FACTORY(services); }
+ private:
+ SERVICES & m_services;
+ };
+
+ static const char * tag;
+
+ ADD_SERVICE(const ADMIN & admin, SERVICES & services)
+ : BASE_PARSER(admin, tag), m_services(services) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string m_name;
+ SERVICES & m_services;
+
+ void CreateAnswer();
+};
+
+class DEL_SERVICE: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(SERVICES & services) : m_services(services) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_SERVICE(admin, m_services); }
+ static void Register(REGISTRY & registry, SERVICES & services)
+ { registry[ToLower(tag)] = new FACTORY(services); }
+ private:
+ SERVICES & m_services;
+ };
+
+ static const char * tag;
+
+ DEL_SERVICE(const ADMIN & admin, SERVICES & services)
+ : BASE_PARSER(admin, tag), m_services(services) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string m_name;
+ SERVICES & m_services;
+
+ void CreateAnswer();
+};
+
+class CHG_SERVICE: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(SERVICES & services) : m_services(services) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_SERVICE(admin, m_services); }
+ static void Register(REGISTRY & registry, SERVICES & services)
+ { registry[ToLower(tag)] = new FACTORY(services); }
+ private:
+ SERVICES & m_services;
+ };
+
+ static const char * tag;
+
+ CHG_SERVICE(const ADMIN & admin, SERVICES & services)
+ : BASE_PARSER(admin, tag), m_services(services) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ SERVICE_CONF_RES m_service;
+ SERVICES & m_services;
+
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_tariffs.h"
+
+#include "stg/tariffs.h"
+#include "stg/users.h"
+#include "stg/resetable.h"
+
+#include <cstdio> // snprintf
+#include <cstring>
+
+using STG::PARSER::GET_TARIFFS;
+using STG::PARSER::ADD_TARIFF;
+using STG::PARSER::DEL_TARIFF;
+using STG::PARSER::CHG_TARIFF;
+
+const char * GET_TARIFFS::tag = "GetTariffs";
+const char * ADD_TARIFF::tag = "AddTariff";
+const char * DEL_TARIFF::tag = "DelTariff";
+const char * CHG_TARIFF::tag = "SetTariff";
+
+namespace
+{
+
+const double pt_mega = 1024 * 1024;
+
+template <typename A, typename C, typename F>
+std::string AOS2String(const A & array, size_t size, const F C::* field, F multiplier)
+{
+ std::string res;
+ for (size_t i = 0; i < size; ++i)
+ {
+ if (!res.empty())
+ res += "/";
+ res += x2str((array[i].*field) * multiplier);
+ }
+ return res;
+}
+
+template <typename T>
+bool str2res(const std::string& source, RESETABLE<T>& dest, T divisor)
+{
+ T value = 0;
+ if (str2x(source, value))
+ return false;
+ dest = value / divisor;
+ return true;
+}
+
+template <typename A, typename C, typename F>
+bool String2AOS(const std::string & source, A & array, size_t size, RESETABLE<F> C::* field, F divisor)
+{
+ size_t index = 0;
+ std::string::size_type from = 0;
+ std::string::size_type pos = 0;
+ while (index < size && (pos = source.find('/', from)) != std::string::npos)
+ {
+ if (!str2res(source.substr(from, pos - from), array[index].*field, divisor))
+ return false;
+ from = pos + 1;
+ ++index;
+ }
+ if (str2res(source.substr(from), array[index].*field, divisor))
+ return false;
+ return true;
+}
+
+}
+
+void GET_TARIFFS::CreateAnswer()
+{
+ m_answer = "<Tariffs>";
+
+ std::list<TARIFF_DATA> dataList;
+ m_tariffs.GetTariffsData(&dataList);
+ std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
+ for (; it != dataList.end(); ++it)
+ {
+ m_answer += "<tariff name=\"" + it->tariffConf.name + "\">";
+
+ for (size_t i = 0; i < DIR_NUM; i++)
+ m_answer += "<Time" + x2str(i) + " value=\"" +
+ x2str(it->dirPrice[i].hDay) + ":" + x2str(it->dirPrice[i].mDay) + "-" +
+ x2str(it->dirPrice[i].hNight) + ":" + x2str(it->dirPrice[i].mNight) + "\"/>";
+
+ m_answer += "<PriceDayA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceDayA, pt_mega) + "\"/>" +
+ "<PriceDayB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceDayB, pt_mega) + "\"/>" +
+ "<PriceNightA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceNightA, pt_mega) + "\"/>" +
+ "<PriceNightB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::priceNightB, pt_mega) + "\"/>" +
+ "<Threshold value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::threshold, 1) + "\"/>" +
+ "<SinglePrice value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::singlePrice, 1) + "\"/>" +
+ "<NoDiscount value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DIRPRICE_DATA::noDiscount, 1) + "\"/>" +
+ "<Fee value=\"" + x2str(it->tariffConf.fee) + "\"/>" +
+ "<PassiveCost value=\"" + x2str(it->tariffConf.passiveCost) + "\"/>" +
+ "<Free value=\"" + x2str(it->tariffConf.free) + "\"/>" +
+ "<TraffType value=\"" + TARIFF::TraffTypeToString(it->tariffConf.traffType) + "\"/>" +
+ "<Period value=\"" + TARIFF::PeriodToString(it->tariffConf.period) + "\"/>" +
+ "<ChangePolicy value=\"" + TARIFF::ChangePolicyToString(it->tariffConf.changePolicy) + "\"/>" +
+ "<ChangePolicyTimeout value=\"" + x2str(it->tariffConf.changePolicyTimeout) + "\"/>" +
+ "</tariff>";
+ }
+
+ m_answer += "</Tariffs>";
+}
+
+int ADD_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ if (attr[1] == NULL)
+ return -1;
+
+ tariff = attr[1];
+ return 0;
+}
+
+void ADD_TARIFF::CreateAnswer()
+{
+ if (m_tariffs.Add(tariff, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
+}
+
+int DEL_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ if (attr[1] == NULL)
+ return -1;
+
+ tariff = attr[1];
+ return 0;
+}
+
+void DEL_TARIFF::CreateAnswer()
+{
+ if (m_users.TariffInUse(tariff))
+ m_answer = "<" + m_tag + " Result=\"Error. Tariff \'" + tariff + "\' cannot be deleted, it is in use.\"/>";
+ else if (m_tariffs.Del(tariff, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+ else
+ m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
+}
+
+int CHG_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+ m_depth++;
+
+ if (m_depth == 1)
+ {
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ const TARIFF * tariff = m_tariffs.FindByName(attr[1]);
+ if (tariff != NULL)
+ td = tariff->GetTariffData();
+ else
+ return -1;
+ return 0;
+ }
+ }
+ else
+ {
+ if (strcasecmp(el, "PriceDayA") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceDayA, pt_mega))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceDayB") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceDayB, pt_mega))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceNightA") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceNightA, pt_mega))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceNightB") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::priceNightB, pt_mega))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "Threshold") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::threshold, 1))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "SinglePrice") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::singlePrice, 1))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ if (strcasecmp(el, "NoDiscount") == 0)
+ {
+ if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DIRPRICE_DATA_RES::noDiscount, 1))
+ return -1; // TODO: log it
+ else
+ return 0;
+ }
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ char st[50];
+ snprintf(st, 50, "Time%d", j);
+ if (strcasecmp(el, st) == 0)
+ {
+ int h1 = 0;
+ int m1 = 0;
+ int h2 = 0;
+ int m2 = 0;
+ if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
+ {
+ td.dirPrice[j].hDay = h1;
+ td.dirPrice[j].mDay = m1;
+ td.dirPrice[j].hNight = h2;
+ td.dirPrice[j].mNight = m2;
+ }
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "Fee") == 0)
+ {
+ double fee;
+ if (strtodouble2(attr[1], fee) == 0)
+ td.tariffConf.fee = fee;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PassiveCost") == 0)
+ {
+ double pc;
+ if (strtodouble2(attr[1], pc) == 0)
+ td.tariffConf.passiveCost = pc;
+ return 0;
+ }
+
+ if (strcasecmp(el, "Free") == 0)
+ {
+ double free;
+ if (strtodouble2(attr[1], free) == 0)
+ td.tariffConf.free = free;
+ return 0;
+ }
+
+ if (strcasecmp(el, "TraffType") == 0)
+ {
+ td.tariffConf.traffType = TARIFF::StringToTraffType(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "Period") == 0)
+ {
+ td.tariffConf.period = TARIFF::StringToPeriod(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "ChangePolicy") == 0)
+ {
+ td.tariffConf.changePolicy = TARIFF::StringToChangePolicy(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "ChangePolicyTimeout") == 0)
+ {
+ int64_t policyTime = 0;
+ if (str2x(attr[1], policyTime) == 0)
+ td.tariffConf.changePolicyTimeout = (time_t)policyTime;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void CHG_TARIFF::CreateAnswer()
+{
+ if (!td.tariffConf.name.data().empty())
+ {
+ TARIFF_DATA tariffData = td.GetData();
+ if (m_tariffs.Chg(tariffData, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " Result=\"ok\"/>";
+ else
+ m_answer = "<" + m_tag + " Result=\"Change tariff error! " + m_tariffs.GetStrError() + "\"/>";
+ }
+ else
+ m_answer = "<" + m_tag + " Result=\"Change tariff error!\"/>";
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_TARIFFS_H__
+#define __STG_SGCONFIG_PARSER_TARIFFS_H__
+
+#include "parser.h"
+
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+
+#include <string>
+
+class TARIFFS;
+class USERS;
+class ADMIN;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class GET_TARIFFS: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(const TARIFFS & tariffs) : m_tariffs(tariffs) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_TARIFFS(admin, m_tariffs); }
+ static void Register(REGISTRY & registry, const TARIFFS & tariffs)
+ { registry[ToLower(tag)] = new FACTORY(tariffs); }
+ private:
+ const TARIFFS & m_tariffs;
+ };
+
+ static const char * tag;
+
+ GET_TARIFFS(const ADMIN & admin, const TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+
+ private:
+ const TARIFFS & m_tariffs;
+
+ void CreateAnswer();
+};
+
+class ADD_TARIFF: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(TARIFFS & tariffs) : m_tariffs(tariffs) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_TARIFF(admin, m_tariffs); }
+ static void Register(REGISTRY & registry, TARIFFS & tariffs)
+ { registry[ToLower(tag)] = new FACTORY(tariffs); }
+ private:
+ TARIFFS & m_tariffs;
+ };
+
+ static const char * tag;
+
+ ADD_TARIFF(const ADMIN & admin, TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string tariff;
+ TARIFFS & m_tariffs;
+
+ void CreateAnswer();
+};
+
+class DEL_TARIFF: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(TARIFFS & tariffs, const USERS & users) : m_tariffs(tariffs), m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_TARIFF(admin, m_users, m_tariffs); }
+ static void Register(REGISTRY & registry, TARIFFS & tariffs, const USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(tariffs, users); }
+ private:
+ TARIFFS & m_tariffs;
+ const USERS & m_users;
+ };
+
+ static const char * tag;
+
+ DEL_TARIFF(const ADMIN & admin, const USERS & users, TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag), m_users(users), m_tariffs(tariffs) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ std::string tariff;
+ const USERS & m_users;
+ TARIFFS & m_tariffs;
+
+ void CreateAnswer();
+};
+
+class CHG_TARIFF: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(TARIFFS & tariffs) : m_tariffs(tariffs) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_TARIFF(admin, m_tariffs); }
+ static void Register(REGISTRY & registry, TARIFFS & tariffs)
+ { registry[ToLower(tag)] = new FACTORY(tariffs); }
+ private:
+ TARIFFS & m_tariffs;
+ };
+
+ static const char * tag;
+
+ CHG_TARIFF(const ADMIN & admin, TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ TARIFF_DATA_RES td;
+ TARIFFS & m_tariffs;
+
+ int CheckTariffData();
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "parser_user_info.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::USER_INFO;
+
+const char * USER_INFO::tag = "GetUserInfo";
+
+int USER_INFO::Start(void * /*data*/, const char *el, const char **attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ if (!attr[1])
+ return -1;
+
+ m_login = attr[1];
+ return 0;
+}
+
+void USER_INFO::CreateAnswer()
+{
+ CONST_USER_PTR u;
+ if (m_users.FindByName(m_login, &u))
+ {
+ m_answer = "<UserInfo result=\"error\"/>";
+ return;
+ }
+
+ m_answer = "<UserInfo lastAuthTime=\"" + x2str(u->GetAuthorizedModificationTime()) + "\"" +
+ " lastDisconnectTime=\"" + x2str(u->GetConnectedModificationTime()) + "\"" +
+ " connected=\"" + (u->GetConnected() ? "true" : "false") + "\"" +
+ " lastDisconnectReason=\"" + u->GetLastDisconnectReason() + "\">";
+ std::vector<std::string> list(u->GetAuthorizers());
+ for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+ m_answer += "<Auth name=\"" + *it + "\"/>";
+ m_answer += "</UserInfo>";
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_PARSER_USER_INFO_H__
+#define __STG_PARSER_USER_INFO_H__
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+class USERS;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class USER_INFO : public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(const USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new USER_INFO(admin, m_users); }
+ static void Register(REGISTRY & registry, const USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ const USERS & m_users;
+ };
+
+ static const char * tag;
+
+ USER_INFO(const ADMIN & admin, const USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ const USERS & m_users;
+ std::string m_login;
+
+ void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_users.h"
+
+#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/user_property.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+
+#include <cstdio>
+#include <cassert>
+
+using STG::PARSER::GET_USERS;
+using STG::PARSER::GET_USER;
+using STG::PARSER::ADD_USER;
+using STG::PARSER::DEL_USER;
+using STG::PARSER::CHG_USER;
+using STG::PARSER::CHECK_USER;
+
+const char * GET_USERS::tag = "GetUsers";
+const char * GET_USER::tag = "GetUser";
+const char * ADD_USER::tag = "AddUser";
+const char * CHG_USER::tag = "SetUser";
+const char * DEL_USER::tag = "DelUser";
+const char * CHECK_USER::tag = "CheckUser";
+
+namespace
+{
+
+std::string UserToXML(const USER & user, bool loginInStart, bool showPass, time_t lastTime = 0)
+{
+ std::string answer;
+
+ if (loginInStart)
+ answer += "<User login=\"" + user.GetLogin() + "\" result=\"ok\">";
+ else
+ answer += "<User result=\"ok\">";
+
+ answer += "<Login value=\"" + user.GetLogin() + "\"/>";
+
+ if (user.GetProperty().password.ModificationTime() > lastTime)
+ {
+ if (showPass)
+ answer += "<Password value=\"" + user.GetProperty().password.Get() + "\" />";
+ else
+ answer += "<Password value=\"++++++\"/>";
+ }
+
+ if (user.GetProperty().cash.ModificationTime() > lastTime)
+ answer += "<Cash value=\"" + x2str(user.GetProperty().cash.Get()) + "\"/>";
+ if (user.GetProperty().freeMb.ModificationTime() > lastTime)
+ answer += "<FreeMb value=\"" + x2str(user.GetProperty().freeMb.Get()) + "\"/>";
+ if (user.GetProperty().credit.ModificationTime() > lastTime)
+ answer += "<Credit value=\"" + x2str(user.GetProperty().credit.Get()) + "\"/>";
+
+ if (user.GetProperty().nextTariff.Get() != "")
+ {
+ if (user.GetProperty().tariffName.ModificationTime() > lastTime ||
+ user.GetProperty().nextTariff.ModificationTime() > lastTime)
+ answer += "<Tariff value=\"" + user.GetProperty().tariffName.Get() + "/" + user.GetProperty().nextTariff.Get() + "\"/>";
+ }
+ else
+ {
+ if (user.GetProperty().tariffName.ModificationTime() > lastTime)
+ answer += "<Tariff value=\"" + user.GetProperty().tariffName.Get() + "\"/>";
+ }
+
+ if (user.GetProperty().note.ModificationTime() > lastTime)
+ answer += "<Note value=\"" + Encode12str(user.GetProperty().note) + "\"/>";
+ if (user.GetProperty().phone.ModificationTime() > lastTime)
+ answer += "<Phone value=\"" + Encode12str(user.GetProperty().phone) + "\"/>";
+ if (user.GetProperty().address.ModificationTime() > lastTime)
+ answer += "<Address value=\"" + Encode12str(user.GetProperty().address) + "\"/>";
+ if (user.GetProperty().email.ModificationTime() > lastTime)
+ answer += "<Email value=\"" + Encode12str(user.GetProperty().email) + "\"/>";
+
+ std::vector<const USER_PROPERTY_LOGGED<std::string> *> userdata;
+ userdata.push_back(user.GetProperty().userdata0.GetPointer());
+ userdata.push_back(user.GetProperty().userdata1.GetPointer());
+ userdata.push_back(user.GetProperty().userdata2.GetPointer());
+ userdata.push_back(user.GetProperty().userdata3.GetPointer());
+ userdata.push_back(user.GetProperty().userdata4.GetPointer());
+ userdata.push_back(user.GetProperty().userdata5.GetPointer());
+ userdata.push_back(user.GetProperty().userdata6.GetPointer());
+ userdata.push_back(user.GetProperty().userdata7.GetPointer());
+ userdata.push_back(user.GetProperty().userdata8.GetPointer());
+ userdata.push_back(user.GetProperty().userdata9.GetPointer());
+
+ for (size_t i = 0; i < userdata.size(); i++)
+ if (userdata[i]->ModificationTime() > lastTime)
+ answer += "<UserData" + x2str(i) + " value=\"" + Encode12str(userdata[i]->Get()) + "\" />";
+
+ if (user.GetProperty().realName.ModificationTime() > lastTime)
+ answer += "<Name value=\"" + Encode12str(user.GetProperty().realName) + "\"/>";
+ if (user.GetProperty().group.ModificationTime() > lastTime)
+ answer += "<Group value=\"" + Encode12str(user.GetProperty().group) + "\"/>";
+ if (user.GetConnectedModificationTime() > lastTime)
+ answer += std::string("<Status value=\"") + (user.GetConnected() ? "1" : "0") + "\"/>";
+ if (user.GetProperty().alwaysOnline.ModificationTime() > lastTime)
+ answer += std::string("<AOnline value=\"") + (user.GetProperty().alwaysOnline.Get() ? "1" : "0") + "\"/>";
+ if (user.GetCurrIPModificationTime() > lastTime)
+ answer += "<CurrIP value=\"" + inet_ntostring(user.GetCurrIP()) + "\"/>";
+ if (user.GetPingTime() > lastTime)
+ answer += "<PingTime value=\"" + x2str(user.GetPingTime()) + "\"/>";
+ if (user.GetProperty().ips.ModificationTime() > lastTime)
+ answer += "<IP value=\"" + user.GetProperty().ips.Get().GetIpStr() + "\"/>";
+
+ answer += "<Traff";
+ const DIR_TRAFF & upload(user.GetProperty().up.Get());
+ const DIR_TRAFF & download(user.GetProperty().down.Get());
+ if (user.GetProperty().up.ModificationTime() > lastTime)
+ for (size_t j = 0; j < DIR_NUM; j++)
+ answer += " MU" + x2str(j) + "=\"" + x2str(upload[j]) + "\"";
+ if (user.GetProperty().down.ModificationTime() > lastTime)
+ for (size_t j = 0; j < DIR_NUM; j++)
+ answer += " MD" + x2str(j) + "=\"" + x2str(download[j]) + "\"";
+ if (user.GetSessionUploadModificationTime() > lastTime)
+ for (size_t j = 0; j < DIR_NUM; j++)
+ answer += " SU" + x2str(j) + "=\"" + x2str(user.GetSessionUpload()[j]) + "\"";
+ if (user.GetSessionDownloadModificationTime() > lastTime)
+ for (size_t j = 0; j < DIR_NUM; j++)
+ answer += " SD" + x2str(j) + "=\"" + x2str(user.GetSessionDownload()[j]) + "\"";
+ answer += "/>";
+
+ if (user.GetProperty().disabled.ModificationTime() > lastTime)
+ answer += std::string("<Down value=\"") + (user.GetProperty().disabled.Get() ? "1" : "0") + "\"/>";
+ if (user.GetProperty().disabledDetailStat.ModificationTime() > lastTime)
+ answer += std::string("<DisableDetailStat value=\"") + (user.GetProperty().disabledDetailStat.Get() ? "1" : "0") + "\"/>";
+ if (user.GetProperty().passive.ModificationTime() > lastTime)
+ answer += std::string("<Passive value=\"") + (user.GetProperty().passive.Get() ? "1" : "0") + "\"/>";
+ if (user.GetProperty().lastCashAdd.ModificationTime() > lastTime)
+ answer += "<LastCash value=\"" + x2str(user.GetProperty().lastCashAdd.Get()) + "\"/>";
+ if (user.GetProperty().lastCashAddTime.ModificationTime() > lastTime)
+ answer += "<LastTimeCash value=\"" + x2str(user.GetProperty().lastCashAddTime.Get()) + "\"/>";
+ if (user.GetProperty().lastActivityTime.ModificationTime() > lastTime)
+ answer += "<LastActivityTime value=\"" + x2str(user.GetProperty().lastActivityTime.Get()) + "\"/>";
+ if (user.GetProperty().creditExpire.ModificationTime() > lastTime)
+ answer += "<CreditExpire value=\"" + x2str(user.GetProperty().creditExpire.Get()) + "\"/>";
+
+ if (lastTime == 0)
+ {
+ answer += "<AuthorizedBy>";
+ std::vector<std::string> list(user.GetAuthorizers());
+ for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+ answer += "<Auth name=\"" + *it + "\"/>";
+ answer += "</AuthorizedBy>";
+ }
+
+ answer += "</User>";
+
+ return answer;
+}
+
+} // namespace anonymous
+
+int GET_USERS::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ {
+ printfd(__FILE__, "Got wrong tag: '%s' instead of '%s'\n", el, m_tag.c_str());
+ return -1;
+ }
+
+ while (attr && *attr && *(attr + 1))
+ {
+ if (strcasecmp(*attr, "LastUpdate") == 0)
+ str2x(*(attr + 1), m_lastUserUpdateTime);
+ ++attr;
+ }
+
+ return 0;
+}
+
+void GET_USERS::CreateAnswer()
+{
+ int h = m_users.OpenSearch();
+ assert(h);
+
+ if (m_lastUserUpdateTime > 0)
+ m_answer = "<Users LastUpdate=\"" + x2str(time(NULL)) + "\">";
+ else
+ m_answer = "<Users>";
+
+ USER_PTR u;
+
+ while (m_users.SearchNext(h, &u) == 0)
+ m_answer += UserToXML(*u, true, m_currAdmin.GetPriv()->userConf || m_currAdmin.GetPriv()->userPasswd, m_lastUserUpdateTime);
+
+ m_users.CloseSearch(h);
+
+ m_answer += "</Users>";
+}
+
+int GET_USER::Start(void *, const char * el, const char ** attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) != 0)
+ return -1;
+
+ if (attr[1] == NULL)
+ return -1;
+
+ m_login = attr[1];
+ return 0;
+}
+
+void GET_USER::CreateAnswer()
+{
+ CONST_USER_PTR u;
+
+ if (m_users.FindByName(m_login, &u))
+ m_answer = "<User result=\"error\" reason=\"User not found.\"/>";
+ else
+ m_answer = UserToXML(*u, false, m_currAdmin.GetPriv()->userConf || m_currAdmin.GetPriv()->userPasswd);
+}
+
+int ADD_USER::Start(void *, const char * el, const char ** attr)
+{
+ m_depth++;
+
+ if (m_depth == 1)
+ {
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ return 0;
+ }
+ else
+ {
+ if (strcasecmp(el, "login") == 0)
+ {
+ m_login = attr[1];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void ADD_USER::CreateAnswer()
+{
+ if (m_users.Exists(m_login))
+ m_answer = "<" + m_tag + " result=\"error\" reason=\"User '" + m_login + "' exists.\"/>";
+ else if (m_users.Add(m_login, &m_currAdmin) == 0)
+ m_answer = "<" + m_tag + " result=\"ok\"/>";
+ else
+ m_answer = "<" + m_tag + " result=\"error\" reason=\"Access denied\"/>";
+}
+
+int CHG_USER::Start(void *, const char * el, const char ** attr)
+{
+ m_depth++;
+
+ if (m_depth == 1)
+ {
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ return 0;
+ }
+ else
+ {
+ if (strcasecmp(el, "login") == 0)
+ {
+ m_login = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "ip") == 0)
+ {
+ m_ucr.ips = StrToIPS(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "password") == 0)
+ {
+ m_ucr.password = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "address") == 0)
+ {
+ m_ucr.address = Decode21str(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "aonline") == 0)
+ {
+ m_ucr.alwaysOnline = (*(attr[1]) != '0');
+ return 0;
+ }
+
+ if (strcasecmp(el, "cash") == 0)
+ {
+ if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
+ m_cashMsg = Decode21str(attr[3]);
+
+ double cash = 0;
+ if (strtodouble2(attr[1], cash) == 0)
+ m_usr.cash = cash;
+
+ m_cashMustBeAdded = (strcasecmp(attr[0], "add") == 0);
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "CreditExpire") == 0)
+ {
+ long int creditExpire = 0;
+ if (str2x(attr[1], creditExpire) == 0)
+ m_ucr.creditExpire = (time_t)creditExpire;
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "credit") == 0)
+ {
+ double credit = 0;
+ if (strtodouble2(attr[1], credit) == 0)
+ m_ucr.credit = credit;
+ return 0;
+ }
+
+ if (strcasecmp(el, "freemb") == 0)
+ {
+ double freeMb = 0;
+ if (strtodouble2(attr[1], freeMb) == 0)
+ m_usr.freeMb = freeMb;
+ return 0;
+ }
+
+ if (strcasecmp(el, "down") == 0)
+ {
+ int down = 0;
+ if (str2x(attr[1], down) == 0)
+ m_ucr.disabled = down;
+ return 0;
+ }
+
+ if (strcasecmp(el, "DisableDetailStat") == 0)
+ {
+ int disabledDetailStat = 0;
+ if (str2x(attr[1], disabledDetailStat) == 0)
+ m_ucr.disabledDetailStat = disabledDetailStat;
+ return 0;
+ }
+
+ if (strcasecmp(el, "email") == 0)
+ {
+ m_ucr.email = Decode21str(attr[1]);
+ return 0;
+ }
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ char name[15];
+ sprintf(name, "userdata%d", i);
+ if (strcasecmp(el, name) == 0)
+ {
+ m_ucr.userdata[i] = Decode21str(attr[1]);
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "group") == 0)
+ {
+ m_ucr.group = Decode21str(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "note") == 0)
+ {
+ m_ucr.note = Decode21str(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "passive") == 0)
+ {
+ int passive = 0;
+ if (str2x(attr[1], passive) == 0)
+ m_ucr.passive = passive;
+ return 0;
+ }
+
+ if (strcasecmp(el, "phone") == 0)
+ {
+ m_ucr.phone = Decode21str(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "Name") == 0)
+ {
+ m_ucr.realName = Decode21str(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "traff") == 0)
+ {
+ int j = 0;
+ while (attr[j])
+ {
+ int dir = attr[j][2] - '0';
+
+ if (strncasecmp(attr[j], "md", 2) == 0)
+ {
+ uint64_t t = 0;
+ str2x(attr[j + 1], t);
+ m_downr[dir] = t;
+ }
+ if (strncasecmp(attr[j], "mu", 2) == 0)
+ {
+ uint64_t t = 0;
+ str2x(attr[j + 1], t);
+ m_upr[dir] = t;
+ }
+ j += 2;
+ }
+ return 0;
+ }
+
+ if (strcasecmp(el, "tariff") == 0)
+ {
+ if (strcasecmp(attr[0], "now") == 0)
+ m_ucr.tariffName = attr[1];
+
+ if (strcasecmp(attr[0], "delayed") == 0)
+ m_ucr.nextTariff = attr[1];
+
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void CHG_USER::CreateAnswer()
+{
+ if (ApplyChanges() == 0)
+ m_answer = "<" + m_tag + " result=\"ok\"/>";
+ else
+ m_answer = "<" + m_tag + " result=\"error\"/>";
+}
+
+int CHG_USER::ApplyChanges()
+{
+ printfd(__FILE__, "PARSER_CHG_USER::ApplyChanges()\n");
+ USER_PTR u;
+
+ if (m_users.FindByName(m_login, &u))
+ return -1;
+
+ bool check = false;
+ bool alwaysOnline = u->GetProperty().alwaysOnline;
+ if (!m_ucr.alwaysOnline.empty())
+ {
+ check = true;
+ alwaysOnline = m_ucr.alwaysOnline.const_data();
+ }
+ bool onlyOneIP = u->GetProperty().ips.ConstData().OnlyOneIP();
+ if (!m_ucr.ips.empty())
+ {
+ check = true;
+ onlyOneIP = m_ucr.ips.const_data().OnlyOneIP();
+ }
+
+ if (check && alwaysOnline && !onlyOneIP)
+ {
+ printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
+ GetStgLogger()("%s Requested change leads to a forbidden state: AlwaysOnline with multiple IP's", m_currAdmin.GetLogStr().c_str());
+ return -1;
+ }
+
+ for (size_t i = 0; i < m_ucr.ips.const_data().Count(); ++i)
+ {
+ CONST_USER_PTR user;
+ uint32_t ip = m_ucr.ips.const_data().operator[](i).ip;
+ if (m_users.IsIPInUse(ip, m_login, &user))
+ {
+ printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
+ GetStgLogger()("%s trying to assign an IP %s to '%s' that is currently in use by '%s'", m_currAdmin.GetLogStr().c_str(), inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
+ return -1;
+ }
+ }
+
+ if (!m_ucr.ips.empty())
+ if (!u->GetProperty().ips.Set(m_ucr.ips.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.alwaysOnline.empty())
+ if (!u->GetProperty().alwaysOnline.Set(m_ucr.alwaysOnline.const_data(),
+ &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.address.empty())
+ if (!u->GetProperty().address.Set(m_ucr.address.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.creditExpire.empty())
+ if (!u->GetProperty().creditExpire.Set(m_ucr.creditExpire.const_data(),
+ &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.credit.empty())
+ if (!u->GetProperty().credit.Set(m_ucr.credit.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_usr.freeMb.empty())
+ if (!u->GetProperty().freeMb.Set(m_usr.freeMb.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.disabled.empty())
+ if (!u->GetProperty().disabled.Set(m_ucr.disabled.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.disabledDetailStat.empty())
+ if (!u->GetProperty().disabledDetailStat.Set(m_ucr.disabledDetailStat.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.email.empty())
+ if (!u->GetProperty().email.Set(m_ucr.email.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.group.empty())
+ if (!u->GetProperty().group.Set(m_ucr.group.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.note.empty())
+ if (!u->GetProperty().note.Set(m_ucr.note.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ std::vector<USER_PROPERTY_LOGGED<std::string> *> userdata;
+ userdata.push_back(u->GetProperty().userdata0.GetPointer());
+ userdata.push_back(u->GetProperty().userdata1.GetPointer());
+ userdata.push_back(u->GetProperty().userdata2.GetPointer());
+ userdata.push_back(u->GetProperty().userdata3.GetPointer());
+ userdata.push_back(u->GetProperty().userdata4.GetPointer());
+ userdata.push_back(u->GetProperty().userdata5.GetPointer());
+ userdata.push_back(u->GetProperty().userdata6.GetPointer());
+ userdata.push_back(u->GetProperty().userdata7.GetPointer());
+ userdata.push_back(u->GetProperty().userdata8.GetPointer());
+ userdata.push_back(u->GetProperty().userdata9.GetPointer());
+
+ for (int i = 0; i < (int)userdata.size(); i++)
+ if (!m_ucr.userdata[i].empty())
+ if(!userdata[i]->Set(m_ucr.userdata[i].const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.passive.empty())
+ if (!u->GetProperty().passive.Set(m_ucr.passive.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.password.empty())
+ if (!u->GetProperty().password.Set(m_ucr.password.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.phone.empty())
+ if (!u->GetProperty().phone.Set(m_ucr.phone.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_ucr.realName.empty())
+ if (!u->GetProperty().realName.Set(m_ucr.realName.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (!m_usr.cash.empty())
+ {
+ if (m_cashMustBeAdded)
+ {
+ if (!u->GetProperty().cash.Set(m_usr.cash.const_data() + u->GetProperty().cash,
+ &m_currAdmin,
+ m_login,
+ &m_store,
+ m_cashMsg))
+ return -1;
+ }
+ else
+ {
+ if (!u->GetProperty().cash.Set(m_usr.cash.const_data(), &m_currAdmin, m_login, &m_store, m_cashMsg))
+ return -1;
+ }
+ }
+
+ if (!m_ucr.tariffName.empty())
+ {
+ const TARIFF * newTariff = m_tariffs.FindByName(m_ucr.tariffName.const_data());
+ if (newTariff)
+ {
+ const TARIFF * tariff = u->GetTariff();
+ std::string message = tariff->TariffChangeIsAllowed(*newTariff, stgTime);
+ if (message.empty())
+ {
+ if (!u->GetProperty().tariffName.Set(m_ucr.tariffName.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+ u->ResetNextTariff();
+ }
+ else
+ {
+ GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
+ }
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ return -1;
+ }
+ }
+
+ if (!m_ucr.nextTariff.empty())
+ {
+ if (m_tariffs.FindByName(m_ucr.nextTariff.const_data()))
+ {
+ if (!u->GetProperty().nextTariff.Set(m_ucr.nextTariff.const_data(), &m_currAdmin, m_login, &m_store))
+ return -1;
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ return -1;
+ }
+ }
+
+ DIR_TRAFF up = u->GetProperty().up;
+ DIR_TRAFF down = u->GetProperty().down;
+ int upCount = 0;
+ int downCount = 0;
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ if (!m_upr[i].empty())
+ {
+ up[i] = m_upr[i].data();
+ upCount++;
+ }
+ if (!m_downr[i].empty())
+ {
+ down[i] = m_downr[i].data();
+ downCount++;
+ }
+ }
+
+ if (upCount)
+ if (!u->GetProperty().up.Set(up, &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ if (downCount)
+ if (!u->GetProperty().down.Set(down, &m_currAdmin, m_login, &m_store))
+ return -1;
+
+ u->WriteConf();
+ u->WriteStat();
+
+ return 0;
+}
+
+int DEL_USER::Start(void *, const char *el, const char **attr)
+{
+ res = 0;
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL)
+ {
+ //CreateAnswer("Parameters error!");
+ CreateAnswer();
+ return 0;
+ }
+
+ if (m_users.FindByName(attr[1], &u))
+ {
+ res = 1;
+ CreateAnswer();
+ return 0;
+ }
+ CreateAnswer();
+ return 0;
+ }
+ return -1;
+}
+
+int DEL_USER::End(void *, const char *el)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ if (!res)
+ m_users.Del(u->GetLogin(), &m_currAdmin);
+
+ return 0;
+ }
+ return -1;
+}
+
+void DEL_USER::CreateAnswer()
+{
+ if (res)
+ m_answer = "<" + m_tag + " value=\"error\" reason=\"User not found\"/>";
+ else
+ m_answer = "<" + m_tag + " value=\"ok\"/>";
+}
+
+int CHECK_USER::Start(void *, const char *el, const char **attr)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL ||
+ attr[2] == NULL || attr[3] == NULL)
+ {
+ CreateAnswer("Invalid parameters.");
+ printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
+ return 0;
+ }
+
+ CONST_USER_PTR user;
+ if (m_users.FindByName(attr[1], &user))
+ {
+ CreateAnswer("User not found.");
+ printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
+ return 0;
+ }
+
+ if (strcmp(user->GetProperty().password.Get().c_str(), attr[3]))
+ {
+ CreateAnswer("Wrong password.");
+ printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
+ return 0;
+ }
+
+ CreateAnswer(NULL);
+ return 0;
+ }
+ return -1;
+}
+
+int CHECK_USER::End(void *, const char *el)
+{
+ if (strcasecmp(el, m_tag.c_str()) == 0)
+ return 0;
+ return -1;
+}
+
+void CHECK_USER::CreateAnswer(const char * error)
+{
+ if (error)
+ m_answer = "<" + m_tag + " value=\"Err\" reason=\"" + error + "\"/>";
+ else
+ m_answer = "<" + m_tag + " value=\"Ok\"/>";
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_PARSER_USERS_H__
+#define __STG_SGCONFIG_PARSER_USERS_H__
+
+#include "parser.h"
+
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+
+class USERS;
+class USER;
+class TARIFFS;
+class ADMIN;
+class STORE;
+
+namespace STG
+{
+namespace PARSER
+{
+
+class GET_USERS: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_USERS(admin, m_users); }
+ static void Register(REGISTRY & registry, USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ USERS & m_users;
+ };
+
+ static const char * tag;
+
+ GET_USERS(const ADMIN & admin, USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users),
+ m_lastUserUpdateTime(0) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ USERS & m_users;
+ time_t m_lastUserUpdateTime;
+
+ void CreateAnswer();
+};
+
+class GET_USER: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(const USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new GET_USER(admin, m_users); }
+ static void Register(REGISTRY & registry, const USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ const USERS & m_users;
+ };
+
+ static const char * tag;
+
+ GET_USER(const ADMIN & admin, const USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ const USERS & m_users;
+ std::string m_login;
+
+ void CreateAnswer();
+};
+
+class ADD_USER: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new ADD_USER(admin, m_users); }
+ static void Register(REGISTRY & registry, USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ USERS & m_users;
+ };
+
+ static const char * tag;
+
+ ADD_USER(const ADMIN & admin, USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users) {}
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ USERS & m_users;
+ std::string m_login;
+
+ void CreateAnswer();
+};
+
+class CHG_USER: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ FACTORY(USERS & users, STORE & store, const TARIFFS & tariffs)
+ : m_users(users), m_store(store), m_tariffs(tariffs)
+ {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
+ static void Register(REGISTRY & registry, USERS & users, STORE & store, const TARIFFS & tariffs)
+ { registry[ToLower(tag)] = new FACTORY(users, store, tariffs); }
+ private:
+ USERS & m_users;
+ STORE & m_store;
+ const TARIFFS & m_tariffs;
+ };
+
+ static const char * tag;
+
+ CHG_USER(const ADMIN & admin, USERS & users,
+ STORE & store, const TARIFFS & tariffs)
+ : BASE_PARSER(admin, tag),
+ m_users(users),
+ m_store(store),
+ m_tariffs(tariffs),
+ m_cashMustBeAdded(false) {}
+
+ int Start(void * data, const char * el, const char ** attr);
+
+ private:
+ USERS & m_users;
+ STORE & m_store;
+ const TARIFFS & m_tariffs;
+ USER_STAT_RES m_usr;
+ USER_CONF_RES m_ucr;
+ RESETABLE<uint64_t> m_upr[DIR_NUM];
+ RESETABLE<uint64_t> m_downr[DIR_NUM];
+ std::string m_cashMsg;
+ std::string m_login;
+ bool m_cashMustBeAdded;
+
+ int ApplyChanges();
+ void CreateAnswer();
+};
+
+class DEL_USER: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new DEL_USER(admin, m_users); }
+ static void Register(REGISTRY & registry, USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ USERS & m_users;
+ };
+
+ static const char * tag;
+
+ DEL_USER(const ADMIN & admin, USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users), res(0), u(NULL) {}
+ int Start(void * data, const char * el, const char ** attr);
+ int End(void * data, const char * el);
+
+ private:
+ USERS & m_users;
+ int res;
+ USER * u;
+
+ void CreateAnswer();
+};
+
+class CHECK_USER: public BASE_PARSER
+{
+ public:
+ class FACTORY : public BASE_PARSER::FACTORY
+ {
+ public:
+ explicit FACTORY(const USERS & users) : m_users(users) {}
+ virtual BASE_PARSER * create(const ADMIN & admin) { return new CHECK_USER(admin, m_users); }
+ static void Register(REGISTRY & registry, const USERS & users)
+ { registry[ToLower(tag)] = new FACTORY(users); }
+ private:
+ const USERS & m_users;
+ };
+
+ static const char * tag;
+
+ CHECK_USER(const ADMIN & admin, const USERS & users)
+ : BASE_PARSER(admin, tag), m_users(users) {}
+ int Start(void * data, const char * el, const char ** attr);
+ int End(void * data, const char * el);
+
+ private:
+ const USERS & m_users;
+
+ void CreateAnswer(const char * error);
+ void CreateAnswer() {} // dummy
+};
+
+} // namespace PARSER
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#include "stgconfig.h"
+
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <csignal>
+#include <cstring>
+#include <cerrno>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+static PLUGIN_CREATOR<STG_CONFIG> stgc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool STG_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+ PARAM_VALUE pv;
+ std::vector<PARAM_VALUE>::const_iterator pvi;
+ ///////////////////////////
+ pv.param = "Port";
+ pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+ if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Port\' is not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return false;
+ }
+ int p;
+ if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Parameter \'Port\' should be an integral value in range (2, 65535). Actual value: '" + pvi->value[0] + "'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return false;
+ }
+ m_port = static_cast<uint16_t>(p);
+
+ pv.param = "BindAddress";
+ pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+ if (pvi != s.moduleParams.end() && !pvi->value.empty())
+ m_bindAddress = pvi->value[0];
+
+ return true;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+extern "C" PLUGIN * GetPlugin()
+{
+return stgc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STG_CONFIG::STG_CONFIG()
+ : nonstop(false),
+ isRunning(false),
+ logger(GetPluginLogger(GetStgLogger(), "conf_sg")),
+ config(logger)
+{
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::ParseSettings()
+{
+ if (stgConfigSettings.ParseSettings(settings))
+ return 0;
+ errorStr = stgConfigSettings.GetStrError();
+ return -1;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Start()
+{
+ if (isRunning)
+ return 0;
+
+ nonstop = true;
+
+ config.SetPort(stgConfigSettings.GetPort());
+ config.SetBindAddress(stgConfigSettings.GetBindAddress());
+
+ if (config.Prepare())
+ {
+ errorStr = config.GetStrError();
+ return -1;
+ }
+
+ if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = std::string("Cannot create thread: '") + strerror(errno) + "'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ logger(errorStr);
+ return -1;
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Stop()
+{
+ if (!isRunning)
+ return 0;
+
+ config.Stop();
+
+ //5 seconds to thread stops itself
+ for (size_t i = 0; i < 25; ++i)
+ {
+ if (!isRunning)
+ break;
+
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+
+ if (isRunning)
+ return -1;
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+void * STG_CONFIG::Run(void * d)
+{
+ sigset_t signalSet;
+ sigfillset(&signalSet);
+ pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+ STG_CONFIG & stgConf = *static_cast<STG_CONFIG *>(d);
+ stgConf.isRunning = true;
+
+ stgConf.config.Run();
+
+ stgConf.isRunning = false;
+
+ return NULL;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#ifndef STGCONFIG_H
+#define STGCONFIG_H
+
+#include "configproto.h"
+
+#include "stg/plugin.h"
+#include "stg/logger.h"
+
+#include <string>
+
+#include <pthread.h>
+
+class STG_CONFIG_SETTINGS
+{
+ public:
+ STG_CONFIG_SETTINGS() : m_port(0), m_bindAddress("0.0.0.0") {}
+ virtual ~STG_CONFIG_SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ bool ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort() const { return m_port; }
+ const std::string & GetBindAddress() const { return m_bindAddress; }
+ private:
+ std::string errorStr;
+ uint16_t m_port;
+ std::string m_bindAddress;
+};
+
+class STG_CONFIG : public PLUGIN
+{
+ public:
+ STG_CONFIG();
+
+ void SetUsers(USERS * users) { config.SetUsers(users); }
+ void SetTariffs(TARIFFS * tariffs) { config.SetTariffs(tariffs); }
+ void SetAdmins(ADMINS * admins) { config.SetAdmins(admins); }
+ void SetServices(SERVICES * services) { config.SetServices(services); }
+ void SetCorporations(CORPORATIONS * corporations) { config.SetCorporations( corporations); }
+ void SetStore(STORE * store) { config.SetStore(store); }
+ void SetStgSettings(const SETTINGS * s) { config.SetSettings(s); }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return "Stg Configurator v. 2.0"; }
+ uint16_t GetStartPosition() const { return 20; }
+ uint16_t GetStopPosition() const { return 20; }
+
+ private:
+ STG_CONFIG(const STG_CONFIG & rvalue);
+ STG_CONFIG & operator=(const STG_CONFIG & rvalue);
+
+ static void * Run(void *);
+
+ mutable std::string errorStr;
+ STG_CONFIG_SETTINGS stgConfigSettings;
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ PLUGIN_LOGGER logger;
+ CONFIGPROTO config;
+ MODULE_SETTINGS settings;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+if ( BUILD_MOD_PING )
+ add_subdirectory ( ping )
+endif ( BUILD_MOD_PING )
+
+if ( BUILD_MOD_RADIUS )
+ add_subdirectory ( radius )
+endif ( BUILD_MOD_RADIUS )
+
+if ( BUILD_MOD_RSCRYPT )
+ add_subdirectory ( rscript )
+endif ( BUILD_MOD_RSCRYPT )
+
+if ( BUILD_MOD_SMUX )
+ add_subdirectory ( smux )
+endif ( BUILD_MOD_SMUX )
--- /dev/null
+set ( CPP_FILES ping.cpp )
+
+add_library ( mod_ping MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_ping scriptexecuter logger pinger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.11 2008/12/04 17:21:14 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_ping.so
+
+SRCS = ./ping.cpp
+
+STGLIBS = pinger \
+ common \
+ logger \
+ scriptexecuter
+
+include ../../Makefile.in
+
--- /dev/null
+#include "ping.h"
+
+#include "stg/user.h"
+#include "stg/locker.h"
+#include "stg/user_property.h"
+#include "stg/plugin_creator.h"
+
+#include <cstdio>
+#include <cassert>
+#include <csignal>
+#include <ctime>
+#include <algorithm>
+
+namespace
+{
+PLUGIN_CREATOR<PING> pc;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename varType>
+class HAS_USER: public std::binary_function<varType, USER_PTR, bool>
+{
+public:
+ explicit HAS_USER(const USER_PTR & u) : user(u) {}
+ bool operator()(varType notifier) const
+ {
+ return notifier.GetUser() == user;
+ }
+private:
+ const USER_PTR & user;
+};
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return pc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int PING_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+PARAM_VALUE pv;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "PingDelay";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'PingDelay\' not found.";
+ printfd(__FILE__, "Parameter 'PingDelay' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
+ {
+ errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
+ printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+PING::PING()
+ : users(NULL),
+ nonstop(false),
+ isRunning(false),
+ onAddUserNotifier(*this),
+ onDelUserNotifier(*this),
+ logger(GetPluginLogger(GetStgLogger(), "ping"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+PING::~PING()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int PING::ParseSettings()
+{
+int ret = pingSettings.ParseSettings(settings);
+if (ret)
+ errorStr = pingSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+int PING::Start()
+{
+GetUsers();
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+pinger.SetDelayTime(pingSettings.GetPingDelay());
+pinger.Start();
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot start thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot start thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PING::Stop()
+{
+STG_LOCKER lock(&mutex);
+
+if (!isRunning)
+ return 0;
+
+pinger.Stop();
+nonstop = false;
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (int i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ nanosleep(&ts, NULL);
+ }
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+std::list<USER_PTR>::iterator users_iter;
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ UnSetUserNotifiers(*users_iter);
+ ++users_iter;
+ }
+
+if (isRunning)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool PING::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * PING::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+PING * ping = static_cast<PING *>(d);
+ping->isRunning = true;
+
+long delay = (10000000 * ping->pingSettings.GetPingDelay()) / 3 + 50000000;
+
+while (ping->nonstop)
+ {
+ std::list<USER_PTR>::iterator iter = ping->usersList.begin();
+ {
+ STG_LOCKER lock(&ping->mutex);
+ while (iter != ping->usersList.end())
+ {
+ if ((*iter)->GetProperty().ips.ConstData().OnlyOneIP())
+ {
+ uint32_t ip = (*iter)->GetProperty().ips.ConstData()[0].ip;
+ time_t t;
+ if (ping->pinger.GetIPTime(ip, &t) == 0)
+ {
+ if (t)
+ (*iter)->UpdatePingTime(t);
+ }
+ }
+ else
+ {
+ uint32_t ip = (*iter)->GetCurrIP();
+ if (ip)
+ {
+ time_t t;
+ if (ping->pinger.GetIPTime(ip, &t) == 0)
+ {
+ if (t)
+ (*iter)->UpdatePingTime(t);
+ }
+ }
+ }
+ ++iter;
+ }
+ }
+ struct timespec ts = {delay / 1000000000, delay % 1000000000};
+ for (int i = 0; i < 100; i++)
+ {
+ if (ping->nonstop)
+ {
+ nanosleep(&ts, NULL);
+ }
+ }
+ }
+
+ping->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void PING::SetUserNotifiers(USER_PTR u)
+{
+CHG_CURRIP_NOTIFIER_PING ChgCurrIPNotifier(*this, u);
+CHG_IPS_NOTIFIER_PING ChgIPNotifier(*this, u);
+
+ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
+ChgIPNotifierList.push_front(ChgIPNotifier);
+
+u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
+u->GetProperty().ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
+}
+//-----------------------------------------------------------------------------
+void PING::UnSetUserNotifiers(USER_PTR u)
+{
+// --- CurrIP ---
+HAS_USER<CHG_CURRIP_NOTIFIER_PING> IsContainsUserCurrIP(u);
+HAS_USER<CHG_IPS_NOTIFIER_PING> IsContainsUserIP(u);
+
+std::list<CHG_CURRIP_NOTIFIER_PING>::iterator currIPter;
+std::list<CHG_IPS_NOTIFIER_PING>::iterator IPIter;
+
+currIPter = find_if(ChgCurrIPNotifierList.begin(),
+ ChgCurrIPNotifierList.end(),
+ IsContainsUserCurrIP);
+
+if (currIPter != ChgCurrIPNotifierList.end())
+ {
+ currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
+ ChgCurrIPNotifierList.erase(currIPter);
+ }
+// --- CurrIP end ---
+
+// --- IP ---
+IPIter = find_if(ChgIPNotifierList.begin(),
+ ChgIPNotifierList.end(),
+ IsContainsUserIP);
+
+if (IPIter != ChgIPNotifierList.end())
+ {
+ IPIter->GetUser()->GetProperty().ips.DelAfterNotifier(&(*IPIter));
+ ChgIPNotifierList.erase(IPIter);
+ }
+// --- IP end ---
+}
+//-----------------------------------------------------------------------------
+void PING::GetUsers()
+{
+STG_LOCKER lock(&mutex);
+
+USER_PTR u;
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (users->SearchNext(h, &u) == 0)
+ {
+ usersList.push_back(u);
+ SetUserNotifiers(u);
+ if (u->GetProperty().ips.ConstData().OnlyOneIP())
+ {
+ pinger.AddIP(u->GetProperty().ips.ConstData()[0].ip);
+ }
+ else
+ {
+ uint32_t ip = u->GetCurrIP();
+ if (ip)
+ pinger.AddIP(ip);
+ }
+ }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void PING::AddUser(USER_PTR u)
+{
+STG_LOCKER lock(&mutex);
+
+SetUserNotifiers(u);
+usersList.push_back(u);
+}
+//-----------------------------------------------------------------------------
+void PING::DelUser(USER_PTR u)
+{
+STG_LOCKER lock(&mutex);
+
+UnSetUserNotifiers(u);
+
+std::list<USER_PTR>::iterator users_iter;
+users_iter = usersList.begin();
+
+while (users_iter != usersList.end())
+ {
+ if (u == *users_iter)
+ {
+ usersList.erase(users_iter);
+ break;
+ }
+ ++users_iter;
+ }
+}
+//-----------------------------------------------------------------------------
+void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
+{
+ping.pinger.DelIP(oldIP);
+if (newIP)
+ ping.pinger.AddIP(newIP);
+}
+//-----------------------------------------------------------------------------
+void CHG_IPS_NOTIFIER_PING::Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS)
+{
+if (oldIPS.OnlyOneIP())
+ ping.pinger.DelIP(oldIPS[0].ip);
+
+if (newIPS.OnlyOneIP())
+ ping.pinger.AddIP(newIPS[0].ip);
+}
+//-----------------------------------------------------------------------------
+void ADD_USER_NONIFIER_PING::Notify(const USER_PTR & user)
+{
+ping.AddUser(user);
+}
+//-----------------------------------------------------------------------------
+void DEL_USER_NONIFIER_PING::Notify(const USER_PTR & user)
+{
+ping.DelUser(user);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.16 $
+ $Date: 2009/06/23 11:32:28 $
+ $Author: faust $
+ */
+
+#ifndef PING_H
+#define PING_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/pinger.h"
+#include "stg/users.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <list>
+#include <cstdint>
+
+#include <pthread.h>
+
+extern "C" PLUGIN * GetPlugin();
+
+class PING;
+class USER;
+class SETTINGS;
+//-----------------------------------------------------------------------------*/
+class CHG_CURRIP_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<uint32_t> {
+public:
+ CHG_CURRIP_NOTIFIER_PING(const PING & p, USER_PTR u)
+ : user(u), ping(p) {}
+ void Notify(const uint32_t & oldIP, const uint32_t & newIP);
+ USER_PTR GetUser() const { return user; }
+
+private:
+ CHG_CURRIP_NOTIFIER_PING & operator=(const CHG_CURRIP_NOTIFIER_PING &);
+
+ USER_PTR user;
+ const PING & ping;
+};
+//-----------------------------------------------------------------------------
+class CHG_IPS_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<USER_IPS> {
+public:
+ CHG_IPS_NOTIFIER_PING(const PING & p, USER_PTR u)
+ : user(u), ping(p) {}
+ void Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS);
+ USER_PTR GetUser() const { return user; }
+
+private:
+ CHG_IPS_NOTIFIER_PING & operator=(const CHG_IPS_NOTIFIER_PING &);
+
+ USER_PTR user;
+ const PING & ping;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER_PING: public NOTIFIER_BASE<USER_PTR> {
+public:
+ explicit ADD_USER_NONIFIER_PING(PING & p) : ping(p) {}
+ void Notify(const USER_PTR & user);
+
+private:
+ ADD_USER_NONIFIER_PING(const ADD_USER_NONIFIER_PING &);
+ ADD_USER_NONIFIER_PING & operator=(const ADD_USER_NONIFIER_PING &);
+
+ PING & ping;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER_PING: public NOTIFIER_BASE<USER_PTR> {
+public:
+ explicit DEL_USER_NONIFIER_PING(PING & p) : ping(p) {}
+ void Notify(const USER_PTR & user);
+
+private:
+ DEL_USER_NONIFIER_PING(const DEL_USER_NONIFIER_PING &);
+ DEL_USER_NONIFIER_PING & operator=(const DEL_USER_NONIFIER_PING &);
+
+ PING & ping;
+};
+//-----------------------------------------------------------------------------
+class PING_SETTINGS {
+public:
+ PING_SETTINGS() : pingDelay(0) {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetPingDelay() const { return pingDelay; }
+private:
+ int pingDelay;
+ mutable std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+class PING : public PLUGIN {
+friend class CHG_CURRIP_NOTIFIER_PING;
+friend class CHG_IPS_NOTIFIER_PING;
+public:
+ PING();
+ virtual ~PING();
+
+ void SetUsers(USERS * u) { users = u; }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return "Pinger v.1.01"; }
+ uint16_t GetStartPosition() const { return 10; }
+ uint16_t GetStopPosition() const { return 10; }
+
+ void AddUser(USER_PTR u);
+ void DelUser(USER_PTR u);
+
+private:
+ explicit PING(const PING & rvalue);
+ PING & operator=(const PING & rvalue);
+
+ void GetUsers();
+ void SetUserNotifiers(USER_PTR u);
+ void UnSetUserNotifiers(USER_PTR u);
+ static void * Run(void * d);
+
+ mutable std::string errorStr;
+ PING_SETTINGS pingSettings;
+ MODULE_SETTINGS settings;
+ USERS * users;
+ std::list<USER_PTR> usersList;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+ bool nonstop;
+ bool isRunning;
+ mutable STG_PINGER pinger;
+
+ std::list<CHG_CURRIP_NOTIFIER_PING> ChgCurrIPNotifierList;
+ std::list<CHG_IPS_NOTIFIER_PING> ChgIPNotifierList;
+
+ ADD_USER_NONIFIER_PING onAddUserNotifier;
+ DEL_USER_NONIFIER_PING onDelUserNotifier;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+find_package ( YAJL REQUIRED )
+
+set ( CPP_FILES radius.cpp
+ config.cpp
+ conn.cpp )
+
+add_library ( mod_radius MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_radius logger json common YAJL::YAJL )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2010/04/26 12:44:42 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD) -lyajl
+
+PROG = mod_radius.so
+
+SRCS = radius.cpp \
+ config.cpp \
+ conn.cpp
+
+STGLIBS = common \
+ crypto \
+ logger \
+ scriptexecuter \
+ json
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "config.h"
+
+#include "stg/user.h"
+#include "stg/common.h"
+
+#include <vector>
+#include <stdexcept>
+
+#include <strings.h> // strncasecmp
+
+using STG::Config;
+
+namespace
+{
+
+struct ParserError : public std::runtime_error
+{
+ ParserError(const std::string& message)
+ : runtime_error("Config is not valid. " + message),
+ position(0),
+ error(message)
+ {}
+ ParserError(size_t pos, const std::string& message)
+ : runtime_error("Parsing error at position " + x2str(pos) + ". " + message),
+ position(pos),
+ error(message)
+ {}
+ virtual ~ParserError() throw() {}
+
+ size_t position;
+ std::string error;
+};
+
+size_t skipSpaces(const std::string& value, size_t start)
+{
+ while (start < value.length() && std::isspace(value[start]))
+ ++start;
+ return start;
+}
+
+size_t checkChar(const std::string& value, size_t start, char ch)
+{
+ if (start >= value.length())
+ throw ParserError(start, "Unexpected end of string. Expected '" + std::string(1, ch) + "'.");
+ if (value[start] != ch)
+ throw ParserError(start, "Expected '" + std::string(1, ch) + "', got '" + std::string(1, value[start]) + "'.");
+ return start + 1;
+}
+
+std::pair<size_t, std::string> readString(const std::string& value, size_t start)
+{
+ std::string dest;
+ while (start < value.length() && !std::isspace(value[start]) &&
+ value[start] != ',' && value[start] != '(' && value[start] != ')')
+ dest.push_back(value[start++]);
+ if (dest.empty()) {
+ if (start == value.length())
+ throw ParserError(start, "Unexpected end of string. Expected string.");
+ else
+ throw ParserError(start, "Unexpected whitespace. Expected string.");
+ }
+ return std::make_pair(start, dest);
+}
+
+Config::Pairs toPairs(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return Config::Pairs();
+ std::string value(values[0]);
+ Config::Pairs res;
+ size_t start = 0;
+ while (start < value.size()) {
+ Config::Pair pair;
+ start = skipSpaces(value, start);
+ if (!res.empty())
+ {
+ start = checkChar(value, start, ',');
+ start = skipSpaces(value, start);
+ }
+ size_t pairStart = start;
+ start = checkChar(value, start, '(');
+ const std::pair<size_t, std::string> key = readString(value, start);
+ start = key.first;
+ pair.first = key.second;
+ start = skipSpaces(value, start);
+ start = checkChar(value, start, ',');
+ start = skipSpaces(value, start);
+ const std::pair<size_t, std::string> val = readString(value, start);
+ start = val.first;
+ pair.second = val.second;
+ start = skipSpaces(value, start);
+ start = checkChar(value, start, ')');
+ if (res.find(pair.first) != res.end())
+ throw ParserError(pairStart, "Duplicate field.");
+ res.insert(pair);
+ }
+ return res;
+}
+
+bool toBool(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return false;
+ std::string value(values[0]);
+ return strncasecmp(value.c_str(), "yes", 3) == 0;
+}
+
+std::string toString(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return "";
+ return values[0];
+}
+
+uid_t toUID(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return -1;
+ uid_t res = str2uid(values[0]);
+ if (res == static_cast<uid_t>(-1))
+ throw ParserError("Invalid user name: '" + values[0] + "'");
+ return res;
+}
+
+gid_t toGID(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return -1;
+ gid_t res = str2gid(values[0]);
+ if (res == static_cast<gid_t>(-1))
+ throw ParserError("Invalid group name: '" + values[0] + "'");
+ return res;
+}
+
+mode_t toMode(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return -1;
+ mode_t res = str2mode(values[0]);
+ if (res == static_cast<mode_t>(-1))
+ throw ParserError("Invalid mode: '" + values[0] + "'");
+ return res;
+}
+
+template <typename T>
+T toInt(const std::vector<std::string>& values)
+{
+ if (values.empty())
+ return 0;
+ T res = 0;
+ if (str2x(values[0], res) == 0)
+ return res;
+ return 0;
+}
+
+uint16_t toPort(const std::string& value)
+{
+ if (value.empty())
+ return 0;
+ uint16_t res = 0;
+ if (str2x(value, res) == 0)
+ return res;
+ throw ParserError("'" + value + "' is not a valid port number.");
+}
+
+typedef std::map<std::string, Config::ReturnCode> Codes;
+
+// One-time call to initialize the list of codes.
+Codes getCodes()
+{
+ Codes res;
+ res["reject"] = Config::REJECT;
+ res["fail"] = Config::FAIL;
+ res["ok"] = Config::OK;
+ res["handled"] = Config::HANDLED;
+ res["invalid"] = Config::INVALID;
+ res["userlock"] = Config::USERLOCK;
+ res["notfound"] = Config::NOTFOUND;
+ res["noop"] = Config::NOOP;
+ res["updated"] = Config::UPDATED;
+ return res;
+}
+
+Config::ReturnCode toReturnCode(const std::vector<std::string>& values)
+{
+ static Codes codes(getCodes());
+ if (values.empty())
+ return Config::REJECT;
+ std::string code = ToLower(values[0]);
+ const Codes::const_iterator it = codes.find(code);
+ if (it == codes.end())
+ return Config::REJECT;
+ return it->second;
+}
+
+Config::Pairs parseVector(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toPairs(params[i].value);
+ return Config::Pairs();
+}
+
+Config::Authorize parseAuthorize(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return Config::Authorize(toPairs(params[i].value));
+ return Config::Authorize();
+}
+
+Config::ReturnCode parseReturnCode(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toReturnCode(params[i].value);
+ return Config::REJECT;
+}
+
+bool parseBool(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toBool(params[i].value);
+ return false;
+}
+
+std::string parseString(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toString(params[i].value);
+ return "";
+}
+
+std::string parseAddress(Config::Type connectionType, const std::string& value)
+{
+ size_t pos = value.find_first_of(':');
+ if (pos == std::string::npos)
+ throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
+ if (connectionType == Config::UNIX)
+ return value.substr(pos + 1);
+ std::string address(value.substr(pos + 1));
+ pos = address.find_first_of(':', pos + 1);
+ if (pos == std::string::npos)
+ throw ParserError("Port is not specified.");
+ return address.substr(0, pos - 1);
+}
+
+std::string parsePort(Config::Type connectionType, const std::string& value)
+{
+ size_t pos = value.find_first_of(':');
+ if (pos == std::string::npos)
+ throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
+ if (connectionType == Config::UNIX)
+ return "";
+ std::string address(value.substr(pos + 1));
+ pos = address.find_first_of(':', pos + 1);
+ if (pos == std::string::npos)
+ throw ParserError("Port is not specified.");
+ return address.substr(pos + 1);
+}
+
+Config::Type parseConnectionType(const std::string& address)
+{
+ size_t pos = address.find_first_of(':');
+ if (pos == std::string::npos)
+ throw ParserError("Connection type is not specified. Should be either 'unix' or 'tcp'.");
+ std::string type = ToLower(address.substr(0, pos));
+ if (type == "unix")
+ return Config::UNIX;
+ else if (type == "tcp")
+ return Config::TCP;
+ throw ParserError("Invalid connection type. Should be either 'unix' or 'tcp', got '" + type + "'");
+}
+
+Config::Section parseSection(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return Config::Section(parseVector("match", params[i].sections),
+ parseVector("modify", params[i].sections),
+ parseVector("reply", params[i].sections),
+ parseReturnCode("no_match", params[i].sections),
+ parseAuthorize("authorize", params[i].sections));
+ return Config::Section();
+}
+
+uid_t parseUID(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toUID(params[i].value);
+ return -1;
+}
+
+gid_t parseGID(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toGID(params[i].value);
+ return -1;
+}
+
+mode_t parseMode(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toMode(params[i].value);
+ return -1;
+}
+
+} // namespace anonymous
+
+bool Config::Authorize::check(const USER& user, const Config::Pairs& radiusData) const
+{
+ if (!m_auth)
+ return false; // No flag - no authorization.
+
+ if (m_cond.empty())
+ return true; // Empty parameter - always authorize.
+
+ Config::Pairs::const_iterator it = m_cond.begin();
+ for (; it != m_cond.end(); ++it)
+ {
+ const Config::Pairs::const_iterator pos = radiusData.find(it->first);
+ if (pos == radiusData.end())
+ return false; // No required Radius parameter.
+ if (user.GetParamValue(it->second) != pos->second)
+ return false; // No match with the user.
+ }
+
+ return true;
+}
+
+Config::Config(const MODULE_SETTINGS& settings)
+ : autz(parseSection("autz", settings.moduleParams)),
+ auth(parseSection("auth", settings.moduleParams)),
+ postauth(parseSection("postauth", settings.moduleParams)),
+ preacct(parseSection("preacct", settings.moduleParams)),
+ acct(parseSection("acct", settings.moduleParams)),
+ verbose(parseBool("verbose", settings.moduleParams)),
+ address(parseString("bind_address", settings.moduleParams)),
+ connectionType(parseConnectionType(address)),
+ bindAddress(parseAddress(connectionType, address)),
+ portStr(parsePort(connectionType, address)),
+ port(toPort(portStr)),
+ key(parseString("key", settings.moduleParams)),
+ sockUID(parseUID("sock_owner", settings.moduleParams)),
+ sockGID(parseGID("sock_group", settings.moduleParams)),
+ sockMode(parseMode("sock_mode", settings.moduleParams))
+{
+ size_t count = 0;
+ if (autz.authorize.exists())
+ ++count;
+ if (auth.authorize.exists())
+ ++count;
+ if (postauth.authorize.exists())
+ ++count;
+ if (preacct.authorize.exists())
+ ++count;
+ if (acct.authorize.exists())
+ ++count;
+ if (count > 0)
+ throw ParserError("Authorization flag is specified in more than one section.");
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_RADIUS_CONFIG_H__
+#define __STG_RADIUS_CONFIG_H__
+
+#include "stg/module_settings.h"
+
+#include <map>
+#include <string>
+#include <cstdint>
+
+#include <unistd.h> // uid_t, gid_t
+#include <sys/stat.h> // mode_t
+
+class USER;
+
+namespace STG
+{
+
+struct Config
+{
+ typedef std::map<std::string, std::string> Pairs;
+ typedef std::pair<std::string, std::string> Pair;
+ enum Type { UNIX, TCP };
+ enum ReturnCode
+ {
+ REJECT, // Reject the request immediately.
+ FAIL, // Module failed.
+ OK, // Module is OK, continue.
+ HANDLED, // The request is handled, no further handling.
+ INVALID, // The request is invalud.
+ USERLOCK, // Reject the request, user is locked.
+ NOTFOUND, // User not found.
+ NOOP, // Module performed no action.
+ UPDATED // Module sends some updates.
+ };
+
+ class Authorize
+ {
+ public:
+ Authorize() : m_auth(false) {}
+ Authorize(const Pairs& cond) : m_auth(true), m_cond(cond) {}
+
+ bool check(const USER& user, const Pairs& radiusData) const;
+ bool exists() const { return m_auth; }
+ private:
+ bool m_auth;
+ Pairs m_cond;
+ };
+
+ struct Section
+ {
+ Section() {}
+ Section(const Pairs& ma, const Pairs& mo, const Pairs& re, ReturnCode code, const Authorize& auth)
+ : match(ma), modify(mo), reply(re), returnCode(code), authorize(auth) {}
+ Pairs match;
+ Pairs modify;
+ Pairs reply;
+ ReturnCode returnCode;
+ Authorize authorize;
+ };
+
+ Config() {}
+ Config(const MODULE_SETTINGS& settings);
+
+ Section autz;
+ Section auth;
+ Section postauth;
+ Section preacct;
+ Section acct;
+
+ bool verbose;
+
+ std::string address;
+ Type connectionType;
+ std::string bindAddress;
+ std::string portStr;
+ uint16_t port;
+ std::string key;
+
+ uid_t sockUID;
+ gid_t sockGID;
+ mode_t sockMode;
+};
+
+} // namespace STG
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "conn.h"
+
+#include "radius.h"
+#include "config.h"
+
+#include "stg/json_parser.h"
+#include "stg/json_generator.h"
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/logger.h"
+#include "stg/common.h"
+
+#include <yajl/yajl_gen.h>
+
+#include <map>
+#include <stdexcept>
+#include <cstring>
+#include <cerrno>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+using STG::Conn;
+using STG::Config;
+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;
+
+enum Packet
+{
+ PING,
+ PONG,
+ DATA
+};
+
+enum Stage
+{
+ AUTHORIZE,
+ AUTHENTICATE,
+ PREACCT,
+ ACCOUNTING,
+ POSTAUTH
+};
+
+std::map<std::string, Packet> packetCodes;
+std::map<std::string, Stage> stageCodes;
+
+class PacketParser : public EnumParser<Packet>
+{
+ 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 StageParser : public EnumParser<Stage>
+{
+ public:
+ StageParser(NodeParser* next, Stage& stage, std::string& stageStr)
+ : EnumParser(next, stage, stageStr, stageCodes)
+ {
+ if (!stageCodes.empty())
+ return;
+ stageCodes["authorize"] = AUTHORIZE;
+ stageCodes["authenticate"] = AUTHENTICATE;
+ stageCodes["preacct"] = PREACCT;
+ stageCodes["accounting"] = ACCOUNTING;
+ stageCodes["postauth"] = POSTAUTH;
+ }
+};
+
+class TopParser : public NodeParser
+{
+ public:
+ typedef void (*Callback) (void* /*data*/);
+ TopParser(Callback callback, void* data)
+ : m_packetParser(this, m_packet, m_packetStr),
+ m_stageParser(this, m_stage, m_stageStr),
+ m_pairsParser(this, m_data),
+ m_callback(callback), m_callbackData(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 == "stage")
+ return &m_stageParser;
+ else if (key == "pairs")
+ return &m_pairsParser;
+
+ return this;
+ }
+ virtual NodeParser* parseEndMap() { m_callback(m_callbackData); return this; }
+
+ const std::string& packetStr() const { return m_packetStr; }
+ Packet packet() const { return m_packet; }
+ const std::string& stageStr() const { return m_stageStr; }
+ Stage stage() const { return m_stage; }
+ const Config::Pairs& data() const { return m_data; }
+
+ private:
+ std::string m_packetStr;
+ Packet m_packet;
+ std::string m_stageStr;
+ Stage m_stage;
+ Config::Pairs m_data;
+
+ PacketParser m_packetParser;
+ StageParser m_stageParser;
+ PairsParser m_pairsParser;
+
+ Callback m_callback;
+ void* m_callbackData;
+};
+
+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& stageStr() const { return m_topParser.stageStr(); }
+ Stage stage() const { return m_topParser.stage(); }
+ const Config::Pairs& data() const { return m_topParser.data(); }
+
+ private:
+ TopParser m_topParser;
+};
+
+class PacketGen : public Gen
+{
+ public:
+ 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;
+ }
+ PacketGen& add(const std::string& key, MapGen& map)
+ {
+ m_gen.add(key, map);
+ return *this;
+ }
+ private:
+ MapGen m_gen;
+ StringGen m_type;
+};
+
+std::string toString(Config::ReturnCode code)
+{
+ switch (code)
+ {
+ case Config::REJECT: return "reject";
+ case Config::FAIL: return "fail";
+ case Config::OK: return "ok";
+ case Config::HANDLED: return "handled";
+ case Config::INVALID: return "invalid";
+ case Config::USERLOCK: return "userlock";
+ case Config::NOTFOUND: return "notfound";
+ case Config::NOOP: return "noop";
+ case Config::UPDATED: return "noop";
+ }
+ return "reject";
+}
+
+}
+
+class Conn::Impl
+{
+ public:
+ Impl(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote);
+ ~Impl();
+
+ int sock() const { return m_sock; }
+
+ bool read();
+ bool tick();
+
+ bool isOk() const { return m_ok; }
+
+ private:
+ USERS& m_users;
+ PLUGIN_LOGGER& m_logger;
+ RADIUS& m_plugin;
+ const Config& m_config;
+ int m_sock;
+ std::string m_remote;
+ bool m_ok;
+ time_t m_lastPing;
+ time_t m_lastActivity;
+ ProtoParser m_parser;
+ std::set<std::string> m_authorized;
+
+ template <typename T>
+ const T& stageMember(T Config::Section::* member) const
+ {
+ switch (m_parser.stage())
+ {
+ case AUTHORIZE: return m_config.autz.*member;
+ case AUTHENTICATE: return m_config.auth.*member;
+ case POSTAUTH: return m_config.postauth.*member;
+ case PREACCT: return m_config.preacct.*member;
+ case ACCOUNTING: return m_config.acct.*member;
+ }
+ throw std::runtime_error("Invalid stage: '" + m_parser.stageStr() + "'.");
+ }
+
+ const Config::Pairs& match() const { return stageMember(&Config::Section::match); }
+ const Config::Pairs& modify() const { return stageMember(&Config::Section::modify); }
+ const Config::Pairs& reply() const { return stageMember(&Config::Section::reply); }
+ Config::ReturnCode returnCode() const { return stageMember(&Config::Section::returnCode); }
+ const Config::Authorize& authorize() const { return stageMember(&Config::Section::authorize); }
+
+ static void process(void* data);
+ void processPing();
+ void processPong();
+ void processData();
+ bool answer(const USER& user);
+ bool answerNo();
+ bool sendPing();
+ bool sendPong();
+
+ static bool write(void* data, const char* buf, size_t size);
+};
+
+Conn::Conn(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote)
+ : m_impl(new Impl(users, logger, plugin, config, fd, remote))
+{
+}
+
+Conn::~Conn()
+{
+}
+
+int Conn::sock() const
+{
+ return m_impl->sock();
+}
+
+bool Conn::read()
+{
+ return m_impl->read();
+}
+
+bool Conn::tick()
+{
+ return m_impl->tick();
+}
+
+bool Conn::isOk() const
+{
+ return m_impl->isOk();
+}
+
+Conn::Impl::Impl(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote)
+ : m_users(users),
+ m_logger(logger),
+ m_plugin(plugin),
+ m_config(config),
+ m_sock(fd),
+ m_remote(remote),
+ m_ok(true),
+ m_lastPing(time(NULL)),
+ m_lastActivity(m_lastPing),
+ m_parser(&Conn::Impl::process, this)
+{
+}
+
+Conn::Impl::~Impl()
+{
+ close(m_sock);
+
+ std::set<std::string>::const_iterator it = m_authorized.begin();
+ for (; it != m_authorized.end(); ++it)
+ m_plugin.unauthorize(*it, "Lost connection to RADIUS server " + m_remote + ".");
+}
+
+bool Conn::Impl::read()
+{
+ static std::vector<char> buffer(1024);
+ ssize_t res = ::read(m_sock, buffer.data(), buffer.size());
+ if (res < 0)
+ {
+ m_logger("Failed to read data from '" + m_remote + "': " + strerror(errno));
+ m_ok = false;
+ return false;
+ }
+ printfd(__FILE__, "Read %d bytes.\n%s\n", res, std::string(buffer.data(), res).c_str());
+ m_lastActivity = time(NULL);
+ if (res == 0)
+ {
+ m_ok = false;
+ return true;
+ }
+ 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);
+ printfd(__FILE__, "Connection to '%s' timed out: %d sec.\n", m_remote.c_str(), delta);
+ m_logger("Connection to " + m_remote + " timed out.");
+ m_ok = false;
+ return false;
+ }
+ if (difftime(now, m_lastPing) > PING_TIMEOUT)
+ {
+ int delta = difftime(now, m_lastPing);
+ printfd(__FILE__, "Ping timeout: %d sec. Sending ping...\n", delta);
+ sendPing();
+ }
+ return true;
+}
+
+void Conn::Impl::process(void* data)
+{
+ Impl& impl = *static_cast<Impl*>(data);
+ try
+ {
+ switch (impl.m_parser.packet())
+ {
+ case PING:
+ impl.processPing();
+ return;
+ case PONG:
+ impl.processPong();
+ return;
+ case DATA:
+ impl.processData();
+ return;
+ }
+ }
+ catch (const std::exception& ex)
+ {
+ printfd(__FILE__, "Processing error. %s", ex.what());
+ impl.m_logger("Processing error. %s", ex.what());
+ }
+ printfd(__FILE__, "Received invalid packet type: '%s'.\n", impl.m_parser.packetStr().c_str());
+ impl.m_logger("Received invalid packet type: " + impl.m_parser.packetStr());
+}
+
+void Conn::Impl::processPing()
+{
+ printfd(__FILE__, "Got ping. Sending pong...\n");
+ sendPong();
+}
+
+void Conn::Impl::processPong()
+{
+ printfd(__FILE__, "Got pong.\n");
+ m_lastActivity = time(NULL);
+}
+
+void Conn::Impl::processData()
+{
+ printfd(__FILE__, "Got data.\n");
+ int handle = m_users.OpenSearch();
+
+ USER_PTR user = NULL;
+ bool matched = false;
+ while (m_users.SearchNext(handle, &user) == 0)
+ {
+ if (user == NULL)
+ continue;
+
+ matched = true;
+ for (Config::Pairs::const_iterator it = match().begin(); it != match().end(); ++it)
+ {
+ Config::Pairs::const_iterator pos = m_parser.data().find(it->first);
+ if (pos == m_parser.data().end())
+ {
+ matched = false;
+ break;
+ }
+ if (user->GetParamValue(it->second) != pos->second)
+ {
+ matched = false;
+ break;
+ }
+ }
+ if (!matched)
+ continue;
+ answer(*user);
+ if (authorize().check(*user, m_parser.data()))
+ {
+ m_plugin.authorize(*user);
+ m_authorized.insert(user->GetLogin());
+ }
+ break;
+ }
+
+ if (!matched)
+ answerNo();
+
+ m_users.CloseSearch(handle);
+}
+
+bool Conn::Impl::answer(const USER& user)
+{
+ printfd(__FILE__, "Got match. Sending answer...\n");
+ MapGen replyData;
+ for (Config::Pairs::const_iterator it = reply().begin(); it != reply().end(); ++it)
+ replyData.add(it->first, new StringGen(user.GetParamValue(it->second)));
+
+ MapGen modifyData;
+ for (Config::Pairs::const_iterator it = modify().begin(); it != modify().end(); ++it)
+ modifyData.add(it->first, new StringGen(user.GetParamValue(it->second)));
+
+ PacketGen gen("data");
+ gen.add("result", "ok")
+ .add("reply", replyData)
+ .add("modify", modifyData);
+
+ m_lastPing = time(NULL);
+
+ return generate(gen, &Conn::Impl::write, this);
+}
+
+bool Conn::Impl::answerNo()
+{
+ printfd(__FILE__, "No match. Sending answer...\n");
+ PacketGen gen("data");
+ gen.add("result", "no");
+ gen.add("return_code", toString(returnCode()));
+
+ m_lastPing = time(NULL);
+
+ return generate(gen, &Conn::Impl::write, this);
+}
+
+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);
+ printfd(__FILE__, "Writing JSON:\n%s\n", json.c_str());
+ Conn::Impl& conn = *static_cast<Conn::Impl*>(data);
+ while (size > 0)
+ {
+ ssize_t res = ::send(conn.m_sock, buf, size, MSG_NOSIGNAL);
+ if (res < 0)
+ {
+ conn.m_logger("Failed to write pong to '" + conn.m_remote + "': " + strerror(errno));
+ conn.m_ok = false;
+ return false;
+ }
+ size -= res;
+ }
+ return true;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONFIG_CONN_H__
+#define __STG_SGCONFIG_CONN_H__
+
+#include <boost/scoped_ptr.hpp>
+
+#include <string>
+
+class USER;
+class USERS;
+class PLUGIN_LOGGER;
+class RADIUS;
+
+namespace STG
+{
+
+struct Config;
+
+class Conn
+{
+ public:
+ Conn(USERS& users, PLUGIN_LOGGER& logger, RADIUS& plugin, const Config& config, int fd, const std::string& remote);
+ ~Conn();
+
+ int sock() const;
+
+ bool read();
+ bool tick();
+
+ bool isOk() const;
+
+ private:
+ class Impl;
+ boost::scoped_ptr<Impl> m_impl;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include "radius.h"
+
+#include "stg/store.h"
+#include "stg/users.h"
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h> // UNIX
+#include <netinet/in.h> // IP
+#include <netinet/tcp.h> // TCP
+#include <netdb.h>
+
+using STG::Config;
+using STG::Conn;
+
+namespace
+{
+
+PLUGIN_CREATOR<RADIUS> creator;
+
+}
+
+extern "C" PLUGIN * GetPlugin()
+{
+ return creator.GetPlugin();
+}
+
+RADIUS::RADIUS()
+ : m_config(),
+ m_running(false),
+ m_stopped(true),
+ m_users(NULL),
+ m_store(NULL),
+ m_listenSocket(0),
+ m_logger(GetPluginLogger(GetStgLogger(), "radius"))
+{
+}
+
+int RADIUS::ParseSettings()
+{
+ try {
+ m_config = STG::Config(m_settings);
+ return reconnect() ? 0 : -1;
+ } catch (const std::runtime_error& ex) {
+ m_logger("Failed to parse settings. %s", ex.what());
+ return -1;
+ }
+}
+
+int RADIUS::Start()
+{
+ if (m_running)
+ return 0;
+
+ int res = pthread_create(&m_thread, NULL, run, this);
+ if (res == 0)
+ return 0;
+
+ m_error = strerror(res);
+ m_logger("Failed to create thread: '" + m_error + "'.");
+ return -1;
+}
+
+int RADIUS::Stop()
+{
+ std::set<std::string>::const_iterator it = m_logins.begin();
+ for (; it != m_logins.end(); ++it)
+ m_users->Unauthorize(*it, this, "Stopping RADIUS plugin.");
+ m_logins.clear();
+
+ if (m_stopped)
+ return 0;
+
+ 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 0;
+ }
+
+ if (m_config.connectionType == Config::UNIX)
+ unlink(m_config.bindAddress.c_str());
+
+ m_error = "Failed to stop thread.";
+ m_logger(m_error);
+ return -1;
+}
+//-----------------------------------------------------------------------------
+void* RADIUS::run(void* d)
+{
+ sigset_t signalSet;
+ sigfillset(&signalSet);
+ pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+ static_cast<RADIUS *>(d)->runImpl();
+
+ return NULL;
+}
+
+bool RADIUS::reconnect()
+{
+ if (!m_conns.empty())
+ {
+ std::deque<STG::Conn *>::const_iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ delete(*it);
+ m_conns.clear();
+ }
+ if (m_listenSocket != 0)
+ {
+ shutdown(m_listenSocket, SHUT_RDWR);
+ close(m_listenSocket);
+ }
+ if (m_config.connectionType == Config::UNIX)
+ m_listenSocket = createUNIX();
+ else
+ m_listenSocket = createTCP();
+ if (m_listenSocket == 0)
+ return false;
+ if (listen(m_listenSocket, 100) == -1)
+ {
+ m_error = std::string("Error starting to listen socket: ") + strerror(errno);
+ m_logger(m_error);
+ return false;
+ }
+ return true;
+}
+
+int RADIUS::createUNIX() const
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ m_error = std::string("Error creating UNIX socket: ") + strerror(errno);
+ m_logger(m_error);
+ return 0;
+ }
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, m_config.bindAddress.c_str(), m_config.bindAddress.length());
+ unlink(m_config.bindAddress.c_str());
+ if (bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1)
+ {
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+ m_error = std::string("Error binding UNIX socket: ") + strerror(errno);
+ m_logger(m_error);
+ return 0;
+ }
+ chown(m_config.bindAddress.c_str(), m_config.sockUID, m_config.sockGID);
+ if (m_config.sockMode != static_cast<mode_t>(-1))
+ chmod(m_config.bindAddress.c_str(), m_config.sockMode);
+ return fd;
+}
+
+int RADIUS::createTCP() const
+{
+ addrinfo hints;
+ memset(&hints, 0, sizeof(addrinfo));
+
+ hints.ai_family = AF_INET; /* Allow IPv4 */
+ hints.ai_socktype = SOCK_STREAM; /* Stream socket */
+ hints.ai_flags = AI_PASSIVE; /* 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.bindAddress.c_str(), m_config.portStr.c_str(), &hints, &ais);
+ if (res != 0)
+ {
+ m_error = "Error resolving address '" + m_config.bindAddress + "': " + gai_strerror(res);
+ m_logger(m_error);
+ return 0;
+ }
+
+ for (addrinfo* ai = ais; ai != NULL; ai = ai->ai_next)
+ {
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ m_error = std::string("Error creating TCP socket: ") + strerror(errno);
+ m_logger(m_error);
+ freeaddrinfo(ais);
+ return 0;
+ }
+ if (bind(fd, ai->ai_addr, ai->ai_addrlen) == -1)
+ {
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+ m_error = std::string("Error binding TCP socket: ") + strerror(errno);
+ m_logger(m_error);
+ continue;
+ }
+ freeaddrinfo(ais);
+ return fd;
+ }
+
+ m_error = "Failed to resolve '" + m_config.bindAddress;
+ m_logger(m_error);
+
+ freeaddrinfo(ais);
+ return 0;
+}
+
+void RADIUS::runImpl()
+{
+ m_running = true;
+ m_stopped = false;
+
+ while (m_running) {
+ fd_set fds;
+
+ buildFDSet(fds);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ int res = select(maxFD() + 1, &fds, NULL, NULL, &tv);
+ if (res < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ m_error = std::string("'select' is failed: '") + strerror(errno) + "'.";
+ m_logger(m_error);
+ break;
+ }
+
+ if (!m_running)
+ break;
+
+ if (res > 0)
+ handleEvents(fds);
+ else
+ {
+ for (std::deque<Conn*>::iterator it = m_conns.begin(); it != m_conns.end(); ++it)
+ (*it)->tick();
+ }
+
+ cleanupConns();
+ }
+
+ m_stopped = true;
+}
+
+int RADIUS::maxFD() const
+{
+ int maxFD = m_listenSocket;
+ std::deque<STG::Conn *>::const_iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ if (maxFD < (*it)->sock())
+ maxFD = (*it)->sock();
+ return maxFD;
+}
+
+void RADIUS::buildFDSet(fd_set & fds) const
+{
+ FD_ZERO(&fds);
+ FD_SET(m_listenSocket, &fds);
+ std::deque<STG::Conn *>::const_iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ FD_SET((*it)->sock(), &fds);
+}
+
+void RADIUS::cleanupConns()
+{
+ std::deque<STG::Conn *>::iterator pos;
+ for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
+ if (!(*pos)->isOk()) {
+ delete *pos;
+ *pos = NULL;
+ }
+
+ pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
+ m_conns.erase(pos, m_conns.end());
+}
+
+void RADIUS::handleEvents(const fd_set & fds)
+{
+ if (FD_ISSET(m_listenSocket, &fds))
+ acceptConnection();
+ else
+ {
+ std::deque<STG::Conn *>::iterator it;
+ for (it = m_conns.begin(); it != m_conns.end(); ++it)
+ if (FD_ISSET((*it)->sock(), &fds))
+ (*it)->read();
+ else
+ (*it)->tick();
+ }
+}
+
+void RADIUS::acceptConnection()
+{
+ if (m_config.connectionType == Config::UNIX)
+ acceptUNIX();
+ else
+ acceptTCP();
+}
+
+void RADIUS::acceptUNIX()
+{
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ socklen_t size = sizeof(addr);
+ int res = accept(m_listenSocket, reinterpret_cast<sockaddr*>(&addr), &size);
+ if (res == -1)
+ {
+ m_error = std::string("Failed to accept UNIX connection: ") + strerror(errno);
+ m_logger(m_error);
+ return;
+ }
+ printfd(__FILE__, "New UNIX connection: '%s'\n", addr.sun_path);
+ m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, addr.sun_path));
+}
+
+void RADIUS::acceptTCP()
+{
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ socklen_t size = sizeof(addr);
+ int res = accept(m_listenSocket, reinterpret_cast<sockaddr*>(&addr), &size);
+ if (res == -1)
+ {
+ m_error = std::string("Failed to accept TCP connection: ") + strerror(errno);
+ m_logger(m_error);
+ return;
+ }
+ std::string remote = inet_ntostring(addr.sin_addr.s_addr) + ":" + x2str(ntohs(addr.sin_port));
+ printfd(__FILE__, "New TCP connection: '%s'\n", remote.c_str());
+ m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, remote));
+}
+
+void RADIUS::authorize(const USER& user)
+{
+ uint32_t ip = 0;
+ const std::string& login(user.GetLogin());
+ if (!m_users->Authorize(login, ip, 0xffFFffFF, this))
+ {
+ m_error = "Unable to authorize user '" + login + "' with ip " + inet_ntostring(ip) + ".";
+ m_logger(m_error);
+ }
+ else
+ m_logins.insert(login);
+}
+
+void RADIUS::unauthorize(const std::string& login, const std::string& reason)
+{
+ const std::set<std::string>::const_iterator it = m_logins.find(login);
+ if (it == m_logins.end())
+ return;
+ m_logins.erase(it);
+ m_users->Unauthorize(login, this, reason);
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_RADIUS_H__
+#define __STG_RADIUS_H__
+
+#include "stg/auth.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include "config.h"
+#include "conn.h"
+
+#include <string>
+#include <deque>
+#include <set>
+#include <cstdint>
+
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/types.h>
+
+extern "C" PLUGIN * GetPlugin();
+
+class STORE;
+class USERS;
+
+class RADIUS : public AUTH {
+public:
+ RADIUS();
+ virtual ~RADIUS() {}
+
+ void SetUsers(USERS* u) { m_users = u; }
+ void SetStore(STORE* s) { m_store = s; }
+ void SetStgSettings(const SETTINGS*) {}
+ void SetSettings(const MODULE_SETTINGS& s) { m_settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & /*ms*/) { return 0; }
+ bool IsRunning() { return m_running; }
+
+ const std::string& GetStrError() const { return m_error; }
+ std::string GetVersion() const { return "RADIUS data access plugin v. 2.0"; }
+ uint16_t GetStartPosition() const { return 30; }
+ uint16_t GetStopPosition() const { return 30; }
+
+ int SendMessage(const STG_MSG&, uint32_t) const { return 0; }
+
+ void authorize(const USER& user);
+ void unauthorize(const std::string& login, const std::string& reason);
+
+private:
+ RADIUS(const RADIUS & rvalue);
+ RADIUS & operator=(const RADIUS & rvalue);
+
+ static void* run(void*);
+
+ bool reconnect();
+ int createUNIX() const;
+ int createTCP() const;
+ void runImpl();
+ int maxFD() const;
+ void buildFDSet(fd_set & fds) const;
+ void cleanupConns();
+ void handleEvents(const fd_set & fds);
+ void acceptConnection();
+ void acceptUNIX();
+ void acceptTCP();
+
+ mutable std::string m_error;
+ STG::Config m_config;
+
+ MODULE_SETTINGS m_settings;
+
+ bool m_running;
+ bool m_stopped;
+
+ USERS* m_users;
+ const STORE* m_store;
+
+ int m_listenSocket;
+ std::deque<STG::Conn*> m_conns;
+ std::set<std::string> m_logins;
+
+ pthread_t m_thread;
+
+ PLUGIN_LOGGER m_logger;
+};
+
+#endif
--- /dev/null
+set ( CPP_FILES rscript.cpp nrmap_parser.cpp )
+
+add_library ( mod_remote_script MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_remote_script crypto scriptexecuter logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.7 2010/02/16 11:41:00 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_remote_script.so
+
+SRCS = ./rscript.cpp \
+ ./nrmap_parser.cpp
+
+STGLIBS = common \
+ crypto \
+ logger \
+ scriptexecuter
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.8 $
+ $Author: faust $
+ $Date: 2009/10/22 09:58:53 $
+ */
+
+#include <fstream>
+#include <cerrno>
+#include <cstring>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "stg/common.h"
+#include "nrmap_parser.h"
+
+bool NRMapParser::ReadFile(const std::string & fileName)
+{
+std::ifstream source(fileName.c_str());
+
+if (!source)
+ {
+ errorStr = "Error opening file ";
+ errorStr += fileName;
+ printfd(__FILE__, "NRMapParser::ReadFile(): %s\n", errorStr.c_str());
+ return true;
+ }
+
+int lineNumber = 0;
+std::string line;
+std::vector<NET_ROUTER> _nrmap;
+
+while (getline(source, line))
+ {
+ ++lineNumber;
+ NET_ROUTER nr;
+
+ if (Trim(line) == "")
+ {
+ continue;
+ }
+
+ if (ParseLine(line, nr))
+ {
+ printfd(__FILE__, "NRMapParser::ReadFile(): Error parsing line %d: '%s'\n", lineNumber, errorStr.c_str());
+ return true;
+ }
+
+ _nrmap.push_back(nr);
+ }
+
+nrmap = _nrmap;
+
+return false;
+}
+
+bool NRMapParser::ParseLine(const std::string & line, NET_ROUTER & nr) const
+{
+// xxx.xxx.xxx.xxx/yy zzz.zzz.zzz.zzz
+size_t pos = line.find_first_of(" \t");
+
+if (pos == std::string::npos)
+ {
+ errorStr = "No space between subnet and router";
+ return true;
+ }
+
+std::string subnet(line.substr(0, pos)); // xxx.xxx.xxx.xxx/yy
+
+uint32_t ip = 0;
+uint32_t mask = 0;
+
+if (ParseNet(subnet, ip, mask))
+ {
+ return true;
+ }
+
+nr.subnetIP = ip;
+nr.subnetMask = mask;
+
+pos = line.find_first_not_of(" \t", pos);
+
+if (pos == std::string::npos)
+ {
+ errorStr = "No router address found";
+ return true;
+ }
+
+size_t pos2 = line.find_first_of(" \t", pos);
+
+std::string router(line.substr(pos, pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos)); //zzz.zzz.zzz.zzz
+
+uint32_t routerIP;
+
+if (ParseRouter(router, routerIP))
+ {
+ return true;
+ }
+
+std::vector<uint32_t>::iterator it;
+
+it = std::lower_bound(
+ nr.routers.begin(),
+ nr.routers.end(),
+ routerIP
+ );
+nr.routers.insert(it, routerIP);
+
+//nr.routers.push_back(routerIP);
+
+while (pos2 != std::string::npos)
+ {
+ pos = line.find_first_not_of(" \t", pos2);
+
+ if (pos == std::string::npos)
+ {
+ return false;
+ }
+
+ pos2 = line.find_first_of(" \t", pos);
+
+ if (ParseRouter(line.substr(
+ pos,
+ pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos),
+ routerIP))
+ {
+ return true;
+ }
+
+ it = std::lower_bound(
+ nr.routers.begin(),
+ nr.routers.end(),
+ routerIP
+ );
+ nr.routers.insert(it, routerIP);
+
+ //nr.routers.push_back(routerIP);
+
+ }
+
+return false;
+}
+
+bool NRMapParser::ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const
+{
+// xxx.xxx.xxx.xxx/yy
+
+size_t pos = line.find_first_of('/');
+
+if (pos == std::string::npos)
+ {
+ errorStr = "Subnet is not in CIDR notation";
+ return true;
+ }
+
+int res = inet_pton(AF_INET, line.substr(0, pos).c_str(), &ip); //xxx.xxx.xxx.xxx
+
+if (res < 0)
+ {
+ errorStr = strerror(errno);
+ return true;
+ }
+else if (res == 0)
+ {
+ errorStr = "Invalid subnet address";
+ return true;
+ }
+
+if (str2x(line.substr(pos + 1, line.length() - pos - 1), mask)) //yy
+ {
+ errorStr = "Invalid subnet mask";
+ return true;
+ }
+if (mask > 32)
+ {
+ errorStr = "Subnet mask is out of range [0..32]";
+ return true;
+ }
+mask = htonl(0xffFFffFF << (32 - mask)); //bitmask
+
+return false;
+}
+
+bool NRMapParser::ParseRouter(const std::string & line, uint32_t & ip) const
+{
+int res = inet_pton(AF_INET, line.c_str(), &ip); //zzz.zzz.zzz.zzz
+
+if (res < 0)
+ {
+ errorStr = strerror(errno);
+ return true;
+ }
+else if (res == 0)
+ {
+ printfd(__FILE__, "NRMapParser::ParseRouter(): IP '%s' is invalid\n", line.c_str());
+ errorStr = "Invalid router address";
+ return true;
+ }
+return false;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.2 $
+ $Author: faust $
+ $Date: 2009/09/23 12:51:42 $
+ */
+
+#ifndef __NRMAP_PARSER_H__
+#define __NRMAP_PARSER_H__
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+struct NET_ROUTER
+{
+ NET_ROUTER() : subnetIP(0), subnetMask(0), routers() {}
+ NET_ROUTER(const NET_ROUTER & rvalue)
+ : subnetIP(rvalue.subnetIP),
+ subnetMask(rvalue.subnetMask),
+ routers(rvalue.routers)
+ {}
+
+ uint32_t subnetIP;
+ uint32_t subnetMask;
+ std::vector<uint32_t> routers;
+
+ NET_ROUTER & operator=(const NET_ROUTER & rvalue)
+ {
+ subnetIP = rvalue.subnetIP;
+ subnetMask = rvalue.subnetMask;
+ routers = rvalue.routers;
+ return *this;
+ }
+};
+
+class NRMapParser {
+public:
+ NRMapParser() : nrmap(), errorStr() {}
+ ~NRMapParser() {}
+
+ bool ReadFile(const std::string & fileName);
+ const std::vector<NET_ROUTER> & GetMap() const { return nrmap; }
+ const std::string & GetErrorStr() const { return errorStr; }
+
+private:
+ NRMapParser(const NRMapParser & rvalue);
+ NRMapParser & operator=(const NRMapParser & rvalue);
+
+ std::vector<NET_ROUTER> nrmap;
+ mutable std::string errorStr;
+
+ bool ParseLine(const std::string & line, NET_ROUTER & nr) const;
+ bool ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const;
+ bool ParseRouter(const std::string & line, uint32_t & ip) const;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "rscript.h"
+
+#include "ur_functor.h"
+#include "send_functor.h"
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/users.h"
+#include "stg/user_property.h"
+#include "stg/plugin_creator.h"
+#include "stg/logger.h"
+
+#include <algorithm>
+
+#include <csignal>
+#include <cassert>
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+
+#include <sys/time.h>
+#include <netinet/ip.h>
+
+extern volatile time_t stgTime;
+
+using RS::REMOTE_SCRIPT;
+
+namespace {
+
+template<typename T>
+struct USER_IS
+{
+ explicit USER_IS(USER_PTR u) : user(u) {}
+ bool operator()(const T & notifier) { return notifier.GetUser() == user; }
+
+ USER_PTR user;
+};
+
+PLUGIN_CREATOR<REMOTE_SCRIPT> rsc;
+
+} // namespace anonymous
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return rsc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RS::SETTINGS::SETTINGS()
+ : sendPeriod(0),
+ port(0)
+{
+}
+//-----------------------------------------------------------------------------
+int RS::SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+netRouters.clear();
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = static_cast<uint16_t>(p);
+///////////////////////////
+pv.param = "SendPeriod";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'SendPeriod\' not found.";
+ printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
+ {
+ errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
+ return -1;
+ }
+///////////////////////////
+pv.param = "UserParams";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'UserParams\' not found.";
+ printfd(__FILE__, "Parameter 'UserParams' not found\n");
+ return -1;
+ }
+userParams = pvi->value;
+///////////////////////////
+pv.param = "Password";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Password\' not found.";
+ printfd(__FILE__, "Parameter 'Password' not found\n");
+ return -1;
+ }
+password = pvi->value[0];
+///////////////////////////
+pv.param = "SubnetFile";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'SubnetFile\' not found.";
+ printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
+ return -1;
+ }
+subnetFile = pvi->value[0];
+
+NRMapParser nrMapParser;
+
+if (!nrMapParser.ReadFile(subnetFile))
+ {
+ netRouters = nrMapParser.GetMap();
+ }
+else
+ {
+ GetStgLogger()("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::REMOTE_SCRIPT()
+ : ctx(),
+ ipNotifierList(),
+ connNotifierList(),
+ authorizedUsers(),
+ errorStr(),
+ rsSettings(),
+ settings(),
+ sendPeriod(15),
+ halfPeriod(8),
+ nonstop(false),
+ isRunning(false),
+ users(NULL),
+ netRouters(),
+ thread(),
+ mutex(),
+ sock(0),
+ onAddUserNotifier(*this),
+ onDelUserNotifier(*this),
+ logger(GetPluginLogger(GetStgLogger(), "rscript"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::~REMOTE_SCRIPT()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void * REMOTE_SCRIPT::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
+
+rs->isRunning = true;
+
+while (rs->nonstop)
+ {
+ rs->PeriodicSend();
+ sleep(2);
+ }
+
+rs->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::ParseSettings()
+{
+int ret = rsSettings.ParseSettings(settings);
+if (ret)
+ errorStr = rsSettings.GetStrError();
+
+sendPeriod = rsSettings.GetSendPeriod();
+halfPeriod = sendPeriod / 2;
+
+return ret;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Start()
+{
+netRouters = rsSettings.GetSubnetsMap();
+
+InitEncrypt(&ctx, rsSettings.GetPassword());
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+if (GetUsers())
+ {
+ return -1;
+ }
+
+if (PrepareNet())
+ {
+ return -1;
+ }
+
+if (!isRunning)
+ {
+ if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+ }
+
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Stop()
+{
+if (!IsRunning())
+ return 0;
+
+nonstop = false;
+
+std::for_each(
+ authorizedUsers.begin(),
+ authorizedUsers.end(),
+ DisconnectUser(*this)
+ );
+
+FinalizeNet();
+
+if (isRunning)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ }
+
+users->DelNotifierUserDel(&onDelUserNotifier);
+users->DelNotifierUserAdd(&onAddUserNotifier);
+
+if (isRunning)
+ {
+ logger("Cannot stop thread.");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Reload(const MODULE_SETTINGS & /*ms*/)
+{
+NRMapParser nrMapParser;
+
+if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
+ {
+ errorStr = nrMapParser.GetErrorStr();
+ logger("Map file reading error: %s", errorStr.c_str());
+ return -1;
+ }
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
+
+ netRouters = nrMapParser.GetMap();
+ }
+
+std::for_each(authorizedUsers.begin(),
+ authorizedUsers.end(),
+ UpdateRouter(*this));
+
+logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
+printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (sock < 0)
+ {
+ errorStr = "Cannot create socket.";
+ logger("Canot create a socket: %s", strerror(errno));
+ printfd(__FILE__, "Cannot create socket\n");
+ return true;
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::FinalizeNet()
+{
+close(sock);
+return false;
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::PeriodicSend()
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
+while (it != authorizedUsers.end())
+ {
+ if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
+ {
+ Send(it->second);
+ }
+ ++it;
+ }
+}
+//-----------------------------------------------------------------------------
+#ifdef NDEBUG
+bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
+#else
+bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
+#endif
+{
+RS::PACKET_HEADER packetHead;
+
+memset(packetHead.padding, 0, sizeof(packetHead.padding));
+strcpy((char*)packetHead.magic, RS_ID);
+packetHead.protoVer[0] = '0';
+packetHead.protoVer[1] = '2';
+if (forceDisconnect)
+ {
+ packetHead.packetType = RS_DISCONNECT_PACKET;
+ printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+ }
+else
+ {
+ if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
+ {
+ //SendLong
+ packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
+ if (rsu.user->IsInetable())
+ printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
+ else
+ printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+ }
+ else
+ {
+ //SendShort
+ packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
+ if (rsu.user->IsInetable())
+ printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
+ else
+ printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+ }
+ }
+rsu.shortPacketsCount++;
+rsu.lastSentTime = stgTime;
+
+packetHead.ip = htonl(rsu.ip);
+packetHead.id = htonl(rsu.user->GetID());
+strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
+packetHead.login[RS_LOGIN_LEN - 1] = 0;
+
+memcpy(buf, &packetHead, sizeof(packetHead));
+
+if (packetHead.packetType == RS_ALIVE_PACKET)
+ {
+ return false;
+ }
+
+RS::PACKET_TAIL packetTail;
+
+memset(packetTail.padding, 0, sizeof(packetTail.padding));
+strcpy((char*)packetTail.magic, RS_ID);
+std::vector<std::string>::const_iterator it;
+std::string params;
+for(it = rsSettings.GetUserParams().begin();
+ it != rsSettings.GetUserParams().end();
+ ++it)
+ {
+ std::string parameter(rsu.user->GetParamValue(it->c_str()));
+ if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
+ {
+ logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + parameter.length(), RS_PARAMS_LEN);
+ break;
+ }
+ params += parameter + " ";
+ }
+strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
+packetTail.params[RS_PARAMS_LEN - 1] = 0;
+
+assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
+
+Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+memset(buffer, 0, sizeof(buffer));
+
+if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
+ {
+ printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
+ return true;
+ }
+
+std::for_each(
+ rsu.routers.begin(),
+ rsu.routers.end(),
+ PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
+ );
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
+ {
+ printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
+ return true;
+ }
+
+struct sockaddr_in sendAddr;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
+sendAddr.sin_addr.s_addr = routerIP;
+
+ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
+
+if (res < 0)
+ logger("sendto error: %s", strerror(errno));
+
+return (res != sizeof(buffer));
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::GetUsers()
+{
+USER_PTR u;
+
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (!users->SearchNext(h, &u))
+ {
+ SetUserNotifiers(u);
+ }
+
+users->CloseSearch(h);
+return false;
+}
+//-----------------------------------------------------------------------------
+std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
+{
+STG_LOCKER lock(&mutex);
+for (size_t i = 0; i < netRouters.size(); ++i)
+ {
+ if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
+ {
+ return netRouters[i].routers;
+ }
+ }
+return std::vector<uint32_t>();
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u)
+{
+ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
+connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u)
+{
+ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
+ ipNotifierList.end(),
+ USER_IS<IP_NOTIFIER>(u)),
+ ipNotifierList.end());
+connNotifierList.erase(std::remove_if(connNotifierList.begin(),
+ connNotifierList.end(),
+ USER_IS<CONNECTED_NOTIFIER>(u)),
+ connNotifierList.end());
+
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::AddRSU(USER_PTR user)
+{
+RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
+Send(rsu);
+
+STG_LOCKER lock(&mutex);
+authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::DelRSU(USER_PTR user)
+{
+STG_LOCKER lock(&mutex);
+std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
+while (it != authorizedUsers.end())
+ {
+ if (it->second.user == user)
+ {
+ Send(it->second, true);
+ authorizedUsers.erase(it);
+ return;
+ }
+ ++it;
+ }
+/*const std::map<uint32_t, RS::USER>::iterator it(
+ authorizedUsers.find(user->GetCurrIP())
+ );
+if (it != authorizedUsers.end())
+ {
+ Send(it->second, true);
+ authorizedUsers.erase(it);
+ }*/
+}
+//-----------------------------------------------------------------------------
+void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
+{
+if (newValue)
+ rs.AddRSU(user);
+else
+ rs.DelRSU(user);
+}
+//-----------------------------------------------------------------------------
+void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
+{
+if (newValue)
+ rs.AddRSU(user);
+else
+ rs.DelRSU(user);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
+{
+unsigned char keyL[PASSWD_LEN]; // Пароль для шифровки
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
+{
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+for (size_t i = 0; i < len8; ++i)
+ Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ * Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef RSCRIPT_H
+#define RSCRIPT_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/user.h"
+#include "stg/blowfish.h"
+#include "stg/rs_packets.h"
+#include "stg/logger.h"
+
+#include "nrmap_parser.h"
+
+#include <string>
+#include <list>
+#include <map>
+#include <functional>
+#include <utility>
+#include <cstdint>
+
+#include <pthread.h>
+
+extern "C" PLUGIN * GetPlugin();
+
+#define RS_DEBUG (1)
+
+#define MAX_SHORT_PCKT (3)
+
+class SETTINGS;
+class USERS;
+
+namespace RS
+{
+
+class REMOTE_SCRIPT;
+class UpdateRouter;
+class DisconnectUser;
+
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
+public:
+ explicit ADD_USER_NONIFIER(REMOTE_SCRIPT & r)
+ : NOTIFIER_BASE<USER_PTR>(), rs(r) {}
+ virtual ~ADD_USER_NONIFIER() {}
+ void Notify(const USER_PTR & user);
+
+private:
+ ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rhs);
+ ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER);
+
+ REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_PTR> {
+public:
+ explicit DEL_USER_NONIFIER(REMOTE_SCRIPT & r)
+ : NOTIFIER_BASE<USER_PTR>(), rs(r) {}
+ virtual ~DEL_USER_NONIFIER() {}
+ void Notify(const USER_PTR & user);
+
+private:
+ DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rhs);
+ DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER);
+
+ REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class IP_NOTIFIER: public PROPERTY_NOTIFIER_BASE<uint32_t> {
+public:
+ IP_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(), user(u), rs(r) { user->AddCurrIPAfterNotifier(this); }
+ IP_NOTIFIER(const IP_NOTIFIER & rhs)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(), user(rhs.user), rs(rhs.rs) { user->AddCurrIPAfterNotifier(this); }
+ ~IP_NOTIFIER() { user->DelCurrIPAfterNotifier(this); }
+
+ IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs)
+ {
+ user->DelCurrIPAfterNotifier(this);
+ user = rhs.user;
+ user->AddCurrIPAfterNotifier(this);
+ return *this;
+ }
+
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ USER_PTR GetUser() const { return user; }
+
+private:
+
+ USER_PTR user;
+ REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class CONNECTED_NOTIFIER: public PROPERTY_NOTIFIER_BASE<bool> {
+public:
+ CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u)
+ : PROPERTY_NOTIFIER_BASE<bool>(), user(u), rs(r) { user->AddConnectedAfterNotifier(this); }
+ CONNECTED_NOTIFIER(const CONNECTED_NOTIFIER & rhs)
+ : PROPERTY_NOTIFIER_BASE<bool>(), user(rhs.user), rs(rhs.rs) { user->AddConnectedAfterNotifier(this); }
+ ~CONNECTED_NOTIFIER() { user->DelConnectedAfterNotifier(this); }
+
+ CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs)
+ {
+ user->DelConnectedAfterNotifier(this);
+ user = rhs.user;
+ user->AddConnectedAfterNotifier(this);
+ return *this;
+ }
+
+ void Notify(const bool & oldValue, const bool & newValue);
+ USER_PTR GetUser() const { return user; }
+
+private:
+
+ USER_PTR user;
+ REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+struct USER {
+ USER(const std::vector<uint32_t> & r, USER_PTR it)
+ : lastSentTime(0),
+ user(it),
+ routers(r),
+ shortPacketsCount(0),
+ ip(user->GetCurrIP())
+ {}
+
+ time_t lastSentTime;
+ USER_PTR user;
+ std::vector<uint32_t> routers;
+ int shortPacketsCount;
+ uint32_t ip;
+};
+//-----------------------------------------------------------------------------
+class SETTINGS {
+public:
+ SETTINGS();
+ virtual ~SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetSendPeriod() const { return sendPeriod; }
+ uint16_t GetPort() const { return port; }
+ const std::vector<NET_ROUTER> & GetSubnetsMap() const { return netRouters; }
+ const std::vector<std::string> & GetUserParams() const { return userParams; }
+ const std::string & GetPassword() const { return password; }
+ const std::string & GetMapFileName() const { return subnetFile; }
+
+private:
+ int sendPeriod;
+ uint16_t port;
+ std::string errorStr;
+ std::vector<NET_ROUTER> netRouters;
+ std::vector<std::string> userParams;
+ std::string password;
+ std::string subnetFile;
+};
+//-----------------------------------------------------------------------------
+class REMOTE_SCRIPT : public PLUGIN {
+public:
+ REMOTE_SCRIPT();
+ virtual ~REMOTE_SCRIPT();
+
+ void SetUsers(USERS * u) { users = u; }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & ms);
+ bool IsRunning() { return isRunning; }
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return "Remote script v 0.3"; }
+ uint16_t GetStartPosition() const { return 10; }
+ uint16_t GetStopPosition() const { return 10; }
+
+ void DelUser(USER_PTR u) { UnSetUserNotifiers(u); }
+ void AddUser(USER_PTR u) { SetUserNotifiers(u); }
+
+ void AddRSU(USER_PTR user);
+ void DelRSU(USER_PTR user);
+
+private:
+ REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs);
+ REMOTE_SCRIPT & operator=(const REMOTE_SCRIPT & rhs);
+
+ static void * Run(void *);
+ bool PrepareNet();
+ bool FinalizeNet();
+
+ bool Send(USER & rsu, bool forceDisconnect = false) const;
+ bool SendDirect(USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const;
+ bool PreparePacket(char * buf, size_t bufSize, USER &rsu, bool forceDisconnect = false) const;
+ void PeriodicSend();
+
+ std::vector<uint32_t> IP2Routers(uint32_t ip);
+ bool GetUsers();
+
+ void SetUserNotifiers(USER_PTR u);
+ void UnSetUserNotifiers(USER_PTR u);
+
+ void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const;
+ void Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const;
+
+ mutable BLOWFISH_CTX ctx;
+
+ std::list<IP_NOTIFIER> ipNotifierList;
+ std::list<CONNECTED_NOTIFIER> connNotifierList;
+ std::map<uint32_t, USER> authorizedUsers;
+
+ mutable std::string errorStr;
+ SETTINGS rsSettings;
+ MODULE_SETTINGS settings;
+ int sendPeriod;
+ int halfPeriod;
+
+ bool nonstop;
+ bool isRunning;
+
+ USERS * users;
+
+ std::vector<NET_ROUTER> netRouters;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+
+ int sock;
+
+ ADD_USER_NONIFIER onAddUserNotifier;
+ DEL_USER_NONIFIER onDelUserNotifier;
+
+ PLUGIN_LOGGER logger;
+
+ friend class RS::UpdateRouter;
+ friend class RS::DisconnectUser;
+ friend class RS::CONNECTED_NOTIFIER;
+};
+//-----------------------------------------------------------------------------
+class DisconnectUser : public std::unary_function<std::pair<const uint32_t, USER> &, void> {
+ public:
+ explicit DisconnectUser(REMOTE_SCRIPT & rs) : rscript(rs) {}
+ void operator()(std::pair<const uint32_t, USER> & p)
+ {
+ rscript.Send(p.second, true);
+ }
+ private:
+ REMOTE_SCRIPT & rscript;
+};
+//-----------------------------------------------------------------------------
+inline void ADD_USER_NONIFIER::Notify(const USER_PTR & user)
+{
+rs.AddUser(user);
+}
+//-----------------------------------------------------------------------------
+inline void DEL_USER_NONIFIER::Notify(const USER_PTR & user)
+{
+rs.DelUser(user);
+}
+//-----------------------------------------------------------------------------
+
+} // namespace RS
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2010/03/04 12:11:09 $
+ $Author: faust $
+*/
+
+#ifndef __SEND_FUNCTOR_H__
+#define __SEND_FUNCTOR_H__
+
+#include <functional>
+#include <cstdint>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+class PacketSender : public std::unary_function<uint32_t, ssize_t> {
+ public:
+ PacketSender(int s, char * b, size_t l, uint16_t p)
+ : sock(s),
+ buffer(b),
+ length(l),
+ port(p) {}
+ ssize_t operator() (uint32_t ip)
+ {
+ struct sockaddr_in sendAddr;
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = port;
+ sendAddr.sin_addr.s_addr = ip;
+
+ return sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ }
+ private:
+ int sock;
+ char * buffer;
+ size_t length;
+ uint16_t port;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef __UR_FUNCTOR_H__
+#define __UR_FUNCTOR_H__
+
+#include "rscript.h"
+
+#include "stg/common.h"
+
+#include <functional>
+#include <algorithm>
+#include <utility>
+#include <cstdint>
+
+namespace RS
+{
+
+class UpdateRouter : public std::unary_function<std::pair<const uint32_t, RS::USER>, void>
+{
+public:
+ explicit UpdateRouter(REMOTE_SCRIPT & t)
+ : obj(t) {}
+
+ void operator() (std::pair<const uint32_t, USER> & val)
+ {
+ std::vector<uint32_t> newRouters = obj.IP2Routers(val.second.ip);
+ std::vector<uint32_t>::const_iterator oldIt(val.second.routers.begin());
+ std::vector<uint32_t>::const_iterator newIt(newRouters.begin());
+ val.second.shortPacketsCount = 0;
+ while (oldIt != val.second.routers.end() ||
+ newIt != newRouters.end())
+ {
+ if (oldIt == val.second.routers.end())
+ {
+ if (newIt != newRouters.end())
+ {
+ obj.SendDirect(val.second, *newIt); // Connect on new router
+ ++newIt;
+ }
+ }
+ else if (newIt == newRouters.end())
+ {
+ obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
+ ++oldIt;
+ }
+ else if (*oldIt < *newIt)
+ {
+ obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
+ ++oldIt;
+ }
+ else if (*oldIt > *newIt)
+ {
+ obj.SendDirect(val.second, *newIt); // Connect on new router
+ ++newIt;
+ }
+ else
+ {
+ ++oldIt;
+ if (newIt != newRouters.end())
+ ++newIt;
+ }
+ }
+ val.second.routers = newRouters;
+ }
+private:
+ REMOTE_SCRIPT & obj;
+};
+
+} // namespace RS
+
+#endif
--- /dev/null
+set ( CPP_FILES smux.cpp
+ sensors.cpp
+ tables.cpp
+ handlers.cpp
+ utils.cpp
+ types.cpp )
+
+add_library ( mod_smux MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_smux scriptexecuter logger smux common )
--- /dev/null
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_smux.so
+
+SRCS = smux.cpp \
+ sensors.cpp \
+ tables.cpp \
+ handlers.cpp \
+ utils.cpp \
+ types.cpp
+
+STGLIBS = common \
+ smux \
+ logger \
+ scriptexecuter
+
+CFLAGS += -I ../../../../../stglibs/smux.lib/include/stg
+CXXFLAGS += -I ../../../../../stglibs/smux.lib/include/stg
+
+include ../../Makefile.in
--- /dev/null
+STG-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ enterprises,
+ MODULE-IDENTITY, OBJECT-TYPE,
+ Integer32 FROM SNMPv2-SMI
+ DisplayString FROM SNMPv2-TC;
+
+stgMIB MODULE-IDENTITY
+ LAST-UPDATED "201101060000Z"
+ ORGANIZATION "STG"
+ CONTACT-INFO
+ "Primary Contact: Maxim Mamontov
+ email: faust@stg.dp.ua"
+ DESCRIPTION
+ "This MIB module defines objects for Stargazer data."
+ REVISION "201101060000Z"
+ DESCRIPTION "Initial revision"
+ ::= { enterprises 38313 }
+
+stg24 OBJECT IDENTIFIER ::= { stgMIB 1 }
+
+users OBJECT IDENTIFIER ::= { stg24 1 }
+tariffs OBJECT IDENTIFIER ::= { stg24 2 }
+admins OBJECT IDENTIFIER ::= { stg24 3 }
+services OBJECT IDENTIFIER ::= { stg24 4 }
+corporations OBJECT IDENTIFIER ::= { stg24 5 }
+traffcounter OBJECT IDENTIFIER ::= { stg24 6 }
+
+totalUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total users registered in the billing"
+ DEFVAL { 0 }
+ ::= { users 1 }
+
+onlineUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of currently online users"
+ DEFVAL { 0 }
+ ::= { users 2 }
+
+authorizedUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of currently authorized users"
+ DEFVAL { 0 }
+ ::= { users 3 }
+
+alwaysOnlineUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users with 'always online' option"
+ DEFVAL { 0 }
+ ::= { users 4 }
+
+noCashUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users with negative cash"
+ DEFVAL { 0 }
+ ::= { users 5 }
+
+disabledDetailStatsUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users with disabled detail stats"
+ DEFVAL { 0 }
+ ::= { users 6 }
+
+disabledUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of disabled users"
+ DEFVAL { 0 }
+ ::= { users 7 }
+
+passiveUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of passive users"
+ DEFVAL { 0 }
+ ::= { users 8 }
+
+creditUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users with positive credit"
+ DEFVAL { 0 }
+ ::= { users 9 }
+
+freeMbUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users with positive freeMb"
+ DEFVAL { 0 }
+ ::= { users 10 }
+
+tariffChangeUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of users changing tariff next month"
+ DEFVAL { 0 }
+ ::= { users 11 }
+
+activeUsers OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of online users with traffic during session"
+ DEFVAL {0}
+ ::= { users 12 }
+
+totalTariffs OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total tariffs registered in the billing"
+ DEFVAL { 0 }
+ ::= { tariffs 1 }
+
+tariffUsageTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF TariffUsageTable
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The number of users by each tariff"
+ DEFVAL { 0 }
+ ::= { tariffs 2 }
+
+tariffUsageTableEntry OBJECT-TYPE
+ SYNTAX TariffUsageTable
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A row describing a given tariff"
+ INDEX { tariffIndex }
+ ::= {tariffUsageTable 1 }
+
+TariffUsageTable ::= SEQUENCE {
+ tariffIndex Integer32,
+ tariffName DisplayString,
+ userCount Integer32
+}
+
+tariffIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..255)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The id of the tariff this table describes."
+ ::= { tariffUsageTableEntry 1 }
+
+tariffName OBJECT-TYPE
+ SYNTAX DisplayString
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The name of the tariff this table describes."
+ ::= { tariffUsageTableEntry 2 }
+
+userCount OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The count fo users of the tariff this table describes."
+ ::= { tariffUsageTableEntry 3 }
+
+totalAdmins OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total admins registered in the billing"
+ DEFVAL { 0 }
+ ::= { admins 1 }
+
+totalServices OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total services registered in the billing"
+ DEFVAL { 0 }
+ ::= { services 1 }
+
+totalCorporations OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total corporations registered in the billing"
+ DEFVAL { 0 }
+ ::= { corporations 1 }
+
+totalRules OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total traffic classification rules described by rules file"
+ DEFVAL { 0 }
+ ::= { traffcounter 1 }
+
+END
--- /dev/null
+Количество пользователей всего в биллинге
+Количество пользователей онлайн
+Количество пользователей с отрицательный балансом
+Количество пользователей с всегда онлайн
+Количество пользователей по отношению к каждому из тарифов
+Количество пользователей по отношению к каждому UserData полю - ?
+Количество пользователей с отключенной детальной статистикой
+Количество отключенных пользователей
+Количество замороженных пользователей
+Количество пользователей, у которых есть кредит
+Количество пользователей, у которых есть предоплаченный трафик
+
+Количество тарифов
+Количество направлений
--- /dev/null
+#include <cassert>
+
+#include "stg/GetRequest-PDU.h"
+#include "stg/GetResponse-PDU.h"
+#include "stg/VarBindList.h"
+#include "stg/VarBind.h"
+
+#include "stg/common.h"
+
+#include "utils.h"
+#include "smux.h"
+
+#ifdef SMUX_DEBUG
+bool SMUX::CloseHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::CloseHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::CloseHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+#ifdef SMUX_DEBUG
+bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::RegisterResponseHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+bool SMUX::PDUsRequestHandler(const SMUX_PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::PDUsRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+#endif
+PDUsHandlers::iterator it(pdusHandlers.find(pdus->choice.pdus.present));
+if (it != pdusHandlers.end())
+ {
+ return (this->*(it->second))(&pdus->choice.pdus);
+ }
+#ifdef SMUX_DEBUG
+else
+ {
+ switch (pdus->present)
+ {
+ case PDUs_PR_NOTHING:
+ printfd(__FILE__, "SMUX::PDUsRequestHandler() - nothing\n");
+ break;
+ case PDUs_PR_get_response:
+ printfd(__FILE__, "SMUX::PDUsRequestHandler() - get response\n");
+ break;
+ case PDUs_PR_trap:
+ printfd(__FILE__, "SMUX::PDUsRequestHandler() - trap\n");
+ break;
+ default:
+ printfd(__FILE__, "SMUX::PDUsRequestHandler() - undefined\n");
+ }
+ }
+#endif
+return true;
+}
+
+#ifdef SMUX_DEBUG
+bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::CommitOrRollbackHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+bool SMUX::GetRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::GetRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
+GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
+assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
+VarBindList_t * varBindList = &msg->variable_bindings;
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg->request_id, id);
+asn_long2INTEGER(&msg->error_status, 0);
+asn_long2INTEGER(&msg->error_index, 0);
+
+const VarBindList_t * vbl = &getRequest->variable_bindings;
+for (int i = 0; i < vbl->list.count; ++i)
+ {
+ VarBind_t * vb = getRequest->variable_bindings.list.array[i];
+ Sensors::iterator it;
+ it = sensors.find(OID(&vb->name));
+ if (it == sensors.end())
+ {
+ return SendGetResponseErrorPDU(sock, getRequest,
+ PDU__error_status_noSuchName, i);
+ }
+
+ VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
+ assert(newVb && "Enought mempry to allocate VarBind_t");
+
+ it->first.ToOID(&newVb->name);
+ it->second->GetValue(&newVb->value);
+
+ ASN_SEQUENCE_ADD(varBindList, newVb);
+ }
+
+bool res = SendGetResponsePDU(sock, msg);
+#ifdef SMUX_DEBUG
+asn_fprint(stderr, &asn_DEF_GetResponse_PDU, msg);
+#endif
+ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
+return res;
+}
+
+bool SMUX::GetNextRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::GetNextRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
+GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
+assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
+VarBindList_t * varBindList = &msg->variable_bindings;
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg->request_id, id);
+asn_long2INTEGER(&msg->error_status, 0);
+asn_long2INTEGER(&msg->error_index, 0);
+
+const VarBindList_t * vbl = &getRequest->variable_bindings;
+for (int i = 0; i < vbl->list.count; ++i)
+ {
+ VarBind_t * vb = getRequest->variable_bindings.list.array[i];
+ Sensors::iterator it;
+ it = sensors.upper_bound(OID(&vb->name));
+ if (it == sensors.end())
+ {
+#ifdef SMUX_DEBUG
+ printfd(__FILE__, "SMUX::GetNextRequestHandler() - '%s' not found\n", OID(&vb->name).ToString().c_str());
+#endif
+ return SendGetResponseErrorPDU(sock, getRequest,
+ PDU__error_status_noSuchName, i);
+ }
+
+ VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
+ assert(newVb && "Enought mempry to allocate VarBind_t");
+
+ it->first.ToOID(&newVb->name);
+ it->second->GetValue(&newVb->value);
+
+ ASN_SEQUENCE_ADD(varBindList, newVb);
+ }
+
+bool res = SendGetResponsePDU(sock, msg);
+#ifdef SMUX_DEBUG
+asn_fprint(stderr, &asn_DEF_PDU, msg);
+#endif
+ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
+return res;
+}
+
+bool SMUX::SetRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::SetRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+return SendGetResponseErrorPDU(sock, &pdus->choice.set_request,
+ PDU__error_status_readOnly, 0);
+}
--- /dev/null
+#ifndef __PEN_H__
+#define __PEN_H__
+
+#define PEN_PREFIX ".1.3.6.1.4.1.38313"
+
+#endif
--- /dev/null
+#include <cassert>
+
+#include "stg/INTEGER.h"
+
+#include "stg/user.h"
+
+#include "sensors.h"
+
+bool UsersSensor::GetValue(ObjectSyntax_t * objectSyntax) const
+{
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+USER_PTR user;
+size_t count = 0;
+while (!users.SearchNext(handle, &user))
+ {
+ if (UserPredicate(user))
+ ++count;
+ }
+
+users.CloseSearch(handle);
+
+ValueToOS(count, objectSyntax);
+return true;
+}
+
+#ifdef DEBUG
+std::string UsersSensor::ToString() const
+{
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+USER_PTR user;
+size_t count = 0;
+while (!users.SearchNext(handle, &user))
+ {
+ if (UserPredicate(user))
+ ++count;
+ }
+
+users.CloseSearch(handle);
+
+std::string res;
+x2str(count, res);
+return res;
+}
+#endif
+
+bool ActiveUsersSensor::UserPredicate(USER_PTR userPtr) const
+{
+if (!userPtr->GetConnected())
+ return false;
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ if (userPtr->GetSessionUpload()[i] > 0 ||
+ userPtr->GetSessionDownload()[i] > 0)
+ return true;
+ }
+return false;
+}
--- /dev/null
+#ifndef __SENSORS_H__
+#define __SENSORS_H__
+
+#include <map>
+
+#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/admins.h"
+#include "stg/services.h"
+#include "stg/corporations.h"
+#include "stg/traffcounter.h"
+#include "stg/user_property.h"
+
+#include "stg/ObjectSyntax.h"
+
+#include "value2os.h"
+#include "types.h"
+
+class Sensor {
+ public:
+ virtual ~Sensor() {}
+ virtual bool GetValue(ObjectSyntax_t * objectSyntax) const = 0;
+#ifdef DEBUG
+ virtual std::string ToString() const = 0;
+#endif
+};
+
+typedef std::map<OID, Sensor *> Sensors;
+
+class TotalUsersSensor : public Sensor {
+ public:
+ explicit TotalUsersSensor(const USERS & u) : users(u) {}
+ virtual ~TotalUsersSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(users.Count(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(users.Count(), res); return res; }
+#endif
+
+ private:
+ const USERS & users;
+};
+
+class UsersSensor : public Sensor {
+ public:
+ explicit UsersSensor(USERS & u) : users(u) {}
+ virtual ~UsersSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const;
+#ifdef DEBUG
+ std::string ToString() const;
+#endif
+
+ private:
+ USERS & users;
+
+ virtual bool UserPredicate(USER_PTR userPtr) const = 0;
+};
+
+class ConnectedUsersSensor : public UsersSensor {
+ public:
+ explicit ConnectedUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~ConnectedUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetConnected(); }
+};
+
+class AuthorizedUsersSensor : public UsersSensor {
+ public:
+ explicit AuthorizedUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~AuthorizedUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetAuthorized(); }
+};
+
+class AlwaysOnlineUsersSensor : public UsersSensor {
+ public:
+ explicit AlwaysOnlineUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~AlwaysOnlineUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().alwaysOnline; }
+};
+
+class NoCashUsersSensor : public UsersSensor {
+ public:
+ explicit NoCashUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~NoCashUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().cash < 0; }
+};
+
+class DisabledDetailStatsUsersSensor : public UsersSensor {
+ public:
+ explicit DisabledDetailStatsUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~DisabledDetailStatsUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().disabledDetailStat; }
+};
+
+class DisabledUsersSensor : public UsersSensor {
+ public:
+ explicit DisabledUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~DisabledUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().disabled; }
+};
+
+class PassiveUsersSensor : public UsersSensor {
+ public:
+ explicit PassiveUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~PassiveUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().passive; }
+};
+
+class CreditUsersSensor : public UsersSensor {
+ public:
+ explicit CreditUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~CreditUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().credit > 0; }
+};
+
+class FreeMbUsersSensor : public UsersSensor {
+ public:
+ explicit FreeMbUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~FreeMbUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return userPtr->GetProperty().freeMb > 0; }
+};
+
+class TariffChangeUsersSensor : public UsersSensor {
+ public:
+ explicit TariffChangeUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~TariffChangeUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const
+ { return !userPtr->GetProperty().nextTariff.ConstData().empty(); }
+};
+
+class ActiveUsersSensor : public UsersSensor {
+ public:
+ explicit ActiveUsersSensor(USERS & u) : UsersSensor(u) {}
+ virtual ~ActiveUsersSensor() {}
+
+ private:
+ bool UserPredicate(USER_PTR userPtr) const;
+};
+
+class TotalTariffsSensor : public Sensor {
+ public:
+ explicit TotalTariffsSensor(const TARIFFS & t) : tariffs(t) {}
+ virtual ~TotalTariffsSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(tariffs.Count(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(tariffs.Count(), res); return res; }
+#endif
+
+ private:
+ const TARIFFS & tariffs;
+};
+
+class TotalAdminsSensor : public Sensor {
+ public:
+ explicit TotalAdminsSensor(const ADMINS & a) : admins(a) {}
+ virtual ~TotalAdminsSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(admins.Count(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(admins.Count(), res); return res; }
+#endif
+
+ private:
+ const ADMINS & admins;
+};
+
+class TotalServicesSensor : public Sensor {
+ public:
+ explicit TotalServicesSensor(const SERVICES & s) : services(s) {}
+ virtual ~TotalServicesSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(services.Count(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(services.Count(), res); return res; }
+#endif
+
+ private:
+ const SERVICES & services;
+};
+
+class TotalCorporationsSensor : public Sensor {
+ public:
+ explicit TotalCorporationsSensor(const CORPORATIONS & c) : corporations(c) {}
+ virtual ~TotalCorporationsSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(corporations.Count(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(corporations.Count(), res); return res; }
+#endif
+
+ private:
+ const CORPORATIONS & corporations;
+};
+
+class TotalRulesSensor : public Sensor {
+ public:
+ explicit TotalRulesSensor(const TRAFFCOUNTER & t) : traffcounter(t) {}
+ virtual ~TotalRulesSensor() {}
+
+ bool GetValue(ObjectSyntax_t * objectSyntax) const
+ {
+ ValueToOS(traffcounter.RulesCount(), objectSyntax);
+ return true;
+ }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(traffcounter.RulesCount(), res); return res; }
+#endif
+
+ private:
+ const TRAFFCOUNTER & traffcounter;
+};
+
+template <typename T>
+class ConstSensor : public Sensor {
+ public:
+ explicit ConstSensor(const T & v) : value(v) {}
+ virtual ~ConstSensor() {}
+
+ bool GetValue(ObjectSyntax * objectSyntax) const
+ { return ValueToOS(value, objectSyntax); }
+
+#ifdef DEBUG
+ std::string ToString() const
+ { std::string res; x2str(value, res); return res; }
+#endif
+
+ private:
+ T value;
+};
+
+#ifdef DEBUG
+template <>
+inline
+std::string ConstSensor<std::string>::ToString() const
+{
+return value;
+}
+#endif
+
+#endif
--- /dev/null
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <cstring>
+#include <cerrno>
+#include <ctime>
+#include <csignal>
+#include <cassert>
+
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <stdexcept>
+#include <utility>
+
+#include "stg/common.h"
+#include "stg/plugin_creator.h"
+
+#include "smux.h"
+#include "utils.h"
+
+namespace
+{
+PLUGIN_CREATOR<SMUX> smc;
+
+bool SPrefixLess(const Sensors::value_type & a,
+ const Sensors::value_type & b)
+{
+return a.first.PrefixLess(b.first);
+}
+
+}
+
+extern "C" PLUGIN * GetPlugin();
+
+PLUGIN * GetPlugin()
+{
+return smc.GetPlugin();
+}
+
+SMUX_SETTINGS::SMUX_SETTINGS()
+ : errorStr(),
+ ip(0),
+ port(0),
+ password()
+{}
+
+int SMUX_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+PARAM_VALUE pv;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+int p;
+
+pv.param = "Port";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = static_cast<uint16_t>(p);
+
+pv.param = "Password";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Password\' not found.";
+ printfd(__FILE__, "Parameter 'Password' not found\n");
+ password = "";
+ }
+else
+ {
+ password = pvi->value[0];
+ }
+
+pv.param = "Server";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'Server\' not found.";
+ printfd(__FILE__, "Parameter 'Server' not found\n");
+ return -1;
+ }
+ip = inet_strington(pvi->value[0]);
+
+return 0;
+}
+
+SMUX::SMUX()
+ : PLUGIN(),
+ users(NULL),
+ tariffs(NULL),
+ admins(NULL),
+ services(NULL),
+ corporations(NULL),
+ traffcounter(NULL),
+ errorStr(),
+ smuxSettings(),
+ settings(),
+ thread(),
+ mutex(),
+ running(false),
+ stopped(true),
+ needReconnect(false),
+ lastReconnectTry(0),
+ reconnectTimeout(1),
+ sock(-1),
+ smuxHandlers(),
+ pdusHandlers(),
+ sensors(),
+ tables(),
+ notifiers(),
+ addUserNotifier(*this),
+ delUserNotifier(*this),
+ addDelTariffNotifier(*this),
+ logger(GetPluginLogger(GetStgLogger(), "smux"))
+{
+pthread_mutex_init(&mutex, NULL);
+
+smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
+smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
+smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsRequestHandler;
+smuxHandlers[SMUX_PDUs_PR_commitOrRollback] = &SMUX::CommitOrRollbackHandler;
+
+pdusHandlers[PDUs_PR_get_request] = &SMUX::GetRequestHandler;
+pdusHandlers[PDUs_PR_get_next_request] = &SMUX::GetNextRequestHandler;
+pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
+}
+
+SMUX::~SMUX()
+{
+ {
+ Sensors::iterator it;
+ for (it = sensors.begin(); it != sensors.end(); ++it)
+ delete it->second;
+ }
+ {
+ Tables::iterator it;
+ for (it = tables.begin(); it != tables.end(); ++it)
+ delete it->second;
+ }
+printfd(__FILE__, "SMUX::~SMUX()\n");
+pthread_mutex_destroy(&mutex);
+}
+
+int SMUX::ParseSettings()
+{
+return smuxSettings.ParseSettings(settings);
+}
+
+int SMUX::Start()
+{
+assert(users != NULL && "users must not be NULL");
+assert(tariffs != NULL && "tariffs must not be NULL");
+assert(admins != NULL && "admins must not be NULL");
+assert(services != NULL && "services must not be NULL");
+assert(corporations != NULL && "corporations must not be NULL");
+assert(traffcounter != NULL && "traffcounter must not be NULL");
+
+if (PrepareNet())
+ needReconnect = true;
+
+// Users
+sensors[OID(".1.3.6.1.4.1.38313.1.1.1")] = new TotalUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.2")] = new ConnectedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.3")] = new AuthorizedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.4")] = new AlwaysOnlineUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.5")] = new NoCashUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.6")] = new DisabledDetailStatsUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.7")] = new DisabledUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.8")] = new PassiveUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.9")] = new CreditUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.10")] = new FreeMbUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new TariffChangeUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new ActiveUsersSensor(*users);
+// Tariffs
+sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
+// Admins
+sensors[OID(".1.3.6.1.4.1.38313.1.3.1")] = new TotalAdminsSensor(*admins);
+// Services
+sensors[OID(".1.3.6.1.4.1.38313.1.4.1")] = new TotalServicesSensor(*services);
+// Corporations
+sensors[OID(".1.3.6.1.4.1.38313.1.5.1")] = new TotalCorporationsSensor(*corporations);
+// Traffcounter
+sensors[OID(".1.3.6.1.4.1.38313.1.6.1")] = new TotalRulesSensor(*traffcounter);
+
+// Table data
+tables[".1.3.6.1.4.1.38313.1.2.2"] = new TariffUsersTable(".1.3.6.1.4.1.38313.1.2.2", *tariffs, *users);
+
+UpdateTables();
+SetNotifiers();
+
+#ifdef SMUX_DEBUG
+Sensors::const_iterator it(sensors.begin());
+while (it != sensors.end())
+ {
+ printfd(__FILE__, "%s = %s\n",
+ it->first.ToString().c_str(),
+ it->second->ToString().c_str());
+ ++it;
+ }
+#endif
+
+if (!running)
+ {
+ if (pthread_create(&thread, NULL, Runner, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+
+int SMUX::Stop()
+{
+printfd(__FILE__, "SMUX::Stop() - Before\n");
+running = false;
+
+if (!stopped)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && !stopped; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ }
+
+if (stopped)
+ pthread_join(thread, NULL);
+
+ResetNotifiers();
+
+ {
+ Tables::iterator it;
+ for (it = tables.begin(); it != tables.end(); ++it)
+ delete it->second;
+ }
+ {
+ Sensors::iterator it;
+ for (it = sensors.begin(); it != sensors.end(); ++it)
+ delete it->second;
+ }
+
+tables.erase(tables.begin(), tables.end());
+sensors.erase(sensors.begin(), sensors.end());
+
+close(sock);
+
+if (!stopped)
+ {
+ running = true;
+ return -1;
+ }
+
+printfd(__FILE__, "SMUX::Stop() - After\n");
+return 0;
+}
+
+int SMUX::Reload(const MODULE_SETTINGS & /*ms*/)
+{
+if (Stop())
+ return -1;
+if (Start())
+ return -1;
+if (!needReconnect)
+ {
+ printfd(__FILE__, "SMUX reconnected succesfully.\n");
+ logger("Reconnected successfully.");
+ }
+return 0;
+}
+
+void * SMUX::Runner(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+SMUX * smux = static_cast<SMUX *>(d);
+
+smux->Run();
+
+return NULL;
+}
+
+void SMUX::Run()
+{
+stopped = true;
+if (!SendOpenPDU(sock))
+ needReconnect = true;
+if (!SendRReqPDU(sock))
+ needReconnect = true;
+running = true;
+stopped = false;
+
+while(running)
+ {
+ if (WaitPackets(sock) && !needReconnect)
+ {
+ SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
+ if (pdus)
+ {
+ DispatchPDUs(pdus);
+ ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
+ }
+ else if (running)
+ Reconnect();
+ }
+ else if (running && needReconnect)
+ Reconnect();
+ if (!running)
+ break;
+ }
+SendClosePDU(sock);
+stopped = true;
+}
+
+bool SMUX::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_STREAM, 0);
+
+if (sock < 0)
+ {
+ errorStr = "Cannot create socket.";
+ logger("Cannot create a socket: %s", strerror(errno));
+ printfd(__FILE__, "Cannot create socket\n");
+ return true;
+ }
+
+struct sockaddr_in addr;
+
+addr.sin_family = AF_INET;
+addr.sin_port = htons(smuxSettings.GetPort());
+addr.sin_addr.s_addr = smuxSettings.GetIP();
+
+if (connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)))
+ {
+ errorStr = "Cannot connect.";
+ logger("Cannot connect the socket: %s", strerror(errno));
+ printfd(__FILE__, "Cannot connect. Message: '%s'\n", strerror(errno));
+ return true;
+ }
+
+return false;
+}
+
+bool SMUX::Reconnect()
+{
+if (needReconnect && difftime(time(NULL), lastReconnectTry) < reconnectTimeout)
+ return true;
+
+time(&lastReconnectTry);
+SendClosePDU(sock);
+close(sock);
+if (!PrepareNet())
+ if (SendOpenPDU(sock))
+ if (SendRReqPDU(sock))
+ {
+ reconnectTimeout = 1;
+ needReconnect = false;
+ logger("Connected successfully");
+ printfd(__FILE__, "Connected successfully\n");
+ return false;
+ }
+
+if (needReconnect)
+ if (reconnectTimeout < 60)
+ reconnectTimeout *= 2;
+
+needReconnect = true;
+return true;
+}
+
+bool SMUX::DispatchPDUs(const SMUX_PDUs_t * pdus)
+{
+SMUXHandlers::iterator it(smuxHandlers.find(pdus->present));
+if (it != smuxHandlers.end())
+ {
+ return (this->*(it->second))(pdus);
+ }
+#ifdef SMUX_DEBUG
+else
+ {
+ switch (pdus->present)
+ {
+ case SMUX_PDUs_PR_NOTHING:
+ printfd(__FILE__, "PDUs: nothing\n");
+ break;
+ case SMUX_PDUs_PR_open:
+ printfd(__FILE__, "PDUs: open\n");
+ break;
+ case SMUX_PDUs_PR_registerRequest:
+ printfd(__FILE__, "PDUs: registerRequest\n");
+ break;
+ default:
+ printfd(__FILE__, "PDUs: undefined\n");
+ }
+ asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+ }
+#endif
+return false;
+}
+
+bool SMUX::UpdateTables()
+{
+Sensors newSensors;
+bool done = true;
+Tables::iterator it(tables.begin());
+while (it != tables.end())
+ {
+ try
+ {
+ it->second->UpdateSensors(newSensors);
+ }
+ catch (const std::runtime_error & ex)
+ {
+ printfd(__FILE__,
+ "SMUX::UpdateTables - failed to update table '%s': '%s'\n",
+ it->first.c_str(), ex.what());
+ done = false;
+ break;
+ }
+ ++it;
+ }
+if (!done)
+ {
+ Sensors::iterator it(newSensors.begin());
+ while (it != newSensors.end())
+ {
+ delete it->second;
+ ++it;
+ }
+ return false;
+ }
+
+it = tables.begin();
+while (it != tables.end())
+ {
+ std::pair<Sensors::iterator, Sensors::iterator> res;
+ res = std::equal_range(sensors.begin(),
+ sensors.end(),
+ std::pair<OID, Sensor *>(OID(it->first), NULL),
+ SPrefixLess);
+ Sensors::iterator sit(res.first);
+ while (sit != res.second)
+ {
+ delete sit->second;
+ ++sit;
+ }
+ sensors.erase(res.first, res.second);
+ ++it;
+ }
+
+sensors.insert(newSensors.begin(), newSensors.end());
+
+return true;
+}
+
+void SMUX::SetNotifier(USER_PTR userPtr)
+{
+notifiers.push_back(CHG_AFTER_NOTIFIER(*this, userPtr));
+userPtr->GetProperty().tariffName.AddAfterNotifier(¬ifiers.back());
+}
+
+void SMUX::UnsetNotifier(USER_PTR userPtr)
+{
+std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
+while (it != notifiers.end())
+ {
+ if (it->GetUserPtr() == userPtr)
+ {
+ userPtr->GetProperty().tariffName.DelAfterNotifier(&(*it));
+ notifiers.erase(it);
+ break;
+ }
+ ++it;
+ }
+}
+
+void SMUX::SetNotifiers()
+{
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+USER_PTR u;
+while (!users->SearchNext(h, &u))
+ SetNotifier(u);
+
+users->CloseSearch(h);
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+tariffs->AddNotifierAdd(&addDelTariffNotifier);
+tariffs->AddNotifierDel(&addDelTariffNotifier);
+}
+
+void SMUX::ResetNotifiers()
+{
+tariffs->DelNotifierDel(&addDelTariffNotifier);
+tariffs->DelNotifierAdd(&addDelTariffNotifier);
+
+users->DelNotifierUserDel(&delUserNotifier);
+users->DelNotifierUserAdd(&addUserNotifier);
+
+std::list<CHG_AFTER_NOTIFIER>::iterator it(notifiers.begin());
+while (it != notifiers.end())
+ {
+ it->GetUserPtr()->GetProperty().tariffName.DelAfterNotifier(&(*it));
+ ++it;
+ }
+notifiers.clear();
+}
--- /dev/null
+#ifndef __SMUX_H__
+#define __SMUX_H__
+
+#include <pthread.h>
+
+#include <string>
+#include <map>
+#include <list>
+#include <cstdint>
+
+#include "stg/SMUX-PDUs.h"
+#include "stg/ObjectSyntax.h"
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include "sensors.h"
+#include "tables.h"
+#include "types.h"
+
+class USER;
+class SETTINGS;
+class SMUX;
+class USERS;
+class TARIFFS;
+class SERVICES;
+class CORPORATIONS;
+class TRAFFCOUNTER;
+
+typedef bool (SMUX::*SMUXPacketHandler)(const SMUX_PDUs_t * pdus);
+typedef bool (SMUX::*PDUsHandler)(const PDUs_t * pdus);
+typedef std::map<SMUX_PDUs_PR, SMUXPacketHandler> SMUXHandlers;
+typedef std::map<PDUs_PR, PDUsHandler> PDUsHandlers;
+//-----------------------------------------------------------------------------
+class SMUX_SETTINGS {
+public:
+ SMUX_SETTINGS();
+ virtual ~SMUX_SETTINGS() {}
+ const std::string & GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+
+ uint32_t GetIP() const { return ip; }
+ uint16_t GetPort() const { return port; }
+ const std::string GetPassword() const { return password; }
+
+private:
+ mutable std::string errorStr;
+
+ uint32_t ip;
+ uint16_t port;
+ std::string password;
+};
+//-----------------------------------------------------------------------------
+class CHG_AFTER_NOTIFIER : public PROPERTY_NOTIFIER_BASE<std::string> {
+public:
+ CHG_AFTER_NOTIFIER(SMUX & s, const USER_PTR & u)
+ : PROPERTY_NOTIFIER_BASE<std::string>(),
+ smux(s), userPtr(u) {}
+ CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER & rvalue)
+ : PROPERTY_NOTIFIER_BASE<std::string>(),
+ smux(rvalue.smux), userPtr(rvalue.userPtr) {}
+ void Notify(const std::string &, const std::string &);
+
+ USER_PTR GetUserPtr() const { return userPtr; }
+
+private:
+ CHG_AFTER_NOTIFIER & operator=(const CHG_AFTER_NOTIFIER & rvalue);
+ SMUX & smux;
+ USER_PTR userPtr;
+};
+//-----------------------------------------------------------------------------
+class ADD_DEL_TARIFF_NOTIFIER : public NOTIFIER_BASE<TARIFF_DATA>, private NONCOPYABLE {
+public:
+ explicit ADD_DEL_TARIFF_NOTIFIER(SMUX & s)
+ : NOTIFIER_BASE<TARIFF_DATA>(), smux(s) {}
+ void Notify(const TARIFF_DATA &);
+
+private:
+ SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NOTIFIER : public NOTIFIER_BASE<USER_PTR>, private NONCOPYABLE {
+public:
+ explicit ADD_USER_NOTIFIER(SMUX & s) : NOTIFIER_BASE<USER_PTR>(), smux(s) {}
+ void Notify(const USER_PTR &);
+
+private:
+ SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NOTIFIER : public NOTIFIER_BASE<USER_PTR>, private NONCOPYABLE {
+public:
+ explicit DEL_USER_NOTIFIER(SMUX & s) : NOTIFIER_BASE<USER_PTR>(), smux(s) {}
+ void Notify(const USER_PTR &);
+
+private:
+ SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class SMUX : public PLUGIN {
+public:
+ SMUX();
+ virtual ~SMUX();
+
+ void SetUsers(USERS * u) { users = u; }
+ void SetTariffs(TARIFFS * t) { tariffs = t; }
+ void SetAdmins(ADMINS * a) { admins = a; }
+ void SetServices(SERVICES * s) { services = s; }
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffcounter = tc; }
+ void SetCorporations(CORPORATIONS * c) { corporations = c; }
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload(const MODULE_SETTINGS & ms);
+ bool IsRunning() { return running && !stopped; }
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const { return "Stg SMUX Plugin 1.1"; }
+ uint16_t GetStartPosition() const { return 10; }
+ uint16_t GetStopPosition() const { return 10; }
+
+ bool UpdateTables();
+
+ void SetNotifier(USER_PTR userPtr);
+ void UnsetNotifier(USER_PTR userPtr);
+
+private:
+ SMUX(const SMUX & rvalue);
+ SMUX & operator=(const SMUX & rvalue);
+
+ static void * Runner(void * d);
+ void Run();
+ bool PrepareNet();
+ bool Reconnect();
+
+ bool DispatchPDUs(const SMUX_PDUs_t * pdus);
+
+ bool CloseHandler(const SMUX_PDUs_t * pdus);
+ bool RegisterResponseHandler(const SMUX_PDUs_t * pdus);
+ bool PDUsRequestHandler(const SMUX_PDUs_t * pdus);
+ bool CommitOrRollbackHandler(const SMUX_PDUs_t * pdus);
+
+ bool GetRequestHandler(const PDUs_t * pdus);
+ bool GetNextRequestHandler(const PDUs_t * pdus);
+ bool SetRequestHandler(const PDUs_t * pdus);
+
+ void SetNotifiers();
+ void ResetNotifiers();
+
+ USERS * users;
+ TARIFFS * tariffs;
+ ADMINS * admins;
+ SERVICES * services;
+ CORPORATIONS * corporations;
+ TRAFFCOUNTER * traffcounter;
+
+ mutable std::string errorStr;
+ SMUX_SETTINGS smuxSettings;
+ MODULE_SETTINGS settings;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+ bool running;
+ bool stopped;
+ bool needReconnect;
+
+ time_t lastReconnectTry;
+ unsigned reconnectTimeout;
+
+ int sock;
+
+ SMUXHandlers smuxHandlers;
+ PDUsHandlers pdusHandlers;
+ Sensors sensors;
+ Tables tables;
+
+ std::list<CHG_AFTER_NOTIFIER> notifiers;
+ ADD_USER_NOTIFIER addUserNotifier;
+ DEL_USER_NOTIFIER delUserNotifier;
+ ADD_DEL_TARIFF_NOTIFIER addDelTariffNotifier;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+inline
+void CHG_AFTER_NOTIFIER::Notify(const std::string &, const std::string &)
+{
+smux.UpdateTables();
+}
+
+inline
+void ADD_DEL_TARIFF_NOTIFIER::Notify(const TARIFF_DATA &)
+{
+smux.UpdateTables();
+}
+
+inline
+void ADD_USER_NOTIFIER::Notify(const USER_PTR & userPtr)
+{
+smux.SetNotifier(userPtr);
+smux.UpdateTables();
+}
+
+inline
+void DEL_USER_NOTIFIER::Notify(const USER_PTR & userPtr)
+{
+smux.UnsetNotifier(userPtr);
+smux.UpdateTables();
+}
+
+#endif
--- /dev/null
+#include <cassert>
+#include <utility>
+#include <iterator>
+#include <algorithm>
+
+#include "stg/user_property.h"
+#include "stg/tariffs.h"
+#include "stg/users.h"
+
+#include "tables.h"
+
+std::pair<std::string, size_t> TD2Info(const TARIFF_DATA & td);
+
+void TariffUsersTable::UpdateSensors(Sensors & sensors) const
+{
+std::map<std::string, size_t> data;
+
+std::list<TARIFF_DATA> tdl;
+tariffs.GetTariffsData(&tdl);
+std::transform(tdl.begin(),
+ tdl.end(),
+ std::inserter(data, data.begin()),
+ TD2Info);
+
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+USER_PTR user;
+while (!users.SearchNext(handle, &user))
+ {
+ if (user->GetDeleted())
+ continue;
+ std::string tariffName(user->GetProperty().tariffName.ConstData());
+ std::map<std::string, size_t>::iterator it(data.lower_bound(tariffName));
+ if (it == data.end() ||
+ it->first != tariffName)
+ {
+ data.insert(it, std::make_pair(tariffName, 1));
+ }
+ else
+ {
+ ++it->second;
+ }
+ }
+
+users.CloseSearch(handle);
+
+size_t idx = 1;
+OID prefixOid(prefix);
+
+std::map<std::string, size_t>::const_iterator it(data.begin());
+while (it != data.end())
+ {
+ sensors[prefixOid.copyWithSuffix(2, static_cast<unsigned int>(idx))] = new ConstSensor<std::string>(it->first);
+ sensors[prefixOid.copyWithSuffix(3, static_cast<unsigned int>(idx))] = new ConstSensor<unsigned long>(it->second);
+ ++idx;
+ ++it;
+ }
+}
+
+std::pair<std::string, size_t> TD2Info(const TARIFF_DATA & td)
+{
+return std::make_pair(td.tariffConf.name, 0);
+}
--- /dev/null
+#ifndef __TABLES_H__
+#define __TABLES_H__
+
+#include <string>
+#include <map>
+
+#include "sensors.h"
+
+class TARIFFS;
+class USERS;
+
+class TableSensor {
+ public:
+ explicit TableSensor(const std::string & p) : prefix(p) {}
+ virtual ~TableSensor() {}
+
+ const std::string & GetPrefix() const { return prefix; }
+ virtual void UpdateSensors(Sensors & sensors) const = 0;
+
+ protected:
+ std::string prefix;
+};
+
+class TariffUsersTable : public TableSensor {
+ public:
+ TariffUsersTable(const std::string & p,
+ TARIFFS & t,
+ USERS & u)
+ : TableSensor(p),
+ tariffs(t),
+ users(u)
+ {}
+ virtual ~TariffUsersTable() {}
+
+ void UpdateSensors(Sensors & sensors) const;
+
+ private:
+ TARIFFS & tariffs;
+ USERS & users;
+};
+
+typedef std::map<std::string, TableSensor *> Tables;
+
+#endif
--- /dev/null
+#include <stdexcept>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+
+#include "types.h"
+
+namespace
+{
+
+bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos);
+bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
+bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
+
+bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos)
+{
+if (length == 0)
+ return false;
+const char * left = str;
+if (*left == '.')
+ ++left;
+size_t arcPos = 0;
+while ((left - str) < length)
+ {
+ char * pos = NULL;
+ unsigned arc = static_cast<unsigned int>(strtoul(left, &pos, 10));
+ if (pos == left)
+ return false;
+ a[arcPos++] = arc;
+ if (arcPos >= 1024)
+ return false;
+ left = pos + 1;
+ }
+*pos = arcPos;
+return true;
+}
+
+bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
+{
+unsigned a[1024];
+size_t pos = 0;
+
+if (!ParseArcs(str, length, a, &pos))
+ return false;
+
+arcs.assign(a, a + pos);
+return true;
+}
+
+bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
+{
+unsigned a[1024];
+size_t pos = 0;
+
+if (!ParseArcs(str, length, a, &pos))
+ return false;
+
+std::copy(&a[0], &a[pos], std::back_inserter(arcs));
+return true;
+}
+
+}
+
+OID::OID(const std::string & str)
+ : arcs()
+{
+if (!StringToArcs(str.c_str(), str.length(), arcs))
+ throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const char * str, size_t length)
+ : arcs()
+{
+if (!StringToArcs(str, length, arcs))
+ throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const std::vector<unsigned> & a)
+ : arcs(a)
+{
+}
+
+OID::OID(const unsigned * a, size_t length)
+ : arcs()
+{
+std::vector<unsigned> newArcs(a, a + length);
+arcs.swap(newArcs);
+}
+
+OID::OID(OBJECT_IDENTIFIER_t * oid)
+ : arcs()
+{
+unsigned a[1024];
+int count = OBJECT_IDENTIFIER_get_arcs(oid, a, sizeof(a[0]), 1024);
+
+if (count > 1024)
+ throw std::runtime_error("OID is too long");
+
+std::vector<unsigned> newArcs(a, a + count);
+arcs.swap(newArcs);
+}
+
+OID::OID(const OID & rvalue)
+ : arcs(rvalue.arcs)
+{
+}
+
+OID::~OID()
+{
+}
+
+bool OID::addSuffix(const char * suffix, size_t length)
+{
+if (!AppendToArcs(suffix, length, arcs))
+ return false;
+return true;
+}
+
+bool OID::addSuffix(const std::string & suffix)
+{
+if (!AppendToArcs(suffix.c_str(), suffix.length(), arcs))
+ return false;
+return true;
+}
+
+bool OID::addSuffix(const unsigned * suffix, size_t length)
+{
+std::copy(suffix, suffix + length, std::back_inserter(arcs));
+return true;
+}
+
+bool OID::addSuffix(const std::vector<unsigned> & suffix)
+{
+std::copy(suffix.begin(), suffix.end(), std::back_inserter(arcs));
+return true;
+}
+
+bool OID::addSuffix(unsigned a, unsigned b)
+{
+arcs.push_back(a);
+arcs.push_back(b);
+return true;
+}
+
+OID OID::copyWithSuffix(const char * suffix, size_t length) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix, length))
+ throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const std::string & suffix) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix))
+ throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const unsigned * suffix, size_t length) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix, length))
+ throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const std::vector<unsigned> & suffix) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix))
+ throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(unsigned a, unsigned b) const
+{
+OID oid(*this);
+oid.addSuffix(a, b);
+return oid;
+}
+
+std::string OID::ToString() const
+{
+std::stringstream stream;
+for (size_t i = 0; i < arcs.size(); ++i)
+ stream << "." << arcs[i];
+return stream.str();
+}
+
+void OID::ToOID(OBJECT_IDENTIFIER_t * oid) const
+{
+OBJECT_IDENTIFIER_set_arcs(oid, &arcs.front(), sizeof(unsigned), static_cast<unsigned int>(arcs.size()));
+}
+
+OID & OID::operator=(const OID & rvalue)
+{
+arcs = rvalue.arcs;
+return *this;
+}
+
+bool OID::operator==(const OID & rvalue) const
+{
+if (arcs.size() != rvalue.arcs.size())
+ return false;
+for (size_t i = 0; i < arcs.size(); ++i)
+ if (arcs[i] != rvalue.arcs[i])
+ return false;
+return true;
+}
+
+bool OID::operator<(const OID & rvalue) const
+{
+size_t i = 0;
+size_t min = std::min(arcs.size(), rvalue.arcs.size());
+while (i < min &&
+ arcs[i] == rvalue.arcs[i])
+ ++i;
+if (i == min)
+ {
+ if (rvalue.arcs.size() > arcs.size())
+ return true;
+ return false;
+ }
+
+if (arcs[i] < rvalue.arcs[i])
+ return true;
+
+return false;
+}
+
+bool OID::PrefixLess(const OID & rvalue) const
+{
+size_t i = 0;
+size_t min = std::min(arcs.size(), rvalue.arcs.size());
+while (i < min &&
+ arcs[i] == rvalue.arcs[i])
+ ++i;
+if (i == min)
+ return false;
+if (arcs[i] < rvalue.arcs[i])
+ return true;
+return false;
+}
+
+std::ostream & operator<<(std::ostream & stream, const OID & oid)
+{
+for (size_t i = 0; i < oid.arcs.size(); ++i)
+ stream << "." << oid.arcs[i];
+return stream;
+}
--- /dev/null
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "stg/OBJECT_IDENTIFIER.h"
+
+class OID {
+ public:
+ explicit OID(const std::string & str);
+ OID(const char * str, size_t length);
+ explicit OID(const std::vector<unsigned> & arcs);
+ OID(const unsigned * arcs, size_t length);
+ explicit OID(OBJECT_IDENTIFIER_t * oid);
+ OID(const OID & rvalue);
+ ~OID();
+
+ bool addSuffix(const char * suffix, size_t length);
+ bool addSuffix(const std::string & suffix);
+ bool addSuffix(const unsigned * suffix, size_t length);
+ bool addSuffix(const std::vector<unsigned> & suffix);
+ bool addSuffix(unsigned a, unsigned b);
+
+ OID copyWithSuffix(const char * suffix, size_t length) const;
+ OID copyWithSuffix(const std::string & suffix) const;
+ OID copyWithSuffix(const unsigned * suffix, size_t length) const;
+ OID copyWithSuffix(const std::vector<unsigned> & suffix) const;
+ OID copyWithSuffix(unsigned a, unsigned b) const;
+
+ std::string ToString() const;
+ const std::vector<unsigned> & ToVector() const { return arcs; }
+ void ToOID(OBJECT_IDENTIFIER_t * oid) const;
+
+ OID & operator=(const OID & rvalue);
+ bool operator==(const OID & rvalue) const;
+ bool operator!=(const OID & rvalue) const { return !operator==(rvalue); }
+ bool operator<(const OID & rvalue) const;
+ bool operator>(const OID & rvalue) const
+ { return !operator==(rvalue) && !operator<(rvalue); }
+
+ bool PrefixLess(const OID & rvalue) const;
+
+ friend std::ostream & operator<<(std::ostream & stream, const OID & oid);
+
+ private:
+ std::vector<unsigned> arcs;
+};
+
+inline
+bool PrefixLess(const OID & a, const OID & b)
+{
+return a.PrefixLess(b);
+}
+
+#endif
--- /dev/null
+#include <unistd.h> // write
+
+#include <cstring> // memset
+#include <cerrno>
+
+#include "stg/common.h"
+
+#include "stg/OpenPDU.h"
+#include "stg/ClosePDU.h"
+#include "stg/RReqPDU.h"
+#include "stg/ber_decoder.h"
+#include "stg/der_encoder.h"
+
+#include "pen.h"
+#include "utils.h"
+
+bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
+{
+size_t left = 0, pos = 0, arcPos = 0;
+int arcs[1024];
+pos = str.find_first_of('.', left);
+if (pos == 0)
+ {
+ left = 1;
+ pos = str.find_first_of('.', left);
+ }
+while (pos != std::string::npos)
+ {
+ int arc = 0;
+ if (str2x(str.substr(left, left - pos), arc))
+ {
+ return false;
+ }
+ arcs[arcPos++] = arc;
+ left = pos + 1;
+ pos = str.find_first_of('.', left);
+ }
+if (left < str.length())
+ {
+ int arc = 0;
+ if (str2x(str.substr(left, left - pos), arc))
+ {
+ return false;
+ }
+ arcs[arcPos++] = arc;
+ }
+OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), static_cast<unsigned int>(arcPos));
+return true;
+}
+
+bool SendOpenPDU(int fd)
+{
+const char * description = "Stg SMUX Plugin";
+asn_enc_rval_t error;
+OpenPDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+msg.present = OpenPDU_PR_simple;
+asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
+if (!String2OI(PEN_PREFIX, &msg.choice.simple.identity))
+ {
+ printfd(__FILE__,
+ "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
+ return false;
+ }
+OCTET_STRING_fromString(&msg.choice.simple.description, description);
+OCTET_STRING_fromString(&msg.choice.simple.password, "");
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OpenPDU, &msg);
+
+if (error.encoded == -1)
+ {
+ printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
+ error.failed_type ? error.failed_type->name : "unknown");
+ return false;
+ }
+else
+ {
+ if (write(fd, buffer, error.encoded) < 0)
+ {
+ printfd(__FILE__, "Failed to send OpenPDU: %s\n", strerror(errno));
+ return false;
+ }
+ }
+return true;
+}
+
+bool SendClosePDU(int fd)
+{
+ClosePDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+asn_long2INTEGER(&msg, ClosePDU_goingDown);
+
+char buffer[1024];
+asn_enc_rval_t error;
+error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_ClosePDU, &msg);
+
+if (error.encoded == -1)
+ {
+ printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
+ error.failed_type ? error.failed_type->name : "unknown");
+ return false;
+ }
+else
+ {
+ if (write(fd, buffer, error.encoded) < 0)
+ {
+ printfd(__FILE__, "Failed to send ClosePDU: %s\n", strerror(errno));
+ return false;
+ }
+ }
+return true;
+}
+
+bool SendRReqPDU(int fd)
+{
+int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
+asn_enc_rval_t error;
+RReqPDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+msg.priority = 0;
+asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
+OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
+ oid,
+ sizeof(oid[0]),
+ 8);
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RReqPDU, &msg);
+
+if (error.encoded == -1)
+ {
+ printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
+ error.failed_type ? error.failed_type->name : "unknown");
+ return false;
+ }
+else
+ {
+ if (write(fd, buffer, error.encoded) < 0)
+ {
+ printfd(__FILE__, "Failed to send RReqPDU: %s\n", strerror(errno));
+ return false;
+ }
+ }
+return true;
+}
+
+SMUX_PDUs_t * RecvSMUXPDUs(int fd)
+{
+char buffer[1024];
+SMUX_PDUs_t * pdus = NULL;
+
+memset(buffer, 0, sizeof(buffer));
+
+size_t length = read(fd, buffer, sizeof(buffer));
+if (length < 1)
+ return NULL;
+asn_dec_rval_t error;
+error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
+
+if(error.code != RC_OK)
+ {
+ printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
+ (long)error.consumed);
+ return NULL;
+ }
+return pdus;
+}
+
+bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
+{
+asn_enc_rval_t error;
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
+ sizeof(buffer));
+
+if (error.encoded == -1)
+ {
+ printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
+ error.failed_type ? error.failed_type->name : "unknown");
+ return false;
+ }
+else
+ {
+ if (write(fd, buffer, error.encoded) < 0)
+ {
+ printfd(__FILE__, "Failed to send GetResponsePDU: %s\n", strerror(errno));
+ return false;
+ }
+ }
+return true;
+}
+
+bool SendGetResponseErrorPDU(int fd,
+ const PDU_t * getRequest,
+ int errorStatus,
+ int errorIndex)
+{
+asn_enc_rval_t error;
+GetResponse_PDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg.request_id, id);
+asn_long2INTEGER(&msg.error_status, errorStatus);
+asn_long2INTEGER(&msg.error_index, errorIndex);
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
+ sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetResponse_PDU, &msg);
+
+if (error.encoded == -1)
+ {
+ printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
+ error.failed_type ? error.failed_type->name : "unknown");
+ return false;
+ }
+else
+ {
+ if (write(fd, buffer, error.encoded) < 0)
+ {
+ printfd(__FILE__, "Failed to send GetResponseErrorPDU: %s\n", strerror(errno));
+ return false;
+ }
+ }
+return true;
+}
--- /dev/null
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+
+#include "stg/OBJECT_IDENTIFIER.h"
+#include "stg/SMUX-PDUs.h"
+#include "stg/GetResponse-PDU.h"
+
+bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi);
+bool SendOpenPDU(int fd);
+bool SendClosePDU(int fd);
+bool SendRReqPDU(int fd);
+SMUX_PDUs_t * RecvSMUXPDUs(int fd);
+bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse);
+bool SendGetResponseErrorPDU(int fd,
+ const PDU_t * getRequest,
+ int errorStatus,
+ int errorIndex);
+
+#endif
--- /dev/null
+#ifndef __VALUE_2_OS_H__
+#define __VALUE_2_OS_H__
+
+#include "stg/ObjectSyntax.h"
+
+template <typename T>
+bool ValueToOS(const T & value, ObjectSyntax * objectSyntax);
+
+template <>
+inline
+bool ValueToOS<int>(const int & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<unsigned int>(const unsigned int & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<long>(const long & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<unsigned long>(const unsigned long & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<std::string>(const std::string & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_string;
+OCTET_STRING_fromBuf(&simpleSyntax->choice.string, value.c_str(), static_cast<int>(value.length()));
+return true;
+}
+
+#endif
--- /dev/null
+if ( BUILD_MOD_STORE_FILES )
+ add_subdirectory ( files )
+endif ( BUILD_MOD_STORE_FILES )
+
+if ( BUILD_MOD_STORE_FIREBIRD )
+ add_subdirectory ( firebird )
+endif ( BUILD_MOD_STORE_FIREBIRD )
+
+if ( BUILD_MOD_STORE_MYSQL )
+ add_subdirectory ( mysql )
+endif ( BUILD_MOD_STORE_MYSQL )
+
+if ( BUILD_MOD_STORE_POSTGRESQL )
+ add_subdirectory ( postgresql )
+endif ( BUILD_MOD_STORE_POSTGRESQL )
--- /dev/null
+set ( CPP_FILES file_store.cpp )
+
+add_library ( mod_store_files MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_store_files crypto conffiles logger common )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.16 2010/03/04 10:47:45 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_files.so
+
+SRCS = ./file_store.cpp
+
+STGLIBS = conffiles \
+ common \
+ logger \
+ crypto
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.67 $
+ $Date: 2010/10/07 19:53:11 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include <cstdio>
+#include <ctime>
+#include <cerrno>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+#include "stg/common.h"
+#include "stg/user_ips.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/const.h"
+#include "stg/blowfish.h"
+#include "stg/logger.h"
+#include "stg/locker.h"
+#include "stg/plugin_creator.h"
+#include "file_store.h"
+
+#define DELETED_USERS_DIR "deleted_users"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext);
+
+const int pt_mega = 1024 * 1024;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<FILES_STORE> fsc;
+
+bool CheckAndCreate(const std::string & dir, mode_t mode)
+{
+if (access(dir.c_str(), F_OK) == 0)
+ return true;
+if (mkdir(dir.c_str(), mode) == 0)
+ return true;
+return false;
+}
+
+}
+
+extern "C" STORE * GetStore();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STORE * GetStore()
+{
+return fsc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
+ : settings(NULL),
+ statMode(0),
+ statUID(0),
+ statGID(0),
+ confMode(0),
+ confUID(0),
+ confGID(0),
+ userLogMode(0),
+ userLogUID(0),
+ userLogGID(0),
+ removeBak(true),
+ readBak(true)
+{
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseOwner(const std::vector<PARAM_VALUE> & moduleParams, const std::string & owner, uid_t * uid)
+{
+PARAM_VALUE pv;
+pv.param = owner;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'" + owner + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (User2UID(pvi->value[0].c_str(), uid) < 0)
+ {
+ errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseGroup(const std::vector<PARAM_VALUE> & moduleParams, const std::string & group, gid_t * gid)
+{
+PARAM_VALUE pv;
+pv.param = group;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'" + group + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (Group2GID(pvi->value[0].c_str(), gid) < 0)
+ {
+ errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseYesNo(const std::string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+ {
+ *val = true;
+ return 0;
+ }
+if (0 == strcasecmp(value.c_str(), "no"))
+ {
+ *val = false;
+ return 0;
+ }
+
+errorStr = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseMode(const std::vector<PARAM_VALUE> & moduleParams, const std::string & modeStr, mode_t * mode)
+{
+PARAM_VALUE pv;
+pv.param = modeStr;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'" + modeStr + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
+ {
+ errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
+ return -1;
+
+if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
+ return -1;
+
+if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
+ return -1;
+
+std::vector<PARAM_VALUE>::const_iterator pvi;
+PARAM_VALUE pv;
+pv.param = "RemoveBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ removeBak = true;
+ }
+else
+ {
+ if (ParseYesNo(pvi->value[0], &removeBak))
+ {
+ printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
+ return -1;
+ }
+ }
+
+pv.param = "ReadBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ readBak = false;
+ }
+else
+ {
+ if (ParseYesNo(pvi->value[0], &readBak))
+ {
+ printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
+ return -1;
+ }
+ }
+
+pv.param = "WorkDir";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'WorkDir\' not found.";
+ printfd(__FILE__, "Parameter 'WorkDir' not found\n");
+ return -1;
+ }
+
+workDir = pvi->value[0];
+if (workDir.size() && workDir[workDir.size() - 1] == '/')
+ {
+ workDir.resize(workDir.size() - 1);
+ }
+usersDir = workDir + "/users/";
+if (!CheckAndCreate(usersDir, GetConfModeDir()))
+ {
+ errorStr = usersDir + " doesn't exist. Failed to create.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+tariffsDir = workDir + "/tariffs/";
+if (!CheckAndCreate(tariffsDir, GetConfModeDir()))
+ {
+ errorStr = tariffsDir + " doesn't exist. Failed to create.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+adminsDir = workDir + "/admins/";
+if (!CheckAndCreate(adminsDir, GetConfModeDir()))
+ {
+ errorStr = adminsDir + " doesn't exist. Failed to create.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+servicesDir = workDir + "/services/";
+if (!CheckAndCreate(servicesDir, GetConfModeDir()))
+ {
+ errorStr = servicesDir + " doesn't exist. Failed to create.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+const std::string & FILES_STORE_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
+{
+struct passwd * pw;
+pw = getpwnam(user);
+if (!pw)
+ {
+ errorStr = std::string("User \'") + std::string(user) + std::string("\' not found in system.");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+*uid = pw->pw_uid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
+{
+struct group * grp;
+grp = getgrnam(gr);
+if (!grp)
+ {
+ errorStr = std::string("Group \'") + std::string(gr) + std::string("\' not found in system.");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+*gid = grp->gr_gid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
+{
+char a;
+char b;
+char c;
+if (strlen(str) > 3)
+ {
+ errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+for (int i = 0; i < 3; i++)
+ if (str[i] > '7' || str[i] < '0')
+ {
+ errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+a = str[0] - '0';
+b = str[1] - '0';
+c = str[2] - '0';
+
+*mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
+{
+mode_t mode = statMode;
+if (statMode & S_IRUSR) mode |= S_IXUSR;
+if (statMode & S_IRGRP) mode |= S_IXGRP;
+if (statMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
+{
+mode_t mode = confMode;
+if (confMode & S_IRUSR) mode |= S_IXUSR;
+if (confMode & S_IRGRP) mode |= S_IXGRP;
+if (confMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FILES_STORE::FILES_STORE()
+ : errorStr(),
+ version("file_store v.1.04"),
+ storeSettings(),
+ settings(),
+ mutex(),
+ logger(GetPluginLogger(GetStgLogger(), "store_files"))
+{
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+if (ret)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = storeSettings.GetStrError();
+ }
+return ret;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetUsersList(std::vector<std::string> * userList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetUsersDir(), S_IFDIR, ""))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Failed to open '" + storeSettings.GetUsersDir() + "': " + std::string(strerror(errno));
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex);
+
+userList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetAdminsList(std::vector<std::string> * adminList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetAdminsDir(), S_IFREG, ".adm"))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Failed to open '" + storeSettings.GetAdminsDir() + "': " + std::string(strerror(errno));
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex);
+
+adminList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetTariffsList(std::vector<std::string> * tariffList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetTariffsDir(), S_IFREG, ".tf"))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Failed to open '" + storeSettings.GetTariffsDir() + "': " + std::string(strerror(errno));
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex);
+
+tariffList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetServicesList(std::vector<std::string> * list) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetServicesDir(), S_IFREG, ".serv"))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Failed to open '" + storeSettings.GetServicesDir() + "': " + std::string(strerror(errno));
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex);
+
+list->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RemoveDir(const char * path) const
+{
+DIR * d = opendir(path);
+
+if (!d)
+ {
+ errorStr = "failed to open dir. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILE_STORE::RemoveDir() - Failed to open dir '%s': '%s'\n", path, strerror(errno));
+ return -1;
+ }
+
+dirent * entry;
+while ((entry = readdir(d)))
+ {
+ if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
+ continue;
+
+ std::string str = path;
+ str += "/" + std::string(entry->d_name);
+
+ struct stat st;
+ if (stat(str.c_str(), &st))
+ continue;
+
+ if ((st.st_mode & S_IFREG))
+ {
+ if (unlink(str.c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::RemoveDir() - unlink failed. Message: '%s'\n", strerror(errno));
+ closedir(d);
+ return -1;
+ }
+ }
+
+ if (!(st.st_mode & S_IFDIR))
+ {
+ if (RemoveDir(str.c_str()))
+ {
+ closedir(d);
+ return -1;
+ }
+
+ }
+ }
+
+closedir(d);
+
+if (rmdir(path))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "rmdir failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::RemoveDir() - rmdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddUser(const std::string & login) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+
+if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("mkdir failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (Touch(fileName))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file \"" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (Touch(fileName))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file \"" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelUser(const std::string & login) const
+{
+std::string dirName;
+std::string dirName1;
+
+strprintf(&dirName, "%s/%s", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR);
+if (access(dirName.c_str(), F_OK) != 0)
+ {
+ if (mkdir(dirName.c_str(), 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Directory '" + dirName + "' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+if (access(dirName.c_str(), F_OK) == 0)
+ {
+ strprintf(&dirName, "%s/%s/%s.%lu", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR, login.c_str(), time(NULL));
+ strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+ if (rename(dirName1.c_str(), dirName.c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
+ printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+else
+ {
+ strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+ if (RemoveDir(dirName.c_str()))
+ {
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+if (RestoreUserConf(conf, login, fileName))
+ {
+ if (!storeSettings.GetReadBak())
+ {
+ return -1;
+ }
+ return RestoreUserConf(conf, login, fileName + ".bak");
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login, const std::string & fileName) const
+{
+CONFIGFILE cf(fileName);
+int e = cf.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("Password", &conf->password, "") < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter Password.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+if (conf->password.empty())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' password is blank.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+if (conf->tariffName.empty())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' tariff is blank.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+std::string ipStr;
+cf.ReadString("IP", &ipStr, "?");
+USER_IPS ips;
+try
+ {
+ ips = StrToIPS(ipStr);
+ }
+catch (const std::string & s)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+conf->ips = ips;
+
+if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("down", &conf->disabled, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("passive", &conf->passive, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
+cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
+cf.ReadString("TariffChange", &conf->nextTariff, "");
+cf.ReadString("Group", &conf->group, "");
+cf.ReadString("RealName", &conf->realName, "");
+cf.ReadString("Address", &conf->address, "");
+cf.ReadString("Phone", &conf->phone, "");
+cf.ReadString("Note", &conf->note, "");
+cf.ReadString("email", &conf->email, "");
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ snprintf(userdataName, 12, "Userdata%d", i);
+ cf.ReadString(userdataName, &conf->userdata[i], "");
+ }
+
+if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+if (RestoreUserStat(stat, login, fileName))
+ {
+ if (!storeSettings.GetReadBak())
+ {
+ return -1;
+ }
+ return RestoreUserStat(stat, login, fileName + ".bak");
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login, const std::string & fileName) const
+{
+CONFIGFILE cf(fileName);
+
+int e = cf.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+char s[22];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ uint64_t traff;
+ snprintf(s, 22, "D%d", i);
+ if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+ stat->monthDown[i] = traff;
+
+ snprintf(s, 22, "U%d", i);
+ if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+ stat->monthUp[i] = traff;
+ }
+
+if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserConf(const USER_CONF & conf, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+
+CONFIGFILE cfstat(fileName, true);
+
+int e = cfstat.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("User \'") + login + "\' conf not written\n";
+ printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+e = chmod(fileName.c_str(), storeSettings.GetConfMode());
+e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+cfstat.WriteString("Password", conf.password);
+cfstat.WriteInt ("Passive", conf.passive);
+cfstat.WriteInt ("Down", conf.disabled);
+cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
+cfstat.WriteInt ("AlwaysOnline", conf.alwaysOnline);
+cfstat.WriteString("Tariff", conf.tariffName);
+cfstat.WriteString("Address", conf.address);
+cfstat.WriteString("Phone", conf.phone);
+cfstat.WriteString("Email", conf.email);
+cfstat.WriteString("Note", conf.note);
+cfstat.WriteString("RealName", conf.realName);
+cfstat.WriteString("Group", conf.group);
+cfstat.WriteDouble("Credit", conf.credit);
+cfstat.WriteString("TariffChange", conf.nextTariff);
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ snprintf(userdataName, 12, "Userdata%d", i);
+ cfstat.WriteString(userdataName, conf.userdata[i]);
+ }
+cfstat.WriteInt("CreditExpire", conf.creditExpire);
+
+std::ostringstream ipStr;
+ipStr << conf.ips;
+cfstat.WriteString("IP", ipStr.str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserStat(const USER_STAT & stat, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+ {
+ CONFIGFILE cfstat(fileName, true);
+ int e = cfstat.Error();
+
+ if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("User \'") + login + "\' stat not written\n";
+ printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ char s[22];
+ snprintf(s, 22, "D%d", i);
+ cfstat.WriteInt(s, stat.monthDown[i]);
+ snprintf(s, 22, "U%d", i);
+ cfstat.WriteInt(s, stat.monthUp[i]);
+ }
+
+ cfstat.WriteDouble("Cash", stat.cash);
+ cfstat.WriteDouble("FreeMb", stat.freeMb);
+ cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
+ cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
+ cfstat.WriteInt("PassiveTime", stat.passiveTime);
+ cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
+ }
+
+int e = chmod(fileName.c_str(), storeSettings.GetStatMode());
+e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLogString(const std::string & str, const std::string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+ {
+ fprintf(f, "%s", LogDate(tm));
+ fprintf(f, " -- ");
+ fprintf(f, "%s", str.c_str());
+ fprintf(f, "\n");
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot open \'" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLog2String(const std::string & str, const std::string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+ {
+ fprintf(f, "%s", LogDate(tm));
+ fprintf(f, " -- ");
+ fprintf(f, "%s", str.c_str());
+ fprintf(f, "\n");
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot open \'" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const
+{
+std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+ + paramName + "\' parameter changed from \'" + oldValue +
+ "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+std::string logStr = "Connect, " + inet_ntostring(ip);
+if (WriteLogString(logStr, login))
+ return -1;
+return WriteLog2String(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & monthUp,
+ const DIR_TRAFF & monthDown,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+std::ostringstream logStr;
+logStr << "Disconnect, "
+ << " session upload: \'"
+ << sessionUp
+ << "\' session download: \'"
+ << sessionDown
+ << "\' month upload: \'"
+ << monthUp
+ << "\' month download: \'"
+ << monthDown
+ << "\' cash: \'"
+ << cash
+ << "\'";
+
+if (WriteLogString(logStr.str(), login))
+ return -1;
+
+logStr << " freeMb: \'"
+ << freeMb
+ << "\'"
+ << " reason: \'"
+ << reason
+ << "\'";
+
+return WriteLog2String(logStr.str(), login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
+{
+// Classic stats
+std::string stat1;
+strprintf(&stat1,"%s/%s/stat.%d.%02d",
+ storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
+
+CONFIGFILE s(stat1, true);
+
+if (s.Error())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file '" + stat1 + "'";
+ printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+// New stats
+std::string stat2;
+strprintf(&stat2,"%s/%s/stat2.%d.%02d",
+ storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
+
+CONFIGFILE s2(stat2, true);
+
+if (s2.Error())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file '" + stat2 + "'";
+ printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+for (size_t i = 0; i < DIR_NUM; i++)
+ {
+ char dirName[3];
+ snprintf(dirName, 3, "U%llu", (unsigned long long)i);
+ s.WriteInt(dirName, stat.monthUp[i]); // Classic
+ s2.WriteInt(dirName, stat.monthUp[i]); // New
+ snprintf(dirName, 3, "D%llu", (unsigned long long)i);
+ s.WriteInt(dirName, stat.monthDown[i]); // Classic
+ s2.WriteInt(dirName, stat.monthDown[i]); // New
+ }
+
+// Classic
+s.WriteDouble("cash", stat.cash);
+
+// New
+s2.WriteDouble("Cash", stat.cash);
+s2.WriteDouble("FreeMb", stat.freeMb);
+s2.WriteDouble("LastCashAdd", stat.lastCashAdd);
+s2.WriteInt("LastCashAddTime", stat.lastCashAddTime);
+s2.WriteInt("PassiveTime", stat.passiveTime);
+s2.WriteInt("LastActivityTime", stat.lastActivityTime);
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::AddAdmin(const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+
+if (Touch(fileName))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file " + fileName;
+ printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::DelAdmin(const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+if (unlink(fileName.c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
+
+ {
+ CONFIGFILE cf(fileName, true);
+
+ int e = cf.Error();
+
+ if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot write admin " + ac.login + ". " + fileName;
+ printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
+ return -1;
+ }
+
+ char pass[ADM_PASSWD_LEN + 1];
+ memset(pass, 0, sizeof(pass));
+
+ char adminPass[ADM_PASSWD_LEN + 1];
+ memset(adminPass, 0, sizeof(adminPass));
+
+ BLOWFISH_CTX ctx;
+ InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+ adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
+ }
+
+ pass[ADM_PASSWD_LEN - 1] = 0;
+ char passwordE[2 * ADM_PASSWD_LEN + 2];
+ Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+ cf.WriteString("password", passwordE);
+ cf.WriteInt("ChgConf", ac.priv.userConf);
+ cf.WriteInt("ChgPassword", ac.priv.userPasswd);
+ cf.WriteInt("ChgStat", ac.priv.userStat);
+ cf.WriteInt("ChgCash", ac.priv.userCash);
+ cf.WriteInt("UsrAddDel", ac.priv.userAddDel);
+ cf.WriteInt("ChgTariff", ac.priv.tariffChg);
+ cf.WriteInt("ChgAdmin", ac.priv.adminChg);
+ cf.WriteInt("ChgService", ac.priv.serviceChg);
+ cf.WriteInt("ChgCorp", ac.priv.corpChg);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+CONFIGFILE cf(fileName);
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+std::string p;
+
+if (cf.Error())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot open " + fileName;
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("password", &p, "*"))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter password";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+ {
+ Decode21(pass, passwordE);
+ InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ DecryptBlock(password + 8*i, pass + 8*i, &ctx);
+ }
+ }
+else
+ {
+ password[0] = 0;
+ }
+
+ac->password = password;
+
+uint16_t a;
+
+if (cf.ReadUShortInt("ChgConf", &a, 0) == 0)
+ ac->priv.userConf = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgConf";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgPassword", &a, 0) == 0)
+ ac->priv.userPasswd = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgPassword";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgStat", &a, 0) == 0)
+ ac->priv.userStat = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgStat";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgCash", &a, 0) == 0)
+ ac->priv.userCash = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgCash";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("UsrAddDel", &a, 0) == 0)
+ ac->priv.userAddDel = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter UsrAddDel";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgAdmin", &a, 0) == 0)
+ ac->priv.adminChg = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgAdmin";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgTariff", &a, 0) == 0)
+ ac->priv.tariffChg = a;
+else
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter ChgTariff";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadUShortInt("ChgService", &a, 0) == 0)
+ ac->priv.serviceChg = a;
+else
+ ac->priv.serviceChg = 0;
+
+if (cf.ReadUShortInt("ChgCorp", &a, 0) == 0)
+ ac->priv.corpChg = a;
+else
+ ac->priv.corpChg = 0;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddTariff(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+if (Touch(fileName))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file " + fileName;
+ printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelTariff(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+if (unlink(fileName.c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const
+{
+std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+CONFIGFILE conf(fileName);
+std::string str;
+td->tariffConf.name = tariffName;
+
+if (conf.Error() != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read file " + fileName;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+std::string param;
+for (int i = 0; i<DIR_NUM; i++)
+ {
+ strprintf(¶m, "Time%d", i);
+ if (conf.ReadString(param, &str, "00:00-00:00") < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
+ return -1;
+ }
+
+ ParseTariffTimeStr(str.c_str(),
+ td->dirPrice[i].hDay,
+ td->dirPrice[i].mDay,
+ td->dirPrice[i].hNight,
+ td->dirPrice[i].mNight);
+
+ strprintf(¶m, "PriceDayA%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceDayA /= (1024*1024);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceDayB /= (1024*1024);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceNightA /= (1024*1024);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceNightB /= (1024*1024);
+
+ strprintf(¶m, "Threshold%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+ strprintf(¶m, "SinglePrice%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+ strprintf(¶m, "NoDiscount%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ }
+
+if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadString("TraffType", &str, "") < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+td->tariffConf.traffType = TARIFF::StringToTraffType(str);
+
+if (conf.ReadString("Period", &str, "month") < 0)
+ td->tariffConf.period = TARIFF::MONTH;
+else
+ td->tariffConf.period = TARIFF::StringToPeriod(str);
+
+if (conf.ReadString("ChangePolicy", &str, "allow") < 0)
+ td->tariffConf.changePolicy = TARIFF::ALLOW;
+else
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
+
+conf.ReadTime("ChangePolicyTimeout", &td->tariffConf.changePolicyTimeout, 0);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
+{
+std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+
+ {
+ CONFIGFILE cf(fileName, true);
+
+ int e = cf.Error();
+
+ if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error writing tariff " + tariffName;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
+ return e;
+ }
+
+ std::string param;
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, "PriceDayA%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
+
+ strprintf(¶m, "Threshold%d", i);
+ cf.WriteInt(param, td.dirPrice[i].threshold);
+
+ std::string s;
+ strprintf(¶m, "Time%d", i);
+
+ strprintf(&s, "%0d:%0d-%0d:%0d",
+ td.dirPrice[i].hDay,
+ td.dirPrice[i].mDay,
+ td.dirPrice[i].hNight,
+ td.dirPrice[i].mNight);
+
+ cf.WriteString(param, s);
+
+ strprintf(¶m, "NoDiscount%d", i);
+ cf.WriteInt(param, td.dirPrice[i].noDiscount);
+
+ strprintf(¶m, "SinglePrice%d", i);
+ cf.WriteInt(param, td.dirPrice[i].singlePrice);
+ }
+
+ cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
+ cf.WriteDouble("Fee", td.tariffConf.fee);
+ cf.WriteDouble("Free", td.tariffConf.free);
+ cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType));
+ cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period));
+ cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
+ cf.WriteTime("ChangePolicyTimeout", td.tariffConf.changePolicyTimeout);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::AddService(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+
+if (Touch(fileName))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot create file " + fileName;
+ printfd(__FILE__, "FILES_STORE::AddService - failed to add service '%s'\n", name.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::DelService(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+if (unlink(fileName.c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::SaveService(const SERVICE_CONF & conf) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), conf.name.c_str());
+
+ {
+ CONFIGFILE cf(fileName, true);
+
+ int e = cf.Error();
+
+ if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot write service " + conf.name + ". " + fileName;
+ printfd(__FILE__, "FILES_STORE::SaveService - failed to save service '%s'\n", conf.name.c_str());
+ return -1;
+ }
+
+ cf.WriteString("name", conf.name);
+ cf.WriteString("comment", conf.comment);
+ cf.WriteDouble("cost", conf.cost);
+ cf.WriteInt("pay_day", conf.payDay);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreService(SERVICE_CONF * conf, const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+CONFIGFILE cf(fileName);
+
+if (cf.Error())
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot open " + fileName;
+ printfd(__FILE__, "FILES_STORE::RestoreService - failed to restore service '%s'\n", name.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("name", &conf->name, name))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter 'name'";
+ printfd(__FILE__, "FILES_STORE::RestoreService - name read failed for service '%s'\n", name.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("comment", &conf->comment, ""))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter 'comment'";
+ printfd(__FILE__, "FILES_STORE::RestoreService - comment read failed for service '%s'\n", name.c_str());
+ return -1;
+ }
+
+if (cf.ReadDouble("cost", &conf->cost, 0.0))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter 'cost'";
+ printfd(__FILE__, "FILES_STORE::RestoreService - cost read failed for service '%s'\n", name.c_str());
+ return -1;
+ }
+
+unsigned short value = 0;
+if (cf.ReadUShortInt("pay_day", &value, 0))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error in parameter 'pay_day'";
+ printfd(__FILE__, "FILES_STORE::RestoreService - pay day read failed for service '%s'\n", name.c_str());
+ return -1;
+ }
+conf->payDay = value;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ time_t lastStat,
+ const std::string & login) const
+{
+char fn[FN_STR_LEN];
+char dn[FN_STR_LEN];
+FILE * statFile;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+ {
+ t -= 3600 * 24;
+ lt = localtime(&t);
+ }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
+ storeSettings.GetUsersDir().c_str(),
+ login.c_str(),
+ lt->tm_year+1900);
+
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d",
+ storeSettings.GetUsersDir().c_str(),
+ login.c_str(),
+ lt->tm_year+1900,
+ lt->tm_mon+1 < 10 ? "0" : "",
+ lt->tm_mon+1);
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
+
+statFile = fopen (fn, "at");
+
+if (!statFile)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "File \'" + std::string(fn) + "\' cannot be written.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
+ h1, m1, s1, h2, m2, s2) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("fprint failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ fclose(statFile);
+ return -1;
+ }
+
+std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+stIter = statTree.begin();
+
+while (stIter != statTree.end())
+ {
+ std::string u, d;
+ x2str(stIter->second.up, u);
+ x2str(stIter->second.down, d);
+ #ifdef TRAFF_STAT_WITH_PORTS
+ if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.port,
+ stIter->first.dir,
+ d.c_str(),
+ u.c_str(),
+ stIter->second.cash) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "fprint failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ fclose(statFile);
+ return -1;
+ }
+ #else
+ if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.dir,
+ d.c_str(),
+ u.c_str(),
+ stIter->second.cash) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("fprint failed. Message: '");
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ fclose(statFile);
+ return -1;
+ }
+ #endif
+
+ ++stIter;
+ }
+
+fclose(statFile);
+
+e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(fn, storeSettings.GetStatMode());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
+{
+std::string fn;
+std::string dn;
+struct timeval tv;
+
+strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn.c_str(), F_OK) != 0)
+ {
+ if (mkdir(dn.c_str(), 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Directory \'";
+ errorStr += dn;
+ errorStr += "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+chmod(dn.c_str(), storeSettings.GetConfModeDir());
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
+
+if (Touch(fn))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "File \'";
+ errorStr += fn;
+ errorStr += "\' cannot be writen.";
+ printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
+{
+std::string fileName;
+
+FILE * msgFile;
+strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
+
+if (access(fileName.c_str(), F_OK) != 0)
+ {
+ std::string idstr;
+ x2str(msg.header.id, idstr);
+ STG_LOCKER lock(&mutex);
+ errorStr = "Message for user \'";
+ errorStr += login + "\' with ID \'";
+ errorStr += idstr + "\' does not exist.";
+ printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
+ return -1;
+ }
+
+Touch(fileName + ".new");
+
+msgFile = fopen((fileName + ".new").c_str(), "wt");
+if (!msgFile)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "File \'" + fileName + "\' cannot be writen.";
+ printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+bool res = true;
+res &= (fprintf(msgFile, "%u\n", msg.header.type) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
+res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
+res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
+
+if (!res)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("fprintf failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
+ fclose(msgFile);
+ return -1;
+ }
+
+fclose(msgFile);
+
+chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
+
+if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
+ printfd(__FILE__, "FILES_STORE::EditMessage - rename failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
+{
+std::string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+msg->header.id = id;
+return ReadMessage(fn, &msg->header, &msg->text);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelMessage(uint64_t id, const std::string & login) const
+{
+std::string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+
+return unlink(fn.c_str());
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
+{
+std::string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
+
+if (access(dn.c_str(), F_OK) != 0)
+ {
+ return 0;
+ }
+
+std::vector<std::string> messages;
+GetFileList(&messages, dn, S_IFREG, "");
+
+for (unsigned i = 0; i < messages.size(); i++)
+ {
+ unsigned long long id = 0;
+
+ if (str2x(messages[i].c_str(), id))
+ {
+ if (unlink((dn + messages[i]).c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ continue;
+ }
+
+ STG_MSG_HDR hdr;
+ if (ReadMessage(dn + messages[i], &hdr, NULL))
+ {
+ return -1;
+ }
+
+ if (hdr.repeat < 0)
+ {
+ if (unlink((dn + messages[i]).c_str()))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ continue;
+ }
+
+ hdr.id = id;
+ hdrsList->push_back(hdr);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ReadMessage(const std::string & fileName,
+ STG_MSG_HDR * hdr,
+ std::string * text) const
+{
+FILE * msgFile;
+msgFile = fopen(fileName.c_str(), "rt");
+if (!msgFile)
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "File \'";
+ errorStr += fileName;
+ errorStr += "\' cannot be openned.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+char p[20];
+unsigned * d[6];
+d[0] = &hdr->type;
+d[1] = &hdr->lastSendTime;
+d[2] = &hdr->creationTime;
+d[3] = &hdr->showTime;
+d[4] = (unsigned*)(&hdr->repeat);
+d[5] = &hdr->repeatPeriod;
+
+memset(p, 0, sizeof(p));
+
+for (int pos = 0; pos < 6; pos++)
+ {
+ if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Missing data.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
+ printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+ fclose(msgFile);
+ return -1;
+ }
+
+ char * ep;
+ ep = strrchr(p, '\r');
+ if (ep) *ep = 0;
+ ep = strrchr(p, '\n');
+ if (ep) *ep = 0;
+
+ if (feof(msgFile))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Missing data.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
+ printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+ fclose(msgFile);
+ return -1;
+ }
+
+ if (str2x(p, *(d[pos])))
+ {
+ STG_LOCKER lock(&mutex);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Incorrect value. \'";
+ errorStr += p;
+ errorStr += "\'";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
+ fclose(msgFile);
+ return -1;
+ }
+ }
+
+char txt[2048];
+memset(txt, 0, sizeof(txt));
+if (text)
+ {
+ text->erase(text->begin(), text->end());
+ while (!feof(msgFile))
+ {
+ txt[0] = 0;
+ if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
+ break;
+ }
+
+ (*text) += txt;
+ }
+ }
+fclose(msgFile);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::Touch(const std::string & path) const
+{
+FILE * f = fopen(path.c_str(), "wb");
+if (f)
+ {
+ fclose(f);
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext)
+{
+DIR * d = opendir(directory.c_str());
+
+if (!d)
+ {
+ printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
+ return -1;
+ }
+
+dirent * entry;
+while ((entry = readdir(d)))
+ {
+ if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
+ continue;
+
+ std::string str = directory + "/" + std::string(entry->d_name);
+
+ struct stat st;
+ if (stat(str.c_str(), &st))
+ continue;
+
+ if (!(st.st_mode & mode)) // Filter by mode
+ continue;
+
+ if (!ext.empty())
+ {
+ // Check extension
+ size_t d_nameLen = strlen(entry->d_name);
+ if (d_nameLen <= ext.size())
+ continue;
+
+ if (ext == entry->d_name + (d_nameLen - ext.size()))
+ {
+ entry->d_name[d_nameLen - ext.size()] = 0;
+ fileList->push_back(entry->d_name);
+ }
+ }
+ else
+ {
+ fileList->push_back(entry->d_name);
+ }
+ }
+
+closedir(d);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.22 $
+ $Date: 2010/01/19 11:06:53 $
+ $Author: faust $
+ */
+
+
+#ifndef FILE_STORE_H
+#define FILE_STORE_H
+
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <string>
+
+#include "stg/module_settings.h"
+#include "stg/store.h"
+#include "stg/conffiles.h"
+#include "stg/user_traff.h"
+#include "stg/logger.h"
+
+//-----------------------------------------------------------------------------
+class FILES_STORE_SETTINGS {
+public:
+ FILES_STORE_SETTINGS();
+ int ParseSettings(const MODULE_SETTINGS & s);
+ const std::string & GetStrError() const;
+
+ std::string GetWorkDir() const { return workDir; }
+ std::string GetUsersDir() const { return usersDir; }
+ std::string GetAdminsDir() const { return adminsDir; }
+ std::string GetTariffsDir() const { return tariffsDir; }
+ std::string GetServicesDir() const { return servicesDir; }
+
+ mode_t GetStatMode() const { return statMode; }
+ mode_t GetStatModeDir() const;
+ uid_t GetStatUID() const { return statUID; }
+ gid_t GetStatGID() const { return statGID; }
+
+ mode_t GetConfMode() const { return confMode; }
+ mode_t GetConfModeDir() const;
+ uid_t GetConfUID() const { return confUID; }
+ gid_t GetConfGID() const { return confGID; }
+
+ mode_t GetLogMode() const { return userLogMode; }
+ uid_t GetLogUID() const { return userLogUID; }
+ gid_t GetLogGID() const { return userLogGID; }
+
+ bool GetRemoveBak() const { return removeBak; }
+ bool GetReadBak() const { return readBak; }
+
+private:
+ FILES_STORE_SETTINGS(const FILES_STORE_SETTINGS & rvalue);
+ FILES_STORE_SETTINGS & operator=(const FILES_STORE_SETTINGS & rvalue);
+
+ const MODULE_SETTINGS * settings;
+
+ int User2UID(const char * user, uid_t * uid);
+ int Group2GID(const char * gr, gid_t * gid);
+ int Str2Mode(const char * str, mode_t * mode);
+ int ParseOwner(const std::vector<PARAM_VALUE> & moduleParams, const std::string & owner, uid_t * uid);
+ int ParseGroup(const std::vector<PARAM_VALUE> & moduleParams, const std::string & group, uid_t * uid);
+ int ParseMode(const std::vector<PARAM_VALUE> & moduleParams, const std::string & modeStr, mode_t * mode);
+ int ParseYesNo(const std::string & value, bool * val);
+
+ std::string errorStr;
+
+ std::string workDir;
+ std::string usersDir;
+ std::string adminsDir;
+ std::string tariffsDir;
+ std::string servicesDir;
+
+ mode_t statMode;
+ uid_t statUID;
+ gid_t statGID;
+
+ mode_t confMode;
+ uid_t confUID;
+ gid_t confGID;
+
+ mode_t userLogMode;
+ uid_t userLogUID;
+ gid_t userLogGID;
+
+ bool removeBak;
+ bool readBak;
+};
+//-----------------------------------------------------------------------------
+class FILES_STORE: public STORE {
+public:
+ FILES_STORE();
+ virtual ~FILES_STORE() {}
+ virtual const std::string & GetStrError() const { return errorStr; }
+
+ //User
+ virtual int GetUsersList(std::vector<std::string> * usersList) const;
+ virtual int AddUser(const std::string & login) const;
+ virtual int DelUser(const std::string & login) const;
+ virtual int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ virtual int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+
+ virtual int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+
+ virtual int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message = "") const;
+ virtual int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ virtual int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+
+ virtual int WriteDetailedStat(const TRAFF_STAT & statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ virtual int AddMessage(STG_MSG * msg, const std::string & login) const;
+ virtual int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ virtual int DelMessage(uint64_t id, const std::string & login) const;
+ virtual int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+ virtual int ReadMessage(const std::string & fileName,
+ STG_MSG_HDR * hdr,
+ std::string * text) const;
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ //Admin
+ virtual int GetAdminsList(std::vector<std::string> * adminsList) const;
+ virtual int AddAdmin(const std::string & login) const;
+ virtual int DelAdmin(const std::string & login) const;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const;
+
+ //Tariff
+ virtual int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ virtual int AddTariff(const std::string & name) const;
+ virtual int DelTariff(const std::string & name) const;
+ virtual int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ virtual int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ //Corparation
+ virtual int GetCorpsList(std::vector<std::string> *) const { return 0; }
+ virtual int SaveCorp(const CORP_CONF &) const { return 0; }
+ virtual int RestoreCorp(CORP_CONF *, const std::string &) const { return 0; }
+ virtual int AddCorp(const std::string &) const { return 0; }
+ virtual int DelCorp(const std::string &) const { return 0; }
+
+ // Services
+ virtual int GetServicesList(std::vector<std::string> *) const;
+ virtual int SaveService(const SERVICE_CONF &) const;
+ virtual int RestoreService(SERVICE_CONF *, const std::string &) const;
+ virtual int AddService(const std::string &) const;
+ virtual int DelService(const std::string &) const;
+
+ virtual void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ virtual int ParseSettings();
+ virtual const std::string & GetVersion() const { return version; }
+
+private:
+ FILES_STORE(const FILES_STORE & rvalue);
+ FILES_STORE & operator=(const FILES_STORE & rvalue);
+
+ virtual int RestoreUserStat(USER_STAT * stat, const std::string & login, const std::string & fileName) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const std::string & login, const std::string & fileName) const;
+
+ virtual int WriteLogString(const std::string & str, const std::string & login) const;
+ virtual int WriteLog2String(const std::string & str, const std::string & login) const;
+ int RemoveDir(const char * path) const;
+ int Touch(const std::string & path) const;
+
+ mutable std::string errorStr;
+ std::string version;
+ FILES_STORE_SETTINGS storeSettings;
+ MODULE_SETTINGS settings;
+ mutable pthread_mutex_t mutex;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+find_package ( FBClient REQUIRED )
+
+set ( CPP_FILES firebird_store.cpp
+ firebird_store_admins.cpp
+ firebird_store_corporations.cpp
+ firebird_store_messages.cpp
+ firebird_store_services.cpp
+ firebird_store_tariffs.cpp
+ firebird_store_users.cpp
+ firebird_store_utils.cpp )
+
+add_library ( mod_store_firebird MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_store_firebird crypto common logger ibpp FBClient::FBClient )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:15:53 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+DEFS += -DIBPP_LINUX
+
+PROG = mod_store_firebird.so
+
+SRCS = ./firebird_store.cpp \
+ ./firebird_store_admins.cpp \
+ ./firebird_store_corporations.cpp \
+ ./firebird_store_messages.cpp \
+ ./firebird_store_services.cpp \
+ ./firebird_store_tariffs.cpp \
+ ./firebird_store_users.cpp \
+ ./firebird_store_utils.cpp
+
+STGLIBS = ibpp \
+ common \
+ logger \
+ crypto
+
+CXXFLAGS += $(FB_CFLAGS)
+LDFLAGS += $(FB_LDFLAGS)
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * This file contains a realization of a base firebird-storage plugin class
+ *
+ * $Revision: 1.18 $
+ * $Date: 2010/01/08 16:00:45 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/plugin_creator.h"
+
+#include <string>
+#include <vector>
+
+namespace
+{
+PLUGIN_CREATOR<FIREBIRD_STORE> frsc;
+}
+
+extern "C" STORE * GetStore();
+//-----------------------------------------------------------------------------
+STORE * GetStore()
+{
+return frsc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::FIREBIRD_STORE()
+ : version("firebird_store v.1.4"),
+ db_server("localhost"),
+ db_database("/var/stg/stargazer.fdb"),
+ db_user("stg"),
+ db_password("123456"),
+ til(IBPP::ilConcurrency),
+ tlr(IBPP::lrWait),
+ schemaVersion(0),
+ logger(GetPluginLogger(GetStgLogger(), "store_firebird"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::~FIREBIRD_STORE()
+{
+db->Disconnect();
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::ParseSettings()
+{
+std::vector<PARAM_VALUE>::iterator i;
+std::string s;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+ {
+ if (i->value.empty())
+ continue;
+ s = ToLower(i->param);
+
+ if (s == "server")
+ db_server = i->value.front();
+
+ if (s == "database")
+ db_database = i->value.front();
+
+ if (s == "user")
+ db_user = i->value.front();
+
+ if (s == "password")
+ db_password = i->value.front();
+
+ // Advanced settings block
+
+ if (s == "isolationLevel")
+ {
+ if (i->value.front() == "Concurrency")
+ til = IBPP::ilConcurrency;
+ else if (i->value.front() == "DirtyRead")
+ til = IBPP::ilReadDirty;
+ else if (i->value.front() == "ReadCommitted")
+ til = IBPP::ilReadCommitted;
+ else if (i->value.front() == "Consistency")
+ til = IBPP::ilConsistency;
+ }
+
+ if (s == "lockResolution")
+ {
+ if (i->value.front() == "Wait")
+ tlr = IBPP::lrWait;
+ else if (i->value.front() == "NoWait")
+ tlr = IBPP::lrNoWait;
+ }
+ }
+
+try
+ {
+ db = IBPP::DatabaseFactory(db_server, db_database, db_user, db_password, "", "KOI8U", "");
+ db->Connect();
+ return CheckVersion();
+ }
+catch (IBPP::Exception & ex)
+ {
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::CheckVersion()
+{
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Execute("SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_NAME = 'TB_INFO'");
+ if (!st->Fetch())
+ {
+ schemaVersion = 0;
+ }
+ else
+ {
+ st->Execute("SELECT version FROM tb_info");
+ while (st->Fetch())
+ st->Get(1, schemaVersion);
+ }
+ tr->Commit();
+ logger("FIREBIRD_STORE: Current DB schema version: %d", schemaVersion);
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Firebird storage class definition
+ *
+ * $Revision: 1.13 $
+ * $Date: 2010/01/19 11:07:25 $
+ *
+ */
+
+#ifndef FIREBIRD_STORE_H
+#define FIREBIRD_STORE_H
+
+#include <ctime>
+#include <string>
+#include <vector>
+
+#include "stg/store.h"
+#include "stg/locker.h"
+#include "stg/ibpp.h"
+#include "stg/logger.h"
+
+struct ToLower {
+ char operator() (char c) const { return static_cast<char>(std::tolower(c)); }
+};
+
+class FIREBIRD_STORE : public STORE {
+public:
+ FIREBIRD_STORE();
+ virtual ~FIREBIRD_STORE();
+
+ int GetUsersList(std::vector<std::string> * usersList) const;
+ int AddUser(const std::string & login) const;
+ int DelUser(const std::string & login) const;
+ int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+ int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+ int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const;
+ int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+ int WriteDetailedStat(const TRAFF_STAT & statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ int AddMessage(STG_MSG * msg, const std::string & login) const;
+ int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ int DelMessage(uint64_t id, const std::string & login) const;
+ int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+
+ int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ int GetAdminsList(std::vector<std::string> * adminsList) const;
+ int SaveAdmin(const ADMIN_CONF & ac) const;
+ int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ int AddAdmin(const std::string & login) const;
+ int DelAdmin(const std::string & login) const;
+
+ int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ int AddTariff(const std::string & name) const;
+ int DelTariff(const std::string & name) const;
+ int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ int GetCorpsList(std::vector<std::string> * corpsList) const;
+ int SaveCorp(const CORP_CONF & cc) const;
+ int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
+ int AddCorp(const std::string & name) const;
+ int DelCorp(const std::string & name) const;
+
+ inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ inline const std::string & GetStrError() const { return strError; }
+
+ inline const std::string & GetVersion() const { return version; }
+
+ int GetServicesList(std::vector<std::string> * servicesList) const;
+ int SaveService(const SERVICE_CONF & sc) const;
+ int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
+ int AddService(const std::string & name) const;
+ int DelService(const std::string & name) const;
+
+private:
+ FIREBIRD_STORE(const FIREBIRD_STORE & rvalue);
+ FIREBIRD_STORE & operator=(const FIREBIRD_STORE & rvalue);
+
+ std::string version;
+ mutable std::string strError;
+ std::string db_server, db_database, db_user, db_password;
+ MODULE_SETTINGS settings;
+ mutable IBPP::Database db;
+ mutable pthread_mutex_t mutex;
+ IBPP::TIL til;
+ IBPP::TLR tlr;
+ int schemaVersion;
+ PLUGIN_LOGGER logger;
+
+ int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
+ int CheckVersion();
+};
+
+time_t ts2time_t(const IBPP::Timestamp & ts);
+void time_t2ts(time_t t, IBPP::Timestamp * ts);
+void ym2date(int year, int month, IBPP::Date * date);
+
+template <typename T>
+inline
+T Get(IBPP::Statement st, size_t pos)
+{
+ T value;
+ st->Get(pos, value);
+ return value;
+}
+
+#endif //FIREBIRD_STORE_H
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Administrators manipulation methods
+ *
+ * $Revision: 1.11 $
+ * $Date: 2008/12/04 17:10:06 $
+ *
+ */
+
+#include <string>
+#include <vector>
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+#include "stg/blowfish.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string login;
+
+try
+ {
+ tr->Start();
+ st->Execute("select login from tb_admins");
+ while (st->Fetch())
+ {
+ st->Get(1, login);
+ adminsList->push_back(login);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+try
+ {
+ tr->Start();
+ st->Prepare("update tb_admins set passwd=?, \
+ chg_conf=?, \
+ chg_password=?, \
+ chg_stat=?, \
+ chg_cash=?, \
+ usr_add_del=?, \
+ chg_tariff=?, \
+ chg_admin=? \
+ where login=?");
+ st->Set(1, encodedPass);
+ st->Set(2, static_cast<int16_t>(ac.priv.userConf));
+ st->Set(3, static_cast<int16_t>(ac.priv.userPasswd));
+ st->Set(4, static_cast<int16_t>(ac.priv.userStat));
+ st->Set(5, static_cast<int16_t>(ac.priv.userCash));
+ st->Set(6, static_cast<int16_t>(ac.priv.userAddDel));
+ st->Set(7, static_cast<int16_t>(ac.priv.tariffChg));
+ st->Set(8, static_cast<int16_t>(ac.priv.adminChg));
+ st->Set(9, ac.login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_admins where login = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(2, ac->login);
+ st->Get(3, ac->password);
+ st->Get(4, (int16_t &)ac->priv.userConf);
+ st->Get(5, (int16_t &)ac->priv.userPasswd);
+ st->Get(6, (int16_t &)ac->priv.userStat);
+ st->Get(7, (int16_t &)ac->priv.userCash);
+ st->Get(8, (int16_t &)ac->priv.userAddDel);
+ st->Get(9, (int16_t &)ac->priv.tariffChg);
+ st->Get(10, (int16_t &)ac->priv.adminChg);
+ }
+ else
+ {
+ strError = "Admin \"" + login + "\" not found in database";
+ printfd(__FILE__, "Admin '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+if (ac->password == "")
+ {
+ return 0;
+ }
+
+Decode21(cryptedPass, ac->password.c_str());
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ {
+ DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+ }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_admins(login, \
+ passwd, \
+ chg_conf, \
+ chg_password, \
+ chg_stat, \
+ chg_cash, \
+ usr_add_del, \
+ chg_tariff, \
+ chg_admin, \
+ chg_service, \
+ chg_corporation) \
+ values (?, '', 0, 0, 0, 0, 0, 0, 0, 0, 0)");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_admins where login = ?");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Corporations manipulation methods
+ *
+ * $Revision: 1.5 $
+ * $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_corporations");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ corpsList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveCorp(const CORP_CONF & cc) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Execute("update tb_corporations set cash = ? where name = ?");
+ st->Set(1, cc.cash);
+ st->Set(2, cc.name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreCorp(CORP_CONF * cc, const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select cash from tb_corporations where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(1, cc->cash);
+ }
+ else
+ {
+ strError = "Corporation \"" + name + "\" not found in database";
+ tr->Rollback();
+ printfd(__FILE__, "Corporation '%s' not found in database\n", name.c_str());
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_corporations (name, cash), values (?, 0)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_corporations where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ * Messages manipualtion methods
+ *
+ * $Revision: 1.10 $
+ * $Date: 2009/03/03 16:16:23 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_message(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ st->Set(1, login);
+ st->Set(2, (int32_t)msg->header.ver);
+ st->Set(3, (int32_t)msg->header.type);
+ st->Set(4, (int32_t)msg->header.lastSendTime);
+ st->Set(5, (int32_t)msg->header.creationTime);
+ st->Set(6, (int32_t)msg->header.showTime);
+ st->Set(7, msg->header.repeat);
+ st->Set(8, (int32_t)msg->header.repeatPeriod);
+ st->Set(9, msg->text);
+ st->Execute();
+ st->Get(1, (int64_t &)msg->header.id);
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::EditMessage(const STG_MSG & msg,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_message(?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ st->Set(1, (int64_t)msg.header.id);
+ st->Set(2, login);
+ st->Set(3, (int32_t)msg.header.ver);
+ st->Set(4, (int32_t)msg.header.type);
+ st->Set(5, (int32_t)msg.header.lastSendTime);
+ st->Set(6, (int32_t)msg.header.creationTime);
+ st->Set(7, (int32_t)msg.header.showTime);
+ st->Set(8, msg.header.repeat);
+ st->Set(9, (int32_t)msg.header.repeatPeriod);
+ st->Set(10, msg.text.c_str());
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessage(uint64_t id,
+ STG_MSG * msg,
+ const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_messages where pk_message = ?");
+ st->Set(1, (int64_t)id);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(1, (int64_t &)msg->header.id);
+ st->Get(3, (int32_t &)msg->header.ver);
+ st->Get(4, (int32_t &)msg->header.type);
+ st->Get(5, (int32_t &)msg->header.lastSendTime);
+ st->Get(6, (int32_t &)msg->header.creationTime);
+ st->Get(7, (int32_t &)msg->header.showTime);
+ st->Get(8, msg->header.repeat);
+ st->Get(9, (int32_t &)msg->header.repeatPeriod);
+ st->Get(10, msg->text);
+ }
+ else
+ {
+ strprintf(&strError, "Message with id = %d not found in database", id);
+ printfd(__FILE__, "Message with id - %d not found in database\n", id);
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelMessage(uint64_t id, const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_messages where pk_message = ?");
+ st->Set(1, (int64_t)id);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+STG_MSG_HDR header;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_message, ver, msg_type, \
+ last_send_time, creation_time, \
+ show_time, repeat, repeat_period \
+ from tb_messages where \
+ fk_user = (select pk_user from tb_users where name = ?)");
+ st->Set(1, login);
+ st->Execute();
+ while (st->Fetch())
+ {
+ st->Get(1, (int64_t &)header.id);
+ st->Get(2, (int32_t &)header.ver);
+ st->Get(3, (int32_t &)header.type);
+ st->Get(4, (int32_t &)header.lastSendTime);
+ st->Get(5, (int32_t &)header.creationTime);
+ st->Get(6, (int32_t &)header.showTime);
+ st->Get(7, header.repeat);
+ st->Get(8, (int32_t &)header.repeatPeriod);
+ hdrsList->push_back(header);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ * Services manipulation methods
+ *
+ * $Revision: 1.6 $
+ * $Date: 2009/05/13 13:19:33 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetServicesList(std::vector<std::string> * servicesList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_services");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ servicesList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveService(const SERVICE_CONF & sc) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("update tb_services set \
+ comments = ?, \
+ cost = ?, \
+ pay_day = ? \
+ where name = ?");
+ st->Set(1, sc.comment);
+ st->Set(2, sc.cost);
+ st->Set(3, static_cast<int16_t>(sc.payDay));
+ st->Set(4, sc.name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreService(SERVICE_CONF * sc,
+ const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_services where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(3, sc->comment);
+ st->Get(4, sc->cost);
+ int16_t pd;
+ st->Get(5, pd);
+ sc->payDay = static_cast<uint8_t>(pd);
+ }
+ else
+ {
+ strError = "Service \"" + name + "\" not found in database";
+ printfd(__FILE__, "Service '%s' not found in database\n", name.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_services (name, comment, cost, pay_day) \
+ values (?, '', 0, 0)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_service(?)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Tariffs manipulation methods
+ *
+ * $Revision: 1.5 $
+ * $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include <cmath>
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+namespace
+{
+
+const int pt_mega = 1024 * 1024;
+
+}
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_tariffs");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ tariffsList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_tariff(?, ?)");
+ st->Set(1, name);
+ st->Set(2, DIR_NUM);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_tariff(?)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveTariff(const TARIFF_DATA & td,
+ const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_tariff from tb_tariffs where name = ?");
+ st->Set(1, tariffName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ tr->Rollback();
+ strprintf(&strError, "Tariff \"%s\" not found in database", tariffName.c_str());
+ printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+ return -1;
+ }
+ int32_t id;
+ st->Get(1, id);
+ st->Close();
+
+ std::string query = "update tb_tariffs set \
+ fee = ?, \
+ free = ?, \
+ passive_cost = ?, \
+ traff_type = ?";
+
+ if (schemaVersion > 0)
+ query += ", period = ?";
+ if (schemaVersion > 1)
+ query += ", change_policy = ?, \
+ change_policy_timeout = ?";
+
+ query += " where pk_tariff = ?";
+
+ unsigned num = 5;
+ st->Prepare(query);
+ st->Set(1, td.tariffConf.fee);
+ st->Set(2, td.tariffConf.free);
+ st->Set(3, td.tariffConf.passiveCost);
+ st->Set(4, td.tariffConf.traffType);
+
+ if (schemaVersion > 0)
+ {
+ st->Set(5, TARIFF::PeriodToString(td.tariffConf.period));
+ ++num;
+ }
+
+ if (schemaVersion > 1)
+ {
+ st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
+ IBPP::Timestamp policyTimeout;
+ time_t2ts(td.tariffConf.changePolicyTimeout, &policyTimeout);
+ st->Set(7, policyTimeout);
+ num += 2;
+ }
+
+ st->Set(num, id);
+ st->Execute();
+ st->Close();
+
+ IBPP::Time tb;
+ IBPP::Time te;
+
+ for(int i = 0; i < DIR_NUM; i++)
+ {
+
+ tb.SetTime(td.dirPrice[i].hDay, td.dirPrice[i].mDay, 0);
+ te.SetTime(td.dirPrice[i].hNight, td.dirPrice[i].mNight, 0);
+
+ double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+ double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+ double pna = 0;
+ double pnb = 0;
+
+ if (td.dirPrice[i].singlePrice)
+ {
+ pna = pda;
+ pnb = pdb;
+ }
+ else
+ {
+ pna = td.dirPrice[i].priceNightA;
+ pnb = td.dirPrice[i].priceNightB;
+ }
+
+ int threshold = 0;
+ if (td.dirPrice[i].noDiscount)
+ {
+ threshold = 0xffFFffFF;
+ }
+ else
+ {
+ threshold = td.dirPrice[i].threshold;
+ }
+
+ st->Prepare("update tb_tariffs_params set \
+ price_day_a = ?, \
+ price_day_b = ?, \
+ price_night_a = ?, \
+ price_night_b = ?, \
+ threshold = ?, \
+ time_day_begins = ?, \
+ time_day_ends = ? \
+ where fk_tariff = ? and dir_num = ?");
+ st->Set(1, pda);
+ st->Set(2, pdb);
+ st->Set(3, pna);
+ st->Set(4, pnb);
+ st->Set(5, threshold);
+ st->Set(6, tb);
+ st->Set(7, te);
+ st->Set(8, id);
+ st->Set(9, i);
+ st->Execute();
+ st->Close();
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreTariff(TARIFF_DATA * td,
+ const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+
+td->tariffConf.name = tariffName;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_tariffs where name = ?"); // TODO: explicit field order!
+ st->Set(1, tariffName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "Tariff \"" + tariffName + "\" not found in database";
+ printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ int32_t id;
+ st->Get(1, id);
+ st->Get(3, td->tariffConf.fee);
+ st->Get(4, td->tariffConf.free);
+ st->Get(5, td->tariffConf.passiveCost);
+ td->tariffConf.traffType = TARIFF::IntToTraffType(Get<int>(st, 6));
+ if (schemaVersion > 0)
+ td->tariffConf.period = TARIFF::StringToPeriod(Get<std::string>(st, 7));
+ if (schemaVersion > 1)
+ {
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(Get<std::string>(st, 8));
+ td->tariffConf.changePolicyTimeout = ts2time_t(Get<IBPP::Timestamp>(st, 9));
+ }
+ st->Close();
+ st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
+ st->Set(1, id);
+ st->Execute();
+ int i = 0;
+ while (st->Fetch())
+ {
+ i++;
+ if (i > DIR_NUM)
+ {
+ strError = "Too mach params for tariff \"" + tariffName + "\"";
+ printfd(__FILE__, "Too mach params for tariff '%s'\n", tariffName.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ int16_t dir;
+ st->Get(3, dir);
+ st->Get(4, td->dirPrice[dir].priceDayA);
+ td->dirPrice[dir].priceDayA /= 1024*1024;
+ st->Get(5, td->dirPrice[dir].priceDayB);
+ td->dirPrice[dir].priceDayB /= 1024*1024;
+ st->Get(6, td->dirPrice[dir].priceNightA);
+ td->dirPrice[dir].priceNightA /= 1024*1024;
+ st->Get(7, td->dirPrice[dir].priceNightB);
+ td->dirPrice[dir].priceNightB /= 1024*1024;
+ st->Get(8, td->dirPrice[dir].threshold);
+ if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
+ std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
+ {
+ td->dirPrice[dir].singlePrice = true;
+ }
+ else
+ {
+ td->dirPrice[dir].singlePrice = false;
+ }
+ if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+ {
+ td->dirPrice[dir].noDiscount = true;
+ }
+ else
+ {
+
+ td->dirPrice[dir].noDiscount = false;
+ }
+ IBPP::Time tb;
+ st->Get(9, tb);
+ IBPP::Time te;
+ st->Get(10, te);
+ int h, m, s;
+ tb.GetTime(h, m, s);
+ td->dirPrice[dir].hDay = h;
+ td->dirPrice[dir].mDay = m;
+ te.GetTime(h, m, s);
+ td->dirPrice[dir].hNight = h;
+ td->dirPrice[dir].mNight = m;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * User manipulation methods
+ *
+ * $Revision: 1.19 $
+ * $Date: 2010/01/19 11:07:25 $
+ *
+ */
+
+#include "stg/const.h"
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_users");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ usersList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddUser(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_user(?, ?)");
+ st->Set(1, name);
+ st->Set(2, DIR_NUM);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelUser(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_user(?)");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserStat(const USER_STAT & stat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveStat(const USER_STAT & stat,
+ const std::string & login,
+ int year,
+ int month) const
+{
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ int32_t uid = Get<int32_t>(st, 1);
+ st->Close();
+ st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
+ st->Set(1, uid);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ tr->Rollback();
+ strError = "No stat info for user \"" + login + "\"";
+ printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+ return -1;
+ }
+ int32_t sid;
+ st->Get(1, sid);
+ st->Close();
+
+ IBPP::Timestamp actTime;
+ time_t2ts(stat.lastActivityTime, &actTime);
+ IBPP::Timestamp addTime;
+ time_t2ts(stat.lastCashAddTime, &addTime);
+ IBPP::Date dt;
+ if (year != 0)
+ ym2date(year, month, &dt);
+ else
+ dt.Today();
+
+ st->Prepare("update tb_stats set \
+ cash = ?, \
+ free_mb = ?, \
+ last_activity_time = ?, \
+ last_cash_add = ?, \
+ last_cash_add_time = ?, \
+ passive_time = ?, \
+ stats_date = ? \
+ where pk_stat = ?");
+
+ st->Set(1, stat.cash);
+ st->Set(2, stat.freeMb);
+ st->Set(3, actTime);
+ st->Set(4, stat.lastCashAdd);
+ st->Set(5, addTime);
+ st->Set(6, (int32_t)stat.passiveTime);
+ st->Set(7, dt);
+ st->Set(8, sid);
+
+ st->Execute();
+ st->Close();
+
+ for(int i = 0; i < DIR_NUM; i++)
+ {
+ st->Prepare("update tb_stats_traffic set \
+ upload = ?, \
+ download = ? \
+ where fk_stat = ? and dir_num = ?");
+ st->Set(1, (int64_t)stat.monthUp[i]);
+ st->Set(2, (int64_t)stat.monthDown[i]);
+ st->Set(3, sid);
+ st->Set(4, i);
+ st->Execute();
+ st->Close();
+ }
+
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserConf(const USER_CONF & conf,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ int32_t uid;
+ st->Get(1, uid);
+ st->Close();
+
+ IBPP::Timestamp creditExpire;
+ time_t2ts(conf.creditExpire, &creditExpire);
+
+ st->Prepare("update tb_users set \
+ address = ?, \
+ always_online = ?, \
+ credit = ?, \
+ credit_expire = ?, \
+ disabled = ?, \
+ disabled_detail_stat = ?, \
+ email = ?, \
+ grp = ?, \
+ note = ?, \
+ passive = ?, \
+ passwd = ?, \
+ phone = ?, \
+ fk_tariff = (select pk_tariff from tb_tariffs \
+ where name = ?), \
+ fk_tariff_change = (select pk_tariff from tb_tariffs \
+ where name = ?), \
+ fk_corporation = (select pk_corporation from tb_corporations \
+ where name = ?), \
+ real_name = ? \
+ where pk_user = ?");
+
+ st->Set(1, conf.address);
+ st->Set(2, (bool)conf.alwaysOnline);
+ st->Set(3, conf.credit);
+ st->Set(4, creditExpire);
+ st->Set(5, (bool)conf.disabled);
+ st->Set(6, (bool)conf.disabledDetailStat);
+ st->Set(7, conf.email);
+ st->Set(8, conf.group);
+ st->Set(9, conf.note);
+ st->Set(10, (bool)conf.passive);
+ st->Set(11, conf.password);
+ st->Set(12, conf.phone);
+ st->Set(13, conf.tariffName);
+ st->Set(14, conf.nextTariff);
+ st->Set(15, conf.corp);
+ st->Set(16, conf.realName);
+ st->Set(17, uid);
+
+ st->Execute();
+ st->Close();
+
+ st->Prepare("delete from tb_users_services where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ st->Close();
+
+ st->Prepare("insert into tb_users_services (fk_user, fk_service) \
+ values (?, (select pk_service from tb_services \
+ where name = ?))");
+ for(std::vector<std::string>::const_iterator it = conf.services.begin(); it != conf.services.end(); ++it)
+ {
+ st->Set(1, uid);
+ st->Set(2, *it);
+ st->Execute();
+ }
+ st->Close();
+
+ st->Prepare("delete from tb_users_data where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ st->Close();
+
+ int i = 0;
+ st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
+ for (std::vector<std::string>::const_iterator it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
+ {
+ st->Set(1, uid);
+ st->Set(2, *it);
+ st->Set(3, i++);
+ st->Execute();
+ }
+ st->Close();
+
+ st->Prepare("delete from tb_allowed_ip where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+
+ st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
+ for(size_t i = 0; i < conf.ips.Count(); i++)
+ {
+ st->Set(1, uid);
+ st->Set(2, (int32_t)conf.ips[i].ip);
+ st->Set(3, (int32_t)conf.ips[i].mask);
+ st->Execute();
+ }
+ tr->Commit();
+ }
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserStat(USER_STAT * stat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ return -1;
+ }
+ int32_t uid;
+ st->Get(1, uid);
+ st->Close();
+
+ st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
+ last_cash_add, last_cash_add_time, passive_time from tb_stats \
+ where fk_user = ? order by stats_date desc");
+ st->Set(1, uid);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "No stat info for user \"" + login + "\"";
+ printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+
+ int32_t sid;
+ st->Get(1, sid);
+ st->Get(2, stat->cash);
+ st->Get(3, stat->freeMb);
+ IBPP::Timestamp actTime;
+ st->Get(4, actTime);
+ st->Get(5, stat->lastCashAdd);
+ IBPP::Timestamp addTime;
+ st->Get(6, addTime);
+ int32_t passiveTime;
+ st->Get(7, passiveTime);
+
+ stat->passiveTime = passiveTime;
+
+ stat->lastActivityTime = ts2time_t(actTime);
+
+ stat->lastCashAddTime = ts2time_t(addTime);
+
+ st->Close();
+ st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
+ st->Set(1, sid);
+ st->Execute();
+ for(int i = 0; i < DIR_NUM; i++)
+ {
+ if (st->Fetch())
+ {
+ int dir;
+ st->Get(3, dir);
+ st->Get(5, (int64_t &)stat->monthUp[dir]);
+ st->Get(4, (int64_t &)stat->monthDown[dir]);
+ }
+ else
+ {
+ break;
+ }
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserConf(USER_CONF * conf,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
+ tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
+ tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
+ tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
+ tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
+ from tb_users left join tb_tariffs tf1 \
+ on tf1.pk_tariff = tb_users.fk_tariff \
+ left join tb_tariffs tf2 \
+ on tf2.pk_tariff = tb_users.fk_tariff_change \
+ left join tb_corporations \
+ on tb_corporations.pk_corporation = tb_users.fk_corporation \
+ where tb_users.name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ int32_t uid;
+ st->Get(1, uid);
+ // Getting base config
+ st->Get(2, conf->address);
+ bool test;
+ st->Get(3, test);
+ conf->alwaysOnline = test;
+ st->Get(4, conf->credit);
+ IBPP::Timestamp timestamp;
+ st->Get(5, timestamp);
+
+ conf->creditExpire = ts2time_t(timestamp);
+
+ st->Get(6, test);
+ conf->disabled = test;
+ st->Get(7, test);
+ conf->disabledDetailStat = test;
+ st->Get(8, conf->email);
+ st->Get(9, conf->group);
+ st->Get(10, conf->note);
+ st->Get(11, test);
+ conf->passive = test;
+ st->Get(12, conf->password);
+ st->Get(13, conf->phone);
+ st->Get(14, conf->realName);
+ st->Get(15, conf->tariffName);
+ st->Get(16, conf->nextTariff);
+ st->Get(17, conf->corp);
+
+ if (conf->tariffName == "")
+ conf->tariffName = NO_TARIFF_NAME;
+ if (conf->corp == "")
+ conf->corp = NO_CORP_NAME;
+
+ // Services
+ st->Close();
+ st->Prepare("select name from tb_services \
+ where pk_service in \
+ (select fk_service from tb_users_services \
+ where fk_user = ?)");
+ st->Set(1, uid);
+ st->Execute();
+ while (st->Fetch())
+ {
+ std::string name;
+ st->Get(1, name);
+ conf->services.push_back(name);
+ }
+
+ // User data
+ st->Close();
+ st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
+ st->Set(1, uid);
+ st->Execute();
+ while (st->Fetch())
+ {
+ int i;
+ st->Get(2, i);
+ st->Get(1, conf->userdata[i]);
+ }
+
+ // User IPs
+ st->Close();
+ st->Prepare("select ip, mask from tb_allowed_ip \
+ where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ USER_IPS ips;
+ while (st->Fetch())
+ {
+ IP_MASK im;
+ st->Get(1, (int32_t &)im.ip);
+ st->Get(2, (int32_t &)im.mask);
+ ips.Add(im);
+ }
+ conf->ips = ips;
+
+ tr->Commit();
+ }
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message = "") const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+std::string temp = ""; // Composed message for log
+
+try
+ {
+ tr->Start();
+ temp += "Admin \"" + admLogin + "\", ";
+ temp += inet_ntostring(admIP);
+ temp += ": ";
+ temp = temp + message;
+ //----------------------------------------------------------------------------------------
+ // Checking and inserting parameters in params table
+ st->Prepare("select pk_parameter from tb_parameters where name = ?");
+ st->Set(1, paramName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ st->Close();
+ st->Prepare("insert into tb_parameters (name) values (?)");
+ st->Set(1, paramName);
+ st->Execute();
+ }
+ st->Close();
+ //----------------------------------------------------------------------------------------
+ st->Prepare("insert into tb_params_log \
+ (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
+ values ((select pk_user from tb_users \
+ where name = ?), \
+ (select pk_parameter from tb_parameters \
+ where name = ?), \
+ ?, ?, ?, ?)");
+ st->Set(1, login);
+ st->Set(2, paramName);
+ st->Set(3, now);
+ st->Set(4, oldValue);
+ st->Set(5, newValue);
+ st->Set(6, temp);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Set(3, (int32_t)ip);
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double /*cash*/,
+ double /*freeMb*/,
+ const std::string & /*reason*/) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Execute();
+ int32_t id;
+ st->Get(1, id);
+ st->Prepare("insert into tb_sessions_data \
+ (fk_session_log, dir_num, session_upload, \
+ session_download, month_upload, month_download) \
+ values (?, ?, ?, ?, ?, ?)");
+ for(int i = 0; i < DIR_NUM; i++)
+ {
+ st->Set(1, id);
+ st->Set(2, i);
+ st->Set(3, (int64_t)sessionUp[i]);
+ st->Set(4, (int64_t)sessionDown[i]);
+ st->Set(5, (int64_t)up[i]);
+ st->Set(6, (int64_t)down[i]);
+ st->Execute();
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ time_t lastStat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp statTime, now;
+now.Now();
+
+time_t2ts(lastStat, &statTime);
+
+try
+ {
+ tr->Start();
+ std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
+ it = statTree.begin();
+ st->Prepare("insert into tb_detail_stats \
+ (till_time, from_time, fk_user, dir_num, \
+ ip, download, upload, cost) \
+ values (?, ?, (select pk_user from tb_users \
+ where name = ?), \
+ ?, ?, ?, ?, ?)");
+ while (it != statTree.end())
+ {
+ st->Set(1, now);
+ st->Set(2, statTime);
+ st->Set(3, login);
+ st->Set(4, it->first.dir);
+ st->Set(5, (int32_t)it->first.ip);
+ st->Set(6, (int64_t)it->second.down);
+ st->Set(7, (int64_t)it->second.up);
+ st->Set(8, it->second.cash);
+ st->Execute();
+ ++it;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp now;
+IBPP::Date nowDate;
+nowDate.Today();
+now.Now();
+
+if (SaveStat(stat, login, year, month))
+ {
+ return -1;
+ }
+
+try
+ {
+ tr->Start();
+
+ st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Set(3, now);
+ st->Set(4, nowDate);
+
+ st->Execute();
+ int32_t id;
+ st->Get(1, id);
+ st->Close();
+
+ st->Prepare("insert into tb_stats_traffic \
+ (fk_stat, dir_num, upload, download) \
+ values (?, ?, 0, 0)");
+
+ for(int i = 0; i < DIR_NUM; i++)
+ {
+ st->Set(1, id);
+ st->Set(2, i);
+ st->Execute();
+ }
+
+ tr->Commit();
+ }
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Vairous utility methods
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/03/04 12:20:32 $
+ *
+ */
+
+#include <cstdio>
+
+#include "firebird_store.h"
+#include "stg/ibpp.h"
+
+//-----------------------------------------------------------------------------
+time_t ts2time_t(const IBPP::Timestamp & ts)
+{
+ char buf[32];
+ int year, month, day, hour, min, sec;
+ struct tm time_tm;
+
+ memset(&time_tm, 0, sizeof(time_tm));
+ ts.GetDate(year, month, day);
+ ts.GetTime(hour, min, sec);
+ if (year < 1990)
+ return 0;
+ sprintf(buf, "%d-%d-%d %d:%d:%d", year, month, day, hour, min, sec);
+ stg_strptime(buf, "%Y-%m-%d %H:%M:%S", &time_tm);
+
+ return mktime(&time_tm);
+}
+//-----------------------------------------------------------------------------
+void time_t2ts(time_t t, IBPP::Timestamp * ts)
+{
+ struct tm res;
+
+ localtime_r(&t, &res); // Reenterable
+
+ *ts = IBPP::Timestamp(res.tm_year + 1900, res.tm_mon + 1, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);
+}
+//-----------------------------------------------------------------------------
+void ym2date(int year, int month, IBPP::Date * date)
+{
+ date->SetDate(year + 1900, month + 1, 1);
+ date->EndOfMonth();
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+find_package ( MySQLConnector REQUIRED )
+
+set ( CPP_FILES mysql_store.cpp )
+
+add_library ( mod_store_mysql MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_store_mysql crypto logger common MySQL::Connector )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.6 2010/03/25 10:35:55 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_mysql.so
+
+SRCS = ./mysql_store.cpp
+
+STGLIBS = common \
+ crypto \
+ logger
+
+CXXFLAGS += $(MYSQL_CFLAGS)
+LIBS += $(MYSQL_LDFLAGS)
+
+include ../../Makefile.in
+
--- /dev/null
+#include <sys/time.h>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <algorithm>
+
+#include <mysql/errmsg.h>
+
+#include "stg/common.h"
+#include "stg/user_ips.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/blowfish.h"
+#include "stg/plugin_creator.h"
+#include "stg/logger.h"
+#include "mysql_store.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+namespace
+{
+char qbuf[4096];
+
+const int pt_mega = 1024 * 1024;
+const std::string badSyms = "'`";
+const char repSym = '\"';
+const int RepitTimes = 3;
+
+template <typename T>
+int GetInt(const std::string & str, T * val, T defaultVal = T())
+{
+ char *res;
+
+ *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetDouble(const std::string & str, double * val, double defaultVal)
+{
+ char *res;
+
+ *val = strtod(str.c_str(), &res);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetTime(const std::string & str, time_t * val, time_t defaultVal)
+{
+ char *res;
+
+ *val = strtol(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+std::string ReplaceStr(std::string source, const std::string & symlist, const char chgsym)
+{
+ std::string::size_type pos=0;
+
+ while( (pos = source.find_first_of(symlist,pos)) != std::string::npos)
+ source.replace(pos, 1,1, chgsym);
+
+ return source;
+}
+
+int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
+{
+ char *res;
+
+ *val = strtoull(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+PLUGIN_CREATOR<MYSQL_STORE> msc;
+}
+
+extern "C" STORE * GetStore();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STORE * GetStore()
+{
+return msc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
+ : settings(NULL)
+{
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseParam(const std::vector<PARAM_VALUE> & moduleParams,
+ const std::string & name, std::string & result)
+{
+PARAM_VALUE pv;
+pv.param = name;
+std::vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+ {
+ errorStr = "Parameter \'" + name + "\' not found.";
+ return -1;
+ }
+
+result = pvi->value[0];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+if (ParseParam(s.moduleParams, "user", dbUser) < 0 &&
+ ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "password", dbPass) < 0 &&
+ ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "database", dbName) < 0 &&
+ ParseParam(s.moduleParams, "dbname", dbName) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "server", dbHost) < 0 &&
+ ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+MYSQL_STORE::MYSQL_STORE()
+ : version("mysql_store v.0.67"),
+ schemaVersion(0),
+ logger(GetPluginLogger(GetStgLogger(), "store_mysql"))
+{
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
+{
+ int ret;
+
+ if( (ret = mysql_query(sock,sQuery)) )
+ {
+ for(int i=0; i<RepitTimes; i++)
+ {
+ if( (ret = mysql_query(sock,sQuery)) )
+ ;//need to send error result
+ else
+ return 0;
+ }
+ }
+
+ return ret;
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+MYSQL mysql;
+mysql_init(&mysql);
+if (ret)
+ errorStr = storeSettings.GetStrError();
+else
+{
+ if(storeSettings.GetDBPassword().length() == 0)
+ {
+ errorStr = "Database password must be not empty. Please read Manual.";
+ return -1;
+ }
+ MYSQL * sock;
+ if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(&mysql);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ errorStr = "Couldn't select database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ ret = CheckAllTables(sock);
+ }
+ }
+ else
+ {
+ ret = CheckAllTables(sock);
+ }
+ if (!ret)
+ {
+ logger("MYSQL_STORE: Current DB schema version: %d", schemaVersion);
+ MakeUpdates(sock);
+ }
+ mysql_close(sock);
+ }
+}
+return ret;
+}
+//-----------------------------------------------------------------------------
+bool MYSQL_STORE::IsTablePresent(const std::string & str,MYSQL * sock)
+{
+MYSQL_RES* result;
+
+if (!(result=mysql_list_tables(sock,str.c_str() )))
+{
+ errorStr = "Couldn't get tables list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+my_ulonglong num_rows = mysql_num_rows(result);
+
+if(result)
+ mysql_free_result(result);
+
+return num_rows == 1;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::CheckAllTables(MYSQL * sock)
+{
+//info-------------------------------------------------------------------------
+if(!IsTablePresent("info",sock))
+{
+ sprintf(qbuf,"CREATE TABLE info (version INTEGER NOT NULL)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create info table With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ sprintf(qbuf,"INSERT INTO info SET version=0");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't write default version. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ schemaVersion = 0;
+}
+else
+{
+ std::vector<std::string> info;
+ if (GetAllParams(&info, "info", "version"))
+ schemaVersion = 0;
+ else
+ {
+ if (info.empty())
+ schemaVersion = 0;
+ else
+ GetInt(info.front(), &schemaVersion, 0);
+ }
+}
+//admins-----------------------------------------------------------------------
+if(!IsTablePresent("admins",sock))
+{
+ sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
+ "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
+ "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
+ "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
+ "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
+ "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
+ "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create default admin. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//tariffs-----------------------------------------------------------------------
+std::string param, res;
+if(!IsTablePresent("tariffs",sock))
+{
+ res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d INT DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
+ res += param;
+
+ strprintf(¶m, " NoDiscount%d INT DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d INT DEFAULT 0,", i);
+ res += param;
+ }
+
+ res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
+ "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
+ "period VARCHAR(32) NOT NULL DEFAULT 'month',"
+ "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow',"
+ "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create tariffs table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO tariffs SET name='tariff',";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " NoDiscount%d=1,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " Time%d='0:0-0:0',", i);
+ res += param;
+
+ if(i != 0 && i != 1)
+ {
+ strprintf(¶m, " SinglePrice%d=0,", i);
+ res += param;
+ }
+
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayB%d=0.0,", i);
+ res += param;
+ }
+
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightB%d=0.0,", i);
+ res += param;
+ }
+ }
+
+ res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
+ "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
+ "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
+ "change_policy='allow', change_policy_timeout=0";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default tariff. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ sprintf(qbuf,"UPDATE info SET version=1");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't write default version. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ schemaVersion = 2;
+}
+
+//users-----------------------------------------------------------------------
+if(!IsTablePresent("users",sock))
+{
+ res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
+ "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
+ "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d VARCHAR(254) NOT NULL,", i);
+ res += param;
+ }
+
+ param = " CreditExpire INT(11) DEFAULT 0,";
+ res += param;
+
+ strprintf(¶m, " IP VARCHAR(254) DEFAULT '*',");
+ res += param;
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+ }
+
+ strprintf(¶m, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
+ "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
+ "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
+ " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
+ res += param;
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create users table list With error:\n";
+ errorStr += mysql_error(sock);
+ errorStr += "\n\n" + res;
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
+ "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
+ "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
+ "Phone='', RealName='',Tariff='tariff',TariffChange='',NAS='',";
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d='',", i);
+ res += param;
+ }
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d=0,", i);
+ res += param;
+ }
+
+ res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
+ "LastCashAddTime=0, PassiveTime=0";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default user. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+/*
+//logs-----------------------------------------------------------------------
+if(!IsTablePresent("logs"))
+{
+ sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
+
+ if(MysqlQuery(qbuf))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ return -1;
+ }
+}
+*/
+//messages---------------------------------------------------------------------
+if(!IsTablePresent("messages",sock))
+{
+ sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
+ "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
+ "stgRepeat INT, repeatPeriod INT, text TEXT)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create messages table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//month_stat-------------------------------------------------------------------
+if(!IsTablePresent("stat",sock))
+{
+ res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d BIGINT,", i);
+ res += param;
+
+ strprintf(¶m, " D%d BIGINT,", i);
+ res += param;
+ }
+
+ res += " cash DOUBLE, INDEX (login))";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create stat table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MakeUpdates(MYSQL * sock)
+{
+if (schemaVersion < 1)
+ {
+ if (MysqlQuery("ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month'", sock))
+ {
+ errorStr = "Couldn't update tariffs table to version 1. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ if (MysqlQuery("UPDATE info SET version = 1", sock))
+ {
+ errorStr = "Couldn't update DB schema version to 1. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ schemaVersion = 1;
+ logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+ }
+
+if (schemaVersion < 2)
+ {
+ if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) ||
+ MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock))
+ {
+ errorStr = "Couldn't update tariffs table to version 2. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ if (MysqlQuery("UPDATE info SET version = 2", sock))
+ {
+ errorStr = "Couldn't update DB schema version to 2. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ schemaVersion = 2;
+ logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList,
+ const std::string & table, const std::string & name) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock=NULL;
+my_ulonglong num, i;
+
+ParamList->clear();
+
+sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetAllParams Query for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetAllParams Results for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ return -1;
+}
+
+num = mysql_num_rows(res);
+
+for(i = 0; i < num; i++)
+{
+ row = mysql_fetch_row(res);
+ ParamList->push_back(row[0]);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+if(GetAllParams(usersList, "users", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+if(GetAllParams(adminsList, "admins", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+if(GetAllParams(tariffsList, "tariffs", "name"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddUser(const std::string & login) const
+{
+std::string query = "INSERT INTO users SET login='" + login + "',Note='',NAS=''";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ query += ",Userdata" + x2str(i) + "=''";
+
+if(MysqlSetQuery(query.c_str()))
+{
+ errorStr = "Couldn't add user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelUser(const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+std::string query;
+
+query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
+ AlwaysOnline, Tariff, Address, Phone, Email, Note, \
+ RealName, StgGroup, Credit, TariffChange, ";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+{
+ sprintf(qbuf, "Userdata%d, ", i);
+ query += qbuf;
+}
+
+query += "CreditExpire, IP FROM users WHERE login='";
+query += login + "' LIMIT 1";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str(),sock))
+{
+ errorStr = "Couldn't restore Tariff(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (mysql_num_rows(res) != 1)
+{
+ errorStr = "User not found";
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+conf->password = row[1];
+
+if (conf->password.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' password is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[2],&conf->passive) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &conf->disabled) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &conf->disabledDetailStat) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &conf->alwaysOnline) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->tariffName = row[6];
+
+if (conf->tariffName.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' tariff is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->address = row[7];
+conf->phone = row[8];
+conf->email = row[9];
+conf->note = row[10];
+conf->realName = row[11];
+conf->group = row[12];
+
+if (GetDouble(row[13], &conf->credit, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->nextTariff = row[14];
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ conf->userdata[i] = row[15+i];
+ }
+
+GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
+
+std::string ipStr = row[16+USERDATA_NUM];
+USER_IPS i;
+try
+ {
+ i = StrToIPS(ipStr);
+ }
+catch (const std::string & s)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+ mysql_close(sock);
+ return -1;
+ }
+conf->ips = i;
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+std::string query;
+
+query = "SELECT ";
+
+for (int i = 0; i < DIR_NUM; i++)
+{
+ sprintf(qbuf, "D%d, U%d, ", i, i);
+ query += qbuf;
+}
+
+query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
+ FROM users WHERE login = '";
+query += login + "'";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str() ,sock))
+{
+ errorStr = "Couldn't restore UserStat(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore UserStat(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+unsigned int startPos=0;
+
+char s[22];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ uint64_t traff;
+ sprintf(s, "D%d", i);
+ if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->monthDown[i] = traff;
+
+ sprintf(s, "U%d", i);
+ if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->monthUp[i] = traff;
+ }//for
+
+startPos += (2*DIR_NUM);
+
+if (GetDouble(row[startPos], &stat->cash, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const std::string & login) const
+{
+std::string param;
+std::string res;
+
+strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
+ "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
+ "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ",
+ conf.password.c_str(),
+ conf.passive,
+ conf.disabled,
+ conf.disabledDetailStat,
+ conf.alwaysOnline,
+ conf.tariffName.c_str(),
+ (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
+ conf.credit,
+ conf.nextTariff.c_str()
+ );
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d='%s',", i,
+ (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
+ res += param;
+ }
+
+strprintf(¶m, " CreditExpire=%d,", conf.creditExpire);
+res += param;
+
+std::ostringstream ipStr;
+ipStr << conf.ips;
+
+strprintf(¶m, " IP='%s'", ipStr.str().c_str());
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user conf:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const std::string & login) const
+{
+std::string param;
+std::string res;
+
+res = "UPDATE users SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=%lld,", i, stat.monthDown[i]);
+ res += param;
+
+ strprintf(¶m, " U%d=%lld,", i, stat.monthUp[i]);
+ res += param;
+ }
+
+strprintf(¶m, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
+ " PassiveTime=%d, LastActivityTime=%d",
+ stat.cash,
+ stat.freeMb,
+ stat.lastCashAdd,
+ stat.lastCashAddTime,
+ stat.passiveTime,
+ stat.lastActivityTime
+ );
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user stat:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteLogString(const std::string & str, const std::string & login) const
+{
+std::string res, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+if (!(sock=MysqlConnect())){
+ errorStr = "Couldn't connect to Server";
+ return -1;
+}
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+my_ulonglong num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
+
+std::string send;
+
+strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
+
+if(MysqlQuery(send.c_str(),sock))
+{
+ errorStr = "Couldn't write log string:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+mysql_close(sock);
+return 0;
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const
+{
+std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+ + paramName + "\' parameter changed from \'" + oldValue +
+ "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+std::string logStr = "Connect, " + inet_ntostring(ip);
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double /*freeMb*/,
+ const std::string & /*reason*/) const
+{
+std::string logStr = "Disconnect, ";
+std::ostringstream sssu;
+std::ostringstream sssd;
+std::ostringstream ssmu;
+std::ostringstream ssmd;
+std::ostringstream sscash;
+
+ssmu << up;
+ssmd << down;
+
+sssu << sessionUp;
+sssd << sessionDown;
+
+sscash << cash;
+
+logStr += " session upload: \'";
+logStr += sssu.str();
+logStr += "\' session download: \'";
+logStr += sssd.str();
+logStr += "\' month upload: \'";
+logStr += ssmu.str();
+logStr += "\' month download: \'";
+logStr += ssmd.str();
+logStr += "\' cash: \'";
+logStr += sscash.str();
+logStr += "\'";
+
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
+ const std::string & login) const
+{
+std::string param, res;
+
+strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,",
+ login.c_str(), month+1, year+1900);
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d=%lld,", i, stat.monthUp[i]);
+ res += param;
+
+ strprintf(¶m, " D%d=%lld,", i, stat.monthDown[i]);
+ res += param;
+ }
+
+strprintf(¶m, " cash=%f", stat.cash);
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't SaveMonthStat:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::AddAdmin(const std::string & login) const
+{
+sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::DelAdmin(const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+char pass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+
+memset(pass, 0, sizeof(pass));
+memset(adminPass, 0, sizeof(adminPass));
+
+BLOWFISH_CTX ctx;
+InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
+ }
+
+pass[ADM_PASSWD_LEN - 1] = 0;
+Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
+ "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
+ "WHERE login='%s' LIMIT 1",
+ passwordE,
+ ac.priv.userConf,
+ ac.priv.userPasswd,
+ ac.priv.userStat,
+ ac.priv.userCash,
+ ac.priv.userAddDel,
+ ac.priv.tariffChg,
+ ac.priv.adminChg,
+ ac.login.c_str()
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't save admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
+{
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2*ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+memset(password, 0, sizeof(password));
+
+std::string p;
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if ( mysql_num_rows(res) == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Couldn't restore admin as couldn't found him in table.\n";
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+p = row[1];
+
+if(p.length() == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Error in parameter password";
+ mysql_close(sock);
+ return -1;
+}
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+ {
+ Decode21(pass, passwordE);
+ InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ DecryptBlock(password + 8*i, pass + 8*i, &ctx);
+ }
+ }
+else
+ {
+ password[0] = 0;
+ }
+
+ac->password = password;
+
+uint16_t a;
+
+if (GetInt(row[2], &a) == 0)
+ ac->priv.userConf = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgConf";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &a) == 0)
+ ac->priv.userPasswd = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgPassword";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &a) == 0)
+ ac->priv.userStat = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgStat";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &a) == 0)
+ ac->priv.userCash = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgCash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[6], &a) == 0)
+ ac->priv.userAddDel = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter UsrAddDel";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[7], &a) == 0)
+ ac->priv.tariffChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgTariff";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[8], &a) == 0)
+ ac->priv.adminChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgAdmin";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddTariff(const std::string & name) const
+{
+sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add tariff:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelTariff(const std::string & name) const
+{
+sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete tariff: ";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+std::string str;
+td->tariffConf.name = tariffName;
+
+row = mysql_fetch_row(res);
+
+std::string param;
+for (int i = 0; i<DIR_NUM; i++)
+ {
+ strprintf(¶m, "Time%d", i);
+ str = row[6+i*8];
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ ParseTariffTimeStr(str.c_str(),
+ td->dirPrice[i].hDay,
+ td->dirPrice[i].mDay,
+ td->dirPrice[i].hNight,
+ td->dirPrice[i].mNight);
+
+ strprintf(¶m, "PriceDayA%d", i);
+ if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayA /= (1024*1024);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayB /= (1024*1024);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightA /= (1024*1024);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightB /= (1024*1024);
+
+ strprintf(¶m, "Threshold%d", i);
+ if (GetInt(row[5+i*8], &td->dirPrice[i].threshold) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "SinglePrice%d", i);
+ if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "NoDiscount%d", i);
+ if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ }//main for
+
+if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+ mysql_close(sock);
+ return -1;
+ }
+
+ str = row[4+8*DIR_NUM];
+ param = "TraffType";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+td->tariffConf.traffType = TARIFF::StringToTraffType(str);
+
+if (schemaVersion > 0)
+{
+ str = row[5+8*DIR_NUM];
+ param = "Period";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ td->tariffConf.period = TARIFF::StringToPeriod(str);
+ }
+else
+ {
+ td->tariffConf.period = TARIFF::MONTH;
+ }
+
+if (schemaVersion > 1)
+ {
+ str = row[6+8*DIR_NUM];
+ param = "ChangePolicy";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
+
+ str = row[7+8*DIR_NUM];
+ param = "ChangePolicyTimeout";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ td->tariffConf.changePolicyTimeout = readTime(str);
+ }
+else
+ {
+ td->tariffConf.changePolicy = TARIFF::ALLOW;
+ td->tariffConf.changePolicyTimeout = 0;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
+{
+std::string param;
+
+std::string res="UPDATE tariffs SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d=%f,", i,
+ td.dirPrice[i].priceDayA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d=%f,", i,
+ td.dirPrice[i].priceDayB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d=%f,", i,
+ td.dirPrice[i].priceNightA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d=%f,", i,
+ td.dirPrice[i].priceNightB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=%d,", i,
+ td.dirPrice[i].threshold);
+ res += param;
+
+ std::string s;
+ strprintf(¶m, " Time%d", i);
+
+ strprintf(&s, "%0d:%0d-%0d:%0d",
+ td.dirPrice[i].hDay,
+ td.dirPrice[i].mDay,
+ td.dirPrice[i].hNight,
+ td.dirPrice[i].mNight);
+
+ res += (param + "='" + s + "',");
+
+ strprintf(¶m, " NoDiscount%d=%d,", i,
+ td.dirPrice[i].noDiscount);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d=%d,", i,
+ td.dirPrice[i].singlePrice);
+ res += param;
+ }
+
+strprintf(¶m, " PassiveCost=%f,", td.tariffConf.passiveCost);
+res += param;
+
+strprintf(¶m, " Fee=%f,", td.tariffConf.fee);
+res += param;
+
+strprintf(¶m, " Free=%f,", td.tariffConf.free);
+res += param;
+
+res += " TraffType='" + TARIFF::TraffTypeToString(td.tariffConf.traffType) + "'";
+
+if (schemaVersion > 0)
+ res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'";
+
+if (schemaVersion > 1)
+ res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"\
+ ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'";
+
+strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save tariff:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ time_t lastStat,
+ const std::string & login) const
+{
+std::string res, stTime, endTime, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+ {
+ t -= 3600 * 24;
+ lt = localtime(&t);
+ }
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+
+if (!(sock=MysqlConnect())){
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+my_ulonglong num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
+ "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
+ "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
+ "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
+strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
+
+strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
+ "day=%d,startTime='%s',endTime='%s',",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(),
+ lt->tm_mday,
+ stTime.c_str(),
+ endTime.c_str()
+ );
+
+std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+stIter = statTree.begin();
+
+while (stIter != statTree.end())
+ {
+ strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.dir,
+ stIter->second.down,
+ stIter->second.up,
+ stIter->second.cash
+ );
+
+ if( MysqlQuery((res+tempStr).c_str(),sock) )
+ {
+ errorStr = "Couldn't insert data in WriteDetailedStat:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ result=mysql_store_result(sock);
+ if(result)
+ mysql_free_result(result);
+
+ ++stIter;
+ }
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
+{
+struct timeval tv;
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(tv.tv_usec);
+
+sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld",
+ login.c_str(),
+ static_cast<long long>(msg->header.id)
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
+{
+std::string res;
+
+strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
+ "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
+ "WHERE login='%s' AND id=%lld LIMIT 1",
+ msg.header.type,
+ msg.header.lastSendTime,
+ msg.header.creationTime,
+ msg.header.showTime,
+ msg.header.repeat,
+ msg.header.repeatPeriod,
+ (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
+ login.c_str(),
+ msg.header.id
+ );
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't edit message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
+ login.c_str(), static_cast<unsigned long long>(id));
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+if(row[2]&&str2x(row[2], msg->header.type))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[3] && str2x(row[3], msg->header.lastSendTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[4] && str2x(row[4], msg->header.creationTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[5] && str2x(row[5], msg->header.showTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[6] && str2x(row[6], msg->header.repeat))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[7] && str2x(row[7], msg->header.repeatPeriod))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+msg->header.id = id;
+msg->text = row[8];
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelMessage(uint64_t id, const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+ login.c_str(), static_cast<long long>(id));
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete Message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int i;
+my_ulonglong num_rows = mysql_num_rows(res);
+uint64_t id = 0;
+
+for (i = 0; i < num_rows; i++)
+{
+ row = mysql_fetch_row(res);
+ if (str2x(row[1], id))
+ continue;
+
+ STG_MSG_HDR hdr;
+ if (row[2])
+ if(str2x(row[2], hdr.type))
+ continue;
+
+ if (row[3])
+ if(str2x(row[3], hdr.lastSendTime))
+ continue;
+
+ if (row[4])
+ if(str2x(row[4], hdr.creationTime))
+ continue;
+
+ if (row[5])
+ if(str2x(row[5], hdr.showTime))
+ continue;
+
+ if (row[6])
+ if(str2x(row[6], hdr.repeat))
+ continue;
+
+ if (row[7])
+ if(str2x(row[7], hdr.repeatPeriod))
+ continue;
+
+ hdr.id = id;
+ hdrsList->push_back(hdr);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
+
+ MYSQL * sock;
+ int ret=MysqlGetQuery(Query,sock);
+ mysql_close(sock);
+ return ret;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
+ if (!(sock=MysqlConnect())) {
+ return -1;
+ }
+ return MysqlQuery(Query,sock);
+}
+//-----------------------------------------------------------------------------
+MYSQL * MYSQL_STORE::MysqlConnect() const {
+ MYSQL * sock;
+ if ( !(sock=mysql_init(NULL)) ){
+ errorStr= "mysql init susck\n";
+ return NULL;
+ }
+ if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(sock);
+ return NULL;
+ }
+ else{
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
+ errorStr = "Database lost !\n";
+ return NULL;
+ }
+ }
+ return sock;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.5 $
+ $Date: 2010/10/07 19:45:52 $
+ */
+
+
+#ifndef MYSQL_STORE_H
+#define MYSQL_STORE_H
+
+#include <mysql/mysql.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "stg/module_settings.h"
+#include "stg/store.h"
+#include "stg/user_traff.h"
+#include "stg/logger.h"
+
+//-----------------------------------------------------------------------------
+class MYSQL_STORE_SETTINGS
+{
+public:
+ MYSQL_STORE_SETTINGS();
+ virtual ~MYSQL_STORE_SETTINGS() {}
+ virtual int ParseSettings(const MODULE_SETTINGS & s);
+ virtual const std::string & GetStrError() const { return errorStr; }
+
+ const std::string & GetDBUser() const { return dbUser; }
+ const std::string & GetDBPassword() const { return dbPass; }
+ const std::string & GetDBHost() const { return dbHost; }
+ const std::string & GetDBName() const { return dbName; }
+
+private:
+ MYSQL_STORE_SETTINGS(const MYSQL_STORE_SETTINGS & rvalue);
+ MYSQL_STORE_SETTINGS & operator=(const MYSQL_STORE_SETTINGS & rvalue);
+
+ const MODULE_SETTINGS * settings;
+
+ int ParseParam(const std::vector<PARAM_VALUE> & moduleParams,
+ const std::string & name, std::string & result);
+
+ std::string errorStr;
+
+ std::string dbUser;
+ std::string dbPass;
+ std::string dbName;
+ std::string dbHost;
+};
+//-----------------------------------------------------------------------------
+class MYSQL_STORE: public STORE
+{
+public:
+ MYSQL_STORE();
+ virtual ~MYSQL_STORE() {}
+ virtual const std::string & GetStrError() const { return errorStr; }
+
+ //User
+ virtual int GetUsersList(std::vector<std::string> * usersList) const;
+ virtual int AddUser(const std::string & login) const;
+ virtual int DelUser(const std::string & login) const;
+ virtual int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ virtual int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+ virtual int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+ virtual int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message = "") const;
+ virtual int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ virtual int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+
+ virtual int WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ virtual int AddMessage(STG_MSG * msg, const std::string & login) const;
+ virtual int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ virtual int DelMessage(uint64_t id, const std::string & login) const;
+ virtual int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ //Admin
+ virtual int GetAdminsList(std::vector<std::string> * adminsList) const;
+ virtual int AddAdmin(const std::string & login) const;
+ virtual int DelAdmin(const std::string & login) const;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const;
+
+ //Tariff
+ virtual int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ virtual int AddTariff(const std::string & name) const;
+ virtual int DelTariff(const std::string & name) const;
+ virtual int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ virtual int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ //Corparation
+ virtual int GetCorpsList(std::vector<std::string> *) const {return 0;}
+ virtual int SaveCorp(const CORP_CONF &) const {return 0;}
+ virtual int RestoreCorp(CORP_CONF *, const std::string &) const {return 0;}
+ virtual int AddCorp(const std::string &) const {return 0;}
+ virtual int DelCorp(const std::string &) const {return 0;}
+
+ // Services
+ virtual int GetServicesList(std::vector<std::string> *) const {return 0;}
+ virtual int SaveService(const SERVICE_CONF &) const {return 0;}
+ virtual int RestoreService(SERVICE_CONF *, const std::string &) const {return 0;}
+ virtual int AddService(const std::string &) const {return 0;}
+ virtual int DelService(const std::string &) const {return 0;}
+
+ virtual void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ virtual int ParseSettings();
+ virtual const std::string & GetVersion() const { return version; }
+
+private:
+ MYSQL_STORE(const MYSQL_STORE & rvalue);
+ MYSQL_STORE & operator=(const MYSQL_STORE & rvalue);
+
+ virtual int WriteLogString(const std::string & str, const std::string & login) const;
+ int GetAllParams(std::vector<std::string> * ParamList, const std::string & table, const std::string & name) const;
+ int CheckAllTables(MYSQL * sock);
+ int MakeUpdates(MYSQL * sock);
+ bool IsTablePresent(const std::string & str,MYSQL * sock);
+ mutable std::string errorStr;
+ int MysqlQuery(const char* sQuery,MYSQL * sock) const;
+ int MysqlGetQuery(const char * Query,MYSQL * & sock) const;
+ int MysqlSetQuery(const char * Query) const;
+ MYSQL * MysqlConnect() const ;
+ std::string version;
+ MYSQL_STORE_SETTINGS storeSettings;
+ MODULE_SETTINGS settings;
+ int schemaVersion;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+find_package ( PostgreSQL REQUIRED )
+
+set ( CPP_FILES postgresql_store.cpp
+ postgresql_store_admins.cpp
+ postgresql_store_corporations.cpp
+ postgresql_store_messages.cpp
+ postgresql_store_services.cpp
+ postgresql_store_tariffs.cpp
+ postgresql_store_users.cpp
+ postgresql_store_utils.cpp )
+
+add_library ( mod_store_postgresql MODULE ${CPP_FILES} )
+
+target_link_libraries ( mod_store_postgresql crypto logger common PostgreSQL::PostgreSQL )
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2010/04/26 12:44:42 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_postgresql.so
+
+SRCS = ./postgresql_store.cpp \
+ ./postgresql_store_admins.cpp \
+ ./postgresql_store_corporations.cpp \
+ ./postgresql_store_messages.cpp \
+ ./postgresql_store_services.cpp \
+ ./postgresql_store_tariffs.cpp \
+ ./postgresql_store_users.cpp \
+ ./postgresql_store_utils.cpp
+
+STGLIBS = common \
+ crypto \
+ logger
+
+CXXFLAGS += $(PG_CFLAGS)
+LDFLAGS += $(PG_LDFLAGS)
+
+LIBS += -lpq
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * This file contains a realization of a base postgresql-storage plugin class
+ *
+ * v. 1.3
+ * FreeMb logging on disconnects added
+ *
+ * v. 1.2
+ * Reconnection on faults added
+ *
+ * v. 1.1
+ * tb_stats removed
+ *
+ * v. 1.0
+ * Initial implementation
+ *
+ * $Revision: 1.5 $
+ * $Date: 2010/01/06 10:43:48 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "postgresql_store_utils.h"
+#include "postgresql_store.h"
+
+#include "stg/module_settings.h"
+#include "stg/plugin_creator.h"
+
+#include <string>
+#include <vector>
+
+#include <libpq-fe.h>
+
+namespace
+{
+PLUGIN_CREATOR<POSTGRESQL_STORE> pgsc;
+}
+
+extern "C" STORE * GetStore();
+
+//-----------------------------------------------------------------------------
+STORE * GetStore()
+{
+return pgsc.GetPlugin();
+}
+
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::POSTGRESQL_STORE()
+ : versionString("postgresql_store v.1.3"),
+ server("localhost"),
+ database("stargazer"),
+ user("stg"),
+ password("123456"),
+ clientEncoding("KOI8"),
+ version(0),
+ retries(3),
+ connection(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "store_postgresql"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::~POSTGRESQL_STORE()
+{
+if (connection)
+ {
+ PQfinish(connection);
+ }
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::ParseSettings()
+{
+std::vector<PARAM_VALUE>::iterator i;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+ {
+ if (i->value.empty())
+ continue;
+ std::string s = ToLower(i->param);
+ if (s == "server")
+ {
+ server = i->value.front();
+ }
+ if (s == "database")
+ {
+ database = i->value.front();
+ }
+ if (s == "user")
+ {
+ user = i->value.front();
+ }
+ if (s == "password")
+ {
+ password = i->value.front();
+ }
+ if (s == "retries")
+ {
+ if (str2x(i->value.front(), retries))
+ {
+ strError = "Invalid 'retries' value";
+ printfd(__FILE__, "POSTGRESQL_STORE::ParseSettings(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+ }
+
+clientEncoding = "KOI8";
+
+return Connect();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Connect()
+{
+std::string params;
+params = "host=" + server + " "
+ + "dbname=" + database + " "
+ + "user=" + user + " "
+ + "password=" + password;
+
+connection = PQconnectdb(params.c_str());
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+ // Will try to connect later
+ return 0;
+ }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Reset() const
+{
+for (int i = 0; i < retries && PQstatus(connection) != CONNECTION_OK; ++i)
+ {
+ struct timespec ts = {1, 0};
+ nanosleep(&ts, NULL);
+ PQreset(connection);
+ }
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::CheckVersion() const
+{
+
+if (StartTransaction())
+ {
+ strError = "Failed to start transaction";
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
+ RollbackTransaction();
+ return -1;
+ }
+
+if (str2x(PQgetvalue(result, 0, 0), version))
+ {
+ strError = "Invalid DB version";
+ PQclear(result);
+ RollbackTransaction();
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+if (version < DB_MIN_VERSION)
+ {
+ strError = "DB version too old";
+ RollbackTransaction();
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+if (version < 6)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
+ }
+
+if (CommitTransaction())
+ {
+ strError = "Failed to commit transaction";
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+logger("POSTGRESQL_STORE: Current DB schema version: %d", version);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * PostgreSQL storage class definition
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/01/19 11:06:53 $
+ *
+ */
+
+#ifndef POSTGRESQL_STORE_H
+#define POSTGRESQL_STORE_H
+
+#include <libpq-fe.h>
+
+#include <string>
+#include <vector>
+
+#include "stg/store.h"
+#include "stg/logger.h"
+
+// Minimal DB version is 5
+// Recommended DB version is 6 (support FreeMb logging on disconnects)
+#define DB_MIN_VERSION 5
+
+class POSTGRESQL_STORE : public STORE {
+public:
+ POSTGRESQL_STORE();
+ virtual ~POSTGRESQL_STORE();
+
+ // Users
+ int GetUsersList(std::vector<std::string> * usersList) const;
+ int AddUser(const std::string & login) const;
+ int DelUser(const std::string & login) const;
+ int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+ int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+ int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const;
+ int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+ int WriteDetailedStat(const TRAFF_STAT & statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ // Messages
+ int AddMessage(STG_MSG * msg, const std::string & login) const;
+ int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ int DelMessage(uint64_t id, const std::string & login) const;
+ int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+
+ // Stats
+ int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ // Admins
+ int GetAdminsList(std::vector<std::string> * adminsList) const;
+ int SaveAdmin(const ADMIN_CONF & ac) const;
+ int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ int AddAdmin(const std::string & login) const;
+ int DelAdmin(const std::string & login) const;
+
+ // Tariffs
+ int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ int AddTariff(const std::string & name) const;
+ int DelTariff(const std::string & name) const;
+ int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ // Corporations
+ int GetCorpsList(std::vector<std::string> * corpsList) const;
+ int SaveCorp(const CORP_CONF & cc) const;
+ int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
+ int AddCorp(const std::string & name) const;
+ int DelCorp(const std::string & name) const;
+
+ // Services
+ int GetServicesList(std::vector<std::string> * servicesList) const;
+ int SaveService(const SERVICE_CONF & sc) const;
+ int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
+ int AddService(const std::string & name) const;
+ int DelService(const std::string & name) const;
+
+ // Settings
+ inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ inline const std::string & GetStrError() const { return strError; }
+ inline const std::string & GetVersion() const { return versionString; }
+private:
+ POSTGRESQL_STORE(const POSTGRESQL_STORE & rvalue);
+ POSTGRESQL_STORE & operator=(const POSTGRESQL_STORE & rvalue);
+
+ int StartTransaction() const;
+ int CommitTransaction() const;
+ int RollbackTransaction() const;
+
+ int EscapeString(std::string & value) const;
+
+ int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
+
+ int SaveUserServices(uint32_t uid, const std::vector<std::string> & services) const;
+ int SaveUserData(uint32_t uid, const std::vector<std::string> & data) const;
+ int SaveUserIPs(uint32_t uid, const USER_IPS & ips) const;
+
+ void MakeDate(std::string & date, int year = 0, int month = 0) const;
+
+ int Connect();
+ int Reset() const;
+ int CheckVersion() const;
+
+ std::string versionString;
+ mutable std::string strError;
+ std::string server;
+ std::string database;
+ std::string user;
+ std::string password;
+ std::string clientEncoding;
+ MODULE_SETTINGS settings;
+ mutable pthread_mutex_t mutex;
+ mutable int version;
+ int retries;
+
+ PGconn * connection;
+
+ PLUGIN_LOGGER logger;
+};
+
+#endif //POSTGRESQL_STORE_H
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Administrators manipulation methods
+ *
+ * $Revision: 1.3 $
+ * $Date: 2010/11/08 10:10:24 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "stg/locker.h"
+#include "stg/admin_conf.h"
+#include "stg/blowfish.h"
+#include "postgresql_store.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT login FROM tb_admins WHERE login <> '@stargazer'");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ adminsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+std::string pass = encodedPass;
+std::string login = ac.login;
+
+if (EscapeString(pass))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape password'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(login))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_admins SET "
+ << "passwd = '" << pass << "', "
+ << "chg_conf = " << ac.priv.userConf << ", "
+ << "chg_password = " << ac.priv.userPasswd << ", "
+ << "chg_stat = " << ac.priv.userStat << ", "
+ << "chg_cash = " << ac.priv.userCash << ", "
+ << "usr_add_del = " << ac.priv.userAddDel << ", "
+ << "chg_tariff = " << ac.priv.tariffChg << ", "
+ << "chg_admin = " << ac.priv.adminChg << " "
+ << "WHERE login = '" << login << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT login, passwd, \
+ chg_conf, chg_password, chg_stat, \
+ chg_cash, usr_add_del, chg_tariff, \
+ chg_admin, chg_service, chg_corporation \
+ FROM tb_admins \
+ WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch admin's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ac->login = PQgetvalue(result, 0, 0);
+ac->password = PQgetvalue(result, 0, 1);
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 2) << " "
+ << PQgetvalue(result, 0, 3) << " "
+ << PQgetvalue(result, 0, 4) << " "
+ << PQgetvalue(result, 0, 5) << " "
+ << PQgetvalue(result, 0, 6) << " "
+ << PQgetvalue(result, 0, 7) << " "
+ << PQgetvalue(result, 0, 8) << " "
+ << PQgetvalue(result, 0, 9) << " "
+ << PQgetvalue(result, 0, 10);
+
+PQclear(result);
+
+tuple >> ac->priv.userConf
+ >> ac->priv.userPasswd
+ >> ac->priv.userStat
+ >> ac->priv.userCash
+ >> ac->priv.userAddDel
+ >> ac->priv.tariffChg
+ >> ac->priv.adminChg;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to commit transacion'\n");
+ return -1;
+ }
+
+if (ac->password == "")
+ {
+ return 0;
+ }
+
+Decode21(cryptedPass, ac->password.c_str());
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ {
+ DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+ }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "INSERT INTO tb_admins \
+ (login, passwd, \
+ chg_conf, chg_password, chg_stat, \
+ chg_cash, usr_add_del, chg_tariff, \
+ chg_admin, chg_service, chg_corporation) \
+ VALUES "
+ << "('" << elogin << "', \
+ '', 0, 0, 0, 0, 0, 0, 0, 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_admins WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Corporations manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:39 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg/locker.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_corporations");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ corpsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveCorp(const CORP_CONF & cc) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = cc.name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "UPDATE tb_corporations SET "
+ << "cash = " << cc.cash
+ << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreCorp(CORP_CONF * cc, const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT cash FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch corp's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> cc->cash;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "INSERT INTO tb_corporations \
+ (name, cash) \
+ VALUES \
+ ('" << ename << "', 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ * Messages manipualtion methods
+ *
+ * $Revision: 1.6 $
+ * $Date: 2009/07/15 11:19:42 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "stg/common.h"
+#include "postgresql_store.h"
+#include "stg/locker.h"
+#include "stg/message.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+std::string etext = msg->text;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etext))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape message text'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT sp_add_message("
+ << "'" << elogin << "', "
+ << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually
+ << "CAST(" << msg->header.type << " AS SMALLINT), "
+ << "CAST('" << formatTime(msg->header.lastSendTime) << "' AS TIMESTAMP), "
+ << "CAST('" << formatTime(msg->header.creationTime) << "' AS TIMESTAMP), "
+ << msg->header.showTime << ", "
+ << "CAST(" << msg->header.repeat << " AS SMALLINT), "
+ << msg->header.repeatPeriod << ", "
+ << "'" << etext << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch newlly added message ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> msg->header.id;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::EditMessage(const STG_MSG & msg,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+std::string etext = msg.text;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etext))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape message text'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "UPDATE tb_messages SET "
+ << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+ << "ver = " << msg.header.ver << ", "
+ << "msg_type = " << msg.header.type << ", "
+ << "last_send_time = CAST('" << formatTime(msg.header.lastSendTime) << "' AS TIMESTAMP), "
+ << "creation_time = CAST('" << formatTime(msg.header.creationTime) << "' AS TIMESTAMP), "
+ << "show_time = " << msg.header.showTime << ", "
+ << "repeat = " << msg.header.repeat << ", "
+ << "repeat_period = " << msg.header.repeatPeriod << ", "
+ << "msg_text = '" << etext << "' "
+ << "WHERE pk_message = " << msg.header.id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessage(uint64_t id,
+ STG_MSG * msg,
+ const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT ver, msg_type, last_send_time, \
+ creation_time, show_time, repeat, \
+ repeat_period, msg_text \
+ FROM tb_messages \
+ WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch message data";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+str2x(PQgetvalue(result, 0, 0), msg->header.ver);
+str2x(PQgetvalue(result, 0, 1), msg->header.type);
+msg->header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 2)));
+msg->header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 3)));
+str2x(PQgetvalue(result, 0, 4), msg->header.showTime);
+str2x(PQgetvalue(result, 0, 5), msg->header.repeat);
+str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod);
+msg->text = PQgetvalue(result, 0, 7);
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelMessage(uint64_t id, const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_messages WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT pk_message, ver, msg_type, \
+ last_send_time, creation_time, show_time, \
+ repeat, repeat_period \
+ FROM tb_messages \
+ WHERE fk_user IN \
+ (SELECT pk_user FROM tb_users \
+ WHERE name = '" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ std::stringstream tuple;
+ STG_MSG_HDR header;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+ header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 3)));
+ header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 4)));
+ tuple << PQgetvalue(result, i, 5) << " ";
+ tuple << PQgetvalue(result, i, 6) << " ";
+ tuple << PQgetvalue(result, i, 7) << " ";
+
+ tuple >> header.id;
+ tuple >> header.ver;
+ tuple >> header.type;
+ tuple >> header.showTime;
+ tuple >> header.repeat;
+ tuple >> header.repeatPeriod;
+ hdrsList->push_back(header);
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ * Services manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg/locker.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetServicesList(std::vector<std::string> * servicesList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_services");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ servicesList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveService(const SERVICE_CONF & sc) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = sc.name;
+std::string ecomment = sc.comment;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ecomment))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "UPDATE tb_services SET "
+ << "comment = '" << ecomment << "', "
+ << "cost = " << sc.cost << ", "
+ << "pay_day = " << sc.payDay << " "
+ << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreService(SERVICE_CONF * sc,
+ const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch service's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0) << " "
+ << PQgetvalue(result, 0, 1) << " "
+ << PQgetvalue(result, 0, 2);
+
+PQclear(result);
+
+tuple >> sc->comment
+ >> sc->cost
+ >> sc->payDay;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "INSERT INTO tb_services \
+ (name, comment, cost, pay_day) \
+ VALUES \
+ ('" << ename << "', '', 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Tariffs manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <cmath>
+
+#include <libpq-fe.h>
+
+#include "stg/common.h"
+#include "postgresql_store.h"
+#include "stg/locker.h"
+
+namespace
+{
+
+const int pt_mega = 1024 * 1024;
+
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_tariffs");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ tariffsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
+ const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ {
+ std::ostringstream query;
+ query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch tariff ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int32_t id;
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, 0, 0);
+
+ PQclear(result);
+
+ tuple >> id;
+ }
+
+ {
+ std::ostringstream query;
+ query << "UPDATE tb_tariffs SET \
+ fee = " << td.tariffConf.fee << ", \
+ free = " << td.tariffConf.free << ", \
+ passive_cost = " << td.tariffConf.passiveCost << ", \
+ traff_type = " << td.tariffConf.traffType;
+
+ if (version > 6)
+ query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'";
+
+ if (version > 7)
+ query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "', \
+ change_policy_timeout = CAST('" << formatTime(td.tariffConf.changePolicyTimeout) << "' AS TIMESTAMP)";
+
+ query << " WHERE pk_tariff = " << id;
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+for(int i = 0; i < DIR_NUM; i++)
+ {
+ double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+ double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+ double pna = 0;
+ double pnb = 0;
+
+ if (td.dirPrice[i].singlePrice)
+ {
+ pna = pda;
+ pnb = pdb;
+ }
+ else
+ {
+ pna = td.dirPrice[i].priceNightA * 1024 * 1024;
+ pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
+ }
+
+ int threshold = 0;
+ if (td.dirPrice[i].noDiscount)
+ {
+ threshold = 0xffFFffFF;
+ }
+ else
+ {
+ threshold = td.dirPrice[i].threshold;
+ }
+
+ {
+ std::ostringstream query;
+ query << "UPDATE tb_tariffs_params SET \
+ price_day_a = " << pda << ", \
+ price_day_b = " << pdb << ", \
+ price_night_a = " << pna << ", \
+ price_night_b = " << pnb << ", \
+ threshold = " << threshold << ", \
+ time_day_begins = CAST('" << td.dirPrice[i].hDay
+ << ":"
+ << td.dirPrice[i].mDay << "' AS TIME), \
+ time_day_ends = CAST('" << td.dirPrice[i].hNight
+ << ":"
+ << td.dirPrice[i].mNight << "' AS TIME) \
+ WHERE fk_tariff = " << id << " AND dir_num = " << i;
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
+ const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+td->tariffConf.name = tariffName;
+
+std::ostringstream query;
+query << "SELECT pk_tariff, \
+ fee, \
+ free, \
+ passive_cost, \
+ traff_type";
+
+if (version > 6)
+ query << ", period";
+
+if (version > 7)
+ query << ", change_policy \
+ , change_policy_timeout";
+
+query << " FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch tariff data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int id;
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, 0, 0) << " ";
+ tuple << PQgetvalue(result, 0, 1) << " ";
+ tuple << PQgetvalue(result, 0, 2) << " ";
+ tuple << PQgetvalue(result, 0, 3) << " ";
+ tuple << PQgetvalue(result, 0, 4) << " ";
+
+ tuple >> id;
+ tuple >> td->tariffConf.fee;
+ tuple >> td->tariffConf.free;
+ tuple >> td->tariffConf.passiveCost;
+ tuple >> td->tariffConf.traffType;
+ }
+
+if (version > 6)
+ td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5));
+
+if (version > 7)
+ {
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(PQgetvalue(result, 0, 6));
+ td->tariffConf.changePolicyTimeout = readTime(PQgetvalue(result, 0, 7));
+ }
+
+PQclear(result);
+
+query.str("");
+query << "SELECT dir_num, \
+ price_day_a, \
+ price_day_b, \
+ price_night_a, \
+ price_night_b, \
+ threshold, \
+ EXTRACT(hour FROM time_day_begins), \
+ EXTRACT(minute FROM time_day_begins), \
+ EXTRACT(hour FROM time_day_ends), \
+ EXTRACT(minute FROM time_day_ends) \
+ FROM tb_tariffs_params \
+ WHERE fk_tariff = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+if (tuples != DIR_NUM)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
+ }
+
+for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
+ {
+ int dir;
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+ tuple << PQgetvalue(result, i, 3) << " ";
+ tuple << PQgetvalue(result, i, 4) << " ";
+ tuple << PQgetvalue(result, i, 5) << " ";
+ tuple << PQgetvalue(result, i, 6) << " ";
+ tuple << PQgetvalue(result, i, 7) << " ";
+ tuple << PQgetvalue(result, i, 8) << " ";
+ tuple << PQgetvalue(result, i, 9) << " ";
+
+ tuple >> dir;
+ tuple >> td->dirPrice[dir].priceDayA;
+ td->dirPrice[dir].priceDayA /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceDayB;
+ td->dirPrice[dir].priceDayB /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceNightA;
+ td->dirPrice[dir].priceNightA /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceNightB;
+ td->dirPrice[dir].priceNightB /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].threshold;
+ tuple >> td->dirPrice[dir].hDay;
+ tuple >> td->dirPrice[dir].mDay;
+ tuple >> td->dirPrice[dir].hNight;
+ tuple >> td->dirPrice[dir].mNight;
+ }
+
+ if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
+ std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
+ {
+ td->dirPrice[dir].singlePrice = true;
+ }
+ else
+ {
+ td->dirPrice[dir].singlePrice = false;
+ }
+ if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+ {
+ td->dirPrice[dir].noDiscount = true;
+ }
+ else
+ {
+
+ td->dirPrice[dir].noDiscount = false;
+ }
+
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * User manipulation methods
+ *
+ * $Revision: 1.14 $
+ * $Date: 2010/05/07 07:26:36 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+#include "stg/common.h"
+#include "stg/const.h"
+#include "stg/locker.h"
+#include "../../../stg_timer.h"
+#include "postgresql_store.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_users");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ usersList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddUser(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = name;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT sp_add_user('" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelUser(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserStat(const USER_STAT & stat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveStat(const USER_STAT & stat,
+ const std::string & login,
+ int year,
+ int month) const
+{
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "UPDATE tb_users SET "
+ "cash = " << stat.cash << ", "
+ "free_mb = " << stat.freeMb << ", "
+ "last_activity_time = CAST('" << formatTime(stat.lastActivityTime) << "' AS TIMESTAMP), "
+ "last_cash_add = " << stat.lastCashAdd << ", "
+ "last_cash_add_time = CAST('" << formatTime(stat.lastCashAddTime) << "' AS TIMESTAMP), "
+ "passive_time = " << stat.passiveTime << " "
+ "WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+std::string date;
+
+MakeDate(date, year, month);
+
+for (int dir = 0; dir < DIR_NUM; ++dir)
+ {
+ query.str("");
+ query << "SELECT sp_add_stats_traffic ("
+ "'" << elogin << "', "
+ "CAST('" << date << "' AS DATE), "
+ "CAST(" << dir << " AS SMALLINT), "
+ "CAST(" << stat.monthUp[dir] << " AS BIGINT), "
+ "CAST(" << stat.monthDown[dir] << " AS BIGINT))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserConf(const USER_CONF & conf,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+uint32_t uid;
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, 0, 0);
+
+ PQclear(result);
+
+ tuple >> uid;
+ }
+
+std::string eaddress = conf.address;
+std::string eemail = conf.email;
+std::string egroup = conf.group;
+std::string enote = conf.note;
+std::string epassword = conf.password;
+std::string ephone = conf.phone;
+std::string erealname = conf.realName;
+std::string etariffname = conf.tariffName;
+std::string enexttariff = conf.nextTariff;
+std::string ecorporation = conf.corp;
+
+if (EscapeString(eaddress))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape address'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eemail))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape email'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(egroup))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape group'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enote))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape note'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(epassword))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape password'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ephone))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape phone'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(erealname))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape real name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etariffname))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape tariff name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enexttariff))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape next tariff name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ecorporation))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape corporation name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+query.str("");
+query << "UPDATE tb_users SET "
+ "address = '" << eaddress << "', "
+ "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", "
+ "credit = " << conf.credit << ", "
+ "credit_expire = CAST('" << formatTime(conf.creditExpire) << "' AS TIMESTAMP), "
+ "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", "
+ "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", "
+ "email = '" << eemail << "', "
+ "grp = '" << egroup << "', "
+ "note = '" << enote << "', "
+ "passive = " << (conf.passive ? "'t'" : "'f'") << ", "
+ "passwd = '" << epassword << "', "
+ "phone = '" << ephone << "', "
+ "real_name = '" << erealname << "', "
+ "fk_tariff = (SELECT pk_tariff "
+ "FROM tb_tariffs "
+ "WHERE name = '" << etariffname << "'), "
+ "fk_tariff_change = (SELECT pk_tariff "
+ "FROM tb_tariffs "
+ "WHERE name = '" << enexttariff << "'), "
+ "fk_corporation = (SELECT pk_corporation "
+ "FROM tb_corporations "
+ "WHERE name = '" << ecorporation << "') "
+ "WHERE pk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (SaveUserServices(uid, conf.services))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (SaveUserData(uid, conf.userdata))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's data'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (SaveUserIPs(uid, conf.ips))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's IPs'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserStat(USER_STAT * stat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ {
+ std::ostringstream query;
+ query << "SELECT cash, free_mb, "
+ "last_activity_time, last_cash_add, "
+ "last_cash_add_time, passive_time "
+ "FROM tb_users "
+ "WHERE name = '" << elogin << "'";
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's stat";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, 0, 0) << " ";
+ tuple << PQgetvalue(result, 0, 1) << " ";
+ stat->lastActivityTime = readTime(PQgetvalue(result, 0, 2));
+ tuple << PQgetvalue(result, 0, 3) << " ";
+ stat->lastCashAddTime = readTime(PQgetvalue(result, 0, 4));
+ tuple << PQgetvalue(result, 0, 5) << " ";
+
+ PQclear(result);
+
+ tuple >> stat->cash
+ >> stat->freeMb
+ >> stat->lastCashAdd
+ >> stat->passiveTime;
+ }
+
+ {
+ std::ostringstream query;
+ query << "SELECT dir_num, upload, download "
+ "FROM tb_stats_traffic "
+ "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
+ "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << formatTime(stgTime) << "' AS TIMESTAMP))";
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+
+ int dir;
+
+ tuple >> dir;
+ tuple >> stat->monthUp[dir];
+ tuple >> stat->monthDown[dir];
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserConf(USER_CONF * conf,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ {
+ std::ostringstream query;
+ query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
+ "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
+ "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
+ "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
+ "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
+ "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
+ "ON tf1.pk_tariff = tb_users.fk_tariff "
+ "LEFT JOIN tb_tariffs AS tf2 "
+ "ON tf2.pk_tariff = tb_users.fk_tariff_change "
+ "LEFT JOIN tb_corporations "
+ "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
+ "WHERE tb_users.name = '" << elogin << "'";
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's stat";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+uint32_t uid;
+
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, 0, 0) << " "; // uid
+ conf->address = PQgetvalue(result, 0, 1); // address
+ conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
+ tuple << PQgetvalue(result, 0, 3) << " "; // credit
+ conf->creditExpire = readTime(PQgetvalue(result, 0, 4)); // creditExpire
+ conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
+ conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
+ conf->email = PQgetvalue(result, 0, 7); // email
+ conf->group = PQgetvalue(result, 0, 8); // group
+ conf->note = PQgetvalue(result, 0, 9); // note
+ conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
+ conf->password = PQgetvalue(result, 0, 11); // password
+ conf->phone = PQgetvalue(result, 0, 12); // phone
+ conf->realName = PQgetvalue(result, 0, 13); // realName
+ conf->tariffName = PQgetvalue(result, 0, 14); // tariffName
+ conf->nextTariff = PQgetvalue(result, 0, 15); // nextTariff
+ conf->corp = PQgetvalue(result, 0, 16); // corp
+
+ PQclear(result);
+
+ if (conf->tariffName == "")
+ conf->tariffName = NO_TARIFF_NAME;
+ if (conf->corp == "")
+ conf->corp = NO_CORP_NAME;
+
+ tuple >> uid
+ >> conf->credit;
+ }
+
+ {
+ std::ostringstream query;
+ query << "SELECT name FROM tb_services "
+ "WHERE pk_service IN (SELECT fk_service "
+ "FROM tb_users_services "
+ "WHERE fk_user = " << uid << ")";
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ conf->services.push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+ {
+ std::ostringstream query;
+ query << "SELECT num, data "
+ "FROM tb_users_data "
+ "WHERE fk_user = " << uid;
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ int num;
+ if (str2x(PQgetvalue(result, i, 0), num))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to convert string to int'\n");
+ }
+ else
+ {
+ if (num < USERDATA_NUM &&
+ num >= 0)
+ {
+ conf->userdata[num] = PQgetvalue(result, i, 1);
+ }
+ }
+ }
+
+PQclear(result);
+
+ {
+ std::ostringstream query;
+ query << "SELECT host(ip), masklen(ip) "
+ "FROM tb_allowed_ip "
+ "WHERE fk_user = " << uid;
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+USER_IPS ips;
+for (int i = 0; i < tuples; ++i)
+ {
+ IP_MASK im;
+
+ im.ip = inet_strington(PQgetvalue(result, i, 0));
+
+ if (str2x(PQgetvalue(result, i, 1), im.mask))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to fetch mask'\n");
+ continue;
+ }
+
+ ips.Add(im);
+ }
+conf->ips = ips;
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message = "") const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+std::string eadminLogin(admLogin);
+std::string eparam(paramName);
+std::string eold(oldValue);
+std::string enew(newValue);
+std::string emessage(message);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eadminLogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape admin's login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eparam))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape param's name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eold))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape old value'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enew))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape new value'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+query << "SELECT sp_add_param_log_entry("
+ "'" << elogin << "', "
+ "'" << eadminLogin << "', CAST('"
+ << inet_ntostring(admIP) << "/32' AS INET), "
+ "'" << eparam << "', "
+ "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+ "'" << eold << "', "
+ "'" << enew << "', "
+ "'" << emessage << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::ostringstream query;
+if (version < 6)
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+ "'c', CAST('"
+ << inet_ntostring(ip) << "/32' AS INET), 0)";
+ }
+else
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+ "'c', CAST('"
+ << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')";
+ }
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & monthUp,
+ const DIR_TRAFF & monthDown,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::string ereason(reason);
+
+if (EscapeString(ereason))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape reason'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ {
+ std::ostringstream query;
+ if (version < 6)
+ {
+ // Old database version - no freeMb logging support
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+ "'d', CAST('0.0.0.0/0' AS INET), "
+ << cash << ")";
+ }
+ else
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+ "'d', CAST('0.0.0.0/0' AS INET), "
+ << cash << ", " << freeMb << ", '" << ereason << "')";
+ }
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch session's log ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+uint32_t lid;
+
+if (str2x(PQgetvalue(result, 0, 0), lid))
+ {
+ strError = "Failed to convert string to int";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ std::ostringstream query;
+ query << "INSERT INTO tb_sessions_data "
+ "(fk_session_log, "
+ "dir_num, "
+ "session_upload, "
+ "session_download, "
+ "month_upload, "
+ "month_download)"
+ "VALUES ("
+ << lid << ", "
+ << i << ", "
+ << sessionUp[i] << ", "
+ << sessionDown[i] << ", "
+ << monthUp[i] << ", "
+ << monthDown[i] << ")";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ time_t lastStat,
+ const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
+time_t currTime = time(NULL);
+
+for (it = statTree.begin(); it != statTree.end(); ++it)
+ {
+ std::ostringstream query;
+ query << "INSERT INTO tb_detail_stats "
+ "(till_time, from_time, fk_user, "
+ "dir_num, ip, download, upload, cost) "
+ "VALUES ("
+ "CAST('" << formatTime(currTime) << "' AS TIMESTAMP), "
+ "CAST('" << formatTime(lastStat) << "' AS TIMESTAMP), "
+ "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+ << it->first.dir << ", "
+ << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), "
+ << it->second.down << ", "
+ << it->second.up << ", "
+ << it->second.cash << ")";
+
+ PGresult * result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login, year, month);
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserServices(uint32_t uid,
+ const std::vector<std::string> & services) const
+{
+PGresult * result;
+
+ {
+ std::ostringstream query;
+ query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+std::vector<std::string>::const_iterator it;
+
+for (it = services.begin(); it != services.end(); ++it)
+ {
+ std::string ename = *it;
+
+ if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): 'Failed to escape service name'\n");
+ return -1;
+ }
+
+ std::ostringstream query;
+ query << "INSERT INTO tb_users_services "
+ "(fk_user, fk_service) "
+ "VALUES "
+ "(" << uid << ", "
+ "(SELECT pk_service "
+ "FROM tb_services "
+ "WHERE name = '" << ename << "'))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserIPs(uint32_t uid,
+ const USER_IPS & ips) const
+{
+PGresult * result;
+
+ {
+ std::ostringstream query;
+ query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
+
+ result = PQexec(connection, query.str().c_str());
+ }
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+for (size_t i = 0; i < ips.Count(); ++i)
+ {
+ std::ostringstream query;
+ query << "INSERT INTO tb_allowed_ip "
+ "(fk_user, ip) "
+ "VALUES "
+ "(" << uid << ", CAST('"
+ << inet_ntostring(ips[i].ip) << "/"
+ << static_cast<int>(ips[i].mask) << "' AS INET))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserData(uint32_t uid,
+ const std::vector<std::string> & data) const
+{
+for (unsigned i = 0; i < data.size(); ++i)
+ {
+ std::string edata = data[i];
+
+ if (EscapeString(edata))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): 'Failed to escape userdata field'\n");
+ return -1;
+ }
+
+ PGresult * result;
+
+ std::ostringstream query;
+ query << "SELECT sp_set_user_data("
+ << uid << ", "
+ << "CAST(" << i << " AS SMALLINT), "
+ << "'" << edata << "')";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ * Vairous utility methods
+ *
+ * $Revision: 1.3 $
+ * $Date: 2009/10/22 10:01:08 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/common.h"
+
+#include <string>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+extern volatile time_t stgTime;
+
+int POSTGRESQL_STORE::StartTransaction() const
+{
+PGresult * result = PQexec(connection, "BEGIN");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::StartTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::CommitTransaction() const
+{
+PGresult * result = PQexec(connection, "COMMIT");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::CommitTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::RollbackTransaction() const
+{
+PGresult * result = PQexec(connection, "ROLLBACK");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RollbackTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::EscapeString(std::string & value) const
+{
+int error = 0;
+char * buf = new char[(value.length() << 1) + 1];
+
+PQescapeStringConn(connection,
+ buf,
+ value.c_str(),
+ value.length(),
+ &error);
+
+if (error)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::EscapeString(): '%s'\n", strError.c_str());
+ delete[] buf;
+ return -1;
+ }
+
+value = buf;
+
+delete[] buf;
+return 0;
+}
+
+void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const
+{
+struct tm brokenTime;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+if (year)
+ {
+ brokenTime.tm_hour = 0;
+ brokenTime.tm_min = 0;
+ brokenTime.tm_sec = 0;
+ brokenTime.tm_year = year;
+ brokenTime.tm_mon = month;
+ }
+else
+ {
+ time_t curTime = stgTime;
+ localtime_r(&curTime, &brokenTime);
+ }
+
+brokenTime.tm_mday = DaysInMonth(brokenTime.tm_year + 1900, brokenTime.tm_mon);
+
+char buf[32];
+
+strftime(buf, 32, "%Y-%m-%d", &brokenTime);
+
+date = buf;
+}
--- /dev/null
+#ifndef POSTGRESQL_UTILS_STORE_H
+#define POSTGRESQL_UTILS_STORE_H
+
+#include <functional>
+
+struct ToLower : public std::unary_function<char, char>
+{
+char operator() (char c) const { return static_cast<char>(std::tolower(c)); }
+};
+
+#endif
--- /dev/null
+#!/bin/bash
+
+# Этот скрипт производит очистку файловой БД stargazer-а.
+# Его можно вызывать вручную или покрону, к примеру раз в неделю или раз в месяц.
+
+
+# Эта переменная задает сколько месяцев детальной статистики оставить в БД
+SAVE_MONTHS=3
+
+# Эта переменная задает сколько строк оставить в логах юзеров
+MAX_LOG_LINES=5000
+
+# Тут определяется путь к БД
+DB=/var/stargazer/
+
+
+
+
+declare -i NOW=`date +%s`
+declare -i DT=SAVE_MONTHS*31*24*3600
+declare -i stat_time=0
+
+for usr in $DB/users/*
+do
+ echo cleaning `basename $usr`
+ for ys in $usr/detail_stat/*
+ do
+ year=`basename $ys`
+
+ for ms in $ys/*
+ do
+ month=`basename $ms`
+ stat_time=`date --date="$year/$month/01" +%s`
+
+ if (( $NOW - $stat_time > $DT ))
+ then
+ rm -fr $ms
+ fi
+ done
+ done
+ tail -n $MAX_LOG_LINES $usr/log > /tmp/stg_usr_log.`basename $usr`
+ mv -f /tmp/stg_usr_log.`basename $usr` $usr/log
+done
+
--- /dev/null
+#!/bin/bash
+
+# Данный скрипт производит мониторинг СТГ-сервера на зависание и в
+# случае его зависания перезапускает.
+# Для работы скрипта в настройках СТГ должен быть указан параметер
+# MonitorDir
+# Скрипт отрабатывает один раз и выходит. Т.е. он не работает постоянно
+# и следит за СТГ. Его нужно вызывать по крону или как-то еще с нужной
+# периодичностью!!!
+
+
+# Путь к файлам монитора. Должен совпадать со значением MonitorDir
+# в настройках сервера
+MONITOR_DIR=/var/stargazer/monitor/
+
+
+# Максимальная задержка обновления файлов монитора в секундах.
+# При привышении этого значения сервер считается зависшим и будет
+# перезапущен
+DT=300
+
+
+
+
+declare -i now=`date +%s`
+declare -i DT=300
+declare -i file_time=0
+
+stg_running=`ps ax | grep stargazer`
+if [ -z "$stg_running" ]
+then
+ echo "Stargazer is not running"
+ exit 0
+fi
+
+#wakeuper for traffcounter
+ping -c 1 127.0.0.1 > /dev/null
+sleep 1
+
+for mon in $MONITOR_DIR/*
+do
+ if [ ! -r $mon ]
+ then
+ echo "no monitor files"
+ exit 0
+ fi
+ file_time=`stat -c%Y $mon`
+
+ if (( $now - $file_time > $DT ))
+ then
+ echo "Stargazer is deadlocked!"
+
+ # Команда остаовки СТГ
+ killall -KILL stargazer
+
+ rm -f $MONITOR_DIR/*
+ sleep 15
+
+ # Команда запуска СТГ
+ /etc/init.d/stargazer start
+
+ fi
+
+done
+
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+default_speed=32kbit
+
+# =========== shaping by tariff ===========
+#tariff=$(grep -i "^tariff=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "tariff=$tariff" > /var/stargazer/users/$LOGIN/connect.log
+#case $tariff in
+# minimum) speedkb=128kbit;; # 128 kbit
+# middle) speedkb=256kbit;; # 256 kbi
+# maximum) speedkb=512kbit;; # 512 kbit
+# *) speedkb=$default_speed;; # default speed
+#esac
+# ========= shaping by tariff end =========
+
+# ========= shaping by userdata0 ==========
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ]
+then
+ speedkb=$default_speed
+else
+ speedkb="$speed"kbit
+fi
+# ======= shaping by userdata0 end ========
+
+declare -i mark=$ID+10
+
+echo "$mark" > /var/stargazer/users/$LOGIN/shaper_mark
+echo "$speedkb" > /var/stargazer/users/$LOGIN/shaper_rate
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+tc class add dev $int_iface parent 1:1 classid 1:$mark htb rate $speedkb burst 40k
+tc filter add dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+mark=$(cat /var/stargazer/users/$LOGIN/shaper_mark)
+rate=$(cat /var/stargazer/users/$LOGIN/shaper_rate)
+
+if [ -n "$mark" ]
+then
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+ while [ $? == 0 ]
+ do
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+ done
+fi
+
+tc filter del dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+tc class del dev $int_iface parent 1:1 classid 1:$mark htb rate $rate burst 40k
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+
--- /dev/null
+Настройка шейпера для STG в Linux.
+
+По мотивам форума:
+http://local.com.ua/forum/index.php?showtopic=7920
+
+Настройка сводится к указанию сетевого интерфейса, обращенного к пользователю
+в скриптах shaper.sh, shaper.stop.sh, OnConnect и OnDisconnect, и уточнению
+скоростоей и тарифов в скрипте OnConnect (если нужно).
+
+Скрипты сделаны для БД на файлах, однако, сделать их для БД на Firebird или
+MySQL не составит большого труда.
+
+В OnConnect есть два типа шейпинга.
+1. На основании тарифа. Т.е. для каждого тарифа у задана скорость и задано
+дефолтное значение, на случай отсутсвия тарифа в списке скоростей или
+забывчивости админа.
+2. На основании Userdata0. В этом поле просто прописывается число равное
+скорости в kbit/sec. Также есть дефолтное значение скорости в 32 kbit/sec
+на случай отсутсвия в Userdata0 корректного значения.
+
+В скрипте первый способ закомментирован. Для того чтобы выбрать один из них нужно
+либо удалить, либо закомментировать строчики между
+
+# ========= shaping by tariff ==========
+.........
+# ======= shaping by tariff end ========
+
+и
+
+# ========= shaping by userdata0 ==========
+.........
+# ======= shaping by userdata0 end ========
+
+
+и нужную часть расскоментировать, если она закомментрована.
+
+Скрипт shaper.sh должен быть выполнен один раз при загрузке системы.
+
+Интерфейс обращенный к пользователю определяется в переменной
+int_iface=
+(присутствует во всех 4-х файлах shaper.sh, shaper.stop.sh, OnConnect и
+OnDisconnect !!!)
+
+Скорость по умолчанию в OnConnect в переменной default_speed
+
+Зависимость скорости от тарифа задается в следующем фрагменте кода:
+case $tariff in
+ minimum) speedkb=128kbit;;
+ middle) speedkb=256kbit;;
+ maximum) speedkb=512kbit;;
+ *) speedkb=$default_speed;;
+esac
+
+Т.е. тут нужно вместо minimum, ... maximum подставить имена ваших тарифов
+и соотв. скорость. Пользователи с тарифами не указанными в списке будут иметь
+дефолтную скорость.
+
+Скорость ограничевается только для входящего тарафика, однако расширить
+эти скрипты для исходящего не составит труда.
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+iptables -t mangle --flush
+
+tc qdisc add dev $int_iface root handle 1: htb
+tc class add dev $int_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+#iptables -t mangle --flush
+
+tc qdisc del dev $int_iface root handle 1: htb
+
--- /dev/null
+Настройка такой конфигурации происходит в 3 этапа:
+1. Настройка VPN с использованием pptpd;
+2. Настройка авторизации VPN через FreeRADIUS;
+3. Настройка шейпера;
+
+1. Настройка VPN
+
+Необходимо установить пакеты ppp и pptpd. Также необходима поддержка PPP в ядре:
+ Device Drivers --->
+ Network device support --->
+ <M> PPP (point-to-point protocol) support
+ <M> PPP support for sync tty ports
+ <M> PPP Deflate compression
+ <M> PPP BSD-Compress compression
+ <M> PPP MPPE compression (encryption) (EXPERIMENTAL)
+ <M> PPP over Ethernet (EXPERIMENTAL)
+В файле /etc/pptpd.conf прописываем файл настроек PPP (параметр option). Также
+указываем адреса сервера внутри сети VPN (параметр localip) и диапазон адресов
+клиентов (параметр remoteip). См. пример файла конфигурации.
+В настройках PPP указываем имя сервера (параметр name), параметры шифрования.
+Для использования шифрования MPPE необходима его поддержка в ядре. Кроме того,
+в процессе аутентификации MPPE использует MS-CHAPv2. По этому при
+использовании шифрования MPPE также необходимо указать необходимость
+поддержки MS-CHAPv2 клиентом. По желанию указываем proxyarp (для того чтобы
+клиенты в сети VPN "видели" друг друга) и defaultroute. Прописываем в файле
+/etc/ppp/chap-secrets тестового пользователя и проверяем работоспособность
+VPN.
+
+2. Настройка авторизации VPN через FreeRADIUS
+
+Необходимо установить пакет freeradius.
+Настройку сервера (файл radiusd.conf) проводим в соответствии с документацией
+на модуль rlm_stg.so (см. документацию на систему Stargazer).
+Настройку Stargazer с плагином для FreeRADIUS проводим в соответствиии с
+документацией на модуль mod_radius.so (см. документацию на систему Stargazer).
+В файле clients.conf, расположенном в дирректории с конфигурационными файлами
+FreeRADIUS, описываем, какие клиенты могут использовать FreeRADIUS.
+Рекомендуется заменить стандартный пароль, которым шифруется обмен информации
+с клиентом, "testing123" на что-то более приемлимое с точки зрения безопасности.
+После этого запускаем FreeRADIUS и удостоверяемся, что он работает строчкой
+"Mon Mar 31 16:06:17 2008 : Info: Ready to process requests." в журнале
+(обычно, /var/log/radius/radius.log). Если журнал FreeRADIUS не позволяет
+определить проблему - можно запустить сервер в отладочном режме с ключем -X.
+В этом режиме более детальное журналирование проводится в консоль.
+Если на данном этапе все работает - в файл насттроек PPP прописываем строчку
+plugin radius.so. После этого VPN должен нормально авторизоваться
+пользователями системы Stargazer.
+
+3. Настройка шейпера
+
+Собственно настройки шейпер не требует. Всё, что нужно прописано в скриптах
+OnConnect и OnDisconnect. Шейпер предназначен для работы с хранилищем на
+файлах, однако, переделать скипт под MySQL или Firebird не составит труда.
+Скорость для пользоватлея задается в поле Userdata0 в kbit/sec. В этом поле
+должно быть прописано просто число без всяких kbit/sec и т.п. Если в этом поле
+у пользователя нет данных или стоит некорректное значение, пользователь будет
+ограничен скоростью определенной в переменной default_speed в скрипте
+OnConnect.
--- /dev/null
+#!/bin/bash
+
+#adsl-start
+
+modprobe ip_queue
+
+int_addr=10.0.0.2
+ext_addr=192.168.1.34
+
+int_net=10.0.0.0/16
+ext_net=192.168.1.0/24
+
+echo 1 > /proc/sys/net/ipv4/ip_forward
+
+iptables -P INPUT DROP
+iptables -P OUTPUT ACCEPT
+iptables -P FORWARD ACCEPT
+
+iptables -t nat -F
+iptables -t filter -F
+
+#
+#iptables -A INPUT -d $ip1 -j ACCEPT
+#iptables -A OUTPUT -s $ip1 -j ACCEPT
+
+# Разрешам говорить самому с собой
+iptables -A INPUT -d 127.0.0.1 -j ACCEPT
+iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
+
+#iptables -A INPUT -d $ip4 -j ACCEPT
+#iptables -A INPUT -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -d $ip4 -j ACCEPT
+
+iptables -A INPUT -p icmp -j ACCEPT
+iptables -A OUTPUT -p icmp -j ACCEPT
+
+iptables -A INPUT -p 47 -j ACCEPT
+iptables -A FORWARD -p 47 -j ACCEPT
+iptables -A OUTPUT -p 47 -j ACCEPT
+
+#SSH On this machine
+iptables -A INPUT -p tcp -d $int_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $int_addr --sport 22 -j ACCEPT
+iptables -A INPUT -p tcp -d $ext_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $ext_addr --sport 22 -j ACCEPT
+
+#WEB On this machine
+#iptables -A INPUT -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 80 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 80 -j ACCEPT
+
+#PPTP
+iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
+iptables -A OUTPUT -p tcp --sport 1723 -j ACCEPT
+iptables -A INPUT -p udp --dport 1723 -j ACCEPT
+iptables -A OUTPUT -p udp --sport 1723 -j ACCEPT
+
+#FTP
+#iptables -A INPUT -p tcp -d $ip2 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 -j ACCEPT
+
+#iptables -A INPUT -p tcp -d $ip2 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 20:21 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 20:21 -j ACCEPT
+
+#iptables -A INPUT -p tcp -d $ip2 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+
+#DNS
+iptables -A INPUT -p tcp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
+iptables -A INPUT -p udp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -d $ip1 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip4 --dport 80 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.7 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.16 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128
+
+iptables -t nat -A POSTROUTING -d 0.0.0.0/0 -s 192.168.2.0/24 -j MASQUERADE
+
+
+
--- /dev/null
+#
+# clients.conf - client configuration directives
+#
+#######################################################################
+
+#######################################################################
+#
+# Definition of a RADIUS client (usually a NAS).
+#
+# The information given here over rides anything given in the
+# 'clients' file, or in the 'naslist' file. The configuration here
+# contains all of the information from those two files, and allows
+# for more configuration items.
+#
+# The "shortname" is be used for logging. The "nastype", "login" and
+# "password" fields are mainly used for checkrad and are optional.
+#
+
+#
+# Defines a RADIUS client. The format is 'client [hostname|ip-address]'
+#
+# '127.0.0.1' is another name for 'localhost'. It is enabled by default,
+# to allow testing of the server after an initial installation. If you
+# are not going to be permitting RADIUS queries from localhost, we suggest
+# that you delete, or comment out, this entry.
+#
+client 127.0.0.1 {
+ #
+ # The shared secret use to "encrypt" and "sign" packets between
+ # the NAS and FreeRADIUS. You MUST change this secret from the
+ # default, otherwise it's not a secret any more!
+ #
+ # The secret can be any string, up to 31 characters in length.
+ #
+ secret = testing123
+
+ #
+ # The short name is used as an alias for the fully qualified
+ # domain name, or the IP address.
+ #
+ shortname = localhost
+
+ #
+ # the following three fields are optional, but may be used by
+ # checkrad.pl for simultaneous use checks
+ #
+
+ #
+ # The nastype tells 'checkrad.pl' which NAS-specific method to
+ # use to query the NAS for simultaneous use.
+ #
+ # Permitted NAS types are:
+ #
+ # cisco
+ # computone
+ # livingston
+ # max40xx
+ # multitech
+ # netserver
+ # pathras
+ # patton
+ # portslave
+ # tc
+ # usrhiper
+ # other # for all other types
+
+ #
+ nastype = other # localhost isn't usually a NAS...
+
+ #
+ # The following two configurations are for future use.
+ # The 'naspasswd' file is currently used to store the NAS
+ # login name and password, which is used by checkrad.pl
+ # when querying the NAS for simultaneous use.
+ #
+# login = !root
+# password = someadminpas
+}
--- /dev/null
+##
+## radiusd.conf -- FreeRADIUS server configuration file.
+##
+## http://www.freeradius.org/
+## $Id: radiusd.conf,v 1.1 2008/03/31 13:54:59 faust Exp $
+##
+
+# The location of other config files and
+# logfiles are declared in this file
+#
+# Also general configuration for modules can be done
+# in this file, it is exported through the API to
+# modules that ask for it.
+#
+# The configuration variables defined here are of the form ${foo}
+# They are local to this file, and do not change from request to
+# request.
+#
+# The per-request variables are of the form %{Attribute-Name}, and
+# are taken from the values of the attribute in the incoming
+# request. See 'doc/variables.txt' for more information.
+
+prefix = /usr
+exec_prefix = /usr
+sysconfdir = /etc
+localstatedir = /var
+sbindir = ${exec_prefix}/sbin
+logdir = /var/log/freeradius
+raddbdir = /etc/freeradius
+radacctdir = ${logdir}/radacct
+
+# Location of config and logfiles.
+confdir = ${raddbdir}
+run_dir = ${localstatedir}/run/freeradius
+
+#
+# The logging messages for the server are appended to the
+# tail of this file.
+#
+log_file = ${logdir}/radius.log
+
+#
+# libdir: Where to find the rlm_* modules.
+#
+# This should be automatically set at configuration time.
+#
+# If the server builds and installs, but fails at execution time
+# with an 'undefined symbol' error, then you can use the libdir
+# directive to work around the problem.
+#
+# The cause is usually that a library has been installed on your
+# system in a place where the dynamic linker CANNOT find it. When
+# executing as root (or another user), your personal environment MAY
+# be set up to allow the dynamic linker to find the library. When
+# executing as a daemon, FreeRADIUS MAY NOT have the same
+# personalized configuration.
+#
+# To work around the problem, find out which library contains that symbol,
+# and add the directory containing that library to the end of 'libdir',
+# with a colon separating the directory names. NO spaces are allowed.
+#
+# e.g. libdir = /usr/local/lib:/opt/package/lib
+#
+# You can also try setting the LD_LIBRARY_PATH environment variable
+# in a script which starts the server.
+#
+# If that does not work, then you can re-configure and re-build the
+# server to NOT use shared libraries, via:
+#
+# ./configure --disable-shared
+# make
+# make install
+#
+libdir = /usr/lib/freeradius
+
+# pidfile: Where to place the PID of the RADIUS server.
+#
+# The server may be signalled while it's running by using this
+# file.
+#
+# This file is written when ONLY running in daemon mode.
+#
+# e.g.: kill -HUP `cat /var/run/freeradius/freeradius.pid`
+#
+pidfile = ${run_dir}/freeradius.pid
+
+
+# user/group: The name (or #number) of the user/group to run radiusd as.
+#
+# If these are commented out, the server will run as the user/group
+# that started it. In order to change to a different user/group, you
+# MUST be root ( or have root privleges ) to start the server.
+#
+# We STRONGLY recommend that you run the server with as few permissions
+# as possible. That is, if you're not using shadow passwords, the
+# user and group items below should be set to 'nobody'.
+#
+# On SCO (ODT 3) use "user = nouser" and "group = nogroup".
+#
+# NOTE that some kernels refuse to setgid(group) when the value of
+# (unsigned)group is above 60000; don't use group nobody on these systems!
+#
+# On systems with shadow passwords, you might have to set 'group = shadow'
+# for the server to be able to read the shadow password file. If you can
+# authenticate users while in debug mode, but not in daemon mode, it may be
+# that the debugging mode server is running as a user that can read the
+# shadow info, and the user listed below can not.
+#
+user = freerad
+group = freerad
+
+# max_request_time: The maximum time (in seconds) to handle a request.
+#
+# Requests which take more time than this to process may be killed, and
+# a REJECT message is returned.
+#
+# WARNING: If you notice that requests take a long time to be handled,
+# then this MAY INDICATE a bug in the server, in one of the modules
+# used to handle a request, OR in your local configuration.
+#
+# This problem is most often seen when using an SQL database. If it takes
+# more than a second or two to receive an answer from the SQL database,
+# then it probably means that you haven't indexed the database. See your
+# SQL server documentation for more information.
+#
+# Useful range of values: 5 to 120
+#
+max_request_time = 30
+
+# delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
+# to be handled, then maybe the server should delete it.
+#
+# If you're running in threaded, or thread pool mode, this setting
+# should probably be 'no'. Setting it to 'yes' when using a threaded
+# server MAY cause the server to crash!
+#
+delete_blocked_requests = no
+
+# cleanup_delay: The time to wait (in seconds) before cleaning up
+# a reply which was sent to the NAS.
+#
+# The RADIUS request is normally cached internally for a short period
+# of time, after the reply is sent to the NAS. The reply packet may be
+# lost in the network, and the NAS will not see it. The NAS will then
+# re-send the request, and the server will respond quickly with the
+# cached reply.
+#
+# If this value is set too low, then duplicate requests from the NAS
+# MAY NOT be detected, and will instead be handled as seperate requests.
+#
+# If this value is set too high, then the server will cache too many
+# requests, and some new requests may get blocked. (See 'max_requests'.)
+#
+# Useful range of values: 2 to 10
+#
+cleanup_delay = 5
+
+# max_requests: The maximum number of requests which the server keeps
+# track of. This should be 256 multiplied by the number of clients.
+# e.g. With 4 clients, this number should be 1024.
+#
+# If this number is too low, then when the server becomes busy,
+# it will not respond to any new requests, until the 'cleanup_delay'
+# time has passed, and it has removed the old requests.
+#
+# If this number is set too high, then the server will use a bit more
+# memory for no real benefit.
+#
+# If you aren't sure what it should be set to, it's better to set it
+# too high than too low. Setting it to 1000 per client is probably
+# the highest it should be.
+#
+# Useful range of values: 256 to infinity
+#
+max_requests = 1024
+
+# bind_address: Make the server listen on a particular IP address, and
+# send replies out from that address. This directive is most useful
+# for machines with multiple IP addresses on one interface.
+#
+# It can either contain "*", or an IP address, or a fully qualified
+# Internet domain name. The default is "*"
+#
+# As of 1.0, you can also use the "listen" directive. See below for
+# more information.
+#
+bind_address = *
+
+# port: Allows you to bind FreeRADIUS to a specific port.
+#
+# The default port that most NAS boxes use is 1645, which is historical.
+# RFC 2138 defines 1812 to be the new port. Many new servers and
+# NAS boxes use 1812, which can create interoperability problems.
+#
+# The port is defined here to be 0 so that the server will pick up
+# the machine's local configuration for the radius port, as defined
+# in /etc/services.
+#
+# If you want to use the default RADIUS port as defined on your server,
+# (usually through 'grep radius /etc/services') set this to 0 (zero).
+#
+# A port given on the command-line via '-p' over-rides this one.
+#
+# As of 1.0, you can also use the "listen" directive. See below for
+# more information.
+#
+port = 0
+
+#
+# By default, the server uses "bind_address" to listen to all IP's
+# on a machine, or just one IP. The "port" configuration is used
+# to select the authentication port used when listening on those
+# addresses.
+#
+# If you want the server to listen on additional addresses, you can
+# use the "listen" section. A sample section (commented out) is included
+# below. This "listen" section duplicates the functionality of the
+# "bind_address" and "port" configuration entries, but it only listens
+# for authentication packets.
+#
+# If you comment out the "bind_address" and "port" configuration entries,
+# then it becomes possible to make the server accept only accounting,
+# or authentication packets. Previously, it always listened for both
+# types of packets, and it was impossible to make it listen for only
+# one type of packet.
+#
+#listen {
+ # IP address on which to listen.
+ # Allowed values are:
+ # dotted quad (1.2.3.4)
+ # hostname (radius.example.com)
+ # wildcard (*)
+# ipaddr = *
+
+ # Port on which to listen.
+ # Allowed values are:
+ # integer port number (1812)
+ # 0 means "use /etc/services for the proper port"
+# port = 0
+
+ # Type of packets to listen for.
+ # Allowed values are:
+ # auth listen for authentication packets
+ # acct listen for accounting packets
+ #
+# type = auth
+#}
+
+
+# hostname_lookups: Log the names of clients or just their IP addresses
+# e.g., www.freeradius.org (on) or 206.47.27.232 (off).
+#
+# The default is 'off' because it would be overall better for the net
+# if people had to knowingly turn this feature on, since enabling it
+# means that each client request will result in AT LEAST one lookup
+# request to the nameserver. Enabling hostname_lookups will also
+# mean that your server may stop randomly for 30 seconds from time
+# to time, if the DNS requests take too long.
+#
+# Turning hostname lookups off also means that the server won't block
+# for 30 seconds, if it sees an IP address which has no name associated
+# with it.
+#
+# allowed values: {no, yes}
+#
+hostname_lookups = no
+
+# Core dumps are a bad thing. This should only be set to 'yes'
+# if you're debugging a problem with the server.
+#
+# allowed values: {no, yes}
+#
+allow_core_dumps = no
+
+# Regular expressions
+#
+# These items are set at configure time. If they're set to "yes",
+# then setting them to "no" turns off regular expression support.
+#
+# If they're set to "no" at configure time, then setting them to "yes"
+# WILL NOT WORK. It will give you an error.
+#
+regular_expressions = yes
+extended_expressions = yes
+
+# Log the full User-Name attribute, as it was found in the request.
+#
+# allowed values: {no, yes}
+#
+log_stripped_names = no
+
+# Log authentication requests to the log file.
+#
+# allowed values: {no, yes}
+#
+log_auth = no
+
+# Log passwords with the authentication requests.
+# log_auth_badpass - logs password if it's rejected
+# log_auth_goodpass - logs password if it's correct
+#
+# allowed values: {no, yes}
+#
+log_auth_badpass = no
+log_auth_goodpass = no
+
+# usercollide: Turn "username collision" code on and off. See the
+# "doc/duplicate-users" file
+#
+# WARNING
+# !!!!!!! Setting this to "yes" may result in the server behaving
+# !!!!!!! strangely. The "username collision" code will ONLY work
+# !!!!!!! with clear-text passwords. Even then, it may not do what
+# !!!!!!! you want, or what you expect.
+# !!!!!!!
+# !!!!!!! We STRONGLY RECOMMEND that you do not use this feature,
+# !!!!!!! and that you find another way of acheiving the same goal.
+# !!!!!!!
+# !!!!!!! e,g. module fail-over. See 'doc/configurable_failover'
+# WARNING
+#
+usercollide = no
+
+# lower_user / lower_pass:
+# Lower case the username/password "before" or "after"
+# attempting to authenticate.
+#
+# If "before", the server will first modify the request and then try
+# to auth the user. If "after", the server will first auth using the
+# values provided by the user. If that fails it will reprocess the
+# request after modifying it as you specify below.
+#
+# This is as close as we can get to case insensitivity. It is the
+# admin's job to ensure that the username on the auth db side is
+# *also* lowercase to make this work
+#
+# Default is 'no' (don't lowercase values)
+# Valid values = "before" / "after" / "no"
+#
+lower_user = no
+lower_pass = no
+
+# nospace_user / nospace_pass:
+#
+# Some users like to enter spaces in their username or password
+# incorrectly. To save yourself the tech support call, you can
+# eliminate those spaces here:
+#
+# Default is 'no' (don't remove spaces)
+# Valid values = "before" / "after" / "no" (explanation above)
+#
+nospace_user = no
+nospace_pass = no
+
+# The program to execute to do concurrency checks.
+checkrad = ${sbindir}/checkrad
+
+# SECURITY CONFIGURATION
+#
+# There may be multiple methods of attacking on the server. This
+# section holds the configuration items which minimize the impact
+# of those attacks
+#
+security {
+ #
+ # max_attributes: The maximum number of attributes
+ # permitted in a RADIUS packet. Packets which have MORE
+ # than this number of attributes in them will be dropped.
+ #
+ # If this number is set too low, then no RADIUS packets
+ # will be accepted.
+ #
+ # If this number is set too high, then an attacker may be
+ # able to send a small number of packets which will cause
+ # the server to use all available memory on the machine.
+ #
+ # Setting this number to 0 means "allow any number of attributes"
+ max_attributes = 200
+
+ #
+ # reject_delay: When sending an Access-Reject, it can be
+ # delayed for a few seconds. This may help slow down a DoS
+ # attack. It also helps to slow down people trying to brute-force
+ # crack a users password.
+ #
+ # Setting this number to 0 means "send rejects immediately"
+ #
+ # If this number is set higher than 'cleanup_delay', then the
+ # rejects will be sent at 'cleanup_delay' time, when the request
+ # is deleted from the internal cache of requests.
+ #
+ # Useful ranges: 1 to 5
+ reject_delay = 1
+
+ #
+ # status_server: Whether or not the server will respond
+ # to Status-Server requests.
+ #
+ # Normally this should be set to "no", because they're useless.
+ # See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
+ #
+ # However, certain NAS boxes may require them.
+ #
+ # When sent a Status-Server message, the server responds with
+ # an Access-Accept packet, containing a Reply-Message attribute,
+ # which is a string describing how long the server has been
+ # running.
+ #
+ status_server = no
+}
+
+# PROXY CONFIGURATION
+#
+# proxy_requests: Turns proxying of RADIUS requests on or off.
+#
+# The server has proxying turned on by default. If your system is NOT
+# set up to proxy requests to another server, then you can turn proxying
+# off here. This will save a small amount of resources on the server.
+#
+# If you have proxying turned off, and your configuration files say
+# to proxy a request, then an error message will be logged.
+#
+# To disable proxying, change the "yes" to "no", and comment the
+# $INCLUDE line.
+#
+# allowed values: {no, yes}
+#
+proxy_requests = yes
+$INCLUDE ${confdir}/proxy.conf
+
+
+# CLIENTS CONFIGURATION
+#
+# Client configuration is defined in "clients.conf".
+#
+
+# The 'clients.conf' file contains all of the information from the old
+# 'clients' and 'naslist' configuration files. We recommend that you
+# do NOT use 'client's or 'naslist', although they are still
+# supported.
+#
+# Anything listed in 'clients.conf' will take precedence over the
+# information from the old-style configuration files.
+#
+$INCLUDE ${confdir}/clients.conf
+
+
+# SNMP CONFIGURATION
+#
+# Snmp configuration is only valid if SNMP support was enabled
+# at compile time.
+#
+# To enable SNMP querying of the server, set the value of the
+# 'snmp' attribute to 'yes'
+#
+snmp = no
+$INCLUDE ${confdir}/snmp.conf
+
+
+# THREAD POOL CONFIGURATION
+#
+# The thread pool is a long-lived group of threads which
+# take turns (round-robin) handling any incoming requests.
+#
+# You probably want to have a few spare threads around,
+# so that high-load situations can be handled immediately. If you
+# don't have any spare threads, then the request handling will
+# be delayed while a new thread is created, and added to the pool.
+#
+# You probably don't want too many spare threads around,
+# otherwise they'll be sitting there taking up resources, and
+# not doing anything productive.
+#
+# The numbers given below should be adequate for most situations.
+#
+thread pool {
+ # Number of servers to start initially --- should be a reasonable
+ # ballpark figure.
+ start_servers = 5
+
+ # Limit on the total number of servers running.
+ #
+ # If this limit is ever reached, clients will be LOCKED OUT, so it
+ # should NOT BE SET TOO LOW. It is intended mainly as a brake to
+ # keep a runaway server from taking the system with it as it spirals
+ # down...
+ #
+ # You may find that the server is regularly reaching the
+ # 'max_servers' number of threads, and that increasing
+ # 'max_servers' doesn't seem to make much difference.
+ #
+ # If this is the case, then the problem is MOST LIKELY that
+ # your back-end databases are taking too long to respond, and
+ # are preventing the server from responding in a timely manner.
+ #
+ # The solution is NOT do keep increasing the 'max_servers'
+ # value, but instead to fix the underlying cause of the
+ # problem: slow database, or 'hostname_lookups=yes'.
+ #
+ # For more information, see 'max_request_time', above.
+ #
+ max_servers = 32
+
+ # Server-pool size regulation. Rather than making you guess
+ # how many servers you need, FreeRADIUS dynamically adapts to
+ # the load it sees, that is, it tries to maintain enough
+ # servers to handle the current load, plus a few spare
+ # servers to handle transient load spikes.
+ #
+ # It does this by periodically checking how many servers are
+ # waiting for a request. If there are fewer than
+ # min_spare_servers, it creates a new spare. If there are
+ # more than max_spare_servers, some of the spares die off.
+ # The default values are probably OK for most sites.
+ #
+ min_spare_servers = 3
+ max_spare_servers = 10
+
+ # There may be memory leaks or resource allocation problems with
+ # the server. If so, set this value to 300 or so, so that the
+ # resources will be cleaned up periodically.
+ #
+ # This should only be necessary if there are serious bugs in the
+ # server which have not yet been fixed.
+ #
+ # '0' is a special value meaning 'infinity', or 'the servers never
+ # exit'
+ max_requests_per_server = 0
+}
+
+# MODULE CONFIGURATION
+#
+# The names and configuration of each module is located in this section.
+#
+# After the modules are defined here, they may be referred to by name,
+# in other sections of this configuration file.
+#
+modules {
+ #
+ # Each module has a configuration as follows:
+ #
+ # name [ instance ] {
+ # config_item = value
+ # ...
+ # }
+ #
+ # The 'name' is used to load the 'rlm_name' library
+ # which implements the functionality of the module.
+ #
+ # The 'instance' is optional. To have two different instances
+ # of a module, it first must be referred to by 'name'.
+ # The different copies of the module are then created by
+ # inventing two 'instance' names, e.g. 'instance1' and 'instance2'
+ #
+ # The instance names can then be used in later configuration
+ # INSTEAD of the original 'name'. See the 'radutmp' configuration
+ # below for an example.
+ #
+
+ # PAP module to authenticate users based on their stored password
+ #
+ # Supports multiple encryption schemes
+ # clear: Clear text
+ # crypt: Unix crypt
+ # md5: MD5 ecnryption
+ # sha1: SHA1 encryption.
+ # DEFAULT: crypt
+ pap {
+ encryption_scheme = crypt
+ }
+
+ # CHAP module
+ #
+ # To authenticate requests containing a CHAP-Password attribute.
+ #
+ chap {
+ authtype = CHAP
+ }
+
+ # Extensible Authentication Protocol
+ #
+ # For all EAP related authentications.
+ # Now in another file, because it is very large.
+ #
+$INCLUDE ${confdir}/eap.conf
+
+ # Microsoft CHAP authentication
+ #
+ # This module supports MS-CHAP and MS-CHAPv2 authentication.
+ # It also enforces the SMB-Account-Ctrl attribute.
+ #
+ mschap {
+ #
+ # As of 0.9, the mschap module does NOT support
+ # reading from /etc/smbpasswd.
+ #
+ # If you are using /etc/smbpasswd, see the 'passwd'
+ # module for an example of how to use /etc/smbpasswd
+
+ # if use_mppe is not set to no mschap will
+ # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
+ # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
+ #
+ use_mppe = yes
+ authtype = MS-CHAP
+
+ # if mppe is enabled require_encryption makes
+ # encryption moderate
+ #
+ #require_encryption = yes
+
+ # require_strong always requires 128 bit key
+ # encryption
+ #
+ #require_strong = yes
+
+ # Windows sends us a username in the form of
+ # DOMAIN\user, but sends the challenge response
+ # based on only the user portion. This hack
+ # corrects for that incorrect behavior.
+ #
+ #with_ntdomain_hack = no
+
+ # The module can perform authentication itself, OR
+ # use a Windows Domain Controller. This configuration
+ # directive tells the module to call the ntlm_auth
+ # program, which will do the authentication, and return
+ # the NT-Key. Note that you MUST have "winbindd" and
+ # "nmbd" running on the local machine for ntlm_auth
+ # to work. See the ntlm_auth program documentation
+ # for details.
+ #
+ # Be VERY careful when editing the following line!
+ #
+ #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
+ }
+
+ # Preprocess the incoming RADIUS request, before handing it off
+ # to other modules.
+ #
+ # This module processes the 'huntgroups' and 'hints' files.
+ # In addition, it re-writes some weird attributes created
+ # by some NASes, and converts the attributes into a form which
+ # is a little more standard.
+ #
+ preprocess {
+ huntgroups = ${confdir}/huntgroups
+ hints = ${confdir}/hints
+
+ # This hack changes Ascend's wierd port numberings
+ # to standard 0-??? port numbers so that the "+" works
+ # for IP address assignments.
+ with_ascend_hack = no
+ ascend_channels_per_line = 23
+
+ # Windows NT machines often authenticate themselves as
+ # NT_DOMAIN\username
+ #
+ # If this is set to 'yes', then the NT_DOMAIN portion
+ # of the user-name is silently discarded.
+ #
+ # This configuration entry SHOULD NOT be used.
+ # See the "realms" module for a better way to handle
+ # NT domains.
+ with_ntdomain_hack = no
+
+ # Specialix Jetstream 8500 24 port access server.
+ #
+ # If the user name is 10 characters or longer, a "/"
+ # and the excess characters after the 10th are
+ # appended to the user name.
+ #
+ # If you're not running that NAS, you don't need
+ # this hack.
+ with_specialix_jetstream_hack = no
+
+ # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
+ # with the attribute name *again* in the string, like:
+ #
+ # H323-Attribute = "h323-attribute=value".
+ #
+ # If this configuration item is set to 'yes', then
+ # the redundant data in the the attribute text is stripped
+ # out. The result is:
+ #
+ # H323-Attribute = "value"
+ #
+ # If you're not running a Cisco or Quintum NAS, you don't
+ # need this hack.
+ with_cisco_vsa_hack = no
+ }
+
+ # Write a detailed log of all accounting records received.
+ #
+ detail {
+ # Note that we do NOT use NAS-IP-Address here, as
+ # that attribute MAY BE from the originating NAS, and
+ # NOT from the proxy which actually sent us the
+ # request. The Client-IP-Address attribute is ALWAYS
+ # the address of the client which sent us the
+ # request.
+ #
+ # The following line creates a new detail file for
+ # every radius client (by IP address or hostname).
+ # In addition, a new detail file is created every
+ # day, so that the detail file doesn't have to go
+ # through a 'log rotation'
+ #
+ # If your detail files are large, you may also want
+ # to add a ':%H' (see doc/variables.txt) to the end
+ # of it, to create a new detail file every hour, e.g.:
+ #
+ # ..../detail-%Y%m%d:%H
+ #
+ # This will create a new detail file for every hour.
+ #
+ detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
+
+ #
+ # The Unix-style permissions on the 'detail' file.
+ #
+ # The detail file often contains secret or private
+ # information about users. So by keeping the file
+ # permissions restrictive, we can prevent unwanted
+ # people from seeing that information.
+ detailperm = 0600
+
+ #
+ # Certain attributes such as User-Password may be
+ # "sensitive", so they should not be printed in the
+ # detail file. This section lists the attributes
+ # that should be suppressed.
+ #
+ # The attributes should be listed one to a line.
+ #
+ #suppress {
+ # User-Password
+ #}
+ }
+
+ #
+ # Create a unique accounting session Id. Many NASes re-use
+ # or repeat values for Acct-Session-Id, causing no end of
+ # confusion.
+ #
+ # This module will add a (probably) unique session id
+ # to an accounting packet based on the attributes listed
+ # below found in the packet. See doc/rlm_acct_unique for
+ # more information.
+ #
+ acct_unique {
+ key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+ }
+
+ # Write a 'utmp' style file, of which users are currently
+ # logged in, and where they've logged in from.
+ #
+ # This file is used mainly for Simultaneous-Use checking,
+ # and also 'radwho', to see who's currently logged in.
+ #
+ radutmp {
+ # Where the file is stored. It's not a log file,
+ # so it doesn't need rotating.
+ #
+ filename = ${logdir}/radutmp
+
+ # The field in the packet to key on for the
+ # 'user' name, If you have other fields which you want
+ # to use to key on to control Simultaneous-Use,
+ # then you can use them here.
+ #
+ # Note, however, that the size of the field in the
+ # 'utmp' data structure is small, around 32
+ # characters, so that will limit the possible choices
+ # of keys.
+ #
+ # You may want instead: %{Stripped-User-Name:-%{User-Name}}
+ username = %{User-Name}
+
+
+ # Whether or not we want to treat "user" the same
+ # as "USER", or "User". Some systems have problems
+ # with case sensitivity, so this should be set to
+ # 'no' to enable the comparisons of the key attribute
+ # to be case insensitive.
+ #
+ case_sensitive = yes
+
+ # Accounting information may be lost, so the user MAY
+ # have logged off of the NAS, but we haven't noticed.
+ # If so, we can verify this information with the NAS,
+ #
+ # If we want to believe the 'utmp' file, then this
+ # configuration entry can be set to 'no'.
+ #
+ check_with_nas = yes
+
+ # Set the file permissions, as the contents of this file
+ # are usually private.
+ perm = 0600
+
+ callerid = "yes"
+ }
+
+ # "Safe" radutmp - does not contain caller ID, so it can be
+ # world-readable, and radwho can work for normal users, without
+ # exposing any information that isn't already exposed by who(1).
+ #
+ # This is another 'instance' of the radutmp module, but it is given
+ # then name "sradutmp" to identify it later in the "accounting"
+ # section.
+ radutmp sradutmp {
+ filename = ${logdir}/sradutmp
+ perm = 0644
+ callerid = "no"
+ }
+
+ # attr_filter - filters the attributes received in replies from
+ # proxied servers, to make sure we send back to our RADIUS client
+ # only allowed attributes.
+ attr_filter {
+ attrsfile = ${confdir}/attrs
+ }
+
+ # counter module:
+ # This module takes an attribute (count-attribute).
+ # It also takes a key, and creates a counter for each unique
+ # key. The count is incremented when accounting packets are
+ # received by the server. The value of the increment depends
+ # on the attribute type.
+ # If the attribute is Acct-Session-Time or of an integer type we add the
+ # value of the attribute. If it is anything else we increase the
+ # counter by one.
+ #
+ # The 'reset' parameter defines when the counters are all reset to
+ # zero. It can be hourly, daily, weekly, monthly or never.
+ #
+ # hourly: Reset on 00:00 of every hour
+ # daily: Reset on 00:00:00 every day
+ # weekly: Reset on 00:00:00 on sunday
+ # monthly: Reset on 00:00:00 of the first day of each month
+ #
+ # It can also be user defined. It should be of the form:
+ # num[hdwm] where:
+ # h: hours, d: days, w: weeks, m: months
+ # If the letter is ommited days will be assumed. In example:
+ # reset = 10h (reset every 10 hours)
+ # reset = 12 (reset every 12 days)
+ #
+ #
+ # The check-name attribute defines an attribute which will be
+ # registered by the counter module and can be used to set the
+ # maximum allowed value for the counter after which the user
+ # is rejected.
+ # Something like:
+ #
+ # DEFAULT Max-Daily-Session := 36000
+ # Fall-Through = 1
+ #
+ # You should add the counter module in the instantiate
+ # section so that it registers check-name before the files
+ # module reads the users file.
+ #
+ # If check-name is set and the user is to be rejected then we
+ # send back a Reply-Message and we log a Failure-Message in
+ # the radius.log
+ # If the count attribute is Acct-Session-Time then on each login
+ # we send back the remaining online time as a Session-Timeout attribute
+ #
+ # The counter-name can also be used instead of using the check-name
+ # like below:
+ #
+ # DEFAULT Daily-Session-Time > 3600, Auth-Type = Reject
+ # Reply-Message = "You've used up more than one hour today"
+ #
+ # The allowed-servicetype attribute can be used to only take
+ # into account specific sessions. For example if a user first
+ # logs in through a login menu and then selects ppp there will
+ # be two sessions. One for Login-User and one for Framed-User
+ # service type. We only need to take into account the second one.
+ #
+ # The module should be added in the instantiate, authorize and
+ # accounting sections. Make sure that in the authorize
+ # section it comes after any module which sets the
+ # 'check-name' attribute.
+ #
+ counter daily {
+ filename = ${raddbdir}/db.daily
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = daily
+ counter-name = Daily-Session-Time
+ check-name = Max-Daily-Session
+ allowed-servicetype = Framed-User
+ cache-size = 5000
+ }
+
+ #
+ # The "always" module is here for debugging purposes. Each
+ # instance simply returns the same result, always, without
+ # doing anything.
+ always fail {
+ rcode = fail
+ }
+ always reject {
+ rcode = reject
+ }
+ always ok {
+ rcode = ok
+ simulcount = 0
+ mpp = no
+ }
+
+ stg {
+ local_port = 6667
+ server = localhost
+ port = 6666
+ password = 123456
+ }
+
+}
+
+# Instantiation
+#
+# This section orders the loading of the modules. Modules
+# listed here will get loaded BEFORE the later sections like
+# authorize, authenticate, etc. get examined.
+#
+# This section is not strictly needed. When a section like
+# authorize refers to a module, it's automatically loaded and
+# initialized. However, some modules may not be listed in any
+# of the following sections, so they can be listed here.
+#
+# Also, listing modules here ensures that you have control over
+# the order in which they are initalized. If one module needs
+# something defined by another module, you can list them in order
+# here, and ensure that the configuration will be OK.
+#
+instantiate {
+ stg
+}
+
+# Authorization. First preprocess (hints and huntgroups files),
+# then realms, and finally look in the "users" file.
+#
+# The order of the realm modules will determine the order that
+# we try to find a matching realm.
+#
+# Make *sure* that 'preprocess' comes before any realm if you
+# need to setup hints for the remote radius server
+authorize {
+ #
+ # The preprocess module takes care of sanitizing some bizarre
+ # attributes in the request, and turning them into attributes
+ # which are more standard.
+ #
+ # It takes care of processing the 'raddb/hints' and the
+ # 'raddb/huntgroups' files.
+ #
+ # It also adds the %{Client-IP-Address} attribute to the request.
+ preprocess
+
+ #
+ # The chap module will set 'Auth-Type := CHAP' if we are
+ # handling a CHAP request and Auth-Type has not already been set
+ chap
+
+ #
+ # If the users are logging in with an MS-CHAP-Challenge
+ # attribute for authentication, the mschap module will find
+ # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
+ # to the request, which will cause the server to then use
+ # the mschap module for authentication.
+ mschap
+
+ #
+ # This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
+ # authentication.
+ #
+ # It also sets the EAP-Type attribute in the request
+ # attribute list to the EAP type from the packet.
+ eap
+
+ stg
+}
+
+
+# Authentication.
+#
+#
+# This section lists which modules are available for authentication.
+# Note that it does NOT mean 'try each module in order'. It means
+# that a module from the 'authorize' section adds a configuration
+# attribute 'Auth-Type := FOO'. That authentication type is then
+# used to pick the apropriate module from the list below.
+#
+
+# In general, you SHOULD NOT set the Auth-Type attribute. The server
+# will figure it out on its own, and will do the right thing. The
+# most common side effect of erroneously setting the Auth-Type
+# attribute is that one authentication method will work, but the
+# others will not.
+#
+# The common reasons to set the Auth-Type attribute by hand
+# is to either forcibly reject the user, or forcibly accept him.
+#
+authenticate {
+ #
+ # PAP authentication, when a back-end database listed
+ # in the 'authorize' section supplies a password. The
+ # password can be clear-text, or encrypted.
+ Auth-Type PAP {
+ stg
+ pap
+ }
+
+ #
+ # Most people want CHAP authentication
+ # A back-end database listed in the 'authorize' section
+ # MUST supply a CLEAR TEXT password. Encrypted passwords
+ # won't work.
+ Auth-Type CHAP {
+ stg
+ chap
+ }
+
+ #
+ # MSCHAP authentication.
+ Auth-Type MS-CHAP {
+ stg
+ mschap
+ }
+
+ #
+ # Allow EAP authentication.
+ eap
+}
+
+
+#
+# Pre-accounting. Decide which accounting type to use.
+#
+preacct {
+ preprocess
+
+ #
+ # Ensure that we have a semi-unique identifier for every
+ # request, and many NAS boxes are broken.
+ acct_unique
+}
+
+#
+# Accounting. Log the accounting data.
+#
+accounting {
+ #
+ # Create a 'detail'ed log of the packets.
+ # Note that accounting requests which are proxied
+ # are also logged in the detail file.
+ detail
+# daily
+
+ #
+ # For Simultaneous-Use tracking.
+ #
+ # Due to packet losses in the network, the data here
+ # may be incorrect. There is little we can do about it.
+ radutmp
+
+ stg
+
+}
+
+
+# Session database, used for checking Simultaneous-Use. Either the radutmp
+# or rlm_sql module can handle this.
+# The rlm_sql module is *much* faster
+session {
+ radutmp
+}
+
+
+# Post-Authentication
+# Once we KNOW that the user has been authenticated, there are
+# additional steps we can take.
+post-auth {
+ stg
+}
+
+#
+# When the server decides to proxy a request to a home server,
+# the proxied request is first passed through the pre-proxy
+# stage. This stage can re-write the request, or decide to
+# cancel the proxy.
+#
+# Only a few modules currently have this method.
+#
+pre-proxy {
+}
+
+#
+# When the server receives a reply to a request it proxied
+# to a home server, the request may be massaged here, in the
+# post-proxy stage.
+#
+post-proxy {
+ #
+ # If you are proxying LEAP, you MUST configure the EAP
+ # module, and you MUST list it here, in the post-proxy
+ # stage.
+ #
+ # You MUST also use the 'nostrip' option in the 'realm'
+ # configuration. Otherwise, the User-Name attribute
+ # in the proxied request will not match the user name
+ # hidden inside of the EAP packet, and the end server will
+ # reject the EAP request.
+ #
+ eap
+}
--- /dev/null
+#!/bin/sh
+
+rm -f /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+echo $PPP_IFACE > /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
--- /dev/null
+###############################################################################
+# $Id: pptpd-options,v 1.1 2008/03/31 13:55:20 faust Exp $
+#
+# Sample Poptop PPP options file /etc/ppp/pptpd-options
+# Options used by PPP when a connection arrives from a client.
+# This file is pointed to by /etc/pptpd.conf option keyword.
+# Changes are effective on the next connection. See "man pppd".
+#
+# You are expected to change this file to suit your system. As
+# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
+###############################################################################
+
+
+# Authentication
+
+# Name of the local system for authentication purposes
+# (must match the second field in /etc/ppp/chap-secrets entries)
+name pptpd
+
+# Optional: domain name to use for authentication
+# domain mydomain.net
+
+# Strip the domain prefix from the username before authentication.
+# (applies if you use pppd with chapms-strip-domain patch)
+#chapms-strip-domain
+
+
+# Encryption
+# Debian: on systems with a kernel built with the package
+# kernel-patch-mppe >= 2.4.2 and using ppp >= 2.4.2, ...
+# {{{
+refuse-pap
+refuse-chap
+refuse-mschap
+# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
+# Challenge Handshake Authentication Protocol, Version 2] authentication.
+require-mschap-v2
+# Require MPPE 128-bit encryption
+# (note that MPPE requires the use of MSCHAP-V2 during authentication)
+require-mppe-128
+# }}}
+
+
+
+
+# Network and Routing
+
+# If pppd is acting as a server for Microsoft Windows clients, this
+# option allows pppd to supply one or two DNS (Domain Name Server)
+# addresses to the clients. The first instance of this option
+# specifies the primary DNS address; the second instance (if given)
+# specifies the secondary DNS address.
+# Attention! This information may not be taken into account by a Windows
+# client. See KB311218 in Microsoft's knowledge base for more information.
+#ms-dns 10.0.0.1
+#ms-dns 10.0.0.2
+
+# If pppd is acting as a server for Microsoft Windows or "Samba"
+# clients, this option allows pppd to supply one or two WINS (Windows
+# Internet Name Services) server addresses to the clients. The first
+# instance of this option specifies the primary WINS address; the
+# second instance (if given) specifies the secondary WINS address.
+#ms-wins 10.0.0.3
+#ms-wins 10.0.0.4
+
+# Add an entry to this system's ARP [Address Resolution Protocol]
+# table with the IP address of the peer and the Ethernet address of this
+# system. This will have the effect of making the peer appear to other
+# systems to be on the local ethernet.
+# (you do not need this if your PPTP server is responsible for routing
+# packets to the clients -- James Cameron)
+proxyarp
+
+# Debian: do not replace the default route
+defaultroute
+
+
+# Logging
+
+# Enable connection debugging facilities.
+# (see your syslog configuration for where pppd sends to)
+#debug
+
+# Print out all the option values which have been set.
+# (often requested by mailing list to verify options)
+#dump
+
+
+# Miscellaneous
+
+# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
+# access.
+lock
+
+# Disable BSD-Compress compression
+nobsdcomp
+plugin radius.so
\ No newline at end of file
--- /dev/null
+###############################################################################
+# $Id: pptpd.conf,v 1.1 2008/03/31 13:54:13 faust Exp $
+#
+# Sample Poptop configuration file /etc/pptpd.conf
+#
+# Changes are effective when pptpd is restarted.
+###############################################################################
+
+# TAG: ppp
+# Path to the pppd program, default '/usr/sbin/pppd' on Linux
+#
+#ppp /usr/sbin/pppd
+
+# TAG: option
+# Specifies the location of the PPP options file.
+# By default PPP looks in '/etc/ppp/options'
+#
+option /etc/ppp/pptpd-options
+
+# TAG: debug
+# Turns on (more) debugging to syslog
+#
+#debug
+
+# TAG: stimeout
+# Specifies timeout (in seconds) on starting ctrl connection
+#
+# stimeout 10
+
+# TAG: noipparam
+# Suppress the passing of the client's IP address to PPP, which is
+# done by default otherwise.
+#
+#noipparam
+
+# TAG: logwtmp
+# Use wtmp(5) to record client connections and disconnections.
+#
+logwtmp
+
+# TAG: bcrelay <if>
+# Turns on broadcast relay to clients from interface <if>
+#
+#bcrelay eth1
+
+# TAG: localip
+# TAG: remoteip
+# Specifies the local and remote IP address ranges.
+#
+# Any addresses work as long as the local machine takes care of the
+# routing. But if you want to use MS-Windows networking, you should
+# use IP addresses out of the LAN address space and use the proxyarp
+# option in the pppd options file, or run bcrelay.
+#
+# You can specify single IP addresses seperated by commas or you can
+# specify ranges, or both. For example:
+#
+# 192.168.0.234,192.168.0.245-249,192.168.0.254
+#
+# IMPORTANT RESTRICTIONS:
+#
+# 1. No spaces are permitted between commas or within addresses.
+#
+# 2. If you give more IP addresses than MAX_CONNECTIONS, it will
+# start at the beginning of the list and go until it gets
+# MAX_CONNECTIONS IPs. Others will be ignored.
+#
+# 3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
+# you must type 234-238 if you mean this.
+#
+# 4. If you give a single localIP, that's ok - all local IPs will
+# be set to the given one. You MUST still give at least one remote
+# IP for each simultaneous client.
+#
+# (Recommended)
+#localip 192.168.0.1
+#remoteip 192.168.0.234-238,192.168.0.245
+# or
+#localip 192.168.0.234-238,192.168.0.245
+#remoteip 192.168.1.234-238,192.168.1.245
+localip 192.168.2.1
+remoteip 192.168.2.2-254
--- /dev/null
+localhost testing123
--- /dev/null
+#! /bin/sh
+
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
--- /dev/null
+#!/bin/bash
+
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+iptables -A INPUT -s $IP -j QUEUE
+iptables -A OUTPUT -d $IP -j QUEUE
+iptables -A FORWARD -s $IP -j QUEUE
+iptables -A FORWARD -d $IP -j QUEUE
+
+# shaper
+
+default_speed=32
+
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "speedR=$speedR" >> /var/stargazer/users/$LOGIN/connect.log
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ]
+then
+ speed=$default_speed
+fi
+
+speedkbit=$speed"kbit"
+
+#echo "speed=$speedkbit" >> /var/stargazer/users/$LOGIN/connect.log
+declare -i mark=$ID+1
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+sleep 1
+
+if [ -f "/var/stargazer/ifaces/$IP" ]
+then
+ #echo "1" >> /var/stargazer/users/$LOGIN/connect.log
+ ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+ #echo "2" >> /var/stargazer/users/$LOGIN/connect.log
+ exit 0
+fi
+
+tc qdisc add dev $ppp_iface root handle 1: htb
+tc class add dev $ppp_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+tc class add dev $ppp_iface parent 1:1 classid 1:10 htb rate $speedkbit burst 20k
+tc filter add dev $ppp_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:10
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH $ID $mark $speed $ppp_iface" >> /var/stargazer/users/$LOGIN/connect.log
+
--- /dev/null
+#!/bin/bash
+
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+iptables -D INPUT -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D INPUT -s $IP -j QUEUE
+done
+
+iptables -D OUTPUT -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D OUTPUT -d $IP -j QUEUE
+done
+
+iptables -D FORWARD -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D FORWARD -s $IP -j QUEUE
+done
+
+iptables -D FORWARD -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D FORWARD -d $IP -j QUEUE
+done
+
+
+
+declare -i mark=$ID+1
+
+iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+while [ $? == 0 ]
+do
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+done
+
+
+if [ -f /var/stargazer/ifaces/$IP ]
+then
+ ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+ exit 0
+fi
+
+tc qdisc del dev $ppp_iface root
+
+
--- /dev/null
+#! /bin/sh
+
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
--- /dev/null
+#! /bin/sh
+
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+
+# Имя лог-файла куда пишутся события
+LogFile = /var/log/stargazer.log
+
+
+
+# Имя файла в котором определяются правила подсчета трафика
+Rules = /etc/stargazer/rules
+
+
+
+# Время через которое пишется d БД детальная статистика пользователя
+# Значения: 1, 1/2, 1/4, 1/6.
+# 1 - раз в чаc, 1/2 - раз в пол часа, 1/4 - раз в 15 мин, 1/6 - раз в 10 мин
+DetailStatWritePeriod=1/6
+
+
+
+# Периодичность записи записи в БД информации о статистике пользователя (минуты)
+# При большом кол-ве пользователей эту величину стоит увеличить, т.к.
+# запись в БД может занимать длительное время.
+# Значения: 1...1440 (минуты)
+StatWritePeriod = 10
+
+
+
+# День снятия абонплаты
+# Значения: 0...31. 0 - Последний день месяца
+DayFee = 1
+
+
+
+# Абонплата снимается в последний (yes) или первый (no) день учетного периода.
+# Это влияет на то, как будет снята абонплата (АП) при переходе на новый тариф.
+# Если у пользователя был тариф A с АП=100 и он хочет перейти на тариф B с АП=200,
+# то при переходе на новый тариф со счета пользователя снимется 100, если
+# DayFeeIsLastDay = yes и 200, если DayFeeIsLastDay = no
+DayFeeIsLastDay = yes
+
+
+
+# День сброса данных о трафике за месяц и день перехода пользователей на новые тарифы
+# Значения: 0...31. 0 - Последний день месяца
+DayResetTraff = 1
+
+
+
+# "Размазанное" снятие абонплаты. Снятие АП не раз в месяц, а каждый
+# день 1/30 или 1/31 части АП
+# Значения: yes, no
+SpreadFee = no
+
+
+
+# Данная опция определяет может ли пользователь получить доступ в интерент
+# если у него на счету нет денег, но остался предоплаченный трафик
+# Значения: yes, no
+FreeMbAllowInet = no
+
+
+
+# Эта опция определяет что будет писаться в стоимость трафика в detail_stat.
+# Если у пользователя еще есть предоплаченный трафик и WriteFreeMbTraffCost = no,
+# то в detail_stat стоимость будет 0. Если у пользователя уже нет
+# предоплаченного трафика и WriteFreeMbTraffCost = no, то в detail_stat
+# будет записана стоиость трафика. При WriteFreeMbTraffCost = yes стоимость
+# трафика будет записана в любом случае.
+WriteFreeMbTraffCost = no
+
+
+
+# Необязательный параметр. Указывает снимать полную абонплату у пользователя даже
+# если он быз заморожен только часть учетного периода.
+# По умолчанию установлен в no
+# FullFee=no
+
+# Необязательный параметр указывающий показывать на счету и позволять
+# использовать пользователю абонплату. По умолчанию установлен в yes
+# ShowFeeInCash=yes
+
+
+
+# Названия направлений. Направления без названий не будут отображаться в
+# авторизаторе и конфигураторе. Названия состоящие из нескольких слов должны
+# быть взяты в кавычки
+<DirNames>
+ DirName0 = Local
+ DirName1 = City
+ DirName2 = World
+ DirName3 =
+ DirName4 =
+ DirName5 =
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+
+
+# Кол-во запускаемых процессов stg-exec.
+# Эти процессы отвечают за выполнение скриптов OnConnect, OnDisconnect, ...
+# Кол-во процессов означает сколько скриптов могут выполнятся одновременно.
+# Значения: 1...1024
+ExecutersNum = 2
+
+
+
+# Message Key для stg-exec.
+# Идентификатор очереди сообщений для выполнятеля скриптов.
+# Его изменение может понадобится если есть необходимость запустить несколько
+# экземпляров stg. Если вы не понимаете, что это, не трогайте этот параметр!
+# Значения: 0...2^32
+# Значение по умолчанию: 5555
+# ExecMsgKey = 5555
+
+
+
+# Путь к директории, в которой находятся модули сервера
+ModulesPath = /usr/lib/stg
+
+# Определяет директорию, в которой будут находится файлы "монитора"
+# работы сервера. В этой директории будут созданы пустые файлы, время
+# модификации которых будет меняться примерно раз в минуту. Если какой-то
+# компонент сервера зависнет, файл(ы) перестанет обновлятся, и по этому
+# признаку можно определить сбой в работе сервера и при надобности
+# перезапустить. Если параметр не указан или пустой, мониторинг производится
+# не будет. Параметр не является обязательным, по умолчанию пустой.
+# MonitorDir=/var/stargazer/monitor
+
+
+################################################################################
+# Store module
+# Настройки плагина работающего с БД сервера
+
+# Второй параметр - это имя модуля без mod_ в начале и .so в конце
+# Т.е. полное имя модуля mod_store_files.so
+<StoreModule store_files>
+
+ # Рабочая директория сервера, тут содержатся данные о тарифах, пользователях,
+ # администраторах и т.д.
+ WorkDir = /var/stargazer
+
+
+ # Владелец, группа и права доступа на файлы статистики (stat) пользователя
+ ConfOwner = root
+ ConfGroup = root
+ ConfMode = 600
+
+
+ # Владелец, группа и права доступа на файлы конфигурации (conf) пользователя
+ StatOwner = root
+ StatGroup = root
+ StatMode = 640
+
+ # Владелец, группа и права доступа на лог-файлы (log) пользователя
+ UserLogOwner = root
+ UserLogGroup = root
+ UserLogMode = 640
+
+</StoreModule>
+
+#<StoreModule store_firebird>
+# # Адрес сервера БД
+# server=localhost
+#
+# # Путь к БД на сервере или ее алиас
+# path=/var/stg/stargazer.fdb
+#
+# # Имя пользователя БД
+# user=stg
+#
+# # Пароль пользователя БД
+# password=123456
+#</StoreModule>
+
+#<StoreModule store_mysql>
+# # Имя пользователя БД
+# dbuser = stg
+#
+# # Пароль пользователя БД
+# rootdbpass = 123456
+#
+# # Имя БД на сервере
+# dbname = stg
+#
+# # Адрес сервера БД
+# dbhost = localhost
+#</StoreModule>
+
+
+
+################################################################################
+# Прочие модули
+
+<Modules>
+
+ # Настройки плагина авторизации Always Online "mod_auth_ao.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ # Т.е. полное имя модуля mod_auth_ao.so
+ #<Module auth_ao>
+ #</Module>
+
+
+
+ # Настройки плагина авторизации InetAccess "mod_auth_ia.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ # Т.е. полное имя модуля mod_auth_ia.so
+ #<Module auth_ia>
+ # Port = 5555
+ # UserDelay = 15
+ # UserTimeout = 65
+ # FreeMb = 0
+ #</Module>
+
+
+
+ # Настройки модуля конфигурации SgConfig "mod_conf_sg.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ <Module conf_sg>
+
+ # Порт по которому сервер взаимодействует с конфигуратором
+ # Значения: 1...65535
+ Port = 5555
+
+ </Module>
+
+
+
+ # Модуль захвата трафика "mod_cap_ether.so"
+ # Второй параметер - это имя модуля без mod_ в начале и .so в конце
+ # Без параметров. Только имя модуля.
+ <Module cap_ipq>
+ # Модуль без параметров
+ </Module>
+
+
+
+ # Настройки модуля пингующего пользователей "mod_ping.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ <Module ping>
+
+ # Время, в секундах, между пингами одного и того же пользователя
+ # Значения: 10...3600
+ PingDelay = 15
+
+ </Module>
+
+ <Module radius>
+ Password = 123456
+ ServerIP = 127.0.0.1
+ Port = 6666
+ AuthServices = Login-User
+ AcctServices = Framed-User
+ </Module>
+
+# # Настройки модуля для удаленного выполнения скриптов OnConnect и
+# # OnDisconnect "mod_remote_script.so"
+# # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+# <Module remote_script>
+#
+# # Время, в секундах, между посылками подтверждений, того, что пользователь
+# # всё еще онлайн
+# # Значения: 10...600
+# SendPeriod = 15
+#
+# # Соответствие подсетей, в которой находится пользователь и
+# # соответствующего роутера. Первая часть строки - подсеть, заданная
+# # как IP-адрес и маска, через пробел - IP-адрес роутера на котором
+# # должны выполняться скрипты
+# # Например эта запись "192.168.1.0/24 192.168.1.1" означает, что для
+# # всех пользователей из подсети 192.168.1.0/24, скрипты будут
+# # выполняться на роутере с адресом 192.168.1.1
+# # Subnet0...Subnet100
+# Subnet0 = 192.168.1.0/24 192.168.1.7
+# Subnet1 = 192.168.2.0/24 192.168.2.5
+# Subnet2 = 192.168.3.0/24 192.168.2.5
+# Subnet3 = 192.168.4.0/24 192.168.2.5
+#
+# # Пароль для шифрования пакетов между stg-сервером и сервером,
+# # выполняющим скрипты
+# Password = 123456
+#
+# # Этот параметр определяет какие параметры пользователя передаются
+# # на удаленный сервер
+# # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
+# # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
+# UserParams=Cash Tariff EnabledDirs
+#
+# # Порт по которому сервер отсылает сообщения на роутер
+# # Значения: 1...65535
+# Port = 9999
+#
+# </Module>
+
+</Modules>
+################################################################################
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#include <cerrno>
+#include <cassert>
+#include <algorithm>
+
+#include "stg/admin.h"
+#include "stg/common.h"
+#include "services_impl.h"
+
+//-----------------------------------------------------------------------------
+SERVICES_IMPL::SERVICES_IMPL(STORE * st)
+ : SERVICES(),
+ data(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ searchDescriptors(),
+ handle(0),
+ mutex(),
+ strError()
+{
+pthread_mutex_init(&mutex, NULL);
+Read();
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::Add(const SERVICE_CONF & service, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->serviceChg)
+ {
+ std::string s = admin->GetLogStr() + " Add service \'" + service.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+iterator si(std::find(data.begin(), data.end(), service));
+
+if (si != data.end())
+ {
+ strError = "Service \'" + service.name + "\' cannot not be added. Service already exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+data.push_back(service);
+
+if (store->AddService(service.name) == 0)
+ {
+ WriteServLog("%s Service \'%s\' added.",
+ admin->GetLogStr().c_str(), service.name.c_str());
+ return 0;
+ }
+
+strError = "Service \'" + service.name + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::Del(const std::string & name, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->serviceChg)
+ {
+ std::string s = admin->GetLogStr() + " Delete service \'" + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
+
+if (si == data.end())
+ {
+ strError = "Service \'" + name + "\' cannot be deleted. Service does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+std::map<int, const_iterator>::iterator csi;
+csi = searchDescriptors.begin();
+while (csi != searchDescriptors.end())
+ {
+ if (csi->second == si)
+ (csi->second)++;
+ ++csi;
+ }
+
+data.remove(*si);
+if (store->DelService(name) < 0)
+ {
+ strError = "Service \'" + name + "\' was not deleted. Error: " + store->GetStrError();
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+WriteServLog("%s Service \'%s\' deleted.", admin->GetLogStr().c_str(), name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::Change(const SERVICE_CONF & service, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->serviceChg)
+ {
+ std::string s = admin->GetLogStr() + " Change service \'" + service.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+iterator si(std::find(data.begin(), data.end(), service));
+
+if (si == data.end())
+ {
+ strError = "Service \'" + service.name + "\' cannot be changed " + ". Service does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+printfd(__FILE__, "Old cost = %f, old pay day = %d\n", si->cost, (unsigned)si->payDay);
+*si = service;
+printfd(__FILE__, "New cost = %f, New pay day = %d\n", si->cost, (unsigned)si->payDay);
+if (store->SaveService(service))
+ {
+ WriteServLog("Cannot write service %s.", service.name.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+WriteServLog("%s Service \'%s\' changed.",
+ admin->GetLogStr().c_str(), service.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool SERVICES_IMPL::Read()
+{
+STG_LOCKER lock(&mutex);
+std::vector<std::string> servicesList;
+if (store->GetServicesList(&servicesList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return true;
+ }
+
+for (size_t i = 0; i < servicesList.size(); i++)
+ {
+ SERVICE_CONF service;
+
+ if (store->RestoreService(&service, servicesList[i]))
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return true;
+ }
+
+ data.push_back(service);
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool SERVICES_IMPL::Find(const std::string & name, SERVICE_CONF * service) const
+{
+assert(service != NULL && "Pointer to service is not null");
+
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ return true;
+
+const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
+
+if (si != data.end())
+ {
+ *service = *si;
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool SERVICES_IMPL::Find(const std::string & name, SERVICE_CONF_RES * service) const
+{
+assert(service != NULL && "Pointer to service is not null");
+
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ return true;
+
+const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
+
+if (si != data.end())
+ {
+ *service = *si;
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool SERVICES_IMPL::Exists(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+if (data.empty())
+ {
+ printfd(__FILE__, "No services in the system!\n");
+ return true;
+ }
+
+const_iterator si(std::find(data.begin(), data.end(), SERVICE_CONF(name)));
+
+if (si != data.end())
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::OpenSearch() const
+{
+STG_LOCKER lock(&mutex);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::SearchNext(int h, SERVICE_CONF * service) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("SERVICES. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == data.end())
+ return -1;
+
+*service = *searchDescriptors[h]++;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SERVICES_IMPL::CloseSearch(int h) const
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("SERVICES. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+#ifndef SERVICES_IMPL_H
+#define SERVICES_IMPL_H
+
+#include "stg/services.h"
+#include "stg/service_conf.h"
+#include "stg/locker.h"
+#include "stg/store.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <pthread.h>
+
+class ADMIN;
+
+class SERVICES_IMPL : private NONCOPYABLE, public SERVICES {
+public:
+ explicit SERVICES_IMPL(STORE * st);
+ virtual ~SERVICES_IMPL() {}
+
+ int Add(const SERVICE_CONF & service, const ADMIN * admin);
+ int Del(const std::string & name, const ADMIN * admin);
+ int Change(const SERVICE_CONF & service, const ADMIN * admin);
+ bool Find(const std::string & name, SERVICE_CONF * service) const;
+ bool Find(const std::string & name, SERVICE_CONF_RES * service) const;
+ bool Exists(const std::string & name) const;
+ const std::string & GetStrError() const { return strError; }
+
+ size_t Count() const { return data.size(); }
+
+ int OpenSearch() const;
+ int SearchNext(int, SERVICE_CONF * service) const;
+ int CloseSearch(int) const;
+
+private:
+ SERVICES_IMPL(const SERVICES_IMPL & rvalue);
+ SERVICES_IMPL & operator=(const SERVICES_IMPL & rvalue);
+
+ typedef std::list<SERVICE_CONF>::iterator iterator;
+ typedef std::list<SERVICE_CONF>::const_iterator const_iterator;
+
+ bool Read();
+
+ std::list<SERVICE_CONF> data;
+ STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable std::map<int, const_iterator> searchDescriptors;
+ mutable unsigned int handle;
+ mutable pthread_mutex_t mutex;
+ std::string strError;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#include "settings_impl.h"
+
+#include "stg/logger.h"
+#include "stg/dotconfpp.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <stdexcept>
+#include <cstring>
+#include <cerrno>
+
+namespace
+{
+
+struct Error : public std::runtime_error
+{
+ Error(const std::string& message) : runtime_error(message) {}
+};
+
+std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
+{
+ std::vector<std::string> values;
+
+ size_t i = 0;
+ const char* value = NULL;
+ while ((value = node.getValue(i++)) != NULL)
+ values.push_back(value);
+
+ return values;
+}
+
+std::vector<PARAM_VALUE> toPVS(const DOTCONFDocumentNode& node)
+{
+ std::vector<PARAM_VALUE> pvs;
+
+ const DOTCONFDocumentNode* child = node.getChildNode();
+ while (child != NULL)
+ {
+ if (child->getName() == NULL)
+ continue;
+
+ if (child->getChildNode() == NULL)
+ pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child)));
+ else
+ pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child), toPVS(*child)));
+
+ child = child->getNextNode();
+ }
+
+ return pvs;
+}
+
+unsigned toPeriod(const char* value)
+{
+ if (value == NULL)
+ throw Error("No detail stat period value.");
+
+ std::string period(value);
+ if (period == "1")
+ return dsPeriod_1;
+ else if (period == "1/2")
+ return dsPeriod_1_2;
+ else if (period == "1/4")
+ return dsPeriod_1_4;
+ else if (period == "1/6")
+ return dsPeriod_1_6;
+
+ throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'.");
+}
+
+}
+
+//-----------------------------------------------------------------------------
+SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd)
+ : modulesPath("/usr/lib/stg"),
+ dirName(DIR_NUM),
+ confDir(cd.empty() ? "/etc/stargazer" : cd),
+ scriptsDir(confDir),
+ rules(confDir + "/rules"),
+ logFile("/var/log/stargazer.log"),
+ pidFile("/var/run/stargazer.pid"),
+ monitorDir("/var/stargazer/monitoring"),
+ monitoring(false),
+ detailStatWritePeriod(dsPeriod_1_6),
+ statWritePeriod(10),
+ stgExecMsgKey(5555),
+ executersNum(1),
+ fullFee(false),
+ dayFee(0),
+ dayResetTraff(0),
+ spreadFee(false),
+ freeMbAllowInet(false),
+ dayFeeIsLastDay(false),
+ stopOnError(true),
+ writeFreeMbTraffCost(false),
+ showFeeInCash(true),
+ messageTimeout(0),
+ feeChargeType(0),
+ reconnectOnTariffChange(false),
+ disableSessionLog(false),
+ logger(GetStgLogger())
+{
+ filterParamsLog.push_back("*");
+}
+//-----------------------------------------------------------------------------
+SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval)
+ : modulesPath(rval.modulesPath),
+ dirName(rval.dirName),
+ confDir(rval.confDir),
+ scriptsDir(rval.scriptsDir),
+ rules(rval.rules),
+ logFile(rval.logFile),
+ pidFile(rval.pidFile),
+ monitorDir(rval.monitorDir),
+ monitoring(rval.monitoring),
+ detailStatWritePeriod(rval.detailStatWritePeriod),
+ statWritePeriod(rval.statWritePeriod),
+ stgExecMsgKey(rval.stgExecMsgKey),
+ executersNum(rval.executersNum),
+ fullFee(rval.fullFee),
+ dayFee(rval.dayFee),
+ dayResetTraff(rval.dayResetTraff),
+ spreadFee(rval.spreadFee),
+ freeMbAllowInet(rval.freeMbAllowInet),
+ dayFeeIsLastDay(rval.dayFeeIsLastDay),
+ stopOnError(rval.stopOnError),
+ writeFreeMbTraffCost(rval.writeFreeMbTraffCost),
+ showFeeInCash(rval.showFeeInCash),
+ messageTimeout(rval.messageTimeout),
+ feeChargeType(rval.feeChargeType),
+ reconnectOnTariffChange(rval.reconnectOnTariffChange),
+ disableSessionLog(rval.disableSessionLog),
+ filterParamsLog(rval.filterParamsLog),
+ modulesSettings(rval.modulesSettings),
+ storeModuleSettings(rval.storeModuleSettings),
+ logger(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+SETTINGS_IMPL & SETTINGS_IMPL::operator=(const SETTINGS_IMPL & rhs)
+{
+ modulesPath = rhs.modulesPath;
+ dirName = rhs.dirName;
+ confDir = rhs.confDir;
+ scriptsDir = rhs.scriptsDir;
+ rules = rhs.rules;
+ logFile = rhs.logFile;
+ pidFile = rhs.pidFile;
+ monitorDir = rhs.monitorDir;
+ scriptParams = rhs.scriptParams;
+ monitoring = rhs.monitoring;
+ detailStatWritePeriod = rhs.detailStatWritePeriod;
+ statWritePeriod = rhs.statWritePeriod;
+ stgExecMsgKey = rhs.stgExecMsgKey;
+ executersNum = rhs.executersNum;
+ fullFee = rhs.fullFee;
+ dayFee = rhs.dayFee;
+ dayResetTraff = rhs.dayResetTraff;
+ spreadFee = rhs.spreadFee;
+ freeMbAllowInet = rhs.freeMbAllowInet;
+ dayFeeIsLastDay = rhs.dayFeeIsLastDay;
+ stopOnError = rhs.stopOnError;
+ writeFreeMbTraffCost = rhs.writeFreeMbTraffCost;
+ showFeeInCash = rhs.showFeeInCash;
+ messageTimeout = rhs.messageTimeout;
+ feeChargeType = rhs.feeChargeType;
+ reconnectOnTariffChange = rhs.reconnectOnTariffChange;
+ disableSessionLog = rhs.disableSessionLog;
+ filterParamsLog = rhs.filterParamsLog;
+
+ modulesSettings = rhs.modulesSettings;
+ storeModuleSettings = rhs.storeModuleSettings;
+ return *this;
+}
+//-----------------------------------------------------------------------------
+void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf)
+{
+ printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf);
+ SETTINGS_IMPL * settings = static_cast<SETTINGS_IMPL *>(data);
+ settings->logger("%s", buf);
+}
+//-----------------------------------------------------------------------------
+int SETTINGS_IMPL::ReadSettings()
+{
+const char * requiredOptions[] = {
+ "ModulesPath",
+ "Modules",
+ "StoreModule",
+ "Rules",
+ "LogFile",
+ "DetailStatWritePeriod",
+ "DayFee",
+ "DayResetTraff",
+ "SpreadFee",
+ "FreeMbAllowInet",
+ "DayFeeIsLastDay",
+ "WriteFreeMbTraffCost",
+ NULL
+ };
+int storeModulesCount = 0;
+modulesSettings.clear();
+
+DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
+conf.setErrorCallback(SETTINGS_IMPL::ErrorCallback, this);
+conf.setRequiredOptionNames(requiredOptions);
+std::string confFile = confDir + "/stargazer.conf";
+
+if(conf.setContent(confFile.c_str()) != 0)
+ {
+ strError = "Cannot read file " + confFile;
+ return -1;
+ }
+
+const DOTCONFDocumentNode * node = conf.getFirstNode();
+
+while (node)
+ {
+ if (strcasecmp(node->getName(), "ScriptDir") == 0)
+ {
+ scriptsDir = node->getValue(0);
+ }
+
+ if (strcasecmp(node->getName(), "LogFile") == 0)
+ {
+ logFile = node->getValue(0);
+ }
+
+ if (strcasecmp(node->getName(), "PIDFile") == 0)
+ {
+ pidFile = node->getValue(0);
+ }
+
+ if (strcasecmp(node->getName(), "ModulesPath") == 0)
+ {
+ modulesPath = node->getValue(0);
+ }
+
+ if (strcasecmp(node->getName(), "Rules") == 0)
+ {
+ rules = node->getValue(0);
+ }
+
+ if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
+ {
+ try
+ {
+ detailStatWritePeriod = toPeriod(node->getValue(0));
+ }
+ catch (const Error& error)
+ {
+ strError = error.what();
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
+ {
+ if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
+ {
+ strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
+ {
+ if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
+ {
+ strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ExecutersNum") == 0)
+ {
+ if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
+ {
+ strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "DayFee") == 0)
+ {
+ if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
+ {
+ strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "FullFee") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &fullFee) != 0)
+ {
+ strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "DayResetTraff") == 0)
+ {
+ if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
+ {
+ strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "SpreadFee") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
+ {
+ strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
+ {
+ strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
+ {
+ strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "StopOnError") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
+ {
+ strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
+ {
+ strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
+ {
+ strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "MonitorDir") == 0)
+ {
+ monitorDir = node->getValue(0);
+ struct stat stat;
+ monitoring = false;
+
+ if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
+ {
+ monitoring = true;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "MessageTimeout") == 0)
+ {
+ if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
+ {
+ strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "FeeChargeType") == 0)
+ {
+ if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0)
+ {
+ strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
+ {
+ strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "DisableSessionLog") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &disableSessionLog) != 0)
+ {
+ strError = "Incorrect DisableSessionLog value: \'" + std::string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "FilterParamsLog") == 0)
+ {
+ filterParamsLog.clear();
+ for (int i = 0; node->getValue(i) != NULL; ++i)
+ filterParamsLog.push_back(node->getValue(i));
+ }
+
+ if (strcasecmp(node->getName(), "DirNames") == 0)
+ {
+ const DOTCONFDocumentNode * child = node->getChildNode();
+ if (child)
+ {
+ const DOTCONFDocumentNode * dirNameNode;
+ dirName.reserve(DIR_NUM);
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ char strDirName[12];
+ sprintf(strDirName, "DirName%d", i);
+ dirNameNode = conf.findNode(strDirName, node);
+ if (dirNameNode && dirNameNode->getValue(0))
+ {
+ dirName[i] = dirNameNode->getValue(0);
+ }
+ }
+ }
+ }
+
+ if (strcasecmp(node->getName(), "StoreModule") == 0)
+ {
+ if (node->getValue(1))
+ {
+ strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+ if (storeModulesCount)
+ {
+ strError = "Should be only one StoreModule.";
+ return -1;
+ }
+ storeModulesCount++;
+
+ if (node->getValue(0) == NULL)
+ {
+ strError = "No module name in the StoreModule section.";
+ return -1;
+ }
+ storeModuleSettings.moduleName = node->getValue(0);
+ storeModuleSettings.moduleParams = toPVS(*node);
+ }
+
+ if (strcasecmp(node->getName(), "Modules") == 0)
+ {
+ if (node->getValue(0))
+ {
+ strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'.";
+ return -1;
+ }
+ const DOTCONFDocumentNode * child = node->getChildNode();
+ while (child)
+ {
+ if (strcasecmp(child->getName(), "Module") != 0)
+ {
+ child = child->getNextNode();
+ continue;
+ }
+
+ if (child->getValue(0) == NULL)
+ {
+ strError = "No module name in the Module section.";
+ return -1;
+ }
+
+ modulesSettings.push_back(MODULE_SETTINGS(child->getValue(0), toPVS(*child)));
+
+ child = child->getNextNode();
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ScriptParams") == 0)
+ {
+ for (int i = 0; node->getValue(i) != NULL; ++i)
+ scriptParams.push_back(node->getValue(i));
+ }
+ node = node->getNextNode();
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+#ifndef SETTINGS_IMPL_H
+#define SETTINGS_IMPL_H
+
+#include "stg/settings.h"
+#include "stg/common.h"
+#include "stg/module_settings.h"
+#include "stg/ref.h"
+
+#include <string>
+#include <vector>
+
+//-----------------------------------------------------------------------------
+enum DETAIL_STAT_PERIOD {
+ dsPeriod_1,
+ dsPeriod_1_2,
+ dsPeriod_1_4,
+ dsPeriod_1_6
+};
+//-----------------------------------------------------------------------------
+class STG_LOGGER;
+class DOTCONFDocumentNode;
+//-----------------------------------------------------------------------------
+class SETTINGS_IMPL : public SETTINGS {
+public:
+ explicit SETTINGS_IMPL(const std::string &);
+ SETTINGS_IMPL(const SETTINGS_IMPL & rhs);
+ virtual ~SETTINGS_IMPL() {}
+ SETTINGS_IMPL & operator=(const SETTINGS_IMPL &);
+
+ int Reload() { return ReadSettings(); }
+ int ReadSettings();
+
+ std::string GetStrError() const { return strError; }
+
+ int GetExecMsgKey() const { return stgExecMsgKey; }
+ unsigned GetExecutersNum() const { return executersNum; }
+ const std::string & GetDirName(size_t num) const { return dirName[num]; }
+ const std::string & GetConfDir() const { return confDir; }
+ const std::string & GetScriptsDir() const { return scriptsDir; }
+ const std::string & GetRulesFileName() const { return rules; }
+ const std::string & GetLogFileName() const { return logFile; }
+ const std::string & GetPIDFileName() const { return pidFile; }
+ unsigned GetDetailStatWritePeriod() const
+ { return detailStatWritePeriod; }
+ unsigned GetStatWritePeriod() const { return statWritePeriod * 60; }
+ unsigned GetDayFee() const { return dayFee; }
+ bool GetFullFee() const { return fullFee; }
+ unsigned GetDayResetTraff() const { return dayResetTraff; }
+ bool GetSpreadFee() const { return spreadFee; }
+ bool GetFreeMbAllowInet() const { return freeMbAllowInet; }
+ bool GetDayFeeIsLastDay() const { return dayFeeIsLastDay; }
+ bool GetStopOnError() const { return stopOnError; }
+ bool GetWriteFreeMbTraffCost() const
+ { return writeFreeMbTraffCost; }
+ bool GetShowFeeInCash() const { return showFeeInCash; }
+ const std::string & GetMonitorDir() const { return monitorDir; }
+ bool GetMonitoring() const { return monitoring; }
+ unsigned GetMessageTimeout() const { return messageTimeout * 3600 * 24; }
+ unsigned GetFeeChargeType() const { return feeChargeType; }
+ bool GetReconnectOnTariffChange() const { return reconnectOnTariffChange; }
+ bool GetDisableSessionLog() const { return disableSessionLog; }
+ const std::vector<std::string> & GetFilterParamsLog() const { return filterParamsLog; }
+
+ const std::string & GetModulesPath() const { return modulesPath; }
+ const MODULE_SETTINGS & GetStoreModuleSettings() const
+ { return storeModuleSettings; }
+ const std::vector<MODULE_SETTINGS> & GetModulesSettings() const
+ { return modulesSettings; }
+ const std::vector<std::string> & GetScriptParams() const { return scriptParams; }
+
+private:
+
+ static void ErrorCallback(void * data, const char * buf);
+
+ std::string strError;
+
+ //////////settings
+ std::string modulesPath;
+ std::vector<std::string> dirName;
+ std::string confDir;
+ std::string scriptsDir;
+ std::string rules;
+ std::string logFile;
+ std::string pidFile;
+ std::string monitorDir;
+ std::vector<std::string> scriptParams;
+ bool monitoring;
+ unsigned detailStatWritePeriod;
+ unsigned statWritePeriod;
+ int stgExecMsgKey;
+ unsigned executersNum;
+ bool fullFee;
+ unsigned dayFee;
+ unsigned dayResetTraff;
+ bool spreadFee;
+ bool freeMbAllowInet;
+ bool dayFeeIsLastDay;
+ bool stopOnError;
+ bool writeFreeMbTraffCost;
+ bool showFeeInCash;
+ unsigned messageTimeout;
+ unsigned feeChargeType;
+ bool reconnectOnTariffChange;
+ bool disableSessionLog;
+ std::vector<std::string> filterParamsLog;
+
+ std::vector<MODULE_SETTINGS> modulesSettings;
+ MODULE_SETTINGS storeModuleSettings;
+ STG::RefWrapper<STG_LOGGER> logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+#include "stg_timer.h"
+
+#include "stg/common.h"
+
+#include <ctime>
+#include <cstring>
+#include <csignal>
+
+#include <pthread.h>
+
+void * StgTimer(void *);
+
+static int nonstop;
+static pthread_t thrStgTimer;
+static bool isTimerRunning = false;
+volatile time_t stgTime;
+
+#ifdef STG_TIMER_DEBUG
+const int TIME_SPEED = 1;
+/*
+ 1 - 1x speed
+ 2 - 2x speed
+ 5 - 5x speed
+ 10 - 10x speed
+ */
+
+const int START_TIME = 2;
+/*
+ 0 - as is
+ 1 - start before new day (3 min before) 29.11.2005 23:57:00
+ 2 - start before new month (3 min before) 30.11.2005 23:57:00
+ */
+#endif
+
+//-----------------------------------------------------------------------------
+void * StgTimer(void *)
+{
+#ifdef STG_TIMER_DEBUG
+struct tm lt;
+memset(<, 0, sizeof(lt));
+
+lt.tm_year = 2016 - 1900; // 2005
+lt.tm_mon = 7 - 1; // Nov
+lt.tm_hour = 23; // 23 h
+lt.tm_min = 57; // 50 min
+lt.tm_sec = 0; // 00 sec
+lt.tm_isdst = -1;
+
+switch (START_TIME)
+ {
+ case 0:
+ stgTime = time(NULL);
+ break;
+
+ case 1:
+ lt.tm_mday = 29;
+ stgTime = mktime(<);
+ break;
+
+ case 2:
+ lt.tm_mday = 31;
+ stgTime = mktime(<);
+ break;
+ }
+#else
+stgTime = time(NULL);
+#endif
+
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+nonstop = 1;
+isTimerRunning = true;
+while (nonstop)
+ {
+ #ifdef STG_TIMER_DEBUG
+ struct timespec ts;
+ if (TIME_SPEED == 1)
+ {
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ }
+ else
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000000 / TIME_SPEED;
+ }
+ nanosleep(&ts, NULL);
+ stgTime++;
+ #else
+ struct timespec ts = {0, 500000000};
+ nanosleep(&ts, NULL);
+ stgTime = time(NULL);
+ #endif
+ }
+isTimerRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int RunStgTimer()
+{
+static int a = 0;
+isTimerRunning = false;
+
+if (a == 0)
+ if (pthread_create(&thrStgTimer, NULL, &StgTimer, NULL))
+ {
+ isTimerRunning = false;
+ return -1;
+ }
+
+a = 1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void StopStgTimer()
+{
+nonstop = 0;
+pthread_join(thrStgTimer, NULL); // Cleanup thread resources
+printfd(__FILE__, "STG_TIMER stopped\n");
+}
+//-----------------------------------------------------------------------------
+bool IsStgTimerRunning()
+{
+return isTimerRunning;
+}
+//-----------------------------------------------------------------------------
+int stgUsleep(unsigned long t)
+{
+#ifdef STG_TIMER_DEBUG
+struct timespec ts = {static_cast<time_t>((t / TIME_SPEED) / 1000000), static_cast<long>(((t / TIME_SPEED) % 1000000) * 1000)};
+return nanosleep(&ts, NULL);
+#else
+struct timespec ts = {static_cast<time_t>(t / 1000000), static_cast<long>((t % 1000000) * 1000)};
+return nanosleep(&ts, NULL);
+#endif
+}
+//-----------------------------------------------------------------------------
+void WaitTimer()
+{
+ for (int i = 0; i < 5 && !isTimerRunning; i++)
+ stgUsleep(200000);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/11/03 10:37:52 $
+ $Author: faust $
+ */
+
+#ifndef STG_TIMER_H
+#define STG_TIMER_H
+
+#include <ctime>
+
+extern volatile time_t stgTime;
+int RunStgTimer();
+void StopStgTimer();
+void WaitTimer();
+bool IsStgTimerRunning();
+int stgUsleep(unsigned long t);
+
+#endif //STG_TIMER_H
+
+
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.6 $
+ $Date: 2010/03/04 12:24:19 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII store plugin loader
+ */
+
+#include <dlfcn.h>
+
+#include "stg/common.h"
+#include "stg/store.h"
+#include "store_loader.h"
+#include "settings_impl.h"
+
+STORE_LOADER::STORE_LOADER(const SETTINGS_IMPL & settings)
+ : isLoaded(false),
+ handle(NULL),
+ plugin(NULL),
+ errorStr(),
+ storeSettings(settings.GetStoreModuleSettings()),
+ pluginFileName(settings.GetModulesPath() + "/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 = reinterpret_cast<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()
+{
+printfd(__FILE__, "STORE_LOADER::Unload()\n");
+if (!isLoaded)
+ {
+ return true;
+ }
+
+delete plugin;
+
+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;
+}
--- /dev/null
+/*
+ * 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 <faust@stargazer.dp.ua>
+ */
+
+/*
+ $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 "stg/module_settings.h"
+#include "stg/noncopyable.h"
+
+#include <string>
+
+class STORE;
+class SETTINGS_IMPL;
+
+class STORE_LOADER : private NONCOPYABLE {
+public:
+ explicit STORE_LOADER(const SETTINGS_IMPL & settings);
+ ~STORE_LOADER();
+
+ bool Load();
+ bool Unload();
+
+ STORE & GetStore() { return *plugin; }
+
+ const std::string & GetStrError() const { return errorStr; }
+
+private:
+ STORE_LOADER(const STORE_LOADER & rvalue);
+ STORE_LOADER & operator=(const STORE_LOADER & rvalue);
+
+ bool isLoaded;
+ void * handle;
+ STORE * plugin;
+ std::string errorStr;
+ MODULE_SETTINGS storeSettings;
+ std::string pluginFileName;
+};
+
+#endif
--- /dev/null
+/*
+ * 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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.11 $
+ $Date: 2010/10/07 16:57:21 $
+ $Author: faust $
+ */
+
+#include "tariff_impl.h"
+
+#include "stg_timer.h"
+#include "stg/common.h"
+
+#include <ctime>
+#include <algorithm> // std::max
+
+//-----------------------------------------------------------------------------
+TARIFF_IMPL & TARIFF_IMPL::operator=(const TARIFF_DATA & td)
+{
+tariffData = td;
+return *this;
+}
+//-----------------------------------------------------------------------------
+double TARIFF_IMPL::GetPriceWithTraffType(uint64_t up,
+ uint64_t down,
+ int dir,
+ time_t t) const
+{
+return GetPriceWithoutFreeMb(dir, GetTraffByType(up, down) / (1024 * 1024), t);
+}
+//-----------------------------------------------------------------------------
+int64_t TARIFF_IMPL::GetTraffByType(uint64_t up, uint64_t down) const
+{
+switch (tariffData.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ return up;
+
+ case TRAFF_DOWN:
+ return down;
+
+ case TRAFF_MAX:
+ return std::max(up, down);
+
+ default: //TRAFF_UP_DOWN:
+ return up + down;
+ }
+}
+//-----------------------------------------------------------------------------
+int TARIFF_IMPL::GetThreshold(int dir) const
+{
+ return tariffData.dirPrice[dir].threshold;
+}
+//-----------------------------------------------------------------------------
+void TARIFF_IMPL::Print() const
+{
+printfd(__FILE__, "Traiff name: %s\n", tariffData.tariffConf.name.c_str());
+}
+//-----------------------------------------------------------------------------
+int TARIFF_IMPL::Interval(int dir, time_t t) const
+{
+// Start of the day (and end of the night) in sec from 00:00:00
+int s1 = tariffData.dirPrice[dir].hDay * 3600 +
+ tariffData.dirPrice[dir].mDay * 60;
+// Start of the night (and end of the day) in sec from 00:00:00
+int s2 = tariffData.dirPrice[dir].hNight * 3600 +
+ tariffData.dirPrice[dir].mNight * 60;
+
+struct tm * lt;
+
+lt = localtime(&t);
+
+// Position of time t in sec from 00:00:00
+// Ignoring seconds due to minute precision
+int lts = lt->tm_hour * 3600 + lt->tm_min * 60;
+
+if (s1 < s2)
+ {
+ // Normal situation (00:00:00 is a night)
+ if (lts > s1 && lts < s2)
+ return TARIFF_DAY;
+ else
+ return TARIFF_NIGHT;
+ }
+else
+ {
+ // Not so common but possible situation (00:00:00 is a day)
+ if (lts < s1 && lts > s2)
+ return TARIFF_NIGHT;
+ else
+ return TARIFF_DAY;
+ }
+}
+//-----------------------------------------------------------------------------
+double TARIFF_IMPL::GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const
+{
+int interval = Interval(dir, t);
+
+/*
+ * 0011 - NB
+ * *01* - NA
+ * 0**1 - DB
+ * **** - DA
+ */
+
+bool nd = tariffData.dirPrice[dir].noDiscount;
+bool sp = tariffData.dirPrice[dir].singlePrice;
+bool th = (interval == TARIFF_NIGHT);
+bool tr = (mb > tariffData.dirPrice[dir].threshold);
+
+if (!nd && !sp && th && tr)
+ return tariffData.dirPrice[dir].priceNightB;
+else if (!nd && tr)
+ return tariffData.dirPrice[dir].priceDayB;
+else if (!sp && th)
+ return tariffData.dirPrice[dir].priceNightA;
+else
+ return tariffData.dirPrice[dir].priceDayA;
+}
+//-----------------------------------------------------------------------------
+std::string TARIFF_IMPL::TariffChangeIsAllowed(const TARIFF & to, time_t currentTime) const
+{
+time_t timeout = GetChangePolicyTimeout();
+if (currentTime > timeout && timeout != 0)
+ return "";
+switch (GetChangePolicy())
+ {
+ case TARIFF::ALLOW:
+ return "";
+ case TARIFF::TO_CHEAP:
+ if (to.GetFee() < GetFee())
+ return "";
+ else
+ return "New tariff '" + to.GetName() + "' is more expensive than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
+ case TARIFF::TO_EXPENSIVE:
+ if (to.GetFee() >= GetFee())
+ return "";
+ else
+ return "New tariff '" + to.GetName() + "' is more cheap than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
+ case TARIFF::DENY:
+ return "Current tariff '" + GetName() + "', new tariff '" + to.GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'.";
+ }
+return "";
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.9 $
+ $Date: 2010/10/07 17:53:39 $
+ $Author: faust $
+ */
+
+#ifndef TARIFF_IMPL_H
+#define TARIFF_IMPL_H
+
+#include "stg/tariff.h"
+#include "stg/tariff_conf.h"
+
+#include <string>
+#include <list>
+
+#include <ctime>
+#include <cstdint>
+
+#define TARIFF_DAY 0
+#define TARIFF_NIGHT 1
+
+class TARIFF_IMPL : public TARIFF {
+public:
+ explicit TARIFF_IMPL(const std::string & name)
+ : TARIFF(),
+ tariffData(name)
+ {}
+ explicit TARIFF_IMPL(const TARIFF_DATA & td)
+ : TARIFF(),
+ tariffData(td)
+ {}
+ virtual ~TARIFF_IMPL() {}
+
+ double GetPriceWithTraffType(uint64_t up,
+ uint64_t down,
+ int dir,
+ time_t t) const;
+ double GetFreeMb() const { return tariffData.tariffConf.free; }
+ double GetPassiveCost() const { return tariffData.tariffConf.passiveCost; }
+ double GetFee() const { return tariffData.tariffConf.fee; }
+ double GetFree() const { return tariffData.tariffConf.free; }
+ PERIOD GetPeriod() const { return tariffData.tariffConf.period; }
+ CHANGE_POLICY GetChangePolicy() const { return tariffData.tariffConf.changePolicy; }
+ time_t GetChangePolicyTimeout() const { return tariffData.tariffConf.changePolicyTimeout; }
+
+ void Print() const;
+
+ const std::string & GetName() const { return tariffData.tariffConf.name; }
+ void SetName(const std::string & name) { tariffData.tariffConf.name = name; }
+
+ int GetTraffType() const { return tariffData.tariffConf.traffType; }
+ int64_t GetTraffByType(uint64_t up, uint64_t down) const;
+ int GetThreshold(int dir) const;
+ const TARIFF_DATA & GetTariffData() const { return tariffData; }
+
+ TARIFF_IMPL & operator=(const TARIFF_DATA & td);
+ bool operator==(const TARIFF_IMPL & rhs) const { return GetName() == rhs.GetName(); }
+ bool operator!=(const TARIFF_IMPL & rhs) const { return GetName() != rhs.GetName(); }
+ std::string TariffChangeIsAllowed(const TARIFF & to, time_t currentTime) const;
+
+private:
+ TARIFF_DATA tariffData;
+
+ double GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const;
+ int Interval(int dir, time_t t) const;
+};
+
+#endif
--- /dev/null
+/*
+ * 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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.9 $
+ $Date: 2010/10/07 18:43:21 $
+ $Author: faust $
+ */
+
+#include <cassert>
+#include <algorithm>
+#include <vector>
+
+#include "stg/locker.h"
+#include "stg/logger.h"
+#include "stg/store.h"
+#include "stg/admin.h"
+#include "tariffs_impl.h"
+
+//-----------------------------------------------------------------------------
+TARIFFS_IMPL::TARIFFS_IMPL(STORE * st)
+ : TARIFFS(),
+ tariffs(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ mutex(),
+ strError(),
+ noTariff(NO_TARIFF_NAME),
+ onAddNotifiers(),
+ onDelNotifiers()
+{
+pthread_mutex_init(&mutex, NULL);
+ReadTariffs();
+}
+//-----------------------------------------------------------------------------
+TARIFFS_IMPL::~TARIFFS_IMPL()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int TARIFFS_IMPL::ReadTariffs()
+{
+STG_LOCKER lock(&mutex);
+
+std::vector<std::string> tariffsList;
+if (store->GetTariffsList(&tariffsList))
+ {
+ WriteServLog("Cannot get tariffs list.");
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+Tariffs::size_type tariffsNum = tariffsList.size();
+
+for (Tariffs::size_type i = 0; i < tariffsNum; i++)
+ {
+ TARIFF_DATA td;
+ if (store->RestoreTariff(&td, tariffsList[i]))
+ {
+ WriteServLog("Cannot read tariff %s.", tariffsList[i].c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+ tariffs.push_back(TARIFF_IMPL(td));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+size_t TARIFFS_IMPL::Count() const
+{
+STG_LOCKER lock(&mutex);
+return tariffs.size();
+}
+//-----------------------------------------------------------------------------
+const TARIFF * TARIFFS_IMPL::FindByName(const std::string & name) const
+{
+if (name == NO_TARIFF_NAME)
+ return &noTariff;
+
+STG_LOCKER lock(&mutex);
+std::list<TARIFF_IMPL>::const_iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
+
+if (ti != tariffs.end())
+ return &(*ti);
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS_IMPL::Chg(const TARIFF_DATA & td, const ADMIN * admin)
+{
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->tariffChg)
+ {
+ std::string s = admin->GetLogStr() + " Change tariff \'"
+ + td.tariffConf.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex);
+
+std::list<TARIFF_IMPL>::iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(td.tariffConf.name));
+
+if (ti == tariffs.end())
+ {
+ strError = "Tariff \'" + td.tariffConf.name + "\' cannot be changed. Tariff does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+*ti = td;
+
+if (store->SaveTariff(td, td.tariffConf.name))
+ {
+ std::string error = "Tariff " + td.tariffConf.name + " writing error. " + store->GetStrError();
+ WriteServLog(error.c_str());
+ return -1;
+ }
+
+WriteServLog("%s Tariff \'%s\' changed.",
+ admin->GetLogStr().c_str(), td.tariffConf.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS_IMPL::Del(const std::string & name, const ADMIN * admin)
+{
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->tariffChg)
+ {
+ std::string s = admin->GetLogStr() + " Delete tariff \'"
+ + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+TARIFF_DATA td;
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ std::list<TARIFF_IMPL>::iterator ti;
+ ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
+
+ if (ti == tariffs.end())
+ {
+ strError = "Tariff \'" + name + "\' cannot be deleted. Tariff does not exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+ if (store->DelTariff(name))
+ {
+ WriteServLog("Cannot delete tariff %s.", name.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+ td = ti->GetTariffData();
+
+ tariffs.erase(ti);
+ }
+
+std::set<NOTIFIER_BASE<TARIFF_DATA> *>::iterator ni = onDelNotifiers.begin();
+while (ni != onDelNotifiers.end())
+ {
+ (*ni)->Notify(td);
+ ++ni;
+ }
+
+WriteServLog("%s Tariff \'%s\' deleted.",
+ admin->GetLogStr().c_str(),
+ name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS_IMPL::Add(const std::string & name, const ADMIN * admin)
+{
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->tariffChg)
+ {
+ std::string s = admin->GetLogStr() + " Add tariff \'"
+ + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ std::list<TARIFF_IMPL>::iterator ti;
+ ti = find(tariffs.begin(), tariffs.end(), TARIFF_IMPL(name));
+
+ if (ti != tariffs.end())
+ {
+ strError = "Tariff \'" + name + "\' cannot be added. Tariff already exist.";
+ WriteServLog("%s %s", admin->GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+ tariffs.push_back(TARIFF_IMPL(name));
+ }
+
+if (store->AddTariff(name) < 0)
+ {
+ strError = "Tariff " + name + " adding error. " + store->GetStrError();
+ WriteServLog(strError.c_str());
+ return -1;
+ }
+
+// Fire all "on add" notifiers
+std::set<NOTIFIER_BASE<TARIFF_DATA> *>::iterator ni = onAddNotifiers.begin();
+while (ni != onAddNotifiers.end())
+ {
+ (*ni)->Notify(tariffs.back().GetTariffData());
+ ++ni;
+ }
+
+WriteServLog("%s Tariff \'%s\' added.",
+ admin->GetLogStr().c_str(), name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void TARIFFS_IMPL::GetTariffsData(std::list<TARIFF_DATA> * tdl) const
+{
+assert(tdl != NULL && "Tariffs data list is not null");
+STG_LOCKER lock(&mutex);
+
+Tariffs::const_iterator it = tariffs.begin();
+for (; it != tariffs.end(); ++it)
+ {
+ tdl->push_back(it->GetTariffData());
+ }
+}
+//-----------------------------------------------------------------------------
+void TARIFFS_IMPL::AddNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void TARIFFS_IMPL::DelNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void TARIFFS_IMPL::AddNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void TARIFFS_IMPL::DelNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#ifndef TARIFFS_IMPL_H
+#define TARIFFS_IMPL_H
+
+#include "stg/tariff.h"
+#include "stg/tariffs.h"
+#include "stg/tariff_conf.h"
+#include "tariff_impl.h"
+
+#include <string>
+#include <list>
+#include <set>
+
+#include <pthread.h>
+
+#define TARIFF_DAY 0
+#define TARIFF_NIGHT 1
+
+class STORE;
+class STG_LOGGER;
+class ADMIN;
+
+class TARIFFS_IMPL : public TARIFFS {
+public:
+ typedef std::list<TARIFF_IMPL> Tariffs;
+
+ explicit TARIFFS_IMPL(STORE * store);
+ virtual ~TARIFFS_IMPL();
+ int ReadTariffs ();
+ const TARIFF * FindByName(const std::string & name) const;
+ const TARIFF * GetNoTariff() const { return &noTariff; }
+ size_t Count() const;
+ int Del(const std::string & name, const ADMIN * admin);
+ int Add(const std::string & name, const ADMIN * admin);
+ int Chg(const TARIFF_DATA & td, const ADMIN * admin);
+
+ void AddNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * notifier);
+ void DelNotifierAdd(NOTIFIER_BASE<TARIFF_DATA> * notifier);
+
+ void AddNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * notifier);
+ void DelNotifierDel(NOTIFIER_BASE<TARIFF_DATA> * notifier);
+
+ void GetTariffsData(std::list<TARIFF_DATA> * tdl) const;
+
+ const std::string & GetStrError() const { return strError; }
+
+private:
+ TARIFFS_IMPL(const TARIFFS_IMPL & rvalue);
+ TARIFFS_IMPL & operator=(const TARIFFS_IMPL & rvalue);
+
+ Tariffs tariffs;
+ STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable pthread_mutex_t mutex;
+ std::string strError;
+ TARIFF_IMPL noTariff;
+
+ std::set<NOTIFIER_BASE<TARIFF_DATA>*> onAddNotifiers;
+ std::set<NOTIFIER_BASE<TARIFF_DATA>*> onDelNotifiers;
+};
+
+#endif
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.58 $
+ $Date: 2010/11/03 11:28:07 $
+ $Author: faust $
+ */
+
+/* inet_aton */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <csignal>
+#include <cassert>
+#include <cstdio> // fopen and similar
+#include <cstdlib> // strtol
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/const.h" // MONITOR_TIME_DELAY_SEC
+#include "traffcounter_impl.h"
+#include "stg_timer.h"
+#include "users_impl.h"
+
+#define FLUSH_TIME (10)
+#define REMOVE_TIME (31)
+
+const char protoName[PROTOMAX][8] =
+{"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
+
+enum protoNum
+{
+tcp = 0, udp, icmp, tcp_udp, all
+};
+
+//-----------------------------------------------------------------------------
+TRAFFCOUNTER_IMPL::TRAFFCOUNTER_IMPL(USERS_IMPL * u, const std::string & fn)
+ : WriteServLog(GetStgLogger()),
+ rulesFileName(fn),
+ monitoring(false),
+ touchTimeP(stgTime - MONITOR_TIME_DELAY_SEC),
+ users(u),
+ running(false),
+ stopped(true),
+ addUserNotifier(*this),
+ delUserNotifier(*this)
+{
+for (int i = 0; i < DIR_NUM; i++)
+ strprintf(&dirName[i], "DIR%d", i);
+
+dirName[DIR_NUM] = "NULL";
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+TRAFFCOUNTER_IMPL::~TRAFFCOUNTER_IMPL()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER_IMPL::Start()
+{
+STG_LOCKER lock(&mutex);
+
+if (!stopped)
+ return 0;
+
+if (ReadRules())
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot read rules\n");
+ WriteServLog("TRAFFCOUNTER: Cannot read rules.");
+ return -1;
+ }
+
+printfd(__FILE__, "TRAFFCOUNTER::Start()\n");
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+USER_IMPL * u;
+
+while (users->SearchNext(h, &u) == 0)
+ SetUserNotifiers(u);
+users->CloseSearch(h);
+
+running = true;
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot start thread\n");
+ WriteServLog("TRAFFCOUNTER: Error: Cannot start thread.");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER_IMPL::Stop()
+{
+if (stopped)
+ return 0;
+
+running = false;
+
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+USER_IMPL * u;
+while (users->SearchNext(h, &u) == 0)
+ UnSetUserNotifiers(u);
+users->CloseSearch(h);
+
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (int i = 0; i < 25 && !stopped; i++)
+ {
+ nanosleep(&ts, NULL);
+ }
+
+if (!stopped)
+ return -1;
+
+printfd(__FILE__, "TRAFFCOUNTER::Stop()\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * TRAFFCOUNTER_IMPL::Run(void * data)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+TRAFFCOUNTER_IMPL * tc = static_cast<TRAFFCOUNTER_IMPL *>(data);
+tc->stopped = false;
+int c = 0;
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+struct timespec ts = {0, 500000000};
+while (tc->running)
+ {
+ nanosleep(&ts, 0);
+ if (!tc->running)
+ {
+ tc->FlushAndRemove();
+ break;
+ }
+
+ if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ std::string monFile(tc->monitorDir + "/traffcounter_r");
+ printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
+ touchTime = stgTime;
+ TouchFile(monFile);
+ }
+
+ if (++c % FLUSH_TIME == 0)
+ tc->FlushAndRemove();
+ }
+
+tc->stopped = true;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::Process(const RAW_PACKET & rawPacket)
+{
+if (!running)
+ return;
+
+if (monitoring && (touchTimeP + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ std::string monFile = monitorDir + "/traffcounter_p";
+ printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", monitoring, monFile.c_str());
+ touchTimeP = stgTime;
+ TouchFile(monFile);
+ }
+
+STG_LOCKER lock(&mutex);
+
+//printfd(__FILE__, "TRAFFCOUNTER::Process()\n");
+//TODO replace find with lower_bound.
+
+// Searching a new packet in a tree.
+pp_iter pi = packets.find(rawPacket);
+
+// Packet found - update length and time
+if (pi != packets.end())
+ {
+ pi->second.lenU += rawPacket.GetLen();
+ pi->second.lenD += rawPacket.GetLen();
+ pi->second.updateTime = stgTime;
+ /*printfd(__FILE__, "=============================\n");
+ printfd(__FILE__, "Packet found!\n");
+ printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
+ printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
+ printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
+ printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
+ printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
+ printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
+ printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
+ printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
+ printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
+ printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
+ printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
+ printfd(__FILE__, "=============================\n");*/
+ return;
+ }
+
+PACKET_EXTRA_DATA ed;
+
+// Packet not found - add new packet
+
+ed.updateTime = stgTime;
+ed.flushTime = stgTime;
+
+/*
+ userU is that whose user_ip == packet_ip_src
+ userD is that whose user_ip == packet_ip_dst
+ */
+
+uint32_t ipU = rawPacket.GetSrcIP();
+uint32_t ipD = rawPacket.GetDstIP();
+
+// Searching users with such IP
+if (users->FindByIPIdx(ipU, &ed.userU) == 0)
+ {
+ ed.userUPresent = true;
+ }
+
+if (users->FindByIPIdx(ipD, &ed.userD) == 0)
+ {
+ ed.userDPresent = true;
+ }
+
+if (ed.userUPresent ||
+ ed.userDPresent)
+ {
+ DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
+
+ ed.lenD = ed.lenU = rawPacket.GetLen();
+
+ //TODO use result of lower_bound to inserting new record
+
+ // Adding packet to a tree.
+ std::pair<pp_iter, bool> insertResult = packets.insert(std::make_pair(rawPacket, ed));
+ pp_iter newPacket = insertResult.first;
+
+ // Adding packet reference to an IP index.
+ ip2packets.insert(std::make_pair(ipU, newPacket));
+ ip2packets.insert(std::make_pair(ipD, newPacket));
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::FlushAndRemove()
+{
+STG_LOCKER lock(&mutex);
+
+Packets::size_type oldPacketsSize = packets.size();
+Index::size_type oldIp2packetsSize = ip2packets.size();
+
+pp_iter pi;
+pi = packets.begin();
+Packets newPackets;
+ip2packets.erase(ip2packets.begin(), ip2packets.end());
+while (pi != packets.end())
+ {
+ //Flushing
+ if (stgTime - pi->second.flushTime > FLUSH_TIME)
+ {
+ if (pi->second.userUPresent)
+ {
+ //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
+
+ // Add stat
+ if (pi->second.dirU < DIR_NUM)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi->second.userU->AddTraffStatU(pi->second.dirU,
+ pi->first.GetDstIP(),
+ pi->first.GetDstPort(),
+ pi->second.lenU);
+ #else
+ pi->second.userU->AddTraffStatU(pi->second.dirU,
+ pi->first.GetDstIP(),
+ pi->second.lenU);
+ #endif
+ }
+
+ pi->second.lenU = 0;
+ pi->second.flushTime = stgTime;
+ }
+
+ if (pi->second.userDPresent)
+ {
+ //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
+
+ // Add stat
+ if (pi->second.dirD < DIR_NUM)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi->second.userD->AddTraffStatD(pi->second.dirD,
+ pi->first.GetSrcIP(),
+ pi->first.GetSrcPort(),
+ pi->second.lenD);
+ #else
+ pi->second.userD->AddTraffStatD(pi->second.dirD,
+ pi->first.GetSrcIP(),
+ pi->second.lenD);
+ #endif
+ }
+
+ pi->second.lenD = 0;
+ pi->second.flushTime = stgTime;
+ }
+ }
+
+ if (stgTime - pi->second.updateTime < REMOVE_TIME)
+ {
+ std::pair<pp_iter, bool> res = newPackets.insert(*pi);
+ if (res.second)
+ {
+ ip2packets.insert(std::make_pair(pi->first.GetSrcIP(), res.first));
+ ip2packets.insert(std::make_pair(pi->first.GetDstIP(), res.first));
+ }
+ }
+ ++pi;
+ }
+swap(packets, newPackets);
+printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
+ packets.size(),
+ oldPacketsSize - packets.size(),
+ ip2packets.size(),
+ oldIp2packetsSize - ip2packets.size());
+
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::AddUser(USER_IMPL * user)
+{
+printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
+uint32_t uip = user->GetCurrIP();
+std::pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER lock(&mutex);
+// Find all packets with IP belongs to this user
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+ {
+ if (pi.first->second->first.GetSrcIP() == uip)
+ {
+ assert((!pi.first->second->second.userUPresent ||
+ pi.first->second->second.userU == user) &&
+ "U user present but it's not current user");
+
+ pi.first->second->second.lenU = 0;
+ pi.first->second->second.userU = user;
+ pi.first->second->second.userUPresent = true;
+ }
+
+ if (pi.first->second->first.GetDstIP() == uip)
+ {
+ assert((!pi.first->second->second.userDPresent ||
+ pi.first->second->second.userD == user) &&
+ "D user present but it's not current user");
+
+ pi.first->second->second.lenD = 0;
+ pi.first->second->second.userD = user;
+ pi.first->second->second.userDPresent = true;
+ }
+
+ ++pi.first;
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::DelUser(uint32_t uip)
+{
+printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
+std::pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER lock(&mutex);
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+ {
+ if (pi.first->second->first.GetSrcIP() == uip)
+ {
+ if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+ pi.first->second->first.GetDstIP(),
+ pi.first->second->first.GetDstPort(),
+ pi.first->second->second.lenU);
+ #else
+ pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+ pi.first->second->first.GetDstIP(),
+ pi.first->second->second.lenU);
+ #endif
+ }
+ pi.first->second->second.userUPresent = false;
+ }
+
+ if (pi.first->second->first.GetDstIP() == uip)
+ {
+ if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+ pi.first->second->first.GetSrcIP(),
+ pi.first->second->first.GetSrcPort(),
+ pi.first->second->second.lenD);
+ #else
+ pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+ pi.first->second->first.GetSrcIP(),
+ pi.first->second->second.lenD);
+ #endif
+ }
+
+ pi.first->second->second.userDPresent = false;
+ }
+
+ ++pi.first;
+ }
+
+ip2packets.erase(pi.first, pi.second);
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::SetUserNotifiers(USER_IMPL * user)
+{
+// Adding user. Adding notifiers to user.
+TRF_IP_BEFORE ipBNotifier(*this, user);
+ipBeforeNotifiers.push_front(ipBNotifier);
+user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
+
+TRF_IP_AFTER ipANotifier(*this, user);
+ipAfterNotifiers.push_front(ipANotifier);
+user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::UnSetUserNotifiers(USER_IMPL * user)
+{
+// Removing user. Removing notifiers from user.
+std::list<TRF_IP_BEFORE>::iterator bi;
+std::list<TRF_IP_AFTER>::iterator ai;
+
+bi = ipBeforeNotifiers.begin();
+while (bi != ipBeforeNotifiers.end())
+ {
+ if (user->GetLogin() == bi->GetUser()->GetLogin())
+ {
+ user->DelCurrIPBeforeNotifier(&(*bi));
+ ipBeforeNotifiers.erase(bi);
+ break;
+ }
+ ++bi;
+ }
+
+ai = ipAfterNotifiers.begin();
+while (ai != ipAfterNotifiers.end())
+ {
+ if (user->GetLogin() == ai->GetUser()->GetLogin())
+ {
+ user->DelCurrIPAfterNotifier(&(*ai));
+ ipAfterNotifiers.erase(ai);
+ break;
+ }
+ ++ai;
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::DeterminateDir(const RAW_PACKET & packet,
+ int * dirU, // Direction for incoming packet
+ int * dirD) const // Direction for outgoing packet
+{
+bool addrMatchU = false;
+bool portMatchU = false;
+bool addrMatchD = false;
+bool portMatchD = false;
+bool foundU = false; // Was rule for U found ?
+bool foundD = false; // Was rule for D found ?
+//printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
+
+enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
+
+std::list<RULE>::const_iterator ln;
+ln = rules.begin();
+
+while (ln != rules.end())
+ {
+ if (!foundU)
+ {
+ portMatchU = false;
+
+ switch (ln->proto)
+ {
+ case all:
+ portMatchU = true;
+ break;
+
+ case icmp:
+ portMatchU = (packet.GetProto() == ICMP_RPOTO);
+ break;
+
+ case tcp_udp:
+ if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ case tcp:
+ if (packet.GetProto() == TCP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ case udp:
+ if (packet.GetProto() == UDP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ default:
+ printfd(__FILE__, "Error! Incorrect rule!\n");
+ break;
+ }
+
+ addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
+
+ if (!foundU && addrMatchU && portMatchU)
+ {
+ foundU = true;
+ *dirU = ln->dir;
+ //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
+ }
+
+ } //if (!foundU)
+
+ if (!foundD)
+ {
+ portMatchD = false;
+
+ switch (ln->proto)
+ {
+ case all:
+ portMatchD = true;
+ break;
+
+ case icmp:
+ portMatchD = (packet.GetProto() == ICMP_RPOTO);
+ break;
+
+ case tcp_udp:
+ if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ case tcp:
+ if (packet.GetProto() == TCP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ case udp:
+ if (packet.GetProto() == UDP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ default:
+ printfd(__FILE__, "Error! Incorrect rule!\n");
+ break;
+ }
+
+ addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
+
+ if (!foundD && addrMatchD && portMatchD)
+ {
+ foundD = true;
+ *dirD = ln->dir;
+ //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
+ }
+ } //if (!foundD)
+
+ ++ln;
+ } //while (ln != rules.end())
+
+if (!foundU)
+ *dirU = DIR_NUM;
+
+if (!foundD)
+ *dirD = DIR_NUM;
+}
+//-----------------------------------------------------------------------------
+bool TRAFFCOUNTER_IMPL::ReadRules(bool test)
+{
+//printfd(__FILE__, "TRAFFCOUNTER::ReadRules()\n");
+
+RULE rul;
+FILE * f;
+char str[1024];
+char tp[100]; // protocol
+char ta[100]; // address
+char td[100]; // target direction
+int r;
+int lineNumber = 0;
+f = fopen(rulesFileName.c_str(), "rt");
+
+if (!f)
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - File '%s' cannot be opened.\n", rulesFileName.c_str());
+ WriteServLog("File '%s' cannot be oppened.", rulesFileName.c_str());
+ return true;
+ }
+
+while (fgets(str, 1023, f))
+ {
+ lineNumber++;
+ if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
+ {
+ continue;
+ }
+
+ r = sscanf(str,"%99s %99s %99s", tp, ta, td);
+ if (r != 3)
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. There must be 3 parameters.\n", rulesFileName.c_str(), lineNumber);
+ WriteServLog("Error in file '%s' at line %d. There must be 3 parameters.", rulesFileName.c_str(), lineNumber);
+ fclose(f);
+ return true;
+ }
+
+ rul.proto = 0xff;
+ rul.dir = 0xff;
+
+ for (uint8_t i = 0; i < PROTOMAX; i++)
+ {
+ if (strcasecmp(tp, protoName[i]) == 0)
+ rul.proto = i;
+ }
+
+ for (uint32_t i = 0; i < DIR_NUM + 1; i++)
+ {
+ if (td == dirName[i])
+ rul.dir = i;
+ }
+
+ if (rul.dir == 0xff || rul.proto == 0xff)
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d.\n", rulesFileName.c_str(), lineNumber);
+ WriteServLog("Error in file %s. Line %d.",
+ rulesFileName.c_str(), lineNumber);
+ fclose(f);
+ return true;
+ }
+
+ if (ParseAddress(ta, &rul) != 0)
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. Error in adress.\n", rulesFileName.c_str(), lineNumber);
+ WriteServLog("Error in file %s. Error in adress. Line %d.",
+ rulesFileName.c_str(), lineNumber);
+ fclose(f);
+ return true;
+ }
+ if (!test)
+ rules.push_back(rul);
+ }
+
+fclose(f);
+
+// Adding lastest rule: ALL 0.0.0.0/0 NULL
+rul.dir = DIR_NUM; //NULL
+rul.ip = 0; //0.0.0.0
+rul.mask = 0;
+rul.port1 = 0;
+rul.port2 = 65535;
+rul.proto = all;
+
+if (!test)
+ rules.push_back(rul);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER_IMPL::Reload()
+{
+STG_LOCKER lock(&mutex);
+
+if (ReadRules(true))
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() - Failed to reload rules.\n");
+ WriteServLog("TRAFFCOUNTER: Cannot reload rules. Errors found.");
+ return -1;
+ }
+
+FreeRules();
+ReadRules();
+printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() - Reloaded rules successfully.\n");
+WriteServLog("TRAFFCOUNTER: Reloaded rules successfully.");
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool TRAFFCOUNTER_IMPL::ParseAddress(const char * ta, RULE * rule) const
+{
+char addr[50], mask[20], port1[20], port2[20], ports[40];
+
+size_t len = strlen(ta);
+char n = 0;
+size_t i, p;
+memset(addr, 0, sizeof(addr));
+for (i = 0; i < len; i++)
+ {
+ if (ta[i] == '/' || ta[i] == ':')
+ {
+ addr[i] = 0;
+ n = ta[i];
+ break;
+ }
+ addr[i] = ta[i];
+ n = 0;
+ }
+addr[i + 1] = 0;
+p = i + 1;
+
+if (n == '/')
+ {
+ // mask
+ for (; i < len; i++)
+ {
+ if (ta[i] == ':')
+ {
+ mask[i - p] = 0;
+ n = ':';
+ break;
+ }
+ mask[i - p] = ta[i];
+ }
+ mask[i - p] = 0;
+ }
+else
+ {
+ strcpy(mask, "32");
+ }
+
+p = i + 1;
+i++;
+
+if (n == ':')
+ {
+ // port
+ if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - No ports specified for this protocol.\n");
+ WriteServLog("No ports specified for this protocol.");
+ return true;
+ }
+
+ for (; i < len; i++)
+ ports[i - p] = ta[i];
+
+ ports[i - p] = 0;
+ }
+else
+ {
+ strcpy(ports, "0-65535");
+ }
+
+char *sss;
+char pts[100];
+strcpy(pts, ports);
+
+if ((sss = strchr(ports, '-')) != NULL)
+ {
+ strncpy(port1, ports, int(sss-ports));
+ port1[int(sss - ports)] = 0;
+ strcpy(port2, sss + 1);
+ }
+else
+ {
+ strcpy(port1, ports);
+ strcpy(port2, ports);
+ }
+
+// Convert strings to mask, ports and IP
+uint16_t prt1, prt2, msk;
+struct in_addr ipaddr;
+char *res;
+
+msk = static_cast<uint16_t>(strtol(mask, &res, 10));
+if (*res != 0)
+ return true;
+
+prt1 = static_cast<uint16_t>(strtol(port1, &res, 10));
+if (*res != 0)
+ return true;
+
+prt2 = static_cast<uint16_t>(strtol(port2, &res, 10));
+if (*res != 0)
+ return true;
+
+int r = inet_aton(addr, &ipaddr);
+if (r == 0)
+ return true;
+
+rule->ip = ipaddr.s_addr;
+rule->mask = CalcMask(msk);
+
+if ((ipaddr.s_addr & rule->mask) != ipaddr.s_addr)
+ {
+ printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - Address does'n match mask.\n");
+ WriteServLog("Address does'n match mask.");
+ return true;
+ }
+
+rule->port1 = prt1;
+rule->port2 = prt2;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+uint32_t TRAFFCOUNTER_IMPL::CalcMask(uint32_t msk) const
+{
+if (msk >= 32) return 0xFFffFFff;
+if (msk == 0) return 0;
+return htonl(0xFFffFFff << (32 - msk));
+}
+//---------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::FreeRules()
+{
+rules.clear();
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER_IMPL::SetMonitorDir(const std::string & dir)
+{
+monitorDir = dir;
+monitoring = !monitorDir.empty();
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.23 $
+ $Date: 2010/04/22 12:57:46 $
+ $Author: faust $
+ */
+
+
+#ifndef TRAFFCOUNTER_IMPL_H
+#define TRAFFCOUNTER_IMPL_H
+
+#include "stg/traffcounter.h"
+#include "stg/logger.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/noncopyable.h"
+#include "stg/notifer.h"
+#include "actions.h"
+#include "eventloop.h"
+#include "user_impl.h"
+
+#include <ctime>
+#include <list>
+#include <map>
+#include <string>
+#include <cstdint>
+
+#include <pthread.h>
+
+#define PROTOMAX (5)
+
+class USERS_IMPL;
+
+//-----------------------------------------------------------------------------
+struct RULE {
+uint32_t ip; // IP
+uint32_t mask; // Network mask
+uint16_t port1; // Min port
+uint16_t port2; // Max port
+uint8_t proto; // Protocol
+uint32_t dir; // Direction
+};
+//-----------------------------------------------------------------------------
+struct PACKET_EXTRA_DATA {
+PACKET_EXTRA_DATA()
+ : flushTime(0),
+ updateTime(0),
+ userU(NULL),
+ userUPresent(false),
+ userD(NULL),
+ userDPresent(false),
+ dirU(DIR_NUM),
+ dirD(DIR_NUM),
+ lenU(0),
+ lenD(0)
+{}
+
+time_t flushTime; // Last flush time
+time_t updateTime; // Last update time
+USER_IMPL * userU; // Uploader
+bool userUPresent; // Uploader is registered user
+USER_IMPL * userD; // Downloader
+bool userDPresent; // Downloader is registered user
+int dirU; // Upload direction
+int dirD; // Download direction
+uint32_t lenU; // Upload length
+uint32_t lenD; // Download length
+};
+//-----------------------------------------------------------------------------
+class TRAFFCOUNTER_IMPL;
+//-----------------------------------------------------------------------------
+class TRF_IP_BEFORE: public PROPERTY_NOTIFIER_BASE<uint32_t> {
+public:
+ TRF_IP_BEFORE(TRAFFCOUNTER_IMPL & t, USER_IMPL * u)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(t),
+ user(u)
+ {}
+ TRF_IP_BEFORE(const TRF_IP_BEFORE & rvalue)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(rvalue.traffCnt),
+ user(rvalue.user)
+ {}
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ void SetUser(USER_IMPL * u) { user = u; }
+ USER_IMPL * GetUser() const { return user; }
+
+private:
+ TRF_IP_BEFORE & operator=(const TRF_IP_BEFORE & rvalue);
+
+ TRAFFCOUNTER_IMPL & traffCnt;
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class TRF_IP_AFTER: public PROPERTY_NOTIFIER_BASE<uint32_t> {
+public:
+ TRF_IP_AFTER(TRAFFCOUNTER_IMPL & t, USER_IMPL * u)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(t),
+ user(u)
+ {}
+ TRF_IP_AFTER(const TRF_IP_AFTER & rvalue)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(rvalue.traffCnt),
+ user(rvalue.user)
+ {}
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ void SetUser(USER_IMPL * u) { user = u; }
+ USER_IMPL * GetUser() const { return user; }
+private:
+ TRF_IP_AFTER & operator=(const TRF_IP_AFTER & rvalue);
+
+ TRAFFCOUNTER_IMPL & traffCnt;
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER: public NOTIFIER_BASE<USER_IMPL_PTR> {
+public:
+ explicit ADD_USER_NONIFIER(TRAFFCOUNTER_IMPL & t) :
+ NOTIFIER_BASE<USER_IMPL_PTR>(),
+ traffCnt(t)
+ {}
+ virtual ~ADD_USER_NONIFIER() {}
+ void Notify(const USER_IMPL_PTR & user);
+
+private:
+ ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
+ ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
+
+ TRAFFCOUNTER_IMPL & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER: public NOTIFIER_BASE<USER_IMPL_PTR> {
+public:
+ explicit DEL_USER_NONIFIER(TRAFFCOUNTER_IMPL & t) :
+ NOTIFIER_BASE<USER_IMPL_PTR>(),
+ traffCnt(t)
+ {}
+ virtual ~DEL_USER_NONIFIER() {}
+ void Notify(const USER_IMPL_PTR & user);
+
+private:
+ DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
+ DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
+
+ TRAFFCOUNTER_IMPL & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class TRAFFCOUNTER_IMPL : public TRAFFCOUNTER, private NONCOPYABLE {
+friend class ADD_USER_NONIFIER;
+friend class DEL_USER_NONIFIER;
+friend class TRF_IP_BEFORE;
+friend class TRF_IP_AFTER;
+public:
+ TRAFFCOUNTER_IMPL(USERS_IMPL * users, const std::string & rulesFileName);
+ ~TRAFFCOUNTER_IMPL();
+
+ int Reload();
+ int Start();
+ int Stop();
+
+ void Process(const RAW_PACKET & rawPacket);
+ void SetMonitorDir(const std::string & monitorDir);
+
+ size_t RulesCount() const { return rules.size(); }
+
+private:
+ TRAFFCOUNTER_IMPL(const TRAFFCOUNTER_IMPL &);
+ TRAFFCOUNTER_IMPL & operator=(const TRAFFCOUNTER_IMPL &);
+
+ bool ParseAddress(const char * ta, RULE * rule) const;
+ uint32_t CalcMask(uint32_t msk) const;
+ void FreeRules();
+ bool ReadRules(bool test = false);
+
+ static void * Run(void * data);
+
+ void DeterminateDir(const RAW_PACKET & packet,
+ int * dirU, // Direction for upload
+ int * dirD) const; // Direction for download
+
+ void FlushAndRemove();
+
+ void AddUser(USER_IMPL * user);
+ void DelUser(uint32_t uip);
+ void SetUserNotifiers(USER_IMPL * user);
+ void UnSetUserNotifiers(USER_IMPL * user);
+
+ typedef std::list<RULE>::iterator rule_iter;
+
+ std::list<RULE> rules;
+
+ typedef std::map<RAW_PACKET, PACKET_EXTRA_DATA> Packets;
+ typedef Packets::iterator pp_iter;
+ typedef std::multimap<uint32_t, pp_iter> Index;
+ typedef Index::iterator ip2p_iter;
+ typedef Index::const_iterator ip2p_citer;
+
+ Packets packets; // Packets tree
+
+ Index ip2packets; // IP-to-Packet index
+
+ std::string dirName[DIR_NUM + 1];
+
+ STG_LOGGER & WriteServLog;
+ std::string rulesFileName;
+
+ std::string monitorDir;
+ bool monitoring;
+ time_t touchTimeP;
+
+ USERS_IMPL * users;
+
+ bool running;
+ bool stopped;
+ pthread_mutex_t mutex;
+ pthread_t thread;
+
+ std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
+ std::list<TRF_IP_AFTER> ipAfterNotifiers;
+
+ ADD_USER_NONIFIER addUserNotifier;
+ DEL_USER_NONIFIER delUserNotifier;
+};
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &)
+{
+// User changes his address. Remove old IP
+if (!oldValue)
+ return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::DelUser, oldValue);
+}
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue)
+{
+// User changes his address. Add new IP
+if (!newValue)
+ return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::AddUser, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void ADD_USER_NONIFIER::Notify(const USER_IMPL_PTR & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::SetUserNotifiers, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void DEL_USER_NONIFIER::Notify(const USER_IMPL_PTR & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::UnSetUserNotifiers, user);
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER_IMPL::DelUser, user->GetCurrIP());
+}
+//-----------------------------------------------------------------------------
+#endif //TRAFFCOUNTER_H
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.101 $
+ $Date: 2010/11/03 10:50:03 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "user_impl.h"
+#include "settings_impl.h"
+#include "stg_timer.h"
+
+#include "stg/users.h"
+#include "stg/common.h"
+#include "stg/scriptexecuter.h"
+#include "stg/tariff.h"
+#include "stg/tariffs.h"
+#include "stg/admin.h"
+
+#include <algorithm>
+#include <functional>
+
+#include <cassert>
+#include <cstdlib>
+#include <cmath>
+
+#include <pthread.h>
+#include <unistd.h> // access
+
+namespace
+{
+
+std::string dirsToString(const bool * dirs)
+{
+std::string res;
+for (size_t i = 0; i < DIR_NUM; i++)
+ res += dirs[i] ? '1' : '0';
+return res;
+}
+
+void dirsFromBits(bool * dirs, uint32_t bits)
+{
+for (size_t i = 0; i < DIR_NUM; i++)
+ dirs[i] = bits & (1 << i);
+}
+
+}
+
+#ifdef USE_ABSTRACT_SETTINGS
+USER_IMPL::USER_IMPL(const SETTINGS * s,
+ const STORE * st,
+ const TARIFFS * t,
+ const ADMIN * a,
+ const USERS * u,
+ const SERVICES & svcs)
+ : users(u),
+ property(*s),
+ WriteServLog(GetStgLogger()),
+ lastScanMessages(0),
+ id(0),
+ __connected(0),
+ connected(__connected),
+ __currIP(0),
+ currIP(__currIP),
+ lastIPForDisconnect(0),
+ pingTime(0),
+ sysAdmin(a),
+ store(st),
+ tariffs(t),
+ tariff(NULL),
+ m_services(svcs),
+ settings(s),
+ authorizedModificationTime(0),
+ deleted(false),
+ lastWriteStat(0),
+ lastWriteDetailedStat(0),
+ cash(property.cash),
+ up(property.up),
+ down(property.down),
+ lastCashAdd(property.lastCashAdd),
+ passiveTime(property.passiveTime),
+ lastCashAddTime(property.lastCashAddTime),
+ freeMb(property.freeMb),
+ lastActivityTime(property.lastActivityTime),
+ password(property.password),
+ passive(property.passive),
+ disabled(property.disabled),
+ disabledDetailStat(property.disabledDetailStat),
+ alwaysOnline(property.alwaysOnline),
+ tariffName(property.tariffName),
+ nextTariff(property.nextTariff),
+ address(property.address),
+ note(property.note),
+ group(property.group),
+ email(property.email),
+ phone(property.phone),
+ realName(property.realName),
+ credit(property.credit),
+ creditExpire(property.creditExpire),
+ ips(property.ips),
+ userdata0(property.userdata0),
+ userdata1(property.userdata1),
+ userdata2(property.userdata2),
+ userdata3(property.userdata3),
+ userdata4(property.userdata4),
+ userdata5(property.userdata5),
+ userdata6(property.userdata6),
+ userdata7(property.userdata7),
+ userdata8(property.userdata8),
+ userdata9(property.userdata9),
+ sessionUploadModTime(stgTime),
+ sessionDownloadModTime(stgTime),
+ passiveNotifier(this),
+ disabledNotifier(this),
+ tariffNotifier(this),
+ cashNotifier(this),
+ ipNotifier(this)
+{
+Init();
+}
+#else
+USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
+ const STORE * st,
+ const TARIFFS * t,
+ const ADMIN * a,
+ const USERS * u,
+ const SERVICES & svcs)
+ : users(u),
+ property(*s),
+ WriteServLog(GetStgLogger()),
+ lastScanMessages(0),
+ id(0),
+ __connected(0),
+ connected(__connected),
+ __currIP(0),
+ currIP(__currIP),
+ lastIPForDisconnect(0),
+ pingTime(0),
+ sysAdmin(a),
+ store(st),
+ tariffs(t),
+ tariff(NULL),
+ m_services(svcs),
+ settings(s),
+ authorizedModificationTime(0),
+ deleted(false),
+ lastWriteStat(0),
+ lastWriteDetailedStat(0),
+ cash(property.cash),
+ up(property.up),
+ down(property.down),
+ lastCashAdd(property.lastCashAdd),
+ passiveTime(property.passiveTime),
+ lastCashAddTime(property.lastCashAddTime),
+ freeMb(property.freeMb),
+ lastActivityTime(property.lastActivityTime),
+ password(property.password),
+ passive(property.passive),
+ disabled(property.disabled),
+ disabledDetailStat(property.disabledDetailStat),
+ alwaysOnline(property.alwaysOnline),
+ tariffName(property.tariffName),
+ nextTariff(property.nextTariff),
+ address(property.address),
+ note(property.note),
+ group(property.group),
+ email(property.email),
+ phone(property.phone),
+ realName(property.realName),
+ credit(property.credit),
+ creditExpire(property.creditExpire),
+ ips(property.ips),
+ userdata0(property.userdata0),
+ userdata1(property.userdata1),
+ userdata2(property.userdata2),
+ userdata3(property.userdata3),
+ userdata4(property.userdata4),
+ userdata5(property.userdata5),
+ userdata6(property.userdata6),
+ userdata7(property.userdata7),
+ userdata8(property.userdata8),
+ userdata9(property.userdata9),
+ sessionUploadModTime(stgTime),
+ sessionDownloadModTime(stgTime),
+ passiveNotifier(this),
+ disabledNotifier(this),
+ tariffNotifier(this),
+ cashNotifier(this),
+ ipNotifier(this)
+{
+Init();
+}
+#endif
+//-----------------------------------------------------------------------------
+void USER_IMPL::Init()
+{
+password = "*_EMPTY_PASSWORD_*";
+tariffName = NO_TARIFF_NAME;
+tariff = tariffs->FindByName(tariffName);
+ips = StrToIPS("*");
+lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
+lastWriteDetailedStat = stgTime;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.disabled.AddAfterNotifier(&disabledNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+ips.AddAfterNotifier(&ipNotifier);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USER_IMPL::USER_IMPL(const USER_IMPL & u)
+ : USER(),
+ users(u.users),
+ property(*u.settings),
+ WriteServLog(GetStgLogger()),
+ lastScanMessages(0),
+ login(u.login),
+ id(u.id),
+ __connected(0),
+ connected(__connected),
+ userIDGenerator(u.userIDGenerator),
+ __currIP(u.__currIP),
+ currIP(__currIP),
+ lastIPForDisconnect(0),
+ pingTime(u.pingTime),
+ sysAdmin(u.sysAdmin),
+ store(u.store),
+ tariffs(u.tariffs),
+ tariff(u.tariff),
+ m_services(u.m_services),
+ traffStat(u.traffStat),
+ traffStatSaved(u.traffStatSaved),
+ settings(u.settings),
+ authorizedModificationTime(u.authorizedModificationTime),
+ messages(u.messages),
+ deleted(u.deleted),
+ lastWriteStat(u.lastWriteStat),
+ lastWriteDetailedStat(u.lastWriteDetailedStat),
+ cash(property.cash),
+ up(property.up),
+ down(property.down),
+ lastCashAdd(property.lastCashAdd),
+ passiveTime(property.passiveTime),
+ lastCashAddTime(property.lastCashAddTime),
+ freeMb(property.freeMb),
+ lastActivityTime(property.lastActivityTime),
+ password(property.password),
+ passive(property.passive),
+ disabled(property.disabled),
+ disabledDetailStat(property.disabledDetailStat),
+ alwaysOnline(property.alwaysOnline),
+ tariffName(property.tariffName),
+ nextTariff(property.nextTariff),
+ address(property.address),
+ note(property.note),
+ group(property.group),
+ email(property.email),
+ phone(property.phone),
+ realName(property.realName),
+ credit(property.credit),
+ creditExpire(property.creditExpire),
+ ips(property.ips),
+ userdata0(property.userdata0),
+ userdata1(property.userdata1),
+ userdata2(property.userdata2),
+ userdata3(property.userdata3),
+ userdata4(property.userdata4),
+ userdata5(property.userdata5),
+ userdata6(property.userdata6),
+ userdata7(property.userdata7),
+ userdata8(property.userdata8),
+ userdata9(property.userdata9),
+ sessionUpload(),
+ sessionDownload(),
+ sessionUploadModTime(stgTime),
+ sessionDownloadModTime(stgTime),
+ passiveNotifier(this),
+ disabledNotifier(this),
+ tariffNotifier(this),
+ cashNotifier(this),
+ ipNotifier(this)
+{
+if (&u == this)
+ return;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.disabled.AddAfterNotifier(&disabledNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+ips.AddAfterNotifier(&ipNotifier);
+
+property.SetProperties(u.property);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USER_IMPL::~USER_IMPL()
+{
+property.tariffName.DelBeforeNotifier(&tariffNotifier);
+property.passive.DelBeforeNotifier(&passiveNotifier);
+property.disabled.DelAfterNotifier(&disabledNotifier);
+property.cash.DelBeforeNotifier(&cashNotifier);
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::SetLogin(const std::string & l)
+{
+STG_LOCKER lock(&mutex);
+assert(login.empty() && "Login is already set");
+login = l;
+id = userIDGenerator.GetNextID();
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::ReadConf()
+{
+STG_LOCKER lock(&mutex);
+USER_CONF conf;
+
+if (store->RestoreUserConf(&conf, login))
+ {
+ WriteServLog("Cannot read conf for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+property.SetConf(conf);
+
+tariff = tariffs->FindByName(tariffName);
+if (tariff == NULL)
+ {
+ WriteServLog("Cannot read user %s. Tariff %s not exist.",
+ login.c_str(), property.tariffName.Get().c_str());
+ return -1;
+ }
+
+std::vector<STG_MSG_HDR> hdrsList;
+
+if (store->GetMessageHdrs(&hdrsList, login))
+ {
+ printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
+ WriteServLog("Cannot read user %s. Error reading message headers: %s.",
+ login.c_str(),
+ store->GetStrError().c_str());
+ return -1;
+ }
+
+std::vector<STG_MSG_HDR>::const_iterator it;
+for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
+ {
+ STG_MSG msg;
+ if (store->GetMessage(it->id, &msg, login) == 0)
+ {
+ messages.push_back(msg);
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::ReadStat()
+{
+STG_LOCKER lock(&mutex);
+USER_STAT stat;
+
+if (store->RestoreUserStat(&stat, login))
+ {
+ WriteServLog("Cannot read stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+property.SetStat(stat);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::WriteConf()
+{
+STG_LOCKER lock(&mutex);
+USER_CONF conf(property.GetConf());
+
+printfd(__FILE__, "USER::WriteConf()\n");
+
+if (store->SaveUserConf(conf, login))
+ {
+ WriteServLog("Cannot write conf for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::WriteStat()
+{
+STG_LOCKER lock(&mutex);
+USER_STAT stat(property.GetStat());
+
+if (store->SaveUserStat(stat, login))
+ {
+ WriteServLog("Cannot write stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+lastWriteStat = stgTime;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::WriteMonthStat()
+{
+STG_LOCKER lock(&mutex);
+time_t tt = stgTime - 3600;
+struct tm t1;
+localtime_r(&tt, &t1);
+
+USER_STAT stat(property.GetStat());
+if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
+ {
+ WriteServLog("Cannot write month stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
+{
+STG_LOCKER lock(&mutex);
+/*
+ * Authorize user. It only means that user will be authorized. Nothing more.
+ * User can be connected or disconnected while authorized.
+ * Example: user is authorized but disconnected due to 0 money or blocking
+ */
+
+/*
+ * TODO: in fact "authorization" means allowing access to a service. What we
+ * call "authorization" here, int STG, is "authentication". So this should be
+ * fixed in future.
+ */
+
+/*
+ * Prevent double authorization by identical authorizers
+ */
+if (authorizedBy.find(auth) != authorizedBy.end())
+ return 0;
+
+if (!ip)
+ return -1;
+
+dirsFromBits(enabledDirs, dirs);
+
+if (!authorizedBy.empty())
+ {
+ if (currIP != ip)
+ {
+ // We are already authorized, but with different IP address
+ errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
+ return -1;
+ }
+
+ USER * u = NULL;
+ if (!users->FindByIPIdx(ip, &u))
+ {
+ // Address presents in IP-index.
+ // If it's not our IP - report it.
+ if (u != this)
+ {
+ errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
+ return -1;
+ }
+ }
+ }
+else
+ {
+ if (users->IsIPInIndex(ip))
+ {
+ // Address is already present in IP-index.
+ errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
+ return -1;
+ }
+
+ if (ips.ConstData().IsIPInIPS(ip))
+ {
+ currIP = ip;
+ lastIPForDisconnect = currIP;
+ }
+ else
+ {
+ printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
+ errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
+ return -1;
+ }
+ }
+
+if (authorizedBy.empty())
+ authorizedModificationTime = stgTime;
+authorizedBy.insert(auth);
+
+ScanMessage();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
+{
+STG_LOCKER lock(&mutex);
+/*
+ * Authorizer tries to unauthorize user, that was not authorized by it
+ */
+if (!authorizedBy.erase(auth))
+ return;
+
+authorizedModificationTime = stgTime;
+
+if (authorizedBy.empty())
+ {
+ lastDisconnectReason = reason;
+ lastIPForDisconnect = currIP;
+ currIP = 0; // DelUser in traffcounter
+ if (connected)
+ Disconnect(false, "not authorized");
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
+{
+STG_LOCKER lock(&mutex);
+// Is this user authorized by specified authorizer?
+return authorizedBy.find(auth) != authorizedBy.end();
+}
+//-----------------------------------------------------------------------------
+std::vector<std::string> USER_IMPL::GetAuthorizers() const
+{
+ STG_LOCKER lock(&mutex);
+ std::vector<std::string> list;
+ std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
+ return list;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::Connect(bool fakeConnect)
+{
+/*
+ * Connect user to Internet. This function is differ from Authorize() !!!
+ */
+
+STG_LOCKER lock(&mutex);
+
+if (!fakeConnect)
+ {
+ std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
+
+ if (access(scriptOnConnect.c_str(), X_OK) == 0)
+ {
+ std::string dirs = dirsToString(enabledDirs);
+
+ std::string scriptOnConnectParams;
+ strprintf(&scriptOnConnectParams,
+ "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+ scriptOnConnect.c_str(),
+ login.c_str(),
+ inet_ntostring(currIP).c_str(),
+ cash.ConstData(),
+ id,
+ dirs.c_str());
+
+ std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
+ while (it != settings->GetScriptParams().end())
+ {
+ scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
+ ++it;
+ }
+
+ ScriptExec(scriptOnConnectParams.c_str());
+ }
+ else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
+ }
+
+ connected = true;
+ }
+
+if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
+ {
+ WriteServLog("Cannot write connect for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+if (!fakeConnect)
+ lastIPForDisconnect = currIP;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
+{
+/*
+ * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
+ */
+
+STG_LOCKER lock(&mutex);
+
+if (!lastIPForDisconnect)
+ {
+ printfd(__FILE__, "lastIPForDisconnect\n");
+ return;
+ }
+
+if (!fakeDisconnect)
+ {
+ lastDisconnectReason = reason;
+ std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
+
+ if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
+ {
+ std::string dirs = dirsToString(enabledDirs);
+
+ std::string scriptOnDisonnectParams;
+ strprintf(&scriptOnDisonnectParams,
+ "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+ scriptOnDisonnect.c_str(),
+ login.c_str(),
+ inet_ntostring(lastIPForDisconnect).c_str(),
+ cash.ConstData(),
+ id,
+ dirs.c_str());
+
+ std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
+ while (it != settings->GetScriptParams().end())
+ {
+ scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
+ ++it;
+ }
+
+ ScriptExec(scriptOnDisonnectParams.c_str());
+ }
+ else
+ {
+ WriteServLog("Script OnDisconnect cannot be executed. File not found.");
+ }
+
+ connected = false;
+ }
+
+std::string reasonMessage(reason);
+if (!lastDisconnectReason.empty())
+ reasonMessage += ": " + lastDisconnectReason;
+
+if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
+ cash, freeMb, reasonMessage))
+ {
+ WriteServLog("Cannot write disconnect for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+if (!fakeDisconnect)
+ lastIPForDisconnect = 0;
+
+sessionUpload.Reset();
+sessionDownload.Reset();
+sessionUploadModTime = stgTime;
+sessionDownloadModTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::Run()
+{
+STG_LOCKER lock(&mutex);
+
+if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
+ {
+ printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
+ WriteStat();
+ }
+if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
+ {
+ WriteServLog("User: %s. Credit expired.", login.c_str());
+ credit = 0;
+ creditExpire = 0;
+ WriteConf();
+ }
+
+if (passive.ConstData()
+ && (stgTime % 30 == 0)
+ && (passiveTime.ModificationTime() != stgTime))
+ {
+ passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
+ printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
+ }
+
+if (!authorizedBy.empty())
+ {
+ if (connected)
+ property.Stat().lastActivityTime = stgTime;
+
+ if (!connected && IsInetable())
+ Connect();
+
+ if (connected && !IsInetable())
+ {
+ if (disabled)
+ Disconnect(false, "disabled");
+ else if (passive)
+ Disconnect(false, "passive");
+ else
+ Disconnect(false, "no cash");
+ }
+
+ if (stgTime - lastScanMessages > 10)
+ {
+ ScanMessage();
+ lastScanMessages = stgTime;
+ }
+ }
+else
+ {
+ if (connected)
+ Disconnect(false, "not authorized");
+ }
+
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::UpdatePingTime(time_t t)
+{
+STG_LOCKER lock(&mutex);
+if (t)
+ pingTime = t;
+else
+ pingTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+bool USER_IMPL::IsInetable()
+{
+if (disabled || passive)
+ return false;
+
+if (settings->GetFreeMbAllowInet())
+ {
+ if (freeMb >= 0)
+ return true;
+ }
+
+if (settings->GetShowFeeInCash() || tariff == NULL)
+ return (cash >= -credit);
+
+return (cash - tariff->GetFee() >= -credit);
+}
+//-----------------------------------------------------------------------------
+std::string USER_IMPL::GetEnabledDirs() const
+{
+return dirsToString(enabledDirs);
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex);
+
+if (!connected || tariff == NULL)
+ return;
+
+double cost = 0;
+DIR_TRAFF dt(up);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == TARIFF::TRAFF_UP ||
+ tt == TARIFF::TRAFF_UP_DOWN ||
+ // Check NEW traff data
+ (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
+ {
+ double dc = 0;
+ if (traff < threshold &&
+ traff + len >= threshold)
+ {
+ // cash = partBeforeThreshold * priceBeforeThreshold +
+ // partAfterThreshold * priceAfterThreshold
+ int64_t before = threshold - traff; // Chunk part before threshold
+ int64_t after = len - before; // Chunk part after threshold
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
+ down.ConstData()[dir],
+ dir,
+ stgTime) * before +
+ tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
+ down.ConstData()[dir],
+ dir,
+ stgTime) * after;
+ }
+ else
+ {
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir],
+ dir,
+ stgTime) * len;
+ }
+
+ if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+ cost = dc;
+ else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+ cost = dc - freeMb.ConstData();
+
+ // Direct access to internal data structures via friend-specifier
+ property.Stat().freeMb -= dc;
+ property.Stat().cash -= cost;
+ cash.ModifyTime();
+ freeMb.ModifyTime();
+ }
+
+up = dt;
+sessionUpload[dir] += len;
+sessionUploadModTime = stgTime;
+
+//Add detailed stat
+
+if (!settings->GetWriteFreeMbTraffCost() &&
+ freeMb.ConstData() >= 0)
+ cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IP_DIR_PAIR idp(ip, dir, port);
+#else
+IP_DIR_PAIR idp(ip, dir);
+#endif
+
+std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
+lb = traffStat.lower_bound(idp);
+if (lb == traffStat.end() || lb->first != idp)
+ {
+ traffStat.insert(lb,
+ std::make_pair(idp,
+ STAT_NODE(len, 0, cost)));
+ }
+else
+ {
+ lb->second.cash += cost;
+ lb->second.up += len;
+ }
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex);
+
+if (!connected || tariff == NULL)
+ return;
+
+double cost = 0;
+DIR_TRAFF dt(down);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == TARIFF::TRAFF_DOWN ||
+ tt == TARIFF::TRAFF_UP_DOWN ||
+ // Check NEW traff data
+ (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
+ {
+ double dc = 0;
+ if (traff < threshold &&
+ traff + len >= threshold)
+ {
+ // cash = partBeforeThreshold * priceBeforeThreshold +
+ // partAfterThreshold * priceAfterThreshold
+ int64_t before = threshold - traff; // Chunk part before threshold
+ int64_t after = len - before; // Chunk part after threshold
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir], // Traff before chunk
+ dir,
+ stgTime) * before +
+ tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ dt[dir], // Traff after chunk
+ dir,
+ stgTime) * after;
+ }
+ else
+ {
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir],
+ dir,
+ stgTime) * len;
+ }
+
+ if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+ cost = dc;
+ else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+ cost = dc - freeMb.ConstData();
+
+ property.Stat().freeMb -= dc;
+ property.Stat().cash -= cost;
+ cash.ModifyTime();
+ freeMb.ModifyTime();
+ }
+
+down = dt;
+sessionDownload[dir] += len;
+sessionDownloadModTime = stgTime;
+
+//Add detailed stat
+
+if (!settings->GetWriteFreeMbTraffCost() &&
+ freeMb.ConstData() >= 0)
+ cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IP_DIR_PAIR idp(ip, dir, port);
+#else
+IP_DIR_PAIR idp(ip, dir);
+#endif
+
+std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
+lb = traffStat.lower_bound(idp);
+if (lb == traffStat.end() || lb->first != idp)
+ {
+ traffStat.insert(lb,
+ std::make_pair(idp,
+ STAT_NODE(0, len, cost)));
+ }
+else
+ {
+ lb->second.cash += cost;
+ lb->second.down += len;
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.AddBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.DelBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.AddAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.DelAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.AddBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.DelBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.AddAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.DelAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::OnAdd()
+{
+STG_LOCKER lock(&mutex);
+
+std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
+
+if (access(scriptOnAdd.c_str(), X_OK) == 0)
+ {
+ std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
+
+ ScriptExec(scriptOnAddParams.c_str());
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::OnDelete()
+{
+STG_LOCKER lock(&mutex);
+
+std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
+
+if (access(scriptOnDel.c_str(), X_OK) == 0)
+ {
+ std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
+
+ ScriptExec(scriptOnDelParams.c_str());
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
+ }
+
+Run();
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::WriteDetailStat(bool hard)
+{
+printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
+
+if (!traffStatSaved.second.empty())
+ {
+ if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
+ {
+ printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
+ WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+ traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
+ }
+
+TRAFF_STAT ts;
+
+ {
+ STG_LOCKER lock(&mutex);
+ ts.swap(traffStat);
+ }
+
+printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
+
+if (ts.size() && !disabledDetailStat)
+ {
+ if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
+ {
+ printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
+ WriteServLog("Cannot write detail stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ if (!hard)
+ {
+ printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
+ STG_LOCKER lock(&mutex);
+ traffStatSaved.second.swap(ts);
+ traffStatSaved.first = lastWriteDetailedStat;
+ }
+ return -1;
+ }
+ }
+lastWriteDetailedStat = stgTime;
+return 0;
+}
+//-----------------------------------------------------------------------------
+double USER_IMPL::GetPassiveTimePart() const
+{
+STG_LOCKER lock(&mutex);
+
+static int daysInMonth[12] =
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+struct tm tms;
+time_t t = stgTime;
+localtime_r(&t, &tms);
+
+time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
+
+if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
+ {
+ // Leap year
+ secMonth += 24 * 3600;
+ }
+
+time_t dt = secMonth - passiveTime;
+
+if (dt < 0)
+ dt = 0;
+
+return static_cast<double>(dt) / secMonth;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::SetPassiveTimeAsNewUser()
+{
+STG_LOCKER lock(&mutex);
+
+time_t t = stgTime;
+struct tm tm;
+localtime_r(&t, &tm);
+int daysCurrMon = DaysInCurrentMonth();
+double pt = tm.tm_mday - 1;
+pt /= daysCurrMon;
+
+passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::MidnightResetSessionStat()
+{
+STG_LOCKER lock(&mutex);
+
+if (connected)
+ {
+ Disconnect(true, "fake");
+ Connect(true);
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ProcessNewMonth()
+{
+STG_LOCKER lock(&mutex);
+// Reset traff
+if (connected)
+ Disconnect(true, "fake");
+
+WriteMonthStat();
+
+property.Stat().monthUp.Reset();
+property.Stat().monthDown.Reset();
+
+if (connected)
+ Connect(true);
+
+// Set new tariff
+if (nextTariff.ConstData() != "")
+ {
+ const TARIFF * nt = tariffs->FindByName(nextTariff);
+ if (nt == NULL)
+ {
+ WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
+ login.c_str(), property.tariffName.Get().c_str());
+ }
+ else
+ {
+ std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
+ if (message.empty())
+ {
+ property.tariffName.Set(nextTariff, sysAdmin, login, store);
+ }
+ else
+ {
+ WriteServLog("Tariff change is prohibited for user %s. %s",
+ login.c_str(),
+ message.c_str());
+ }
+ }
+ ResetNextTariff();
+ WriteConf();
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ProcessDayFeeSpread()
+{
+STG_LOCKER lock(&mutex);
+
+if (passive.ConstData() || tariff == NULL)
+ return;
+
+if (tariff->GetPeriod() != TARIFF::MONTH)
+ return;
+
+double fee = tariff->GetFee() / DaysInCurrentMonth();
+
+if (std::fabs(fee) < 1.0e-3)
+ return;
+
+double c = cash;
+switch (settings->GetFeeChargeType())
+ {
+ case 0:
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ case 1:
+ if (c + credit >= 0)
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ case 2:
+ if (c + credit >= fee)
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ case 3:
+ if (c >= 0)
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ }
+ResetPassiveTime();
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ProcessDayFee()
+{
+STG_LOCKER lock(&mutex);
+
+if (tariff == NULL)
+ return;
+
+if (tariff->GetPeriod() != TARIFF::MONTH)
+ return;
+
+double passiveTimePart = 1.0;
+if (!settings->GetFullFee())
+ {
+ passiveTimePart = GetPassiveTimePart();
+ }
+else
+ {
+ if (passive.ConstData())
+ {
+ printfd(__FILE__, "Don't charge fee `cause we are passive\n");
+ return;
+ }
+ }
+double fee = tariff->GetFee() * passiveTimePart;
+
+ResetPassiveTime();
+
+if (std::fabs(fee) < 1.0e-3)
+ {
+ SetPrepaidTraff();
+ return;
+ }
+
+double c = cash;
+printfd(__FILE__, "login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
+ login.c_str(),
+ cash.ConstData(),
+ credit.ConstData(),
+ tariff->GetFee(),
+ passiveTimePart,
+ fee);
+switch (settings->GetFeeChargeType())
+ {
+ case 0:
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ break;
+ case 1:
+ if (c + credit >= 0)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ case 2:
+ if (c + credit >= fee)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ case 3:
+ if (c >= 0)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ProcessDailyFee()
+{
+STG_LOCKER lock(&mutex);
+
+if (passive.ConstData() || tariff == NULL)
+ return;
+
+if (tariff->GetPeriod() != TARIFF::DAY)
+ return;
+
+double fee = tariff->GetFee();
+
+if (fee == 0.0)
+ return;
+
+double c = cash;
+switch (settings->GetFeeChargeType())
+ {
+ case 0:
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ case 1:
+ if (c + credit >= 0)
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ case 2:
+ if (c + credit >= fee)
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ break;
+ }
+ResetPassiveTime();
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ProcessServices()
+{
+struct tm tms;
+time_t t = stgTime;
+localtime_r(&t, &tms);
+
+double passiveTimePart = 1.0;
+if (!settings->GetFullFee())
+ {
+ passiveTimePart = GetPassiveTimePart();
+ }
+else
+ {
+ if (passive.ConstData())
+ {
+ printfd(__FILE__, "Don't charge fee `cause we are passive\n");
+ return;
+ }
+ }
+
+for (size_t i = 0; i < property.Conf().services.size(); ++i)
+ {
+ SERVICE_CONF conf;
+ if (m_services.Find(property.Conf().services[i], &conf))
+ continue;
+ if (conf.payDay == tms.tm_mday ||
+ (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
+ {
+ double c = cash;
+ double fee = conf.cost * passiveTimePart;
+ printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f Fee=%f PassiveTimePart=%f fee=%f\n",
+ login.c_str(),
+ cash.ConstData(),
+ credit.ConstData(),
+ tariff->GetFee(),
+ passiveTimePart,
+ fee);
+ switch (settings->GetFeeChargeType())
+ {
+ case 0:
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ break;
+ case 1:
+ if (c + credit >= 0)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ case 2:
+ if (c + credit >= fee)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ case 3:
+ if (c >= 0)
+ {
+ property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
+ SetPrepaidTraff();
+ }
+ break;
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::SetPrepaidTraff()
+{
+if (tariff != NULL)
+ property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::AddMessage(STG_MSG * msg)
+{
+STG_LOCKER lock(&mutex);
+
+if (SendMessage(*msg))
+ {
+ if (store->AddMessage(msg, login))
+ {
+ errorStr = store->GetStrError();
+ WriteServLog("Error adding message: '%s'", errorStr.c_str());
+ printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+ messages.push_back(*msg);
+ }
+else
+ {
+ if (msg->header.repeat > 0)
+ {
+ msg->header.repeat--;
+ #ifndef DEBUG
+ //TODO: gcc v. 4.x generate ICE on x86_64
+ msg->header.lastSendTime = static_cast<int>(time(NULL));
+ #else
+ msg->header.lastSendTime = static_cast<int>(stgTime);
+ #endif
+ if (store->AddMessage(msg, login))
+ {
+ errorStr = store->GetStrError();
+ WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
+ printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+ messages.push_back(*msg);
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER_IMPL::SendMessage(STG_MSG & msg) const
+{
+// No lock `cause we are already locked from caller
+int ret = -1;
+std::set<const AUTH*>::iterator it(authorizedBy.begin());
+while (it != authorizedBy.end())
+ {
+ if (!(*it++)->SendMessage(msg, currIP))
+ ret = 0;
+ }
+if (!ret)
+ {
+#ifndef DEBUG
+ //TODO: gcc v. 4.x generate ICE on x86_64
+ msg.header.lastSendTime = static_cast<int>(time(NULL));
+#else
+ msg.header.lastSendTime = static_cast<int>(stgTime);
+#endif
+ msg.header.repeat--;
+ }
+return ret;
+}
+//-----------------------------------------------------------------------------
+void USER_IMPL::ScanMessage()
+{
+// No lock `cause we are already locked from caller
+// We need not check for the authorizedBy `cause it has already checked by caller
+
+std::list<STG_MSG>::iterator it(messages.begin());
+while (it != messages.end())
+ {
+ if (settings->GetMessageTimeout() > 0 &&
+ difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
+ {
+ // Timeout exceeded
+ if (store->DelMessage(it->header.id, login))
+ {
+ WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+ printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+ }
+ messages.erase(it++);
+ continue;
+ }
+ if (it->GetNextSendTime() <= stgTime)
+ {
+ if (SendMessage(*it))
+ {
+ // We need to check all messages in queue for timeout
+ ++it;
+ continue;
+ }
+ if (it->header.repeat < 0)
+ {
+ if (store->DelMessage(it->header.id, login))
+ {
+ WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+ printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+ }
+ messages.erase(it++);
+ }
+ else
+ {
+ if (store->EditMessage(*it, login))
+ {
+ WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
+ printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
+ }
+ ++it;
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+std::string USER_IMPL::GetParamValue(const std::string & name) const
+{
+ std::string lowerName = ToLower(name);
+ if (lowerName == "id")
+ {
+ std::ostringstream stream;
+ stream << id;
+ return stream.str();
+ }
+ if (lowerName == "login") return login;
+ if (lowerName == "currip") return currIP.ToString();
+ if (lowerName == "enableddirs") return GetEnabledDirs();
+ if (lowerName == "tariff") return property.tariffName;
+ if (property.Exists(lowerName))
+ return property.GetPropertyValue(lowerName);
+ else
+ {
+ WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
+ return "";
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
+{
+if (newPassive && !oldPassive && user->tariff != NULL)
+ user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
+ user->sysAdmin,
+ user->login,
+ user->store,
+ "Freeze");
+}
+//-----------------------------------------------------------------------------
+void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
+{
+if (oldValue && !newValue && user->GetConnected())
+ user->Disconnect(false, "disabled");
+else if (!oldValue && newValue && user->IsInetable())
+ user->Connect(false);
+}
+//-----------------------------------------------------------------------------
+void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
+{
+STG_LOCKER lock(&user->mutex);
+if (user->settings->GetReconnectOnTariffChange() && user->connected)
+ user->Disconnect(false, "Change tariff");
+user->tariff = user->tariffs->FindByName(newTariff);
+if (user->settings->GetReconnectOnTariffChange() &&
+ !user->authorizedBy.empty() &&
+ user->IsInetable())
+ {
+ // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
+ user->property.Conf().tariffName = newTariff;
+ user->Connect(false);
+ }
+}
+//-----------------------------------------------------------------------------
+void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
+{
+user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
+user->lastCashAdd = newCash - oldCash;
+}
+//-----------------------------------------------------------------------------
+void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
+{
+printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
+if (user->connected)
+ user->Disconnect(false, "Change IP");
+if (!user->authorizedBy.empty() && user->IsInetable())
+ user->Connect(false);
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.48 $
+ $Date: 2010/11/03 10:50:03 $
+ $Author: faust $
+ */
+
+#ifndef USER_IMPL_H
+#define USER_IMPL_H
+
+#include "stg/user.h"
+#include "stg/user_stat.h"
+#include "stg/user_conf.h"
+#include "stg/user_ips.h"
+#include "stg/user_property.h"
+#include "stg/auth.h"
+#include "stg/message.h"
+#include "stg/noncopyable.h"
+#include "stg/const.h"
+
+#include <list>
+#include <vector>
+#include <string>
+#include <set>
+
+#include <ctime>
+#include <cstdint>
+
+//-----------------------------------------------------------------------------
+class TARIFF;
+class TARIFFS;
+class ADMIN;
+class USER_IMPL;
+#ifdef USE_ABSTRACT_SETTINGS
+class SETTINGS;
+#else
+class SETTINGS_IMPL;
+#endif
+//-----------------------------------------------------------------------------
+class USER_ID_GENERATOR {
+friend class USER_IMPL;
+private:
+ USER_ID_GENERATOR() {}
+ int GetNextID() { static int id = 0; return id++; }
+};
+//-----------------------------------------------------------------------------
+class CHG_PASSIVE_NOTIFIER : public PROPERTY_NOTIFIER_BASE<int>,
+ private NONCOPYABLE {
+public:
+ explicit CHG_PASSIVE_NOTIFIER(USER_IMPL * u) : user(u) {}
+ void Notify(const int & oldPassive, const int & newPassive);
+
+private:
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_DISABLED_NOTIFIER : public PROPERTY_NOTIFIER_BASE<int>,
+ private NONCOPYABLE {
+public:
+ explicit CHG_DISABLED_NOTIFIER(USER_IMPL * u) : user(u) {}
+ void Notify(const int & oldValue, const int & newValue);
+
+private:
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_TARIFF_NOTIFIER : public PROPERTY_NOTIFIER_BASE<std::string>,
+ private NONCOPYABLE {
+public:
+ explicit CHG_TARIFF_NOTIFIER(USER_IMPL * u) : user(u) {}
+ void Notify(const std::string & oldTariff, const std::string & newTariff);
+
+private:
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_CASH_NOTIFIER : public PROPERTY_NOTIFIER_BASE<double>,
+ private NONCOPYABLE {
+public:
+ explicit CHG_CASH_NOTIFIER(USER_IMPL * u) : user(u) {}
+ void Notify(const double & oldCash, const double & newCash);
+
+private:
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_IPS_NOTIFIER : public PROPERTY_NOTIFIER_BASE<USER_IPS>,
+ private NONCOPYABLE {
+public:
+ explicit CHG_IPS_NOTIFIER(USER_IMPL * u) : user(u) {}
+ void Notify(const USER_IPS & oldIPs, const USER_IPS & newIPs);
+
+private:
+ USER_IMPL * user;
+};
+//-----------------------------------------------------------------------------
+class USER_IMPL : public USER {
+friend class CHG_PASSIVE_NOTIFIER;
+friend class CHG_DISABLED_NOTIFIER;
+friend class CHG_TARIFF_NOTIFIER;
+friend class CHG_CASH_NOTIFIER;
+friend class CHG_IPS_NOTIFIER;
+public:
+#ifdef USE_ABSTRACT_SETTINGS
+ USER_IMPL(const SETTINGS * settings,
+ const STORE * store,
+ const TARIFFS * tariffs,
+ const ADMIN * sysAdmin,
+ const USERS * u,
+ const SERVICES & svcs);
+#else
+ USER_IMPL(const SETTINGS_IMPL * settings,
+ const STORE * store,
+ const TARIFFS * tariffs,
+ const ADMIN * sysAdmin,
+ const USERS * u,
+ const SERVICES & svcs);
+#endif
+ USER_IMPL(const USER_IMPL & u);
+ virtual ~USER_IMPL();
+
+ int ReadConf();
+ int ReadStat();
+ int WriteConf();
+ int WriteStat();
+ int WriteMonthStat();
+
+ const std::string & GetLogin() const { return login; }
+ void SetLogin(std::string const & l);
+
+ uint32_t GetCurrIP() const { return currIP; }
+ time_t GetCurrIPModificationTime() const { return currIP.ModificationTime(); }
+
+ void AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier);
+ void DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier);
+
+ void AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier);
+ void DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier);
+
+ void AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier);
+ void DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier);
+
+ void AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier);
+ void DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier);
+
+ int GetID() const { return id; }
+
+ double GetPassiveTimePart() const;
+ void ResetPassiveTime() { passiveTime = 0; }
+ void SetPassiveTimeAsNewUser();
+
+ int WriteDetailStat(bool hard = false);
+
+ const TARIFF * GetTariff() const { return tariff; }
+ void ResetNextTariff() { nextTariff = ""; }
+
+ #ifdef TRAFF_STAT_WITH_PORTS
+ void AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len);
+ void AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len);
+ #else
+ void AddTraffStatU(int dir, uint32_t ip, uint32_t len);
+ void AddTraffStatD(int dir, uint32_t ip, uint32_t len);
+ #endif
+
+ const DIR_TRAFF & GetSessionUpload() const { return sessionUpload; }
+ const DIR_TRAFF & GetSessionDownload() const { return sessionDownload; }
+ time_t GetSessionUploadModificationTime() const { return sessionUploadModTime; }
+ time_t GetSessionDownloadModificationTime() const { return sessionDownloadModTime; }
+
+ bool GetConnected() const { return connected; }
+ time_t GetConnectedModificationTime() const { return connected.ModificationTime(); }
+ const std::string & GetLastDisconnectReason() const { return lastDisconnectReason; }
+ int GetAuthorized() const { return static_cast<int>(authorizedBy.size()); }
+ time_t GetAuthorizedModificationTime() const { return authorizedModificationTime; }
+ int Authorize(uint32_t ip, uint32_t enabledDirs, const AUTH * auth);
+ void Unauthorize(const AUTH * auth,
+ const std::string & reason = std::string());
+ bool IsAuthorizedBy(const AUTH * auth) const;
+ std::vector<std::string> GetAuthorizers() const;
+
+ int AddMessage(STG_MSG * msg);
+
+ void UpdatePingTime(time_t t = 0);
+ time_t GetPingTime() const { return pingTime; }
+
+ void Run();
+
+ const std::string & GetStrError() const { return errorStr; }
+
+ USER_PROPERTIES & GetProperty() { return property; }
+ const USER_PROPERTIES & GetProperty() const { return property; }
+
+ void SetDeleted() { deleted = true; }
+ bool GetDeleted() const { return deleted; }
+
+ time_t GetLastWriteStatTime() const { return lastWriteStat; }
+
+ void MidnightResetSessionStat();
+ void ProcessDayFee();
+ void ProcessDayFeeSpread();
+ void ProcessNewMonth();
+ void ProcessDailyFee();
+ void ProcessServices();
+
+ bool IsInetable();
+ std::string GetEnabledDirs() const;
+
+ void OnAdd();
+ void OnDelete();
+
+ virtual std::string GetParamValue(const std::string & name) const;
+
+private:
+ USER_IMPL & operator=(const USER_IMPL & rvalue);
+
+ void Init();
+
+ const USERS * users;
+ USER_PROPERTIES property;
+ STG_LOGGER & WriteServLog;
+
+ void Connect(bool fakeConnect = false);
+ void Disconnect(bool fakeDisconnect, const std::string & reason);
+ int SaveMonthStat(int month, int year);
+
+ void SetPrepaidTraff();
+
+ int SendMessage(STG_MSG & msg) const;
+ void ScanMessage();
+
+ time_t lastScanMessages;
+
+ std::string login;
+ int id;
+ bool __connected;
+ USER_PROPERTY<bool> connected;
+
+ bool enabledDirs[DIR_NUM];
+
+ USER_ID_GENERATOR userIDGenerator;
+
+ uint32_t __currIP; // Current user's ip
+ USER_PROPERTY<uint32_t> currIP;
+
+ uint32_t lastIPForDisconnect; // User's ip after unauth but before disconnect
+ std::string lastDisconnectReason;
+
+ time_t pingTime;
+
+ const ADMIN * sysAdmin;
+ const STORE * store;
+
+ const TARIFFS * tariffs;
+ const TARIFF * tariff;
+
+ const SERVICES & m_services;
+
+ TRAFF_STAT traffStat;
+ std::pair<time_t, TRAFF_STAT> traffStatSaved;
+
+#ifdef USE_ABSTRACT_SETTINGS
+ const SETTINGS * settings;
+#else
+ const SETTINGS_IMPL * settings;
+#endif
+
+ std::set<const AUTH *> authorizedBy;
+ time_t authorizedModificationTime;
+
+ std::list<STG_MSG> messages;
+
+ bool deleted;
+
+ time_t lastWriteStat;
+ time_t lastWriteDetailedStat;
+
+ // Properties
+ USER_PROPERTY<double> & cash;
+ USER_PROPERTY<DIR_TRAFF> & up;
+ USER_PROPERTY<DIR_TRAFF> & down;
+ USER_PROPERTY<double> & lastCashAdd;
+ USER_PROPERTY<time_t> & passiveTime;
+ USER_PROPERTY<time_t> & lastCashAddTime;
+ USER_PROPERTY<double> & freeMb;
+ USER_PROPERTY<time_t> & lastActivityTime;
+ USER_PROPERTY<std::string> & password;
+ USER_PROPERTY<int> & passive;
+ USER_PROPERTY<int> & disabled;
+ USER_PROPERTY<int> & disabledDetailStat;
+ USER_PROPERTY<int> & alwaysOnline;
+ USER_PROPERTY<std::string> & tariffName;
+ USER_PROPERTY<std::string> & nextTariff;
+ USER_PROPERTY<std::string> & address;
+ USER_PROPERTY<std::string> & note;
+ USER_PROPERTY<std::string> & group;
+ USER_PROPERTY<std::string> & email;
+ USER_PROPERTY<std::string> & phone;
+ USER_PROPERTY<std::string> & realName;
+ USER_PROPERTY<double> & credit;
+ USER_PROPERTY<time_t> & creditExpire;
+ USER_PROPERTY<USER_IPS> & ips;
+ USER_PROPERTY<std::string> & userdata0;
+ USER_PROPERTY<std::string> & userdata1;
+ USER_PROPERTY<std::string> & userdata2;
+ USER_PROPERTY<std::string> & userdata3;
+ USER_PROPERTY<std::string> & userdata4;
+ USER_PROPERTY<std::string> & userdata5;
+ USER_PROPERTY<std::string> & userdata6;
+ USER_PROPERTY<std::string> & userdata7;
+ USER_PROPERTY<std::string> & userdata8;
+ USER_PROPERTY<std::string> & userdata9;
+
+ // End properties
+
+ DIR_TRAFF sessionUpload;
+ DIR_TRAFF sessionDownload;
+ time_t sessionUploadModTime;
+ time_t sessionDownloadModTime;
+
+ CHG_PASSIVE_NOTIFIER passiveNotifier;
+ CHG_DISABLED_NOTIFIER disabledNotifier;
+ CHG_TARIFF_NOTIFIER tariffNotifier;
+ CHG_CASH_NOTIFIER cashNotifier;
+ CHG_IPS_NOTIFIER ipNotifier;
+
+ mutable pthread_mutex_t mutex;
+
+ std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+
+typedef USER_IMPL * USER_IMPL_PTR;
+
+#endif //USER_H
--- /dev/null
+#include "stg/user_property.h"
+
+USER_PROPERTIES::USER_PROPERTIES(const SETTINGS& s)
+ : stat(),
+ conf(),
+ cash (stat.cash, "cash", false, true, GetStgLogger(), s, properties),
+ up (stat.monthUp, "upload", false, true, GetStgLogger(), s, properties),
+ down (stat.monthDown, "download", false, true, GetStgLogger(), s, properties),
+ lastCashAdd (stat.lastCashAdd, "lastCashAdd", false, true, GetStgLogger(), s, properties),
+ passiveTime (stat.passiveTime, "passiveTime", false, true, GetStgLogger(), s, properties),
+ lastCashAddTime (stat.lastCashAddTime, "lastCashAddTime", false, true, GetStgLogger(), s, properties),
+ freeMb (stat.freeMb, "freeMb", false, true, GetStgLogger(), s, properties),
+ lastActivityTime(stat.lastActivityTime, "lastActivityTime", false, true, GetStgLogger(), s, properties),
+
+ password (conf.password, "password", true, false, GetStgLogger(), s, properties),
+ passive (conf.passive, "passive", false, false, GetStgLogger(), s, properties),
+ disabled (conf.disabled, "disabled", false, false, GetStgLogger(), s, properties),
+ disabledDetailStat(conf.disabledDetailStat, "DisabledDetailStat", false, false, GetStgLogger(), s, properties),
+ alwaysOnline(conf.alwaysOnline, "alwaysOnline", false, false, GetStgLogger(), s, properties),
+ tariffName (conf.tariffName, "tariffName", false, false, GetStgLogger(), s, properties),
+ nextTariff (conf.nextTariff, "nextTariff", false, false, GetStgLogger(), s, properties),
+ address (conf.address, "address", false, false, GetStgLogger(), s, properties),
+ note (conf.note, "note", false, false, GetStgLogger(), s, properties),
+ group (conf.group, "group", false, false, GetStgLogger(), s, properties),
+ email (conf.email, "email", false, false, GetStgLogger(), s, properties),
+ phone (conf.phone, "phone", false, false, GetStgLogger(), s, properties),
+ realName (conf.realName, "realName", false, false, GetStgLogger(), s, properties),
+ credit (conf.credit, "credit", false, false, GetStgLogger(), s, properties),
+ creditExpire(conf.creditExpire, "creditExpire", false, false, GetStgLogger(), s, properties),
+ ips (conf.ips, "ips", false, false, GetStgLogger(), s, properties),
+ userdata0 (conf.userdata[0], "userdata0", false, false, GetStgLogger(), s, properties),
+ userdata1 (conf.userdata[1], "userdata1", false, false, GetStgLogger(), s, properties),
+ userdata2 (conf.userdata[2], "userdata2", false, false, GetStgLogger(), s, properties),
+ userdata3 (conf.userdata[3], "userdata3", false, false, GetStgLogger(), s, properties),
+ userdata4 (conf.userdata[4], "userdata4", false, false, GetStgLogger(), s, properties),
+ userdata5 (conf.userdata[5], "userdata5", false, false, GetStgLogger(), s, properties),
+ userdata6 (conf.userdata[6], "userdata6", false, false, GetStgLogger(), s, properties),
+ userdata7 (conf.userdata[7], "userdata7", false, false, GetStgLogger(), s, properties),
+ userdata8 (conf.userdata[8], "userdata8", false, false, GetStgLogger(), s, properties),
+ userdata9 (conf.userdata[9], "userdata9", false, false, GetStgLogger(), s, properties)
+{}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.61 $
+ $Date: 2010/09/13 05:56:42 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <pthread.h>
+
+#include <csignal>
+#include <cassert>
+#include <algorithm>
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "stg/settings.h"
+#include "stg/common.h"
+#include "users_impl.h"
+#include "stg_timer.h"
+
+extern volatile time_t stgTime;
+
+//#define USERS_DEBUG 1
+
+//-----------------------------------------------------------------------------
+USERS_IMPL::USERS_IMPL(SETTINGS_IMPL * s, STORE * st,
+ TARIFFS * t, SERVICES & svcs,
+ const ADMIN * sa)
+ : settings(s),
+ tariffs(t),
+ m_services(svcs),
+ store(st),
+ sysAdmin(sa),
+ WriteServLog(GetStgLogger()),
+ nonstop(false),
+ isRunning(false),
+ handle(0)
+{
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USERS_IMPL::~USERS_IMPL()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByNameNonLock(const std::string & login, user_iter * user)
+{
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+if (iter == loginIndex.end())
+ return -1;
+if (user)
+ *user = iter->second;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByNameNonLock(const std::string & login, const_user_iter * user) const
+{
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+if (iter == loginIndex.end())
+ return -1;
+if (user)
+ *user = iter->second;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByName(const std::string & login, USER_PTR * user)
+{
+STG_LOCKER lock(&mutex);
+user_iter u;
+if (FindByNameNonLock(login, &u))
+ return -1;
+*user = &(*u);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByName(const std::string & login, CONST_USER_PTR * user) const
+{
+STG_LOCKER lock(&mutex);
+const_user_iter u;
+if (FindByNameNonLock(login, &u))
+ return -1;
+*user = &(*u);
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::Exists(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+return iter != loginIndex.end();
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::TariffInUse(const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+std::list<USER_IMPL>::const_iterator iter;
+iter = users.begin();
+while (iter != users.end())
+ {
+ if (iter->GetProperty().tariffName.Get() == tariffName)
+ return true;
+ ++iter;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::Add(const std::string & login, const ADMIN * admin)
+{
+STG_LOCKER lock(&mutex);
+const PRIV * priv = admin->GetPriv();
+
+if (!priv->userAddDel)
+ {
+ WriteServLog("%s tried to add user \'%s\'. Access denied.",
+ admin->GetLogStr().c_str(), login.c_str());
+ /*errorStr = "Admin \'" + admin->GetLogin() +
+ "\': tried to add user \'" + ud->login + "\'. Access denied.";*/
+ return -1;
+ }
+
+//////
+if (store->AddUser(login))
+ {
+ //TODO
+ //WriteServLog("Admin \'%s\': tried to add user \'%s\'. Access denied.",
+ // admin->GetLogin().c_str(), ud->login.c_str());
+ return -1;
+ }
+//////
+
+USER_IMPL u(settings, store, tariffs, sysAdmin, this, m_services);
+
+/*struct tm * tms;
+time_t t = stgTime;
+
+tms = localtime(&t);
+
+tms->tm_hour = 0;
+tms->tm_min = 0;
+tms->tm_sec = 0;
+
+if (settings->GetDayResetTraff() > tms->tm_mday)
+ tms->tm_mon -= 1;
+
+tms->tm_mday = settings->GetDayResetTraff();*/
+
+u.SetLogin(login);
+
+u.SetPassiveTimeAsNewUser();
+
+u.WriteConf();
+u.WriteStat();
+
+WriteServLog("%s User \'%s\' added.",
+ admin->GetLogStr().c_str(), login.c_str());
+
+u.OnAdd();
+
+users.push_front(u);
+
+AddUserIntoIndexes(users.begin());
+
+ {
+ // Fire all "on add" notifiers
+ std::set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onAddNotifiers.begin();
+ while (ni != onAddNotifiers.end())
+ {
+ (*ni)->Notify(&users.front());
+ ++ni;
+ }
+ }
+
+ {
+ // Fire all "on add" implementation notifiers
+ std::set<NOTIFIER_BASE<USER_IMPL_PTR> *>::iterator ni = onAddNotifiersImpl.begin();
+ while (ni != onAddNotifiersImpl.end())
+ {
+ (*ni)->Notify(&users.front());
+ ++ni;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::Del(const std::string & login, const ADMIN * admin)
+{
+const PRIV * priv = admin->GetPriv();
+user_iter u;
+
+if (!priv->userAddDel)
+ {
+ WriteServLog("%s tried to remove user \'%s\'. Access denied.",
+ admin->GetLogStr().c_str(), login.c_str());
+ return;
+ }
+
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ if (FindByNameNonLock(login, &u))
+ {
+ WriteServLog("%s tried to delete user \'%s\': not found.",
+ admin->GetLogStr().c_str(),
+ login.c_str());
+ return;
+ }
+
+ u->SetDeleted();
+ }
+
+ {
+ std::set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onDelNotifiers.begin();
+ while (ni != onDelNotifiers.end())
+ {
+ (*ni)->Notify(&(*u));
+ ++ni;
+ }
+ }
+
+ {
+ std::set<NOTIFIER_BASE<USER_IMPL_PTR> *>::iterator ni = onDelNotifiersImpl.begin();
+ while (ni != onDelNotifiersImpl.end())
+ {
+ (*ni)->Notify(&(*u));
+ ++ni;
+ }
+ }
+
+ {
+ STG_LOCKER lock(&mutex);
+
+ u->OnDelete();
+
+ USER_TO_DEL utd;
+ utd.iter = u;
+ utd.delTime = stgTime;
+ usersToDelete.push_back(utd);
+
+ DelUserFromIndexes(u);
+
+ WriteServLog("%s User \'%s\' deleted.",
+ admin->GetLogStr().c_str(), login.c_str());
+
+ }
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::Authorize(const std::string & login, uint32_t ip,
+ uint32_t enabledDirs, const AUTH * auth)
+{
+user_iter iter;
+STG_LOCKER lock(&mutex);
+if (FindByNameNonLock(login, &iter))
+ {
+ WriteServLog("Attempt to authorize non-existant user '%s'", login.c_str());
+ return false;
+ }
+
+if (FindByIPIdx(ip, iter))
+ {
+ if (iter->GetLogin() != login)
+ {
+ WriteServLog("Attempt to authorize user '%s' from ip %s which already occupied by '%s'",
+ login.c_str(), inet_ntostring(ip).c_str(),
+ iter->GetLogin().c_str());
+ return false;
+ }
+ if (iter->Authorize(ip, enabledDirs, auth))
+ return false;
+ return true;
+ }
+
+if (iter->Authorize(ip, enabledDirs, auth))
+ return false;
+
+AddToIPIdx(iter);
+return true;
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::Unauthorize(const std::string & login,
+ const AUTH * auth,
+ const std::string & reason)
+{
+user_iter iter;
+STG_LOCKER lock(&mutex);
+if (FindByNameNonLock(login, &iter))
+ {
+ WriteServLog("Attempt to unauthorize non-existant user '%s'", login.c_str());
+ printfd(__FILE__, "Attempt to unauthorize non-existant user '%s'", login.c_str());
+ return false;
+ }
+
+uint32_t ip = iter->GetCurrIP();
+
+iter->Unauthorize(auth, reason);
+
+if (!iter->GetAuthorized())
+ DelFromIPIdx(ip);
+
+return true;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::ReadUsers()
+{
+std::vector<std::string> usersList;
+usersList.clear();
+if (store->GetUsersList(&usersList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return -1;
+ }
+
+user_iter ui;
+
+unsigned errors = 0;
+for (unsigned int i = 0; i < usersList.size(); i++)
+ {
+ USER_IMPL u(settings, store, tariffs, sysAdmin, this, m_services);
+
+ u.SetLogin(usersList[i]);
+ users.push_front(u);
+ ui = users.begin();
+
+ AddUserIntoIndexes(ui);
+
+ if (settings->GetStopOnError())
+ {
+ if (ui->ReadConf() < 0)
+ return -1;
+
+ if (ui->ReadStat() < 0)
+ return -1;
+ }
+ else
+ {
+ if (ui->ReadConf() < 0)
+ errors++;
+
+ if (ui->ReadStat() < 0)
+ errors++;
+ }
+ }
+
+if (errors > 0)
+ return -1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * USERS_IMPL::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+USERS_IMPL * us = static_cast<USERS_IMPL *>(d);
+
+struct tm t;
+time_t tt = stgTime;
+localtime_r(&tt, &t);
+
+int min = t.tm_min;
+int day = t.tm_mday;
+
+printfd(__FILE__,"Day = %d Min = %d\n", day, min);
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+std::string monFile = us->settings->GetMonitorDir() + "/users_r";
+printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
+
+us->isRunning = true;
+while (us->nonstop)
+ {
+ //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
+ //printfd(__FILE__,"New Day. old = %2d current = %2d\n", day, t->tm_mday);
+
+ for_each(us->users.begin(), us->users.end(), std::mem_fun_ref(&USER_IMPL::Run));
+
+ tt = stgTime;
+ localtime_r(&tt, &t);
+
+ if (min != t.tm_min)
+ {
+ printfd(__FILE__,"Sec = %d\n", stgTime);
+ printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
+ min = t.tm_min;
+
+ us->NewMinute(t);
+ }
+
+ if (day != t.tm_mday)
+ {
+ printfd(__FILE__,"Sec = %d\n", stgTime);
+ printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
+ day = t.tm_mday;
+ us->NewDay(t);
+ }
+
+ if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
+ touchTime = stgTime;
+ TouchFile(monFile);
+ }
+
+ stgUsleep(100000);
+ } //while (us->nonstop)
+
+std::list<USER_TO_DEL>::iterator iter(us->usersToDelete.begin());
+while (iter != us->usersToDelete.end())
+ {
+ iter->delTime -= 2 * userDeleteDelayTime;
+ ++iter;
+ }
+us->RealDelUser();
+
+us->isRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::NewMinute(const struct tm & t)
+{
+//Write traff, reset session traff. Fake disconnect-connect
+if (t.tm_hour == 23 && t.tm_min == 59)
+ {
+ printfd(__FILE__,"MidnightResetSessionStat\n");
+ for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::MidnightResetSessionStat));
+ }
+
+if (TimeToWriteDetailStat(t))
+ {
+ //printfd(__FILE__, "USER::WriteInetStat\n");
+ int usersCnt = 0;
+
+ // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
+ std::list<USER_IMPL>::iterator usr = users.begin();
+ while (usr != users.end())
+ {
+ usersCnt++;
+ usr->WriteDetailStat();
+ ++usr;
+ if (usersCnt % 10 == 0)
+ for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::Run));
+ }
+ }
+
+RealDelUser();
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::NewDay(const struct tm & t)
+{
+struct tm t1;
+time_t tt = stgTime;
+localtime_r(&tt, &t1);
+int dayFee = settings->GetDayFee();
+
+if (dayFee == 0)
+ dayFee = DaysInCurrentMonth();
+
+printfd(__FILE__, "DayFee = %d\n", dayFee);
+printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1.tm_mday, settings->GetDayResetTraff());
+printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
+
+if (!settings->GetDayFeeIsLastDay())
+ {
+ printfd(__FILE__, "DayResetTraff - 1 -\n");
+ DayResetTraff(t1);
+ //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
+ }
+
+if (settings->GetSpreadFee())
+ {
+ printfd(__FILE__, "Spread DayFee\n");
+ for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDayFeeSpread));
+ }
+else
+ {
+ if (t.tm_mday == dayFee)
+ {
+ printfd(__FILE__, "DayFee\n");
+ for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDayFee));
+ }
+ }
+
+std::for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessDailyFee));
+std::for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessServices));
+
+if (settings->GetDayFeeIsLastDay())
+ {
+ printfd(__FILE__, "DayResetTraff - 2 -\n");
+ DayResetTraff(t1);
+ }
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DayResetTraff(const struct tm & t1)
+{
+int dayResetTraff = settings->GetDayResetTraff();
+if (dayResetTraff == 0)
+ dayResetTraff = DaysInCurrentMonth();
+if (t1.tm_mday == dayResetTraff)
+ {
+ printfd(__FILE__, "ResetTraff\n");
+ for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::ProcessNewMonth));
+ //for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::SetPrepaidTraff));
+ }
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::Start()
+{
+if (ReadUsers())
+ {
+ WriteServLog("USERS: Error: Cannot read users!");
+ return -1;
+ }
+
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ WriteServLog("USERS: Error: Cannot start thread!");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::Stop()
+{
+printfd(__FILE__, "USERS::Stop()\n");
+
+if (!isRunning)
+ {
+ //printfd(__FILE__, "Alredy stopped\n");
+ return 0;
+ }
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (size_t i = 0; i < 25 * (users.size() / 50 + 1); i++)
+ {
+ if (!isRunning)
+ break;
+
+ nanosleep(&ts, NULL);
+ }
+
+//after 5 seconds waiting thread still running. now kill it
+if (isRunning)
+ {
+ printfd(__FILE__, "kill USERS thread.\n");
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ //errorStr = "Cannot kill USERS thread.";
+ //printfd(__FILE__, "Cannot kill USERS thread.\n");
+ //return 0;
+ }
+ printfd(__FILE__, "USERS killed\n");
+ }
+
+printfd(__FILE__, "Before USERS::Run()\n");
+for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::Run));
+
+// 'cause bind2st accepts only constant first param
+for (std::list<USER_IMPL>::iterator it = users.begin();
+ it != users.end();
+ ++it)
+ it->WriteDetailStat(true);
+
+for_each(users.begin(), users.end(), std::mem_fun_ref(&USER_IMPL::WriteStat));
+//for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::WriteConf));
+
+printfd(__FILE__, "USERS::Stop()\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::RealDelUser()
+{
+STG_LOCKER lock(&mutex);
+
+printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
+
+std::list<USER_TO_DEL>::iterator iter;
+iter = usersToDelete.begin();
+while (iter != usersToDelete.end())
+ {
+ printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
+ if (iter->delTime + userDeleteDelayTime < stgTime)
+ {
+ printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
+ if (store->DelUser(iter->iter->GetLogin()))
+ {
+ WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
+ }
+ users.erase(iter->iter);
+ usersToDelete.erase(iter++);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+return;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddToIPIdx(user_iter user)
+{
+printfd(__FILE__, "USERS: Add IP Idx\n");
+uint32_t ip = user->GetCurrIP();
+//assert(ip && "User has non-null ip");
+if (!ip)
+ return; // User has disconnected
+
+STG_LOCKER lock(&mutex);
+
+const std::map<uint32_t, user_iter>::iterator it(
+ ipIndex.lower_bound(ip)
+);
+
+assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
+
+ipIndex.insert(it, std::make_pair(ip, user));
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelFromIPIdx(uint32_t ip)
+{
+printfd(__FILE__, "USERS: Del IP Idx\n");
+assert(ip && "User has non-null ip");
+
+STG_LOCKER lock(&mutex);
+
+const std::map<uint32_t, user_iter>::iterator it(
+ ipIndex.find(ip)
+);
+
+if (it == ipIndex.end())
+ return;
+
+ipIndex.erase(it);
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::FindByIPIdx(uint32_t ip, user_iter & iter) const
+{
+std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
+if (it == ipIndex.end())
+ return false;
+iter = it->second;
+return true;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByIPIdx(uint32_t ip, USER_PTR * usr) const
+{
+STG_LOCKER lock(&mutex);
+
+user_iter iter;
+if (FindByIPIdx(ip, iter))
+ {
+ *usr = &(*iter);
+ return 0;
+ }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::FindByIPIdx(uint32_t ip, USER_IMPL ** usr) const
+{
+STG_LOCKER lock(&mutex);
+
+user_iter iter;
+if (FindByIPIdx(ip, iter))
+ {
+ *usr = &(*iter);
+ return 0;
+ }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::IsIPInIndex(uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
+
+return it != ipIndex.end();
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::IsIPInUse(uint32_t ip, const std::string & login, CONST_USER_PTR * user) const
+{
+STG_LOCKER lock(&mutex);
+std::list<USER_IMPL>::const_iterator iter;
+iter = users.begin();
+while (iter != users.end())
+ {
+ if (iter->GetLogin() != login &&
+ !iter->GetProperty().ips.Get().IsAnyIP() &&
+ iter->GetProperty().ips.Get().IsIPInIPS(ip))
+ {
+ if (user != NULL)
+ *user = &(*iter);
+ return true;
+ }
+ ++iter;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiersImpl.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiersImpl.erase(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiersImpl.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiersImpl.erase(n);
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::OpenSearch()
+{
+STG_LOCKER lock(&mutex);
+handle++;
+searchDescriptors[handle] = users.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::SearchNext(int h, USER_PTR * user)
+{
+ USER_IMPL * ptr = NULL;
+ if (SearchNext(h, &ptr))
+ return -1;
+ *user = ptr;
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::SearchNext(int h, USER_IMPL ** user)
+{
+STG_LOCKER lock(&mutex);
+
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("USERS. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == users.end())
+ return -1;
+
+while (searchDescriptors[h]->GetDeleted())
+ {
+ ++searchDescriptors[h];
+ if (searchDescriptors[h] == users.end())
+ {
+ return -1;
+ }
+ }
+
+*user = &(*searchDescriptors[h]);
+
+++searchDescriptors[h];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS_IMPL::CloseSearch(int h)
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("USERS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::AddUserIntoIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex);
+loginIndex.insert(make_pair(user->GetLogin(), user));
+}
+//-----------------------------------------------------------------------------
+void USERS_IMPL::DelUserFromIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex);
+loginIndex.erase(user->GetLogin());
+}
+//-----------------------------------------------------------------------------
+bool USERS_IMPL::TimeToWriteDetailStat(const struct tm & t)
+{
+int statTime = settings->GetDetailStatWritePeriod();
+
+switch (statTime)
+ {
+ case dsPeriod_1:
+ if (t.tm_min == 0)
+ return true;
+ break;
+ case dsPeriod_1_2:
+ if (t.tm_min % 30 == 0)
+ return true;
+ break;
+ case dsPeriod_1_4:
+ if (t.tm_min % 15 == 0)
+ return true;
+ break;
+ case dsPeriod_1_6:
+ if (t.tm_min % 10 == 0)
+ return true;
+ break;
+ }
+return false;
+}
--- /dev/null
+/*
+ * 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 <stg34@stargazer.dp.ua>
+ */
+
+/*
+$Revision: 1.31 $
+$Date: 2010/10/07 20:04:48 $
+$Author: faust $
+*/
+
+
+#ifndef USERS_IMPL_H
+#define USERS_IMPL_H
+
+#include <pthread.h>
+
+#include <string>
+#include <map>
+#include <list>
+#include <set>
+#include <ctime>
+#include <cstdint>
+
+#include "stg/store.h"
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/tariffs.h"
+#include "stg/logger.h"
+#include "stg/notifer.h"
+#include "stg/noncopyable.h"
+#include "actions.h"
+#include "eventloop.h"
+#include "settings_impl.h"
+#include "user_impl.h"
+
+const int userDeleteDelayTime = 120;
+
+typedef std::list<USER_IMPL>::iterator user_iter;
+typedef std::list<USER_IMPL>::const_iterator const_user_iter;
+
+class USERS_IMPL;
+//-----------------------------------------------------------------------------
+struct USER_TO_DEL {
+USER_TO_DEL()
+ : iter(),
+ delTime(0)
+{}
+
+std::list<USER_IMPL>::iterator iter;
+time_t delTime;
+};
+//-----------------------------------------------------------------------------
+class USERS_IMPL : private NONCOPYABLE, public USERS {
+ friend class PROPERTY_NOTIFER_IP_BEFORE;
+ friend class PROPERTY_NOTIFER_IP_AFTER;
+
+public:
+ USERS_IMPL(SETTINGS_IMPL * s, STORE * store,
+ TARIFFS * tariffs, SERVICES & svcs,
+ const ADMIN * sysAdmin);
+ virtual ~USERS_IMPL();
+
+ int FindByName(const std::string & login, USER_PTR * user);
+ int FindByName(const std::string & login, CONST_USER_PTR * user) const;
+
+ bool Exists(const std::string & login) const;
+
+ bool TariffInUse(const std::string & tariffName) const;
+
+ void AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> *);
+ void DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> *);
+
+ void AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> *);
+ void DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> *);
+
+ void AddNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> *);
+ void DelNotifierUserAdd(NOTIFIER_BASE<USER_IMPL_PTR> *);
+
+ void AddNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> *);
+ void DelNotifierUserDel(NOTIFIER_BASE<USER_IMPL_PTR> *);
+
+ int Add(const std::string & login, const ADMIN * admin);
+ void Del(const std::string & login, const ADMIN * admin);
+
+ bool Authorize(const std::string & login, uint32_t ip,
+ uint32_t enabledDirs, const AUTH * auth);
+ bool Unauthorize(const std::string & login,
+ const AUTH * auth,
+ const std::string & reason = std::string());
+
+ int ReadUsers();
+ size_t Count() const { return users.size(); }
+
+ int FindByIPIdx(uint32_t ip, USER_PTR * user) const;
+ int FindByIPIdx(uint32_t ip, USER_IMPL ** user) const;
+ bool IsIPInIndex(uint32_t ip) const;
+ bool IsIPInUse(uint32_t ip, const std::string & login, CONST_USER_PTR * user) const;
+
+ int OpenSearch();
+ int SearchNext(int handler, USER_PTR * user);
+ int SearchNext(int handler, USER_IMPL ** user);
+ int CloseSearch(int handler);
+
+ int Start();
+ int Stop();
+
+private:
+ USERS_IMPL(const USERS_IMPL & rvalue);
+ USERS_IMPL & operator=(const USERS_IMPL & rvalue);
+
+ void AddToIPIdx(user_iter user);
+ void DelFromIPIdx(uint32_t ip);
+ bool FindByIPIdx(uint32_t ip, user_iter & iter) const;
+
+ int FindByNameNonLock(const std::string & login, user_iter * user);
+ int FindByNameNonLock(const std::string & login, const_user_iter * user) const;
+
+ void RealDelUser();
+ void ProcessActions();
+
+ void AddUserIntoIndexes(user_iter user);
+ void DelUserFromIndexes(user_iter user);
+
+ static void * Run(void *);
+ void NewMinute(const struct tm & t);
+ void NewDay(const struct tm & t);
+ void DayResetTraff(const struct tm & t);
+
+ bool TimeToWriteDetailStat(const struct tm & t);
+
+ std::list<USER_IMPL> users;
+ std::list<USER_TO_DEL> usersToDelete;
+
+ std::map<uint32_t, user_iter> ipIndex;
+ std::map<std::string, user_iter> loginIndex;
+
+ SETTINGS_IMPL * settings;
+ TARIFFS * tariffs;
+ SERVICES & m_services;
+ STORE * store;
+ const ADMIN * sysAdmin;
+ STG_LOGGER & WriteServLog;
+
+ bool nonstop;
+ bool isRunning;
+
+ mutable pthread_mutex_t mutex;
+ pthread_t thread;
+ mutable unsigned int handle;
+
+ mutable std::map<int, user_iter> searchDescriptors;
+
+ std::set<NOTIFIER_BASE<USER_PTR>*> onAddNotifiers;
+ std::set<NOTIFIER_BASE<USER_PTR>*> onDelNotifiers;
+ std::set<NOTIFIER_BASE<USER_IMPL_PTR>*> onAddNotifiersImpl;
+ std::set<NOTIFIER_BASE<USER_IMPL_PTR>*> onDelNotifiersImpl;
+};
+//-----------------------------------------------------------------------------
+/*inline
+void PROPERTY_NOTIFER_IP_BEFORE::Notify(const uint32_t & oldValue,
+ const uint32_t &)
+{
+if (!oldValue)
+ return;
+
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::DelFromIPIdx, oldValue);
+// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
+users.DelFromIPIdx(oldValue);
+}
+//-----------------------------------------------------------------------------
+inline
+void PROPERTY_NOTIFER_IP_AFTER::Notify(const uint32_t &,
+ const uint32_t & newValue)
+{
+if (!newValue)
+ return;
+
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::AddToIPIdx, user);
+// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
+users.AddToIPIdx(user);
+}*/
+//-----------------------------------------------------------------------------
+#endif
+++ /dev/null
-###############################################################################
-# $Id: Makefile,v 1.7 2008/03/10 14:00:00 faust Exp $
-###############################################################################
-
-include ../Makefile.conf
-
-.PHONY: all $(STG_LIBS)
-.PHONY: clean install uninstall includes
-all: $(STG_LIBS)
- for LIB in $(STG_LIBS); do\
- $(MAKE) $(MAKECMDGOALS) -C $$LIB;\
- done
-
-includes: all
-
-clean: all
-
-install: all
-
-uninstall: all
+++ /dev/null
-###############################################################################
-# $Id: Makefile.in,v 1.28 2009/03/03 15:50:14 faust Exp $
-###############################################################################
-
-include ../../Makefile.conf
-
-PROG = lib$(LIB_NAME).a
-
-SEARCH_DIRS = -I ../../include -I . -I ./include
-
-ifeq ($(STG_TIME), yes)
-DEFS += -DSTG_TIME
-endif
-
-ifneq ($(LIB_DEFS),)
-DEFS += $(LIB_DEFS)
-endif
-
-ifneq ($(LIB_INCS),)
-SEARCH_DIRS += $(LIB_INCS)
-endif
-
-OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
-
-CXXFLAGS += -fPIC $(SEARCH_DIRS) $(DEFS)
-CFLAGS += -fPIC $(SEARCH_DIRS) $(DEFS)
-
-all: $(PROG)
-
-$(PROG): $(OBJS)
- ar rc lib$(LIB_NAME).a $(OBJS)
- ranlib lib$(LIB_NAME).a
-
-clean:
- rm -f deps $(PROG) *.o *.a *.so tags *.*~
-
-install: $(PROG)
-ifeq ($(DEBUG), yes)
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/stg
- install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
-else
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/stg
- install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
-endif
- mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/include/stg
- install -m $(DATA_MODE) -o $(OWNER) $(addprefix include/stg/,$(INCS)) $(PREFIX)/usr/include/stg/
-
-uninstall:
- rm -f $(PREFIX)/usr/lib/stg/$(PROG)
- for file in $(INCS); do \
- rm -f $(PREFIX)/usr/include/stg/$$file; \
- done
-
-ifneq ($(MAKECMDGOALS),includes)
-ifneq ($(MAKECMDGOALS),clean)
-ifneq ($(MAKECMDGOALS),uninstall)
--include deps
-endif
-endif
-endif
-
-deps: $(SRCS) ../../Makefile.conf
- @>deps ;\
- for file in $(SRCS); do\
- echo "$$file" | grep ".c$$" > /dev/null;\
- if [ $$? -eq 0 ];\
- then\
- echo "`$(CC) $(CFLAGS) -MM $$file` Makefile ../../Makefile.conf" >> deps ;\
- printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\
- else\
- echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile ../../Makefile.conf" >> deps ;\
- printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\
- fi;\
- done
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#include "stg/blockio.h"
-
-namespace
-{
-
-void* adjust(void* base, size_t shift)
-{
- char* ptr = static_cast<char*>(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<ssize_t>(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<ssize_t>(m_remainder))
- m_remainder -= res;
- else
- m_remainder = 0;
- return true;
-}
+++ /dev/null
-//---------------------------------------------------------------------------
-
-#include <vcl.h>
-#pragma hdrstop
-#define Library
-
-// To add a file to the library use the Project menu 'Add to Project'.
-
-
\ No newline at end of file
+++ /dev/null
-<?xml version='1.0' encoding='utf-8' ?>
-<!-- C++Builder XML Project -->
-<PROJECT>
- <MACROS>
- <VERSION value="BCB.06.00"/>
- <PROJECT value="..\..\lib\common.lib"/>
- <OBJFILES value="common.obj"/>
- <RESFILES value=""/>
- <IDLFILES value=""/>
- <IDLGENFILES value=""/>
- <DEFFILE value=""/>
- <RESDEPEN value="$(RESFILES)"/>
- <LIBFILES value=""/>
- <LIBRARIES value=""/>
- <PACKAGES value=""/>
- <PATHCPP value=".;"/>
- <PATHPAS value=".;"/>
- <PATHRC value=".;"/>
- <PATHASM value=".;"/>
- <LINKER value="TLib"/>
- <USERDEFINES value="_DEBUG;WIN32"/>
- <SYSDEFINES value="_RTLDLL;NO_STRICT"/>
- <MAINSOURCE value="common.bpf"/>
- <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>
- <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib;..\..\lib"/>
- <WARNINGS value="-w-par"/>
- <LISTFILE value=""/>
- <OTHERFILES value=""/>
- </MACROS>
- <OPTIONS>
- <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp
- -D_DEBUG -DWIN32 -boa"/>
- <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c
- -tW -tWM"/>
- <PFLAGS value="-$YD -$W -$O- -$A8 -v -JPHNE -M"/>
- <AFLAGS value="/mx /w2 /zd"/>
- <LFLAGS value=""/>
- <OTHERFILES value=""/>
- </OPTIONS>
- <LINKER>
- <ALLOBJ value="$(OBJFILES)"/>
- <ALLLIB value=""/>
- <OTHERFILES value=""/>
- </LINKER>
- <FILELIST>
- <FILE FILENAME="common.bpf" FORMNAME="" UNITNAME="common" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>
- <FILE FILENAME="common.cpp" FORMNAME="" UNITNAME="common.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
- <FILE FILENAME="common.h" FORMNAME="" UNITNAME="common.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
- </FILELIST>
- <BUILDTOOLS>
- </BUILDTOOLS>
-
- <IDEOPTIONS>
-[Version Info]
-IncludeVerInfo=0
-AutoIncBuild=0
-MajorVer=1
-MinorVer=0
-Release=0
-Build=0
-Debug=0
-PreRelease=0
-Special=0
-Private=0
-DLL=0
-Locale=1049
-CodePage=1251
-
-[Version Info Keys]
-CompanyName=
-FileDescription=
-FileVersion=1.0.0.0
-InternalName=
-LegalCopyright=
-LegalTrademarks=
-OriginalFilename=
-ProductName=
-ProductVersion=1.0.0.0
-Comments=
-
-[HistoryLists\hlIncludePath]
-Count=2
-Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include
-Item1=$(BCB)\include;$(BCB)\include\vcl
-
-[HistoryLists\hlLibraryPath]
-Count=2
-Item0=$(BCB)\lib\obj;$(BCB)\lib;..\..\lib
-Item1=$(BCB)\lib\obj;$(BCB)\lib
-
-[HistoryLists\hlDebugSourcePath]
-Count=1
-Item0=$(BCB)\source\vcl
-
-[HistoryLists\hlConditionals]
-Count=2
-Item0=_DEBUG;WIN32
-Item1=_DEBUG
-
-[HistoryLists\hlFinalOutputDir]
-Count=2
-Item0=..\..\lib\
-Item1=..\..\lib
-
-[Debugging]
-DebugSourceDirs=$(BCB)\source\vcl
-
-[Parameters]
-RunParams=
-Launcher=
-UseLauncher=0
-DebugCWD=
-HostApplication=
-RemoteHost=
-RemotePath=
-RemoteLauncher=
-RemoteCWD=
-RemoteDebug=0
-
-[Compiler]
-ShowInfoMsgs=0
-LinkDebugVcl=0
-LinkCGLIB=0
-
-[CORBA]
-AddServerUnit=1
-AddClientUnit=1
-PrecompiledHeaders=1
- </IDEOPTIONS>
-</PROJECT>
\ No newline at end of file
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.42 $
- $Date: 2010/11/08 10:11:19 $
- $Author: faust $
- */
-
-// For old and dub systems
-// Like FreeBSD4
-#include <sys/types.h>
-#include <sys/time.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <sys/select.h>
-
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/select.h>
-#endif
-
-#include <iconv.h>
-
-#include <algorithm>
-
-#include <cstdlib>
-#include <cstdarg>
-#include <cstdio>
-#include <cstring>
-#include <cerrno>
-#include <cassert>
-
-#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<struct sockaddr *>(&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<struct sockaddr *>(&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 (int j = 0; j < (int)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 (int j = 0; j < (int)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<char>(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<char>(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<uint16_t>((value >> 8) |
- (value << 8));
-}
-//---------------------------------------------------------------------------
-void SwapBytes(uint32_t & value)
-{
- value = static_cast<uint32_t>((value >> 24) |
- ((value << 8) & 0x00FF0000L) |
- ((value >> 8) & 0x0000FF00L) |
- (value << 24));
-}
-//---------------------------------------------------------------------------
-void SwapBytes(uint64_t & value)
-{
- value = static_cast<uint64_t>((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<int32_t>(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<uint32_t>(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<int>(str, *val))
- return -1;
-return 0;
-}
-
-int ParseUnsigned(const std::string & str, unsigned * val)
-{
-if (str2x<unsigned>(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<char *>(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<const char *>(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;
-}
+++ /dev/null
-#ifndef __STG_STGLIBS_BLOCK_IO_H__
-#define __STG_STGLIBS_BLOCK_IO_H__
-
-#include <vector>
-
-#include <sys/uio.h>
-
-namespace STG
-{
-
-typedef std::vector<iovec> 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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.32 $
- $Date: 2010/11/08 10:11:19 $
- $Author: faust $
- */
-
-#ifndef common_h
-#define common_h
-
-#include "stg/os_int.h"
-#include "stg/const.h"
-
-#include <string>
-#include <sstream>
-#include <ctime>
-#include <climits> // NAME_MAX
-
-#include <unistd.h> // uid_t, gid_t
-#include <sys/stat.h> // 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 <typename C, typename F>
-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 <typename T>
-inline
-T FromString(const std::string & value)
-{
-T res;
-std::istringstream stream(value);
-stream >> res;
-return res;
-}
-
-template <>
-inline
-std::string FromString<std::string>(const std::string & value)
-{
-return value;
-}
-
-template <typename C>
-inline
-C Split(const std::string & value, char delim)
-{
- return Split<C>(value, delim, FromString<typename C::value_type>);
-}
-
-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 <typename varT>
-int str2x(const std::string & str, varT & x);
-template <typename varT>
-const std::string & x2str(varT x, std::string & s);
-template <typename varT>
-std::string x2str(varT x) { std::string s; return x2str(x, s); }
-template <typename varT>
-const std::string & unsigned2str(varT x, std::string & s);
-template <typename varT>
-std::string unsigned2str(varT x) { std::string s; return unsigned2str(x, s); }
-
-//-----------------------------------------------------------------------------
-template <typename varT>
-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 <typename varT>
-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 <typename varT>
-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
+++ /dev/null
-/*
- * $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 <time.h>
-
-#include "stg/common.h"
-
-char * stg_strptime(const char * a, const char * b, struct tm * tm)
-{
-return strptime(a, b, tm);
-}
-
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-/*
- * 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 <stg34@ua.fm>
- */
-
- /*
- $Revision: 1.5 $
- $Date: 2009/10/22 11:40:22 $
- */
-
-//---------------------------------------------------------------------------
-
-// getpid
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cerrno> // E*
-#include <cstring>
-#include <sstream>
-#include <cstdlib>
-#include <cstdio>
-
-#include <fstream>
-
-#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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
-
-if (it != param_val.end())
- {
- char *res;
- *val = static_cast<int>(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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
-
-if (it != param_val.end())
- {
- char *res;
- *val = static_cast<unsigned int>(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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
-
-if (it != param_val.end())
- {
- char *res;
- *val = (short)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<std::string, std::string, StringCaseCmp_t>::const_iterator it(param_val.find(param));
-
-if (it != param_val.end())
- {
- char *res;
- *val = (short)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<long long int>(val));
-param_val[param] = buf;
-changed = true;
-}
-//---------------------------------------------------------------------------
-void CONFIGFILE::WriteTime(const std::string & param, time_t val)
-{
-std::stringstream ss;
-ss<<val;
-param_val[param] = ss.str();
-changed = true;
-}
-//---------------------------------------------------------------------------
-int CONFIGFILE::ReadDouble(const std::string & param, double * val, double defaultVal) const
-{
-const std::map<std::string, std::string, StringCaseCmp_t>::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<std::string, std::string, StringCaseCmp_t>::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;
-}
-//---------------------------------------------------------------------------
+++ /dev/null
-/*
- * 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 <stg34@ua.fm>
- */
-
-/*
- $Revision: 1.5 $
- $Date: 2009/06/22 16:00:38 $
- */
-
-//---------------------------------------------------------------------------
-
-#ifndef ConfFilesH
-#define ConfFilesH
-
-#include <map>
-#include <string>
-
-#include "stg/os_int.h"
-
-//---------------------------------------------------------------------------
-
-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<std::string, std::string, StringCaseCmp_t> param_val;
- std::string fileName;
- mutable int error;
- mutable bool changed;
-
- int Flush(const std::string & path) const;
-};
-//---------------------------------------------------------------------------
-#endif
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#ifdef WIN32
-#include <process.h>
-#include <windows.h>
-#else
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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<<s | 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)));
-}
-
+++ /dev/null
-#include "stg/bfstream.h"
-
-#include "stg/blowfish.h"
-
-#include <cstring>
-
-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<const char *>(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();
-}
+++ /dev/null
-/*
- * Author : Paul Kocher
- * E-mail : pck@netcom.com
- * Date : 1997
- * Description: C implementation of the Blowfish algorithm.
- */
-
-#include <string.h>
-
-#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;
- }
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-//---------------------------------------------------------------------------\r
-\r
-#include <vcl.h>\r
-#pragma hdrstop\r
-#define Library\r
-\r
-// To add a file to the library use the Project menu 'Add to Project'.\r
-\r
-
\ No newline at end of file
+++ /dev/null
-<?xml version='1.0' encoding='utf-8' ?>\r
-<!-- C++Builder XML Project -->\r
-<PROJECT>\r
- <MACROS>\r
- <VERSION value="BCB.06.00"/>\r
- <PROJECT value="..\..\lib\crypto.lib"/>\r
- <OBJFILES value="obj\ag_md5.obj obj\blowfish.obj"/>\r
- <RESFILES value=""/>\r
- <IDLFILES value=""/>\r
- <IDLGENFILES value=""/>\r
- <DEFFILE value=""/>\r
- <RESDEPEN value="$(RESFILES)"/>\r
- <LIBFILES value=""/>\r
- <LIBRARIES value=""/>\r
- <PACKAGES value=""/>\r
- <PATHCPP value=".;"/>\r
- <PATHPAS value=".;"/>\r
- <PATHRC value=".;"/>\r
- <PATHASM value=".;"/>\r
- <LINKER value="TLib"/>\r
- <USERDEFINES value="_DEBUG;WIN32"/>\r
- <SYSDEFINES value="_RTLDLL;NO_STRICT"/>\r
- <MAINSOURCE value="crypto.bpf"/>\r
- <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>\r
- <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib"/>\r
- <WARNINGS value="-w-par"/>\r
- <LISTFILE value=""/>\r
- <OTHERFILES value=""/>\r
- </MACROS>\r
- <OPTIONS>\r
- <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp \r
- -D_DEBUG -DWIN32 -boa"/>\r
- <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c \r
- -tW -tWM"/>\r
- <PFLAGS value="-N2obj -N0obj -$YD -$W -$O- -$A8 -v -JPHNE -M"/>\r
- <AFLAGS value="/mx /w2 /zd"/>\r
- <LFLAGS value=""/>\r
- <OTHERFILES value=""/>\r
- </OPTIONS>\r
- <LINKER>\r
- <ALLOBJ value="$(OBJFILES)"/>\r
- <ALLLIB value=""/>\r
- <OTHERFILES value=""/>\r
- </LINKER>\r
- <FILELIST>\r
- <FILE FILENAME="crypto.bpf" FORMNAME="" UNITNAME="crypto" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>\r
- <FILE FILENAME="blowfish.h" FORMNAME="" UNITNAME="blowfish.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>\r
- <FILE FILENAME="ag_md5.c" FORMNAME="" UNITNAME="ag_md5.c" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>\r
- <FILE FILENAME="ag_md5.h" FORMNAME="" UNITNAME="ag_md5.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>\r
- <FILE FILENAME="blowfish.cpp" FORMNAME="" UNITNAME="blowfish.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>\r
- </FILELIST>\r
- <BUILDTOOLS>\r
- </BUILDTOOLS>\r
-\r
- <IDEOPTIONS>\r
-[Version Info]\r
-IncludeVerInfo=0\r
-AutoIncBuild=0\r
-MajorVer=1\r
-MinorVer=0\r
-Release=0\r
-Build=0\r
-Debug=0\r
-PreRelease=0\r
-Special=0\r
-Private=0\r
-DLL=0\r
-Locale=1058\r
-CodePage=1251\r
-\r
-[Version Info Keys]\r
-CompanyName=\r
-FileDescription=\r
-FileVersion=1.0.0.0\r
-InternalName=\r
-LegalCopyright=\r
-LegalTrademarks=\r
-OriginalFilename=\r
-ProductName=\r
-ProductVersion=1.0.0.0\r
-Comments=\r
-\r
-[HistoryLists\hlIncludePath]\r
-Count=2\r
-Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include\r
-Item1=$(BCB)\include;$(BCB)\include\vcl\r
-\r
-[HistoryLists\hlLibraryPath]\r
-Count=1\r
-Item0=$(BCB)\lib\obj;$(BCB)\lib\r
-\r
-[HistoryLists\hlDebugSourcePath]\r
-Count=1\r
-Item0=$(BCB)\source\vcl\r
-\r
-[HistoryLists\hlConditionals]\r
-Count=2\r
-Item0=_DEBUG;WIN32\r
-Item1=_DEBUG\r
-\r
-[HistoryLists\hlIntOutputDir]\r
-Count=1\r
-Item0=obj\r
-\r
-[HistoryLists\hlFinalOutputDir]\r
-Count=2\r
-Item0=..\..\lib\\r
-Item1=..\..\lib\r
-\r
-[HistoryLists\hlTlibPageSize]\r
-Count=1\r
-Item0=0x0010\r
-\r
-[Debugging]\r
-DebugSourceDirs=$(BCB)\source\vcl\r
-\r
-[Parameters]\r
-RunParams=\r
-Launcher=\r
-UseLauncher=0\r
-DebugCWD=\r
-HostApplication=\r
-RemoteHost=\r
-RemotePath=\r
-RemoteLauncher=\r
-RemoteCWD=\r
-RemoteDebug=0\r
-\r
-[Compiler]\r
-ShowInfoMsgs=0\r
-LinkDebugVcl=0\r
-LinkCGLIB=0\r
-\r
-[CORBA]\r
-AddServerUnit=1\r
-AddClientUnit=1\r
-PrecompiledHeaders=1\r
-\r
-[Language]\r
-ActiveLang=\r
-ProjectLang=\r
-RootDir=\r
- </IDEOPTIONS>\r
-</PROJECT>
\ No newline at end of file
+++ /dev/null
-#ifndef _MD5_H
-#define _MD5_H
-
-#include <time.h>
-
-#include "stg/os_int.h"
-
-#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
+++ /dev/null
-#ifndef __STG_STGLIBS_BF_STREAM_H__
-#define __STG_STGLIBS_BF_STREAM_H__
-
-#include <string>
-#include <cstddef> // 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
+++ /dev/null
-/*
- * Author : Paul Kocher
- * E-mail : pck@netcom.com
- * Date : 1997
- * Description: C implementation of the Blowfish algorithm.
- */
-
-#ifndef BLOWFISH_H
-#define BLOWFISH_H
-
-#include "stg/os_int.h"
-
-#define MAXKEYBYTES 56 /* 448 bits */
-
-#ifdef __cplusplus
-#include <cstddef> // size_t
-extern "C" {
-#else
-#include <stddef.h> // size_t
-#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
-
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-/* Copyright (C) 2003 Aleksey Krivoshey <krivoshey@users.sourceforge.net>
-*
-* 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 <libgen.h> // dirname
-#include <glob.h> // glob
-#include <string>
-
-#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<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){
- delete(*i);
- }
- for(std::list<char*>::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){
- free(*i);
- }
- for(std::list<char*>::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<char*>::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<DOTCONFDocumentNode*>::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 </%s>", 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<DOTCONFDocumentNode*>::iterator & from)
-{
- int ret = 0;
-
- for(std::list<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::iterator from;
- DOTCONFDocumentNode * tagNode = NULL;
- int vi = 0;
- for(std::list<DOTCONFDocumentNode*>::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<char*>::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<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){
- bool matched = false;
- for(std::list<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::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<DOTCONFDocumentNode*>::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++;
- }
-}
-
+++ /dev/null
-/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
-*
-* 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 <list>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include "stg/os_int.h"
-
-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<DOTCONFDocumentNode *> nodeTree;
- std::list<char *> requiredOptions;
- std::list<char *> processedFiles;
- FILE * file;
- char * fileName;
- std::list<char *> words;
- int (* cmp_func)(const char *, const char *);
-
- int checkRequiredOptions();
- int parseLine();
- int parseFile(DOTCONFDocumentNode * _parent = NULL);
- int checkConfig(const std::list<DOTCONFDocumentNode *>::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
+++ /dev/null
-/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
-*
-* 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; i<chunksCount; i++){
- delete chunks[i];
- }
- ::free(chunks);
-}
-
-int AsyncDNSMemPool::initialize()
-{
- chunksCount = 1;
- chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
- if(chunks == NULL)
- return -1;
-
- chunks[chunksCount-1] = new PoolChunk(defaultSize);
-
- return 0;
-}
-
-void AsyncDNSMemPool::addNewChunk(size_t size)
-{
- chunksCount++;
- chunks = (PoolChunk**)::realloc(chunks, chunksCount*sizeof(PoolChunk*));
- if(size <= defaultSize)
- chunks[chunksCount-1] = new PoolChunk(defaultSize);
- else
- chunks[chunksCount-1] = new PoolChunk(size);
-}
-
-void * AsyncDNSMemPool::alloc(size_t size)
-{
- PoolChunk * chunk = NULL;
- for(size_t i = 0; i<chunksCount; i++){
- chunk = chunks[i];
- if((chunk->size - 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; i<chunksCount; i++){
- pu += chunks[i]->pos;
- 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);
-}
-
+++ /dev/null
-/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
-*
-* 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 <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-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
-
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-//---------------------------------------------------------------------------
-
-#include <vcl.h>
-#pragma hdrstop
-#define Library
-
-// To add a file to the library use the Project menu 'Add to Project'.
-
-
\ No newline at end of file
+++ /dev/null
-<?xml version='1.0' encoding='utf-8' ?>
-<!-- C++Builder XML Project -->
-<PROJECT>
- <MACROS>
- <VERSION value="BCB.06.00"/>
- <PROJECT value="..\..\lib\ia_auth_c.lib"/>
- <OBJFILES value="ia_auth_c.obj"/>
- <RESFILES value=""/>
- <IDLFILES value=""/>
- <IDLGENFILES value=""/>
- <DEFFILE value=""/>
- <RESDEPEN value="$(RESFILES)"/>
- <LIBFILES value=""/>
- <LIBRARIES value=""/>
- <PACKAGES value=""/>
- <PATHCPP value=".;"/>
- <PATHPAS value=".;"/>
- <PATHRC value=".;"/>
- <PATHASM value=".;"/>
- <LINKER value="TLib"/>
- <USERDEFINES value="_DEBUG;WIN32"/>
- <SYSDEFINES value="_RTLDLL;NO_STRICT"/>
- <MAINSOURCE value="ia_auth_c.bpf"/>
- <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>
- <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib"/>
- <WARNINGS value="-w-par"/>
- <LISTFILE value=""/>
- <OTHERFILES value=""/>
- </MACROS>
- <OPTIONS>
- <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp
- -D_DEBUG -DWIN32 -boa"/>
- <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c
- -tW -tWM"/>
- <PFLAGS value="-$YD -$W -$O- -$A8 -v -JPHNE -M"/>
- <AFLAGS value="/mx /w2 /zd"/>
- <LFLAGS value=""/>
- <OTHERFILES value=""/>
- </OPTIONS>
- <LINKER>
- <ALLOBJ value="$(OBJFILES)"/>
- <ALLLIB value=""/>
- <OTHERFILES value=""/>
- </LINKER>
- <FILELIST>
- <FILE FILENAME="ia_auth_c.bpf" FORMNAME="" UNITNAME="ia_auth_c" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>
- <FILE FILENAME="packet.h" FORMNAME="" UNITNAME="packet.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
- <FILE FILENAME="ia_auth_c.h" FORMNAME="" UNITNAME="ia_auth_c.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
- <FILE FILENAME="ia_auth_c.cpp" FORMNAME="" UNITNAME="ia_auth_c.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
- </FILELIST>
- <BUILDTOOLS>
- </BUILDTOOLS>
-
- <IDEOPTIONS>
-[Version Info]
-IncludeVerInfo=0
-AutoIncBuild=0
-MajorVer=1
-MinorVer=0
-Release=0
-Build=0
-Debug=0
-PreRelease=0
-Special=0
-Private=0
-DLL=0
-Locale=1049
-CodePage=1251
-
-[Version Info Keys]
-CompanyName=
-FileDescription=
-FileVersion=1.0.0.0
-InternalName=
-LegalCopyright=
-LegalTrademarks=
-OriginalFilename=
-ProductName=
-ProductVersion=1.0.0.0
-Comments=
-
-[HistoryLists\hlIncludePath]
-Count=2
-Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include
-Item1=$(BCB)\include;$(BCB)\include\vcl
-
-[HistoryLists\hlLibraryPath]
-Count=1
-Item0=$(BCB)\lib\obj;$(BCB)\lib
-
-[HistoryLists\hlDebugSourcePath]
-Count=1
-Item0=$(BCB)\source\vcl
-
-[HistoryLists\hlConditionals]
-Count=2
-Item0=_DEBUG;WIN32
-Item1=_DEBUG
-
-[HistoryLists\hlFinalOutputDir]
-Count=1
-Item0=..\..\lib
-
-[Debugging]
-DebugSourceDirs=$(BCB)\source\vcl
-
-[Parameters]
-RunParams=
-Launcher=
-UseLauncher=0
-DebugCWD=
-HostApplication=
-RemoteHost=
-RemotePath=
-RemoteLauncher=
-RemoteCWD=
-RemoteDebug=0
-
-[Compiler]
-ShowInfoMsgs=0
-LinkDebugVcl=0
-LinkCGLIB=0
-
-[CORBA]
-AddServerUnit=1
-AddClientUnit=1
-PrecompiledHeaders=1
- </IDEOPTIONS>
-</PROJECT>
\ No newline at end of file
+++ /dev/null
-/*
-** 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 <stg34@stargazer.dp.ua>
-* Maxim Mamontov <faust@stargazer.dp.ua>
-* Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - bugfixes.
-*/
-
-//---------------------------------------------------------------------------
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <winbase.h>
-#include <winnt.h>
-#else
-#include <fcntl.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <csignal>
-#endif
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cassert>
-
-#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 <sys/time.h>
-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<std::string, int>::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<std::string> 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;
-}
-//---------------------------------------------------------------------------
+++ /dev/null
-/*
-** 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 <stg34@stargazer.dp.ua>
-*/
-//---------------------------------------------------------------------------
-#ifndef IA_AUTH_C_H
-#define IA_AUTH_C_H
-
-#ifndef WIN32
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <pthread.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include <string>
-#include <vector>
-#include <map>
-
-#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<std::string> & 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<std::string, int> 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
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _dpb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
-// Subject : IBPP, internal DPB class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * DPB == Database Parameter Block/Buffer, see Interbase 6.0 C-API\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-const int DPB::BUFFERINCR = 128;\r
-\r
-void DPB::Grow(int needed)\r
-{\r
- if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
- if ((mSize + needed) > mAlloc)\r
- {\r
- // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
- needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
- char* newbuffer = new char[mAlloc + needed];\r
- if (mBuffer == 0)\r
- {\r
- // Initial allocation, initialize the version tag\r
- newbuffer[0] = isc_dpb_version1;\r
- mSize = 1;\r
- }\r
- else\r
- {\r
- // Move the old buffer content to the new one\r
- memcpy(newbuffer, mBuffer, mSize);\r
- delete [] mBuffer;\r
- }\r
- mBuffer = newbuffer;\r
- mAlloc += needed;\r
- }\r
-}\r
-\r
-void DPB::Insert(char type, const char* data)\r
-{\r
- int len = (int)strlen(data);\r
- Grow(len + 2);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(len);\r
- strncpy(&mBuffer[mSize], data, len);\r
- mSize += len;\r
-}\r
-\r
-void DPB::Insert(char type, int16_t data)\r
-{\r
- Grow(2 + 2);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(2);\r
- *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&data, 2));\r
- mSize += 2;\r
-}\r
-\r
-void DPB::Insert(char type, bool data)\r
-{\r
- Grow(2 + 1);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(1);\r
- mBuffer[mSize++] = char(data ? 1 : 0);\r
-}\r
-\r
-void DPB::Insert(char type, char data)\r
-{\r
- Grow(2 + 1);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(1);\r
- mBuffer[mSize++] = data;\r
-}\r
-\r
-void DPB::Reset()\r
-{\r
- if (mAlloc != 0)\r
- {\r
- delete [] mBuffer;\r
- mBuffer = 0;\r
- mSize = 0;\r
- mAlloc = 0;\r
- }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _ibpp.cpp,v 1.3 2009/03/19 20:00:27 faust Exp $\r
-// Subject : IBPP, Initialization of the library\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <limits>\r
-\r
-#ifdef IBPP_WINDOWS\r
-// New (optional) Registry Keys introduced by Firebird Server 1.5\r
-#define REG_KEY_ROOT_INSTANCES "SOFTWARE\\Firebird Project\\Firebird Server\\Instances"\r
-#define FB_DEFAULT_INSTANCE "DefaultInstance"\r
-#endif\r
-\r
-namespace ibpp_internals\r
-{\r
- const double consts::dscales[19] = {\r
- 1, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,\r
- 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15,\r
- 1E16, 1E17, 1E18 };\r
-\r
- const int consts::Dec31_1899 = 693595;\r
-\r
-// Many compilers confuses those following min/max with macros min and max !\r
-#undef min\r
-#undef max\r
-\r
-#ifdef __DMC__ // Needs to break-down the declaration else compiler crash (!)\r
- const std::numeric_limits<int16_t> i16_limits;\r
- const std::numeric_limits<int32_t> i32_limits;\r
- const int16_t consts::min16 = i16_limits.min();\r
- const int16_t consts::max16 = i16_limits.max();\r
- const int32_t consts::min32 = i32_limits.min();\r
- const int32_t consts::max32 = i32_limits.max();\r
-#else\r
- const int16_t consts::min16 = std::numeric_limits<int16_t>::min();\r
- const int16_t consts::max16 = std::numeric_limits<int16_t>::max();\r
- const int32_t consts::min32 = std::numeric_limits<int32_t>::min();\r
- const int32_t consts::max32 = std::numeric_limits<int32_t>::max();\r
-#endif\r
-\r
- GDS gds; // Global unique GDS instance\r
-\r
-#ifdef IBPP_WINDOWS\r
- std::string AppPath; // Used by GDS::Call() below\r
-#endif\r
-\r
-#ifdef _DEBUG\r
- std::ostream& operator<< (std::ostream& a, flush_debug_stream_type)\r
- {\r
- if (std::stringstream* p = dynamic_cast<std::stringstream*>(&a))\r
- {\r
-#ifdef IBPP_WINDOWS\r
- ::OutputDebugString(("IBPP: " + p->str() + "\n").c_str());\r
-#endif\r
- p->str("");\r
- }\r
- return a;\r
- }\r
-#endif // _DEBUG\r
-\r
-}\r
-\r
-using namespace ibpp_internals;\r
-\r
-GDS* GDS::Call()\r
-{\r
- // Let's load the CLIENT library, if it is not already loaded.\r
- // The load is guaranteed to be done only once per application.\r
-\r
- if (! mReady)\r
- {\r
-#ifdef IBPP_WINDOWS\r
-\r
- // Let's load the FBCLIENT.DLL or GDS32.DLL, we will never release it.\r
- // Windows will do that for us when the executable will terminate.\r
-\r
- char fbdll[MAX_PATH];\r
- HKEY hkey_instances;\r
-\r
- // Try to load FBCLIENT.DLL from each of the additional optional paths\r
- // that may have been specified through ClientLibSearchPaths().\r
- // We also want to actually update the environment PATH so that it references\r
- // the specific path from where we attempt the load. This is useful because\r
- // it directs the system to attempt finding dependencies (like the C/C++\r
- // runtime libraries) from the same location where FBCLIENT is found.\r
-\r
- mHandle = 0;\r
-\r
- std::string SysPath(getenv("PATH"));\r
- std::string::size_type pos = 0;\r
- while (pos < mSearchPaths.size())\r
- {\r
- std::string::size_type newpos = mSearchPaths.find(';', pos);\r
-\r
- std::string path;\r
- if (newpos == std::string::npos) path = mSearchPaths.substr(pos);\r
- else path = mSearchPaths.substr(pos, newpos-pos);\r
-\r
- if (path.size() >= 1)\r
- {\r
- if (path[path.size()-1] != '\\') path += '\\';\r
-\r
- AppPath.assign("PATH=");\r
- AppPath.append(path).append(";").append(SysPath);\r
- putenv(AppPath.c_str());\r
-\r
- path.append("fbclient.dll");\r
- mHandle = LoadLibrary(path.c_str());\r
- if (mHandle != 0 || newpos == std::string::npos) break;\r
- }\r
- pos = newpos + 1;\r
- }\r
-\r
- if (mHandle == 0)\r
- {\r
- // Try to load FBCLIENT.DLL from the current application location. This\r
- // is a usefull step for applications using the embedded version of FB\r
- // or a local copy (for whatever reasons) of the dll.\r
-\r
- if (! AppPath.empty())\r
- {\r
- // Restores the original system path\r
- AppPath.assign("PATH=");\r
- AppPath.append(SysPath);\r
- putenv(AppPath.c_str());\r
- }\r
-\r
- int len = GetModuleFileName(NULL, fbdll, sizeof(fbdll));\r
- if (len != 0)\r
- {\r
- // Get to the last '\' (this one precedes the filename part).\r
- // There is always one after a success call to GetModuleFileName().\r
- char* p = fbdll + len;\r
- do {--p;} while (*p != '\\');\r
- *p = '\0';\r
- lstrcat(fbdll, "\\fbembed.dll");// Local copy could be named fbembed.dll\r
- mHandle = LoadLibrary(fbdll);\r
- if (mHandle == 0)\r
- {\r
- *p = '\0';\r
- lstrcat(fbdll, "\\fbclient.dll"); // Or possibly renamed fbclient.dll\r
- mHandle = LoadLibrary(fbdll);\r
- }\r
- }\r
- }\r
-\r
- if (mHandle == 0)\r
- {\r
- // Try to locate FBCLIENT.DLL through the optional FB registry key.\r
-\r
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_ROOT_INSTANCES, 0,\r
- KEY_READ, &hkey_instances) == ERROR_SUCCESS)\r
- {\r
- DWORD keytype;\r
- DWORD buflen = sizeof(fbdll);\r
- if (RegQueryValueEx(hkey_instances, FB_DEFAULT_INSTANCE, 0,\r
- &keytype, reinterpret_cast<UCHAR*>(fbdll),\r
- &buflen) == ERROR_SUCCESS && keytype == REG_SZ)\r
- {\r
- lstrcat(fbdll, "bin\\fbclient.dll");\r
- mHandle = LoadLibrary(fbdll);\r
- }\r
- RegCloseKey(hkey_instances);\r
- }\r
- }\r
-\r
- if (mHandle == 0)\r
- {\r
- // Let's try from the PATH and System directories\r
- mHandle = LoadLibrary("fbclient.dll");\r
- if (mHandle == 0)\r
- {\r
- // Not found. Last try : attemps loading gds32.dll from PATH and\r
- // System directories\r
- mHandle = LoadLibrary("gds32.dll");\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("GDS::Call()",\r
- _("Can't find or load FBCLIENT.DLL or GDS32.DLL"));\r
- }\r
- }\r
-#endif\r
-\r
- mGDSVersion = 60;\r
-\r
- // Get the entry points that we need\r
-\r
-#ifdef IBPP_WINDOWS\r
-#define IB_ENTRYPOINT(X) \\r
- if ((m_##X = (proto_##X*)GetProcAddress(mHandle, "isc_"#X)) == 0) \\r
- throw LogicExceptionImpl("GDS:gds()", _("Entry-point isc_"#X" not found"))\r
-#endif\r
-#ifdef IBPP_UNIX\r
-/* TODO : perform a late-bind on unix --- not so important, well I think (OM) */\r
-#define IB_ENTRYPOINT(X) m_##X = (proto_##X*)isc_##X\r
-#endif\r
-\r
- IB_ENTRYPOINT(create_database);\r
- IB_ENTRYPOINT(attach_database);\r
- IB_ENTRYPOINT(detach_database);\r
- IB_ENTRYPOINT(drop_database);\r
- IB_ENTRYPOINT(database_info);\r
- IB_ENTRYPOINT(open_blob2);\r
- IB_ENTRYPOINT(create_blob2);\r
- IB_ENTRYPOINT(close_blob);\r
- IB_ENTRYPOINT(cancel_blob);\r
- IB_ENTRYPOINT(get_segment);\r
- IB_ENTRYPOINT(put_segment);\r
- IB_ENTRYPOINT(blob_info);\r
- IB_ENTRYPOINT(array_lookup_bounds);\r
- IB_ENTRYPOINT(array_get_slice);\r
- IB_ENTRYPOINT(array_put_slice);\r
- IB_ENTRYPOINT(vax_integer);\r
- IB_ENTRYPOINT(sqlcode);\r
- IB_ENTRYPOINT(sql_interprete);\r
- IB_ENTRYPOINT(interprete);\r
- IB_ENTRYPOINT(que_events);\r
- IB_ENTRYPOINT(cancel_events);\r
- IB_ENTRYPOINT(start_multiple);\r
- IB_ENTRYPOINT(commit_transaction);\r
- IB_ENTRYPOINT(commit_retaining);\r
- IB_ENTRYPOINT(rollback_transaction);\r
- IB_ENTRYPOINT(rollback_retaining);\r
- IB_ENTRYPOINT(dsql_execute_immediate);\r
- IB_ENTRYPOINT(dsql_allocate_statement);\r
- IB_ENTRYPOINT(dsql_describe);\r
- IB_ENTRYPOINT(dsql_describe_bind);\r
- IB_ENTRYPOINT(dsql_prepare);\r
- IB_ENTRYPOINT(dsql_execute);\r
- IB_ENTRYPOINT(dsql_execute2);\r
- IB_ENTRYPOINT(dsql_fetch);\r
- IB_ENTRYPOINT(dsql_free_statement);\r
- IB_ENTRYPOINT(dsql_set_cursor_name);\r
- IB_ENTRYPOINT(dsql_sql_info);\r
-\r
- IB_ENTRYPOINT(service_attach);\r
- IB_ENTRYPOINT(service_detach);\r
- IB_ENTRYPOINT(service_start);\r
- IB_ENTRYPOINT(service_query);\r
-\r
- mReady = true;\r
- }\r
-\r
- return this;\r
-}\r
-\r
-namespace IBPP\r
-{\r
-\r
- bool CheckVersion(uint32_t AppVersion)\r
- {\r
- //(void)gds.Call(); // Just call it to trigger the initialization\r
- return (AppVersion & 0xFFFFFF00) ==\r
- (IBPP::Version & 0xFFFFFF00) ? true : false;\r
- }\r
-\r
- int GDSVersion()\r
- {\r
- return gds.Call()->mGDSVersion;\r
- }\r
-\r
-#ifdef IBPP_WINDOWS\r
- void ClientLibSearchPaths(const std::string& paths)\r
- {\r
- gds.mSearchPaths.assign(paths);\r
- }\r
-#else\r
- void ClientLibSearchPaths(const std::string&)\r
- {\r
- }\r
-#endif\r
-\r
- // Factories for our Interface objects\r
-\r
- Service ServiceFactory(const std::string& ServerName,\r
- const std::string& UserName, const std::string& UserPassword)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new ServiceImpl(ServerName, UserName, UserPassword);\r
- }\r
-\r
- Database DatabaseFactory(const std::string& ServerName,\r
- const std::string& DatabaseName, const std::string& UserName,\r
- const std::string& UserPassword, const std::string& RoleName,\r
- const std::string& CharSet, const std::string& CreateParams)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new DatabaseImpl(ServerName, DatabaseName, UserName,\r
- UserPassword, RoleName, CharSet, CreateParams);\r
- }\r
-\r
- Transaction TransactionFactory(Database db, TAM am,\r
- TIL il, TLR lr, TFF flags)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new TransactionImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
- am, il, lr, flags);\r
- }\r
-\r
- Statement StatementFactory(Database db, Transaction tr,\r
- const std::string& sql)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new StatementImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
- dynamic_cast<TransactionImpl*>(tr.intf()),\r
- sql);\r
- }\r
-\r
- Blob BlobFactory(Database db, Transaction tr)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new BlobImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
- dynamic_cast<TransactionImpl*>(tr.intf()));\r
- }\r
-\r
- Array ArrayFactory(Database db, Transaction tr)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new ArrayImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
- dynamic_cast<TransactionImpl*>(tr.intf()));\r
- }\r
-\r
- Events EventsFactory(Database db)\r
- {\r
- (void)gds.Call(); // Triggers the initialization, if needed\r
- return new EventsImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
- }\r
-\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
-\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _ibpp.h,v 1.2 2007/05/17 08:37:05 faust Exp $\r
-// Subject : IBPP internal declarations\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-//\r
-// * 'Internal declarations' means everything used to implement ibpp. This\r
-// file and its contents is NOT needed by users of the library. All those\r
-// declarations are wrapped in a namespace : 'ibpp_internals'.\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifndef __INTERNAL_IBPP_H__\r
-#define __INTERNAL_IBPP_H__\r
-\r
-#include "stg/ibpp.h"\r
-\r
-#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__DMC__)\r
-#define HAS_HDRSTOP\r
-#endif\r
-\r
-#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
-// Setting flags for ibase.h -- using GCC/Cygwin/MinGW on Win32\r
-#ifndef _MSC_VER\r
-#define _MSC_VER 1299\r
-#endif\r
-#ifndef _WIN32\r
-#define _WIN32 1\r
-#endif\r
-#endif\r
-\r
-#include "ibase.h" // From Firebird 1.x or InterBase 6.x installation\r
-\r
-#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
-// UNSETTING flags used above for ibase.h -- Huge conflicts with libstdc++ !\r
-#undef _MSC_VER\r
-#undef _WIN32\r
-#endif\r
-\r
-#ifdef IBPP_WINDOWS\r
-#include <windows.h>\r
-#endif\r
-\r
-//#include <limits>\r
-#include <string>\r
-#include <vector>\r
-#include <sstream>\r
-#include <cstdarg>\r
-\r
-#ifdef _DEBUG\r
-#define ASSERTION(x) {if (!(x)) {throw LogicExceptionImpl("ASSERTION", \\r
- "'"#x"' is not verified at %s, line %d", \\r
- __FILE__, __LINE__);}}\r
-#else\r
-#define ASSERTION(x) /* x */\r
-#endif\r
-\r
-// Fix to famous MSVC 6 variable scope bug\r
-#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
-#define for if(true)for\r
-#endif\r
-\r
-namespace ibpp_internals\r
-{\r
-\r
-enum flush_debug_stream_type {fds};\r
-\r
-#ifdef _DEBUG\r
-\r
-struct DebugStream : public std::stringstream\r
-{\r
- // next two operators fix some g++ and vc++ related problems\r
- std::ostream& operator<< (const char* p)\r
- { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
-\r
- std::ostream& operator<< (const std::string& p)\r
- { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
-\r
- DebugStream& operator=(const DebugStream&) {return *this;}\r
- DebugStream(const DebugStream&) {}\r
- DebugStream() {}\r
-};\r
-std::ostream& operator<< (std::ostream& a, flush_debug_stream_type);\r
-\r
-#else\r
-\r
-struct DebugStream\r
-{\r
- template<class T> DebugStream& operator<< (const T&) { return *this; }\r
- // for manipulators\r
- DebugStream& operator<< (std::ostream&(*)(std::ostream&)) { return *this; }\r
-};\r
-\r
-#endif // _DEBUG\r
-\r
-class DatabaseImpl;\r
-class TransactionImpl;\r
-class StatementImpl;\r
-class BlobImpl;\r
-class ArrayImpl;\r
-class EventsImpl;\r
-\r
-// Native data types\r
-typedef enum {ivArray, ivBlob, ivDate, ivTime, ivTimestamp, ivString,\r
- ivInt16, ivInt32, ivInt64, ivFloat, ivDouble,\r
- ivBool, ivDBKey, ivByte} IITYPE;\r
-\r
-//\r
-// Those are the Interbase C API prototypes that we use\r
-// Taken 'asis' from IBASE.H, prefix 'isc_' replaced with 'proto_',\r
-// and 'typedef' preprended...\r
-//\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_create_database (ISC_STATUS *,\r
- short,\r
- char *,\r
- isc_db_handle *,\r
- short,\r
- char *,\r
- short);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_attach_database (ISC_STATUS *,\r
- short,\r
- char *,\r
- isc_db_handle *,\r
- short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_detach_database (ISC_STATUS *,\r
- isc_db_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_drop_database (ISC_STATUS *,\r
- isc_db_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_database_info (ISC_STATUS *,\r
- isc_db_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_execute_immediate (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_open_blob2 (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *,\r
- short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_create_blob2 (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *,\r
- short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_close_blob (ISC_STATUS *,\r
- isc_blob_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_cancel_blob (ISC_STATUS *,\r
- isc_blob_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_get_segment (ISC_STATUS *,\r
- isc_blob_handle *,\r
- unsigned short *,\r
- unsigned short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_put_segment (ISC_STATUS *,\r
- isc_blob_handle *,\r
- unsigned short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_blob_info (ISC_STATUS *,\r
- isc_blob_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_array_lookup_bounds (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- char *,\r
- char *,\r
- ISC_ARRAY_DESC *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_array_get_slice (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- ISC_ARRAY_DESC *,\r
- void *,\r
- ISC_LONG *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_array_put_slice (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- ISC_ARRAY_DESC *,\r
- void *,\r
- ISC_LONG *);\r
-\r
-typedef ISC_LONG ISC_EXPORT proto_vax_integer (char *,\r
- short);\r
-\r
-typedef ISC_LONG ISC_EXPORT proto_sqlcode (ISC_STATUS *);\r
-\r
-typedef void ISC_EXPORT proto_sql_interprete (short,\r
- char *,\r
- short);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_interprete (char *,\r
- ISC_STATUS * *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_que_events (ISC_STATUS *,\r
- isc_db_handle *,\r
- ISC_LONG *,\r
- short,\r
- char *,\r
- isc_callback,\r
- void *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_cancel_events (ISC_STATUS *,\r
- isc_db_handle *,\r
- ISC_LONG *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_start_multiple (ISC_STATUS *,\r
- isc_tr_handle *,\r
- short,\r
- void *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_commit_transaction (ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_commit_retaining (ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_rollback_transaction (ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_rollback_retaining (ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-///////////\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_allocate_statement (ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_stmt_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_describe (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_describe_bind (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_execute (ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_execute2 (ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_fetch (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_free_statement (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_prepare (ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_set_cursor_name (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- char *,\r
- unsigned short);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_dsql_sql_info (ISC_STATUS *,\r
- isc_stmt_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-typedef void ISC_EXPORT proto_decode_date (ISC_QUAD *,\r
- void *);\r
-\r
-typedef void ISC_EXPORT proto_encode_date (void *,\r
- ISC_QUAD *);\r
-\r
-typedef int ISC_EXPORT proto_add_user (ISC_STATUS *, USER_SEC_DATA *);\r
-typedef int ISC_EXPORT proto_delete_user (ISC_STATUS *, USER_SEC_DATA *);\r
-typedef int ISC_EXPORT proto_modify_user (ISC_STATUS *, USER_SEC_DATA *);\r
-\r
-//\r
-// Those API are only available in versions 6.x of the GDS32.DLL\r
-//\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_service_attach (ISC_STATUS *,\r
- unsigned short,\r
- char *,\r
- isc_svc_handle *,\r
- unsigned short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_service_detach (ISC_STATUS *,\r
- isc_svc_handle *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_service_query (ISC_STATUS *,\r
- isc_svc_handle *,\r
- isc_resv_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *);\r
-\r
-typedef ISC_STATUS ISC_EXPORT proto_service_start (ISC_STATUS *,\r
- isc_svc_handle *,\r
- isc_resv_handle *,\r
- unsigned short,\r
- char*);\r
-\r
-typedef void ISC_EXPORT proto_decode_sql_date (ISC_DATE *,\r
- void *);\r
-\r
-typedef void ISC_EXPORT proto_decode_sql_time (ISC_TIME *,\r
- void *);\r
-\r
-typedef void ISC_EXPORT proto_decode_timestamp (ISC_TIMESTAMP *,\r
- void *);\r
-\r
-typedef void ISC_EXPORT proto_encode_sql_date (void *,\r
- ISC_DATE *);\r
-\r
-typedef void ISC_EXPORT proto_encode_sql_time (void *,\r
- ISC_TIME *);\r
-\r
-typedef void ISC_EXPORT proto_encode_timestamp (void *,\r
- ISC_TIMESTAMP *);\r
-\r
-//\r
-// Internal binding structure to the GDS32 DLL\r
-//\r
-\r
-struct GDS\r
-{\r
- // Attributes\r
- bool mReady;\r
- int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0)\r
-\r
-#ifdef IBPP_WINDOWS\r
- HMODULE mHandle; // The GDS32.DLL HMODULE\r
- std::string mSearchPaths; // Optional additional search paths\r
-#endif\r
-\r
- GDS* Call();\r
-\r
- // GDS32 Entry Points\r
- proto_create_database* m_create_database;\r
- proto_attach_database* m_attach_database;\r
- proto_detach_database* m_detach_database;\r
- proto_drop_database* m_drop_database;\r
- proto_database_info* m_database_info;\r
- proto_dsql_execute_immediate* m_dsql_execute_immediate;\r
- proto_open_blob2* m_open_blob2;\r
- proto_create_blob2* m_create_blob2;\r
- proto_close_blob* m_close_blob;\r
- proto_cancel_blob* m_cancel_blob;\r
- proto_get_segment* m_get_segment;\r
- proto_put_segment* m_put_segment;\r
- proto_blob_info* m_blob_info;\r
- proto_array_lookup_bounds* m_array_lookup_bounds;\r
- proto_array_get_slice* m_array_get_slice;\r
- proto_array_put_slice* m_array_put_slice;\r
-\r
- proto_vax_integer* m_vax_integer;\r
- proto_sqlcode* m_sqlcode;\r
- proto_sql_interprete* m_sql_interprete;\r
- proto_interprete* m_interprete;\r
- proto_que_events* m_que_events;\r
- proto_cancel_events* m_cancel_events;\r
- proto_start_multiple* m_start_multiple;\r
- proto_commit_transaction* m_commit_transaction;\r
- proto_commit_retaining* m_commit_retaining;\r
- proto_rollback_transaction* m_rollback_transaction;\r
- proto_rollback_retaining* m_rollback_retaining;\r
- proto_dsql_allocate_statement* m_dsql_allocate_statement;\r
- proto_dsql_describe* m_dsql_describe;\r
- proto_dsql_describe_bind* m_dsql_describe_bind;\r
- proto_dsql_prepare* m_dsql_prepare;\r
- proto_dsql_execute* m_dsql_execute;\r
- proto_dsql_execute2* m_dsql_execute2;\r
- proto_dsql_fetch* m_dsql_fetch;\r
- proto_dsql_free_statement* m_dsql_free_statement;\r
- proto_dsql_set_cursor_name* m_dsql_set_cursor_name;\r
- proto_dsql_sql_info* m_dsql_sql_info;\r
- //proto_decode_date* m_decode_date;\r
- //proto_encode_date* m_encode_date;\r
- //proto_add_user* m_add_user;\r
- //proto_delete_user* m_delete_user;\r
- //proto_modify_user* m_modify_user;\r
-\r
- proto_service_attach* m_service_attach;\r
- proto_service_detach* m_service_detach;\r
- proto_service_start* m_service_start;\r
- proto_service_query* m_service_query;\r
- //proto_decode_sql_date* m_decode_sql_date;\r
- //proto_decode_sql_time* m_decode_sql_time;\r
- //proto_decode_timestamp* m_decode_timestamp;\r
- //proto_encode_sql_date* m_encode_sql_date;\r
- //proto_encode_sql_time* m_encode_sql_time;\r
- //proto_encode_timestamp* m_encode_timestamp;\r
-\r
- // Constructor (No need for a specific destructor)\r
- GDS()\r
- {\r
- mReady = false;\r
- mGDSVersion = 0;\r
-#ifdef IBPP_WINDOWS\r
- mHandle = 0;\r
-#endif\r
- }\r
-};\r
-\r
-extern GDS gds;\r
-\r
-//\r
-// Service Parameter Block (used to define a service)\r
-//\r
-\r
-class SPB\r
-{\r
- static const int BUFFERINCR;\r
-\r
- char* mBuffer; // Dynamically allocated SPB structure\r
- int mSize; // Its used size in bytes\r
- int mAlloc; // Its allocated size in bytes\r
-\r
- void Grow(int needed); // Alloc or grow the mBuffer\r
-\r
-public:\r
- void Insert(char); // Insert a single byte code\r
- void InsertString(char, int, const char*); // Insert a string, len can be defined as 1 or 2 bytes\r
- void InsertByte(char type, char data);\r
- void InsertQuad(char type, int32_t data);\r
- void Reset(); // Clears the SPB\r
- char* Self() { return mBuffer; }\r
- short Size() { return (short)mSize; }\r
-\r
- SPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
- ~SPB() { Reset(); }\r
-};\r
-\r
-//\r
-// Database Parameter Block (used to define a database)\r
-//\r
-\r
-class DPB\r
-{\r
- static const int BUFFERINCR;\r
-\r
- char* mBuffer; // Dynamically allocated DPB structure\r
- int mSize; // Its used size in bytes\r
- int mAlloc; // Its allocated size in bytes\r
-\r
- void Grow(int needed); // Allocate or grow the mBuffer, so that\r
- // 'needed' bytes can be written (at least)\r
-\r
-public:\r
- void Insert(char, const char*); // Insert a new char* 'cluster'\r
- void Insert(char, int16_t); // Insert a new int16_t 'cluster'\r
- void Insert(char, bool); // Insert a new bool 'cluster'\r
- void Insert(char, char); // Insert a new byte 'cluster'\r
- void Reset(); // Clears the DPB\r
- char* Self() { return mBuffer; }\r
- short Size() { return (short)mSize; }\r
-\r
- DPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
- ~DPB() { Reset(); }\r
-};\r
-\r
-//\r
-// Transaction Parameter Block (used to define a transaction)\r
-//\r
-\r
-class TPB\r
-{\r
- static const int BUFFERINCR;\r
-\r
- char* mBuffer; // Dynamically allocated TPB structure\r
- int mSize; // Its used size in bytes\r
- int mAlloc; // Its allocated size\r
-\r
- void Grow(int needed); // Alloc or re-alloc the mBuffer\r
-\r
-public:\r
- void Insert(char); // Insert a flag item\r
- void Insert(const std::string& data); // Insert a string (typically table name)\r
- void Reset(); // Clears the TPB\r
- char* Self() { return mBuffer; }\r
- int Size() { return mSize; }\r
-\r
- TPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
- ~TPB() { Reset(); }\r
-};\r
-\r
-//\r
-// Used to receive (and process) a results buffer in various API calls\r
-//\r
-\r
-class RB\r
-{\r
- char* mBuffer;\r
- int mSize;\r
-\r
- char* FindToken(char token);\r
- char* FindToken(char token, char subtoken);\r
-\r
-public:\r
- void Reset();\r
- int GetValue(char token);\r
- int GetCountValue(char token);\r
- int GetValue(char token, char subtoken);\r
- bool GetBool(char token);\r
- int GetString(char token, std::string& data);\r
-\r
- char* Self() { return mBuffer; }\r
- short Size() { return (short)mSize; }\r
-\r
- RB();\r
- RB(int Size);\r
- ~RB();\r
-};\r
-\r
-//\r
-// Used to receive status info from API calls\r
-//\r
-\r
-class IBS\r
-{\r
- mutable ISC_STATUS mVector[20];\r
- mutable std::string mMessage;\r
-\r
-public:\r
- ISC_STATUS* Self() { return mVector; }\r
- bool Errors() { return (mVector[0] == 1 && mVector[1] > 0) ? true : false; }\r
- const char* ErrorMessage() const;\r
- int SqlCode() const;\r
- int EngineCode() const { return (mVector[0] == 1) ? (int)mVector[1] : 0; }\r
- void Reset();\r
-\r
- IBS();\r
- IBS(IBS&); // Copy Constructor\r
- ~IBS();\r
-};\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Implementation of the "hidden" classes associated with their public\r
-// counterparts. Their private data and methods can freely change without\r
-// breaking the compatibility of the DLL. If they receive new public methods,\r
-// and those methods are reflected in the public class, then the compatibility\r
-// is broken.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-//\r
-// Hidden implementation of Exception classes.\r
-//\r
-\r
-/*\r
- std::exception\r
- |\r
- IBPP::Exception\r
- / \\r
- / \\r
- IBPP::LogicException ExceptionBase IBPP::SQLException\r
- | \ / | \ /\r
- | LogicExceptionImpl | SQLExceptionImpl\r
- | |\r
- IBPP::WrongType |\r
- \ |\r
- IBPP::WrongTypeImpl\r
-*/\r
-\r
-class ExceptionBase\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-protected:\r
- std::string mContext; // Exception context ("IDatabase::Drop")\r
- std::string mWhat; // Full formatted message\r
-\r
- void buildErrorMessage(const char* message);\r
- void raise(const std::string& context, const char* message, va_list argptr);\r
-\r
-public:\r
- // The following constructors are small and could be inlined, but for object\r
- // code compacity of the library it is much better to have them non-inlined.\r
- // The amount of code generated by compilers for a throw is well-enough.\r
-\r
- ExceptionBase() throw();\r
- ExceptionBase(const ExceptionBase& copied) throw();\r
- ExceptionBase& operator=(const ExceptionBase& copied) throw();\r
- ExceptionBase(const std::string& context, const char* message = 0, ...) throw();\r
-\r
- virtual ~ExceptionBase() throw();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
- virtual const char* Origin() const throw();\r
- virtual const char* ErrorMessage() const throw();\r
- virtual const char* what() const throw();\r
-};\r
-\r
-class LogicExceptionImpl : public IBPP::LogicException, public ExceptionBase\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-public:\r
- // The following constructors are small and could be inlined, but for object\r
- // code compacity of the library it is much better to have them non-inlined.\r
- // The amount of code generated by compilers for a throw is well-enough.\r
-\r
- LogicExceptionImpl() throw();\r
- LogicExceptionImpl(const LogicExceptionImpl& copied) throw();\r
- LogicExceptionImpl& operator=(const LogicExceptionImpl& copied) throw();\r
- LogicExceptionImpl(const std::string& context, const char* message = 0, ...) throw();\r
-\r
- virtual ~LogicExceptionImpl() throw ();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
- //\r
- // The object public interface is partly implemented by inheriting from\r
- // the ExceptionBase class.\r
-\r
-public:\r
- virtual const char* Origin() const throw();\r
- virtual const char* ErrorMessage() const throw();\r
- virtual const char* what() const throw();\r
-};\r
-\r
-class SQLExceptionImpl : public IBPP::SQLException, public ExceptionBase\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- int mSqlCode;\r
- int mEngineCode;\r
-\r
-public:\r
- // The following constructors are small and could be inlined, but for object\r
- // code compacity of the library it is much better to have them non-inlined.\r
- // The amount of code generated by compilers for a throw is well-enough.\r
-\r
- SQLExceptionImpl() throw();\r
- SQLExceptionImpl(const SQLExceptionImpl& copied) throw();\r
- SQLExceptionImpl& operator=(const SQLExceptionImpl& copied) throw();\r
- SQLExceptionImpl(const IBS& status, const std::string& context,\r
- const char* message = 0, ...) throw();\r
-\r
- virtual ~SQLExceptionImpl() throw ();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
- //\r
- // The object public interface is partly implemented by inheriting from\r
- // the ExceptionBase class.\r
-\r
-public:\r
- virtual const char* Origin() const throw();\r
- virtual const char* ErrorMessage() const throw();\r
- virtual const char* what() const throw();\r
- virtual int SqlCode() const throw();\r
- virtual int EngineCode() const throw();\r
-};\r
-\r
-class WrongTypeImpl : public IBPP::WrongType, public ExceptionBase\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-public:\r
- // The following constructors are small and could be inlined, but for object\r
- // code compacity of the library it is much better to have them non-inlined.\r
- // The amount of code generated by compilers for a throw is well-enough.\r
-\r
- WrongTypeImpl() throw();\r
- WrongTypeImpl(const WrongTypeImpl& copied) throw();\r
- WrongTypeImpl& operator=(const WrongTypeImpl& copied) throw();\r
- WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
- const char* message = 0, ...) throw();\r
-\r
- virtual ~WrongTypeImpl() throw ();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
- //\r
- // The object public interface is partly implemented by inheriting from\r
- // the ExceptionBase class.\r
-\r
-public:\r
- virtual const char* Origin() const throw();\r
- virtual const char* ErrorMessage() const throw();\r
- virtual const char* what() const throw();\r
-};\r
-\r
-class ServiceImpl : public IBPP::IService\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- int mRefCount; // Reference counter\r
- isc_svc_handle mHandle; // InterBase API Service Handle\r
- std::string mServerName; // Nom du serveur\r
- std::string mUserName; // Nom de l'utilisateur\r
- std::string mUserPassword; // Mot de passe de l'utilisateur\r
- std::string mWaitMessage; // Progress message returned by WaitMsg()\r
-\r
- isc_svc_handle* GetHandlePtr() { return &mHandle; }\r
- void SetServerName(const char*);\r
- void SetUserName(const char*);\r
- void SetUserPassword(const char*);\r
-\r
-public:\r
- isc_svc_handle GetHandle() { return mHandle; }\r
-\r
- ServiceImpl(const std::string& ServerName, const std::string& UserName,\r
- const std::string& UserPassword);\r
- ~ServiceImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void Connect();\r
- bool Connected() { return mHandle == 0 ? false : true; }\r
- void Disconnect();\r
-\r
- void GetVersion(std::string& version);\r
-\r
- void AddUser(const IBPP::User&);\r
- void GetUser(IBPP::User&);\r
- void GetUsers(std::vector<IBPP::User>&);\r
- void ModifyUser(const IBPP::User&);\r
- void RemoveUser(const std::string& username);\r
-\r
- void SetPageBuffers(const std::string& dbfile, int buffers);\r
- void SetSweepInterval(const std::string& dbfile, int sweep);\r
- void SetSyncWrite(const std::string& dbfile, bool);\r
- void SetReadOnly(const std::string& dbfile, bool);\r
- void SetReserveSpace(const std::string& dbfile, bool);\r
-\r
- void Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout);\r
- void Restart(const std::string& dbfile);\r
- void Sweep(const std::string& dbfile);\r
- void Repair(const std::string& dbfile, IBPP::RPF flags);\r
-\r
- void StartBackup(const std::string& dbfile, const std::string& bkfile,\r
- IBPP::BRF flags = IBPP::BRF(0));\r
- void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
- int pagesize, IBPP::BRF flags = IBPP::BRF(0));\r
-\r
- const char* WaitMsg();\r
- void Wait();\r
-\r
- IBPP::IService* AddRef();\r
- void Release();\r
-};\r
-\r
-class DatabaseImpl : public IBPP::IDatabase\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
- int mRefCount; // Reference counter\r
- isc_db_handle mHandle; // InterBase API Session Handle\r
- std::string mServerName; // Server name\r
- std::string mDatabaseName; // Database name (path/file)\r
- std::string mUserName; // User name\r
- std::string mUserPassword; // User password\r
- std::string mRoleName; // Role used for the duration of the connection\r
- std::string mCharSet; // Character Set used for the connection\r
- std::string mCreateParams; // Other parameters (creation only)\r
-\r
- int mDialect; // 1 if IB5, 1 or 3 if IB6/FB1\r
- std::vector<TransactionImpl*> mTransactions;// Table of Transaction*\r
- std::vector<StatementImpl*> mStatements;// Table of Statement*\r
- std::vector<BlobImpl*> mBlobs; // Table of Blob*\r
- std::vector<ArrayImpl*> mArrays; // Table of Array*\r
- std::vector<EventsImpl*> mEvents; // Table of Events*\r
-\r
-public:\r
- isc_db_handle* GetHandlePtr() { return &mHandle; }\r
- isc_db_handle GetHandle() { return mHandle; }\r
-\r
- void AttachTransactionImpl(TransactionImpl*);\r
- void DetachTransactionImpl(TransactionImpl*);\r
- void AttachStatementImpl(StatementImpl*);\r
- void DetachStatementImpl(StatementImpl*);\r
- void AttachBlobImpl(BlobImpl*);\r
- void DetachBlobImpl(BlobImpl*);\r
- void AttachArrayImpl(ArrayImpl*);\r
- void DetachArrayImpl(ArrayImpl*);\r
- void AttachEventsImpl(EventsImpl*);\r
- void DetachEventsImpl(EventsImpl*);\r
-\r
- DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
- const std::string& UserName, const std::string& UserPassword,\r
- const std::string& RoleName, const std::string& CharSet,\r
- const std::string& CreateParams);\r
- ~DatabaseImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- const char* ServerName() const { return mServerName.c_str(); }\r
- const char* DatabaseName() const { return mDatabaseName.c_str(); }\r
- const char* Username() const { return mUserName.c_str(); }\r
- const char* UserPassword() const { return mUserPassword.c_str(); }\r
- const char* RoleName() const { return mRoleName.c_str(); }\r
- const char* CharSet() const { return mCharSet.c_str(); }\r
- const char* CreateParams() const { return mCreateParams.c_str(); }\r
-\r
- void Info(int* ODSMajor, int* ODSMinor,\r
- int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
- bool* SyncWrites, bool* Reserve);\r
- void Statistics(int* Fetches, int* Marks, int* Reads, int* Writes);\r
- void Counts(int* Insert, int* Update, int* Delete,\r
- int* ReadIdx, int* ReadSeq);\r
- void Users(std::vector<std::string>& users);\r
- int Dialect() { return mDialect; }\r
-\r
- void Create(int dialect);\r
- void Connect();\r
- bool Connected() { return mHandle == 0 ? false : true; }\r
- void Inactivate();\r
- void Disconnect();\r
- void Drop();\r
-\r
- IBPP::IDatabase* AddRef();\r
- void Release();\r
-};\r
-\r
-class TransactionImpl : public IBPP::ITransaction\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- int mRefCount; // Reference counter\r
- isc_tr_handle mHandle; // Transaction InterBase\r
-\r
- std::vector<DatabaseImpl*> mDatabases; // Tableau de IDatabase*\r
- std::vector<StatementImpl*> mStatements; // Tableau de IStatement*\r
- std::vector<BlobImpl*> mBlobs; // Tableau de IBlob*\r
- std::vector<ArrayImpl*> mArrays; // Tableau de Array*\r
- std::vector<TPB*> mTPBs; // Tableau de TPB\r
-\r
- void Init(); // A usage exclusif des constructeurs\r
-\r
-public:\r
- isc_tr_handle* GetHandlePtr() { return &mHandle; }\r
- isc_tr_handle GetHandle() { return mHandle; }\r
-\r
- void AttachStatementImpl(StatementImpl*);\r
- void DetachStatementImpl(StatementImpl*);\r
- void AttachBlobImpl(BlobImpl*);\r
- void DetachBlobImpl(BlobImpl*);\r
- void AttachArrayImpl(ArrayImpl*);\r
- void DetachArrayImpl(ArrayImpl*);\r
- void AttachDatabaseImpl(DatabaseImpl* dbi, IBPP::TAM am = IBPP::amWrite,\r
- IBPP::TIL il = IBPP::ilConcurrency,\r
- IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
- void DetachDatabaseImpl(DatabaseImpl* dbi);\r
-\r
- TransactionImpl(DatabaseImpl* db, IBPP::TAM am = IBPP::amWrite,\r
- IBPP::TIL il = IBPP::ilConcurrency,\r
- IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
- ~TransactionImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void AttachDatabase(IBPP::Database db, IBPP::TAM am = IBPP::amWrite,\r
- IBPP::TIL il = IBPP::ilConcurrency,\r
- IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
- void DetachDatabase(IBPP::Database db);\r
- void AddReservation(IBPP::Database db,\r
- const std::string& table, IBPP::TTR tr);\r
-\r
- void Start();\r
- bool Started() { return mHandle == 0 ? false : true; }\r
- void Commit();\r
- void Rollback();\r
- void CommitRetain();\r
- void RollbackRetain();\r
-\r
- IBPP::ITransaction* AddRef();\r
- void Release();\r
-};\r
-\r
-class RowImpl : public IBPP::IRow\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- int mRefCount; // Reference counter\r
-\r
- XSQLDA* mDescrArea; // XSQLDA descriptor itself\r
- std::vector<double> mNumerics; // Temporary storage for Numerics\r
- std::vector<float> mFloats; // Temporary storage for Floats\r
- std::vector<int64_t> mInt64s; // Temporary storage for 64 bits\r
- std::vector<int32_t> mInt32s; // Temporary storage for 32 bits\r
- std::vector<int16_t> mInt16s; // Temporary storage for 16 bits\r
- std::vector<char> mBools; // Temporary storage for Bools\r
- std::vector<std::string> mStrings; // Temporary storage for Strings\r
- std::vector<bool> mUpdated; // Which columns where updated (Set()) ?\r
-\r
- int mDialect; // Related database dialect\r
- DatabaseImpl* mDatabase; // Related Database (important for Blobs, ...)\r
- TransactionImpl* mTransaction; // Related Transaction (same remark)\r
-\r
- void SetValue(int, IITYPE, const void* value, int = 0);\r
- void* GetValue(int, IITYPE, void* = 0);\r
-\r
-public:\r
- void Free();\r
- short AllocatedSize() { return mDescrArea->sqln; }\r
- void Resize(int n);\r
- void AllocVariables();\r
- bool MissingValues(); // Returns wether one of the mMissing[] is true\r
- XSQLDA* Self() { return mDescrArea; }\r
-\r
- RowImpl& operator=(const RowImpl& copied);\r
- RowImpl(const RowImpl& copied);\r
- RowImpl(int dialect, int size, DatabaseImpl* db, TransactionImpl* tr);\r
- ~RowImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void SetNull(int);\r
- void Set(int, bool);\r
- void Set(int, const char*); // c-strings\r
- void Set(int, const void*, int); // byte buffers\r
- void Set(int, const std::string&);\r
- void Set(int, int16_t);\r
- void Set(int, int32_t);\r
- void Set(int, int64_t);\r
- void Set(int, float);\r
- void Set(int, double);\r
- void Set(int, const IBPP::Timestamp&);\r
- void Set(int, const IBPP::Date&);\r
- void Set(int, const IBPP::Time&);\r
- void Set(int, const IBPP::DBKey&);\r
- void Set(int, const IBPP::Blob&);\r
- void Set(int, const IBPP::Array&);\r
-\r
- bool IsNull(int);\r
- bool Get(int, bool&);\r
- bool Get(int, char*); // c-strings, len unchecked\r
- bool Get(int, void*, int&); // byte buffers\r
- bool Get(int, std::string&);\r
- bool Get(int, int16_t&);\r
- bool Get(int, int32_t&);\r
- bool Get(int, int64_t&);\r
- bool Get(int, float&);\r
- bool Get(int, double&);\r
- bool Get(int, IBPP::Timestamp&);\r
- bool Get(int, IBPP::Date&);\r
- bool Get(int, IBPP::Time&);\r
- bool Get(int, IBPP::DBKey&);\r
- bool Get(int, IBPP::Blob&);\r
- bool Get(int, IBPP::Array&);\r
-\r
- bool IsNull(const std::string&);\r
- bool Get(const std::string&, bool&);\r
- bool Get(const std::string&, char*); // c-strings, len unchecked\r
- bool Get(const std::string&, void*, int&); // byte buffers\r
- bool Get(const std::string&, std::string&);\r
- bool Get(const std::string&, int16_t&);\r
- bool Get(const std::string&, int32_t&);\r
- bool Get(const std::string&, int64_t&);\r
- bool Get(const std::string&, float&);\r
- bool Get(const std::string&, double&);\r
- bool Get(const std::string&, IBPP::Timestamp&);\r
- bool Get(const std::string&, IBPP::Date&);\r
- bool Get(const std::string&, IBPP::Time&);\r
- bool Get(const std::string&, IBPP::DBKey&);\r
- bool Get(const std::string&, IBPP::Blob&);\r
- bool Get(const std::string&, IBPP::Array&);\r
-\r
- int ColumnNum(const std::string&);\r
- const char* ColumnName(int);\r
- const char* ColumnAlias(int);\r
- const char* ColumnTable(int);\r
- IBPP::SDT ColumnType(int);\r
- int ColumnSubtype(int);\r
- int ColumnSize(int);\r
- int ColumnScale(int);\r
- int Columns();\r
-\r
- bool ColumnUpdated(int);\r
- bool Updated();\r
-\r
- IBPP::Database DatabasePtr() const;\r
- IBPP::Transaction TransactionPtr() const;\r
-\r
- IBPP::IRow* Clone();\r
- IBPP::IRow* AddRef();\r
- void Release();\r
-};\r
-\r
-class StatementImpl : public IBPP::IStatement\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- friend class TransactionImpl;\r
-\r
- int mRefCount; // Reference counter\r
- isc_stmt_handle mHandle; // Statement Handle\r
-\r
- DatabaseImpl* mDatabase; // Attached database\r
- TransactionImpl* mTransaction; // Attached transaction\r
- RowImpl* mInRow;\r
- //bool* mInMissing; // Quels paramètres n'ont pas été spécifiés\r
- RowImpl* mOutRow;\r
- bool mResultSetAvailable; // Executed and result set is available\r
- bool mCursorOpened; // dsql_set_cursor_name was called\r
- IBPP::STT mType; // Type de requète\r
- std::string mSql; // Last SQL statement prepared or executed\r
-\r
- // Internal Methods\r
- void CursorFree();\r
-\r
-public:\r
- // Properties and Attributes Access Methods\r
- isc_stmt_handle GetHandle() { return mHandle; }\r
-\r
- void AttachDatabaseImpl(DatabaseImpl*);\r
- void DetachDatabaseImpl();\r
- void AttachTransactionImpl(TransactionImpl*);\r
- void DetachTransactionImpl();\r
-\r
- StatementImpl(DatabaseImpl*, TransactionImpl*, const std::string&);\r
- ~StatementImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void Prepare(const std::string& sql);\r
- void Execute(const std::string& sql);\r
- inline void Execute() { Execute(std::string()); }\r
- void ExecuteImmediate(const std::string&);\r
- void CursorExecute(const std::string& cursor, const std::string& sql);\r
- inline void CursorExecute(const std::string& cursor) { CursorExecute(cursor, std::string()); }\r
- bool Fetch();\r
- bool Fetch(IBPP::Row&);\r
- int AffectedRows();\r
- void Close(); // Free resources, attachments maintained\r
- std::string& Sql() { return mSql; }\r
- IBPP::STT Type() { return mType; }\r
-\r
- void SetNull(int);\r
- void Set(int, bool);\r
- void Set(int, const char*); // c-strings\r
- void Set(int, const void*, int); // byte buffers\r
- void Set(int, const std::string&);\r
- void Set(int, int16_t);\r
- void Set(int, int32_t);\r
- void Set(int, int64_t);\r
- void Set(int, float);\r
- void Set(int, double);\r
- void Set(int, const IBPP::Timestamp&);\r
- void Set(int, const IBPP::Date&);\r
- void Set(int, const IBPP::Time&);\r
- void Set(int, const IBPP::DBKey&);\r
- void Set(int, const IBPP::Blob&);\r
- void Set(int, const IBPP::Array&);\r
-\r
- bool IsNull(int);\r
- bool Get(int, bool*);\r
- bool Get(int, bool&);\r
- bool Get(int, char*); // c-strings, len unchecked\r
- bool Get(int, void*, int&); // byte buffers\r
- bool Get(int, std::string&);\r
- bool Get(int, int16_t*);\r
- bool Get(int, int16_t&);\r
- bool Get(int, int32_t*);\r
- bool Get(int, int32_t&);\r
- bool Get(int, int64_t*);\r
- bool Get(int, int64_t&);\r
- bool Get(int, float*);\r
- bool Get(int, float&);\r
- bool Get(int, double*);\r
- bool Get(int, double&);\r
- bool Get(int, IBPP::Timestamp&);\r
- bool Get(int, IBPP::Date&);\r
- bool Get(int, IBPP::Time&);\r
- bool Get(int, IBPP::DBKey&);\r
- bool Get(int, IBPP::Blob&);\r
- bool Get(int, IBPP::Array&);\r
-\r
- bool IsNull(const std::string&);\r
- bool Get(const std::string&, bool*);\r
- bool Get(const std::string&, bool&);\r
- bool Get(const std::string&, char*); // c-strings, len unchecked\r
- bool Get(const std::string&, void*, int&); // byte buffers\r
- bool Get(const std::string&, std::string&);\r
- bool Get(const std::string&, int16_t*);\r
- bool Get(const std::string&, int16_t&);\r
- bool Get(const std::string&, int32_t*);\r
- bool Get(const std::string&, int32_t&);\r
- bool Get(const std::string&, int64_t*);\r
- bool Get(const std::string&, int64_t&);\r
- bool Get(const std::string&, float*);\r
- bool Get(const std::string&, float&);\r
- bool Get(const std::string&, double*);\r
- bool Get(const std::string&, double&);\r
- bool Get(const std::string&, IBPP::Timestamp&);\r
- bool Get(const std::string&, IBPP::Date&);\r
- bool Get(const std::string&, IBPP::Time&);\r
- bool Get(const std::string&, IBPP::DBKey&);\r
- bool Get(const std::string&, IBPP::Blob&);\r
- bool Get(const std::string&, IBPP::Array&);\r
-\r
- int ColumnNum(const std::string&);\r
- int ColumnNumAlias(const std::string&);\r
- const char* ColumnName(int);\r
- const char* ColumnAlias(int);\r
- const char* ColumnTable(int);\r
- IBPP::SDT ColumnType(int);\r
- int ColumnSubtype(int);\r
- int ColumnSize(int);\r
- int ColumnScale(int);\r
- int Columns();\r
-\r
- IBPP::SDT ParameterType(int);\r
- int ParameterSubtype(int);\r
- int ParameterSize(int);\r
- int ParameterScale(int);\r
- int Parameters();\r
-\r
- void Plan(std::string&);\r
-\r
- IBPP::Database DatabasePtr() const;\r
- IBPP::Transaction TransactionPtr() const;\r
-\r
- IBPP::IStatement* AddRef();\r
- void Release();\r
-};\r
-\r
-class BlobImpl : public IBPP::IBlob\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- friend class RowImpl;\r
-\r
- int mRefCount;\r
- bool mIdAssigned;\r
- ISC_QUAD mId;\r
- isc_blob_handle mHandle;\r
- bool mWriteMode;\r
- DatabaseImpl* mDatabase; // Belongs to this database\r
- TransactionImpl* mTransaction; // Belongs to this transaction\r
-\r
- void Init();\r
- void SetId(ISC_QUAD*);\r
- void GetId(ISC_QUAD*);\r
-\r
-public:\r
- void AttachDatabaseImpl(DatabaseImpl*);\r
- void DetachDatabaseImpl();\r
- void AttachTransactionImpl(TransactionImpl*);\r
- void DetachTransactionImpl();\r
-\r
- BlobImpl(const BlobImpl&);\r
- BlobImpl(DatabaseImpl*, TransactionImpl* = 0);\r
- ~BlobImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void Create();\r
- void Open();\r
- void Close();\r
- void Cancel();\r
- int Read(void*, int size);\r
- void Write(const void*, int size);\r
- void Info(int* Size, int* Largest, int* Segments);\r
-\r
- void Save(const std::string& data);\r
- void Load(std::string& data);\r
-\r
- IBPP::Database DatabasePtr() const;\r
- IBPP::Transaction TransactionPtr() const;\r
-\r
- IBPP::IBlob* AddRef();\r
- void Release();\r
-};\r
-\r
-class ArrayImpl : public IBPP::IArray\r
-{\r
- // (((((((( OBJECT INTERNALS ))))))))\r
-\r
-private:\r
- friend class RowImpl;\r
-\r
- int mRefCount; // Reference counter\r
- bool mIdAssigned;\r
- ISC_QUAD mId;\r
- bool mDescribed;\r
- ISC_ARRAY_DESC mDesc;\r
- DatabaseImpl* mDatabase; // Database attachée\r
- TransactionImpl* mTransaction; // Transaction attachée\r
- void* mBuffer; // Buffer for native data\r
- int mBufferSize; // Size of this buffer in bytes\r
- int mElemCount; // Count of elements in this array\r
- int mElemSize; // Size of an element in the buffer\r
-\r
- void Init();\r
- void SetId(ISC_QUAD*);\r
- void GetId(ISC_QUAD*);\r
- void ResetId();\r
- void AllocArrayBuffer();\r
-\r
-public:\r
- void AttachDatabaseImpl(DatabaseImpl*);\r
- void DetachDatabaseImpl();\r
- void AttachTransactionImpl(TransactionImpl*);\r
- void DetachTransactionImpl();\r
-\r
- ArrayImpl(const ArrayImpl&);\r
- ArrayImpl(DatabaseImpl*, TransactionImpl* = 0);\r
- ~ArrayImpl();\r
-\r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void Describe(const std::string& table, const std::string& column);\r
- void ReadTo(IBPP::ADT, void*, int);\r
- void WriteFrom(IBPP::ADT, const void*, int);\r
- IBPP::SDT ElementType();\r
- int ElementSize();\r
- int ElementScale();\r
- int Dimensions();\r
- void Bounds(int dim, int* low, int* high);\r
- void SetBounds(int dim, int low, int high);\r
-\r
- IBPP::Database DatabasePtr() const;\r
- IBPP::Transaction TransactionPtr() const;\r
-\r
- IBPP::IArray* AddRef();\r
- void Release();\r
-};\r
-\r
-//\r
-// EventBufferIterator: used in EventsImpl implementation.\r
-//\r
-\r
-template<class It>\r
-struct EventBufferIterator\r
-{\r
- It mIt;\r
-\r
-public:\r
- EventBufferIterator& operator++()\r
- { mIt += 1 + static_cast<int>(*mIt) + 4; return *this; }\r
-\r
- bool operator == (const EventBufferIterator& i) const { return i.mIt == mIt; }\r
- bool operator != (const EventBufferIterator& i) const { return i.mIt != mIt; }\r
-\r
-#ifdef __BCPLUSPLUS__\r
-#pragma warn -8027\r
-#endif\r
- std::string get_name() const\r
- {\r
- return std::string(mIt + 1, mIt + 1 + static_cast<int32_t>(*mIt));\r
- }\r
-#ifdef __BCPLUSPLUS__\r
-#pragma warn .8027\r
-#endif\r
-\r
- uint32_t get_count() const\r
- {\r
- return (*gds.Call()->m_vax_integer)\r
- (const_cast<char*>(&*(mIt + 1 + static_cast<int>(*mIt))), 4);\r
- }\r
-\r
- // Those container like begin() and end() allow access to the underlying type\r
- It begin() { return mIt; }\r
- It end() { return mIt + 1 + static_cast<int>(*mIt) + 4; }\r
-\r
- EventBufferIterator() {}\r
- EventBufferIterator(It it) : mIt(it) {}\r
-};\r
-\r
-class EventsImpl : public IBPP::IEvents\r
-{\r
- static const size_t MAXEVENTNAMELEN;\r
- static void EventHandler(const char*, short, const char*);\r
-\r
- typedef std::vector<IBPP::EventInterface*> ObjRefs;\r
- ObjRefs mObjectReferences;\r
-\r
- typedef std::vector<char> Buffer;\r
- Buffer mEventBuffer;\r
- Buffer mResultsBuffer;\r
-\r
- int mRefCount; // Reference counter\r
-\r
- DatabaseImpl* mDatabase;\r
- ISC_LONG mId; // Firebird internal Id of these events\r
- bool mQueued; // Has isc_que_events() been called?\r
- bool mTrapped; // EventHandled() was called since last que_events()\r
-\r
- void FireActions();\r
- void Queue();\r
- void Cancel();\r
-\r
- EventsImpl& operator=(const EventsImpl&);\r
- EventsImpl(const EventsImpl&);\r
-\r
-public:\r
- void AttachDatabaseImpl(DatabaseImpl*);\r
- void DetachDatabaseImpl();\r
- \r
- EventsImpl(DatabaseImpl* dbi);\r
- ~EventsImpl();\r
- \r
- // (((((((( OBJECT INTERFACE ))))))))\r
-\r
-public:\r
- void Add(const std::string&, IBPP::EventInterface*);\r
- void Drop(const std::string&);\r
- void List(std::vector<std::string>&);\r
- void Clear(); // Drop all events\r
- void Dispatch(); // Dispatch NON async events\r
-\r
- IBPP::Database DatabasePtr() const;\r
-\r
- IBPP::IEvents* AddRef();\r
- void Release();\r
-};\r
-\r
-void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt);\r
-void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt);\r
-\r
-void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm);\r
-void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm);\r
-\r
-void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts);\r
-void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts);\r
-\r
-struct consts // See _ibpp.cpp for initializations of these constants\r
-{\r
- static const double dscales[19];\r
- static const int Dec31_1899;\r
- static const int16_t min16;\r
- static const int16_t max16;\r
- static const int32_t min32;\r
- static const int32_t max32;\r
-};\r
-\r
-} // namespace ibpp_internal\r
-\r
-#endif // __INTERNAL_IBPP_H__\r
-\r
-//\r
-// Eof\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _ibs.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
-// Subject : IBPP, internal Status class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-int IBS::SqlCode() const\r
-{\r
- return (int)(*gds.Call()->m_sqlcode)(&mVector[0]);\r
-}\r
-\r
-const char* IBS::ErrorMessage() const\r
-{\r
- char msg[1024];\r
- ISC_LONG sqlcode;\r
-\r
- if (! mMessage.empty()) return mMessage.c_str(); // If message compiled, returns it\r
-\r
- // Compiles the message (SQL part)\r
- std::ostringstream message;\r
- sqlcode = (*gds.Call()->m_sqlcode)(mVector);\r
- if (sqlcode != -999)\r
- {\r
- (*gds.Call()->m_sql_interprete)((short)sqlcode, msg, sizeof(msg));\r
- message<< _("SQL Message : ")<< sqlcode<< "\n"<< msg<< "\n\n";\r
- }\r
-\r
- message<< _("Engine Code : ")<< EngineCode()<< "\n";\r
-\r
- // Compiles the message (Engine part)\r
- ISC_STATUS* error = &mVector[0];\r
- try { (*gds.Call()->m_interprete)(msg, &error); }\r
- catch(...) { msg[0] = '\0'; }\r
- message<< _("Engine Message :")<< "\n"<< msg;\r
- try\r
- {\r
- while ((*gds.Call()->m_interprete)(msg, &error))\r
- message<< "\n"<< msg;\r
- }\r
- catch (...) { }\r
-\r
- message<< "\n";\r
- mMessage = message.str();\r
- return mMessage.c_str();\r
-}\r
-\r
-void IBS::Reset()\r
-{\r
- for (int i = 0; i < 20; i++) mVector[i] = 0;\r
- mMessage.erase();\r
-}\r
-\r
-IBS::IBS()\r
-{\r
- Reset();\r
-}\r
-\r
-IBS::~IBS()\r
-{\r
-}\r
-\r
-/** Copy Constructor\r
-*/\r
-\r
-IBS::IBS(IBS& copied)\r
-{\r
- memcpy(mVector, copied.mVector, sizeof(mVector));\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _rb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
-// Subject : IBPP, internal RB class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * RB == Result Block/Buffer, see Interbase 6.0 C-API\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-char* RB::FindToken(char token)\r
-{\r
- char* p = mBuffer;\r
-\r
- while (*p != isc_info_end)\r
- {\r
- int len;\r
-\r
- if (*p == token) return p;\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- p += (len + 3);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-char* RB::FindToken(char token, char subtoken)\r
-{\r
- char* p = mBuffer;\r
-\r
- while (*p != isc_info_end)\r
- {\r
- int len;\r
-\r
- if (*p == token)\r
- {\r
- // Found token, now find subtoken\r
- int inlen = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- p += 3;\r
- while (inlen > 0)\r
- {\r
- if (*p == subtoken) return p;\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- p += (len + 3);\r
- inlen -= (len + 3);\r
- }\r
- return 0;\r
- }\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- p += (len + 3);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-int RB::GetValue(char token)\r
-{\r
- int value;\r
- int len;\r
- char* p = FindToken(token);\r
-\r
- if (p == 0)\r
- throw LogicExceptionImpl("RB::GetValue", _("Token not found."));\r
-\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- if (len == 0) value = 0;\r
- else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
-\r
- return value;\r
-}\r
-\r
-int RB::GetCountValue(char token)\r
-{\r
- // Specifically used on tokens like isc_info_insert_count and the like\r
- // which return detailed counts per relation. We sum up the values.\r
- int value;\r
- int len;\r
- char* p = FindToken(token);\r
-\r
- if (p == 0)\r
- throw LogicExceptionImpl("RB::GetCountValue", _("Token not found."));\r
-\r
- // len is the number of bytes in the following array\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- p += 3;\r
- value = 0;\r
- while (len > 0)\r
- {\r
- // Each array item is 6 bytes : 2 bytes for the relation_id which\r
- // we skip, and 4 bytes for the count value which we sum up accross\r
- // all tables.\r
- value += (*gds.Call()->m_vax_integer)(p+2, 4);\r
- p += 6;\r
- len -= 6;\r
- }\r
-\r
- return value;\r
-}\r
-\r
-int RB::GetValue(char token, char subtoken)\r
-{\r
- int value;\r
- int len;\r
- char* p = FindToken(token, subtoken);\r
-\r
- if (p == 0)\r
- throw LogicExceptionImpl("RB::GetValue", _("Token/Subtoken not found."));\r
-\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- if (len == 0) value = 0;\r
- else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
-\r
- return value;\r
-}\r
-\r
-bool RB::GetBool(char token)\r
-{\r
- int value;\r
- char* p = FindToken(token);\r
-\r
- if (p == 0)\r
- throw LogicExceptionImpl("RB::GetBool", _("Token not found."));\r
-\r
- value = (*gds.Call()->m_vax_integer)(p+1, 4);\r
-\r
- return value == 0 ? false : true;\r
-}\r
-\r
-int RB::GetString(char token, std::string& data)\r
-{\r
- int len;\r
- char* p = FindToken(token);\r
-\r
- if (p == 0)\r
- throw LogicExceptionImpl("RB::GetString", _("Token not found."));\r
-\r
- len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
- data = std::string(p+3, len);\r
- return len;\r
-}\r
-\r
-void RB::Reset()\r
-{\r
- delete [] mBuffer;\r
- mBuffer = new char [mSize];\r
- memset(mBuffer, 255, mSize);\r
-}\r
-\r
-RB::RB()\r
-{\r
- mSize = 1024;\r
- mBuffer = new char [1024];\r
- memset(mBuffer, 255, mSize);\r
-}\r
-\r
-RB::RB(int Size)\r
-{\r
- mSize = Size;\r
- mBuffer = new char [Size];\r
- memset(mBuffer, 255, mSize);\r
-}\r
-\r
-RB::~RB()\r
-{\r
- try { delete [] mBuffer; }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _spb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
-// Subject : IBPP, internal SPB class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * SPB == Service Parameter Block/Buffer, see Interbase 6.0 C-API\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-const int SPB::BUFFERINCR = 128;\r
-\r
-void SPB::Grow(int needed)\r
-{\r
- if ((mSize + needed) > mAlloc)\r
- {\r
- // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
- needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
- char* newbuffer = new char[mAlloc + needed];\r
- if (mBuffer != 0)\r
- {\r
- // Move the old buffer content to the new one\r
- memcpy(newbuffer, mBuffer, mSize);\r
- delete [] mBuffer;\r
- }\r
- mBuffer = newbuffer;\r
- mAlloc += needed;\r
- }\r
-}\r
-\r
-void SPB::Insert(char opcode)\r
-{\r
- Grow(1);\r
- mBuffer[mSize++] = opcode;\r
-}\r
-\r
-void SPB::InsertString(char type, int lenwidth, const char* data)\r
-{\r
- int16_t len = (int16_t)strlen(data);\r
-\r
- Grow(1 + lenwidth + len);\r
- mBuffer[mSize++] = type;\r
- switch (lenwidth)\r
- {\r
- case 1 : mBuffer[mSize] = char(len); mSize++; break;\r
- case 2 : *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&len, 2));\r
- mSize += 2; break;\r
- default : throw LogicExceptionImpl("IISPB::IISPB", _("Invalid length parameter"));\r
- }\r
- strncpy(&mBuffer[mSize], data, len);\r
- mSize += len;\r
-}\r
-\r
-void SPB::InsertByte(char type, char data)\r
-{\r
- Grow(1 + 1);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = data;\r
-}\r
-\r
-void SPB::InsertQuad(char type, int32_t data)\r
-{\r
- Grow(1 + 4);\r
- mBuffer[mSize++] = type;\r
- *(int32_t*)&mBuffer[mSize] = int32_t((*gds.Call()->m_vax_integer)((char*)&data, 4));\r
- mSize += 4;\r
-}\r
-\r
-void SPB::Reset()\r
-{\r
- if (mBuffer != 0)\r
- {\r
- delete [] mBuffer;\r
- mBuffer = 0;\r
- mSize = 0;\r
- mAlloc = 0;\r
- }\r
-}\r
-\r
-/*\r
-void SPB::Insert(char type, short data)\r
-{\r
- Grow(1 + 3);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(2);\r
- *(short*)&mBuffer[mSize] = data;\r
- mSize += 2;\r
-}\r
-\r
-void SPB::Insert(char type, bool data)\r
-{\r
- Grow(1 + 2);\r
- mBuffer[mSize++] = type;\r
- mBuffer[mSize++] = char(1);\r
- mBuffer[mSize++] = char(data ? 1 : 0);\r
-}\r
-*/\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: _tpb.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, internal TPB class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * TPB == Transaction Parameter Block/Buffer, see Interbase 6.0 C-API\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-const int TPB::BUFFERINCR = 128;\r
-\r
-void TPB::Grow(int needed)\r
-{\r
- if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
- if ((mSize + needed) > mAlloc)\r
- {\r
- // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
- needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
- char* newbuffer = new char[mAlloc + needed];\r
- if (mBuffer == 0)\r
- {\r
- // Initial allocation, initialize the version tag\r
- newbuffer[0] = isc_tpb_version3;\r
- mSize = 1;\r
- }\r
- else\r
- {\r
- // Move the old buffer content to the new one\r
- memcpy(newbuffer, mBuffer, mSize);\r
- delete [] mBuffer;\r
- }\r
- mBuffer = newbuffer;\r
- mAlloc += needed;\r
- }\r
-}\r
-\r
-void TPB::Insert(char item)\r
-{\r
- Grow(1);\r
- mBuffer[mSize++] = item;\r
-}\r
-\r
-void TPB::Insert(const std::string& data)\r
-{\r
- int len = (int)data.length();\r
- Grow(1 + len);\r
- mBuffer[mSize++] = (char)len;\r
- strncpy(&mBuffer[mSize], data.c_str(), len);\r
- mSize += len;\r
-}\r
-\r
-void TPB::Reset()\r
-{\r
- if (mSize != 0)\r
- {\r
- delete [] mBuffer;\r
- mBuffer = 0;\r
- mSize = 0;\r
- mAlloc = 0;\r
- }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: all_in_one.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : "All In One" source code file\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-// * This file is just an "all in one" holder for all the core source files\r
-// of IBPP. When you build a project made of each individual source code\r
-// files, please DON'T include this one.\r
-// Though if you prefer, maybe for better compiler optimizations, you can\r
-// compile all of IBPP at once by just compiling this single .cpp file,\r
-// which in turn, includes all the others. Presenting such a single\r
-// compilation unit to the compiler may help it do better optimizations.\r
-// This is just provided for convenience and is in no case required.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#include "_ibpp.cpp"\r
-#include "_dpb.cpp"\r
-#include "_ibs.cpp"\r
-#include "_rb.cpp"\r
-#include "_spb.cpp"\r
-#include "_tpb.cpp"\r
-\r
-#include "array.cpp"\r
-#include "blob.cpp"\r
-#include "database.cpp"\r
-#include "date.cpp"\r
-#include "dbkey.cpp"\r
-#include "events.cpp"\r
-#include "exception.cpp"\r
-#include "row.cpp"\r
-#include "service.cpp"\r
-#include "statement.cpp"\r
-#include "time.cpp"\r
-#include "transaction.cpp"\r
-#include "user.cpp"\r
-\r
-// Eof\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: array.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Array class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <math.h>\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void ArrayImpl::Describe(const std::string& table, const std::string& column)\r
-{\r
- //if (mIdAssigned)\r
- // throw LogicExceptionImpl("Array::Lookup", _("Array already in use."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Array::Lookup", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Array::Lookup", _("No Transaction is attached."));\r
-\r
- ResetId(); // Re-use this array object if was previously assigned\r
-\r
- IBS status;\r
- (*gds.Call()->m_array_lookup_bounds)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), const_cast<char*>(table.c_str()),\r
- const_cast<char*>(column.c_str()), &mDesc);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Array::Lookup",\r
- _("isc_array_lookup_bounds failed."));\r
-\r
- AllocArrayBuffer();\r
-\r
- mDescribed = true;\r
-}\r
-\r
-void ArrayImpl::SetBounds(int dim, int low, int high)\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::SetBounds", _("Array description not set."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Array::SetBounds", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Array::SetBounds", _("No Transaction is attached."));\r
- if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
- throw LogicExceptionImpl("Array::SetBounds", _("Invalid dimension."));\r
- if (low > high ||\r
- low < mDesc.array_desc_bounds[dim].array_bound_lower ||\r
- low > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
- high > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
- high < mDesc.array_desc_bounds[dim].array_bound_lower)\r
- throw LogicExceptionImpl("Array::SetBounds",\r
- _("Invalid bounds. You can only narrow the bounds."));\r
-\r
- mDesc.array_desc_bounds[dim].array_bound_lower = short(low);\r
- mDesc.array_desc_bounds[dim].array_bound_upper = short(high);\r
-\r
- AllocArrayBuffer();\r
-}\r
-\r
-IBPP::SDT ArrayImpl::ElementType()\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::ElementType",\r
- _("Array description not set."));\r
-\r
- IBPP::SDT value;\r
- switch (mDesc.array_desc_dtype)\r
- {\r
- case blr_text : value = IBPP::sdString; break;\r
- case blr_varying : value = IBPP::sdString; break;\r
- case blr_cstring : value = IBPP::sdString; break;\r
- case blr_short : value = IBPP::sdSmallint; break;\r
- case blr_long : value = IBPP::sdInteger; break;\r
- case blr_int64 : value = IBPP::sdLargeint; break;\r
- case blr_float : value = IBPP::sdFloat; break;\r
- case blr_double : value = IBPP::sdDouble; break;\r
- case blr_timestamp : value = IBPP::sdTimestamp; break;\r
- case blr_sql_date : value = IBPP::sdDate; break;\r
- case blr_sql_time : value = IBPP::sdTime; break;\r
- default : throw LogicExceptionImpl("Array::ElementType",\r
- _("Found an unknown sqltype !"));\r
- }\r
-\r
- return value;\r
-}\r
-\r
-int ArrayImpl::ElementSize()\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::ElementSize",\r
- _("Array description not set."));\r
-\r
- return mDesc.array_desc_length;\r
-}\r
-\r
-int ArrayImpl::ElementScale()\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::ElementScale",\r
- _("Array description not set."));\r
-\r
- return mDesc.array_desc_scale;\r
-}\r
-\r
-int ArrayImpl::Dimensions()\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::Dimensions",\r
- _("Array description not set."));\r
-\r
- return mDesc.array_desc_dimensions;\r
-}\r
-\r
-void ArrayImpl::Bounds(int dim, int* low, int* high)\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::Bounds", _("Array description not set."));\r
- if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
- throw LogicExceptionImpl("Array::Bounds", _("Invalid dimension."));\r
- if (low == 0 || high == 0)\r
- throw LogicExceptionImpl("Array::Bounds", _("Null reference detected."));\r
-\r
- *low = mDesc.array_desc_bounds[dim].array_bound_lower;\r
- *high = mDesc.array_desc_bounds[dim].array_bound_upper;\r
-}\r
-\r
-/*\r
-\r
-COMMENTS\r
-\r
-1)\r
-For an array column of type CHAR(X), the internal type returned or expected is blr_text.\r
-In such case, the byte array received or submitted to get/put_slice is formatted in\r
-elements of X bytes, which correspond to what is reported in array_desc_length.\r
-The elements are not '\0' terminated but are right-padded with spaces ' '.\r
-\r
-2)\r
-For an array column of type VARCHAR(X), the internal type is blr_varying.\r
-The underlying format is rather curious and different than what is used in XSQLDA.\r
-The element size is reported in array_desc_length as X.\r
-Yet each element of the byte array is expected to be of size X+2 (just as if we were\r
-to stuff a short in the first 2 bytes to store the length (as is done with XSQLDA).\r
-No. The string of X characters maximum has to be stored in the chunks of X+2 bytes as\r
-a zero-terminated c-string. Note that the buffer is indeed one byte too large.\r
-Internally, the API probably convert in-place in these chunks the zero-terminated string\r
-to a variable-size string with a short in front and the string data non zero-terminated\r
-behind.\r
-\r
-3)\r
-With Interbase 6.0 and Firebird 1.0 (initial april 2002 release), the int64 support is\r
-broken regarding the arrays. It is not possible to work on arrays using a datatype stored\r
-in an int64, as for instance any NUMERIC(x,0) where x is equal or greater than 10. That's\r
-a bug in the engine, not in IBPP, which has been fixed in june 2002. Engines compiled from\r
-the current Firebird CVS code as of july 2002 are okay. As will be the 1.01 Firebird version.\r
-We have no idea if this is fixed or not in Interbase 6.5 though.\r
-\r
-*/\r
-\r
-void ArrayImpl::ReadTo(IBPP::ADT adtype, void* data, int datacount)\r
-{\r
- if (! mIdAssigned)\r
- throw LogicExceptionImpl("Array::ReadTo", _("Array Id not read from column."));\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::ReadTo", _("Array description not set."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Array::ReadTo", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Array::ReadTo", _("No Transaction is attached."));\r
- if (datacount != mElemCount)\r
- throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
-\r
- IBS status;\r
- ISC_LONG lenbuf = mBufferSize;\r
- (*gds.Call()->m_array_get_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Array::ReadTo", _("isc_array_get_slice failed."));\r
- if (lenbuf != mBufferSize)\r
- throw SQLExceptionImpl(status, "Array::ReadTo", _("Internal buffer size discrepancy."));\r
-\r
- // Now, convert the types and copy values to the user array...\r
- int len;\r
- char* src = (char*)mBuffer;\r
- char* dst = (char*)data;\r
-\r
- switch (mDesc.array_desc_dtype)\r
- {\r
- case blr_text :\r
- if (adtype == IBPP::adString)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- strncpy(dst, src, mElemSize);\r
- dst[mElemSize] = '\0';\r
- src += mElemSize;\r
- dst += (mElemSize + 1);\r
- }\r
- }\r
- else if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
- *(bool*)dst = true;\r
- else *(bool*)dst = false;\r
- src += mElemSize;\r
- dst += sizeof(bool);\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- break;\r
-\r
- case blr_varying :\r
- if (adtype == IBPP::adString)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- len = (int)strlen(src);\r
- if (len > mElemSize-2) len = mElemSize-2;\r
- strncpy(dst, src, len);\r
- dst[len] = '\0';\r
- src += mElemSize;\r
- dst += (mElemSize - 2 + 1);\r
- }\r
- }\r
- else if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
- *(bool*)dst = true;\r
- else *(bool*)dst = false;\r
- src += mElemSize;\r
- dst += sizeof(bool);\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- break;\r
-\r
- case blr_short :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(bool*)dst = (*(short*)src != 0) ? true : false;\r
- src += mElemSize;\r
- dst += sizeof(bool);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst = *(short*)src;\r
- src += mElemSize;\r
- dst += sizeof(short);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int*)dst = (int)*(short*)src;\r
- src += mElemSize;\r
- dst += sizeof(int);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = (int64_t)*(short*)src;\r
- src += mElemSize;\r
- dst += sizeof(int64_t);\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(float*)dst = (float)(*(short*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(float);\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = (double)(*(short*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(double);\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- break;\r
-\r
- case blr_long :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(bool*)dst = (*(long*)src != 0) ? true : false;\r
- src += mElemSize;\r
- dst += sizeof(bool);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
- throw LogicExceptionImpl("Array::ReadTo",\r
- _("Out of range numeric conversion !"));\r
- *(short*)dst = short(*(long*)src);\r
- src += mElemSize;\r
- dst += sizeof(short);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst = *(long*)src;\r
- src += mElemSize;\r
- dst += sizeof(long);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = (int64_t)*(long*)src;\r
- src += mElemSize;\r
- dst += sizeof(int64_t);\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(float*)dst = (float)(*(long*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(float);\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = (double)(*(long*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(double);\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- break;\r
-\r
- case blr_int64 :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(bool*)dst = (*(int64_t*)src != 0) ? true : false;\r
- src += mElemSize;\r
- dst += sizeof(bool);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
- throw LogicExceptionImpl("Array::ReadTo",\r
- _("Out of range numeric conversion !"));\r
- *(short*)dst = short(*(int64_t*)src);\r
- src += mElemSize;\r
- dst += sizeof(short);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
- throw LogicExceptionImpl("Array::ReadTo",\r
- _("Out of range numeric conversion !"));\r
- *(long*)dst = (long)*(int64_t*)src;\r
- src += mElemSize;\r
- dst += sizeof(long);\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = *(int64_t*)src;\r
- src += mElemSize;\r
- dst += sizeof(int64_t);\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(float*)dst = (float)(*(int64_t*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(float);\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = (double)(*(int64_t*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(double);\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- break;\r
-\r
- case blr_float :\r
- if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
- throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(float*)dst = *(float*)src;\r
- src += mElemSize;\r
- dst += sizeof(float);\r
- }\r
- break;\r
-\r
- case blr_double :\r
- if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- if (mDesc.array_desc_scale != 0)\r
- {\r
- // Round to scale of NUMERIC(x,y)\r
- double divisor = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = (double)(*(double*)src / divisor);\r
- src += mElemSize;\r
- dst += sizeof(double);\r
- }\r
- }\r
- else\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = *(double*)src;\r
- src += mElemSize;\r
- dst += sizeof(double);\r
- }\r
- }\r
- break;\r
-\r
- case blr_timestamp :\r
- if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- decodeTimestamp(*(IBPP::Timestamp*)dst, *(ISC_TIMESTAMP*)src);\r
- src += mElemSize;\r
- dst += sizeof(IBPP::Timestamp);\r
- }\r
- break;\r
-\r
- case blr_sql_date :\r
- if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- decodeDate(*(IBPP::Date*)dst, *(ISC_DATE*)src);\r
- src += mElemSize;\r
- dst += sizeof(IBPP::Date);\r
- }\r
- break;\r
-\r
- case blr_sql_time :\r
- if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- decodeTime(*(IBPP::Time*)dst, *(ISC_TIME*)src);\r
- src += mElemSize;\r
- dst += sizeof(IBPP::Time);\r
- }\r
- break;\r
-\r
- default :\r
- throw LogicExceptionImpl("Array::ReadTo", _("Unknown sql type."));\r
- }\r
-}\r
-\r
-void ArrayImpl::WriteFrom(IBPP::ADT adtype, const void* data, int datacount)\r
-{\r
- if (! mDescribed)\r
- throw LogicExceptionImpl("Array::WriteFrom", _("Array description not set."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Array::WriteFrom", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Array::WriteFrom", _("No Transaction is attached."));\r
- if (datacount != mElemCount)\r
- throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
-\r
- // Read user data and convert types to the mBuffer\r
- int len;\r
- char* src = (char*)data;\r
- char* dst = (char*)mBuffer;\r
-\r
- switch (mDesc.array_desc_dtype)\r
- {\r
- case blr_text :\r
- if (adtype == IBPP::adString)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- len = (int)strlen(src);\r
- if (len > mElemSize) len = mElemSize;\r
- strncpy(dst, src, len);\r
- while (len < mElemSize) dst[len++] = ' ';\r
- src += (mElemSize + 1);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *dst = *(bool*)src ? 'T' : 'F';\r
- len = 1;\r
- while (len < mElemSize) dst[len++] = ' ';\r
- src += sizeof(bool);\r
- dst += mElemSize;\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
- break;\r
-\r
- case blr_varying :\r
- if (adtype == IBPP::adString)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- len = (int)strlen(src);\r
- if (len > mElemSize-2) len = mElemSize-2;\r
- strncpy(dst, src, len);\r
- dst[len] = '\0';\r
- src += (mElemSize - 2 + 1);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst = (short)1;\r
- dst[2] = *(bool*)src ? 'T' : 'F';\r
- src += sizeof(bool);\r
- dst += mElemSize;\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
- break;\r
-\r
- case blr_short :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst = short(*(bool*)src ? 1 : 0);\r
- src += sizeof(bool);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst = *(short*)src;\r
- src += sizeof(short);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
- throw LogicExceptionImpl("Array::WriteFrom",\r
- _("Out of range numeric conversion !"));\r
- *(short*)dst = (short)*(int*)src;\r
- src += sizeof(int);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
- throw LogicExceptionImpl("Array::WriteFrom",\r
- _("Out of range numeric conversion !"));\r
- *(short*)dst = (short)*(int64_t*)src;\r
- src += sizeof(int64_t);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst =\r
- (short)floor(*(float*)src * multiplier + 0.5);\r
- src += sizeof(float);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(short*)dst =\r
- (short)floor(*(double*)src * multiplier + 0.5);\r
- src += sizeof(double);\r
- dst += mElemSize;\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
- break;\r
-\r
- case blr_long :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst = *(bool*)src ? 1 : 0;\r
- src += sizeof(bool);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst = *(short*)src;\r
- src += sizeof(short);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst = *(long*)src;\r
- src += sizeof(long);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
- throw LogicExceptionImpl("Array::WriteFrom",\r
- _("Out of range numeric conversion !"));\r
- *(long*)dst = (long)*(int64_t*)src;\r
- src += sizeof(int64_t);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_INT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst =\r
- (long)floor(*(float*)src * multiplier + 0.5);\r
- src += sizeof(float);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_INT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(long*)dst =\r
- (long)floor(*(double*)src * multiplier + 0.5);\r
- src += sizeof(double);\r
- dst += mElemSize;\r
- }\r
- }\r
- else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
- break;\r
-\r
- case blr_int64 :\r
- if (adtype == IBPP::adBool)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = *(bool*)src ? 1 : 0;\r
- src += sizeof(bool);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt16)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = *(short*)src;\r
- src += sizeof(short);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt32)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = *(long*)src;\r
- src += sizeof(long);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adInt64)\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst = *(int64_t*)src;\r
- src += sizeof(int64_t);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adFloat)\r
- {\r
- // This SQL_INT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst =\r
- (int64_t)floor(*(float*)src * multiplier + 0.5);\r
- src += sizeof(float);\r
- dst += mElemSize;\r
- }\r
- }\r
- else if (adtype == IBPP::adDouble)\r
- {\r
- // This SQL_INT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(int64_t*)dst =\r
- (int64_t)floor(*(double*)src * multiplier + 0.5);\r
- src += sizeof(double);\r
- dst += mElemSize;\r
- }\r
- }\r
- else\r
- throw LogicExceptionImpl("Array::WriteFrom",\r
- _("Incompatible types (blr_int64 and ADT %d)."), (int)adtype);\r
- break;\r
-\r
- case blr_float :\r
- if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
- throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(float*)dst = *(float*)src;\r
- src += sizeof(float);\r
- dst += mElemSize;\r
- }\r
- break;\r
-\r
- case blr_double :\r
- if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::WriteFrom",\r
- _("Incompatible types."));\r
- if (mDesc.array_desc_scale != 0)\r
- {\r
- // Round to scale of NUMERIC(x,y)\r
- double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst =\r
- floor(*(double*)src * multiplier + 0.5) / multiplier;\r
- src += sizeof(double);\r
- dst += mElemSize;\r
- }\r
- }\r
- else\r
- {\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- *(double*)dst = *(double*)src;\r
- src += sizeof(double);\r
- dst += mElemSize;\r
- }\r
- }\r
- break;\r
-\r
- case blr_timestamp :\r
- if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- encodeTimestamp(*(ISC_TIMESTAMP*)dst, *(IBPP::Timestamp*)src);\r
- src += sizeof(IBPP::Timestamp);\r
- dst += mElemSize;\r
- }\r
- break;\r
-\r
- case blr_sql_date :\r
- if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- encodeDate(*(ISC_DATE*)dst, *(IBPP::Date*)src); \r
- src += sizeof(IBPP::Date);\r
- dst += mElemSize;\r
- }\r
- break;\r
-\r
- case blr_sql_time :\r
- if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
- _("Incompatible types."));\r
- for (int i = 0; i < mElemCount; i++)\r
- {\r
- encodeTime(*(ISC_TIME*)dst, *(IBPP::Time*)src);\r
- src += sizeof(IBPP::Time);\r
- dst += mElemSize;\r
- }\r
- break;\r
-\r
- default :\r
- throw LogicExceptionImpl("Array::WriteFrom", _("Unknown sql type."));\r
- }\r
-\r
- IBS status;\r
- ISC_LONG lenbuf = mBufferSize;\r
- (*gds.Call()->m_array_put_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Array::WriteFrom", _("isc_array_put_slice failed."));\r
- if (lenbuf != mBufferSize)\r
- throw SQLExceptionImpl(status, "Array::WriteFrom", _("Internal buffer size discrepancy."));\r
-}\r
-\r
-IBPP::Database ArrayImpl::DatabasePtr() const\r
-{\r
- if (mDatabase == 0) throw LogicExceptionImpl("Array::DatabasePtr",\r
- _("No Database is attached."));\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction ArrayImpl::TransactionPtr() const\r
-{\r
- if (mTransaction == 0) throw LogicExceptionImpl("Array::TransactionPtr",\r
- _("No Transaction is attached."));\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IArray* ArrayImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void ArrayImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void ArrayImpl::Init()\r
-{\r
- ResetId();\r
- mDescribed = false;\r
- mDatabase = 0;\r
- mTransaction = 0;\r
- mBuffer = 0;\r
- mBufferSize = 0;\r
-}\r
-\r
-void ArrayImpl::SetId(ISC_QUAD* quad)\r
-{\r
- if (quad == 0)\r
- throw LogicExceptionImpl("ArrayImpl::SetId", _("Null Id reference detected."));\r
-\r
- memcpy(&mId, quad, sizeof(mId));\r
- mIdAssigned = true;\r
-}\r
-\r
-void ArrayImpl::GetId(ISC_QUAD* quad)\r
-{\r
- if (quad == 0)\r
- throw LogicExceptionImpl("ArrayImpl::GetId", _("Null Id reference detected."));\r
-\r
- memcpy(quad, &mId, sizeof(mId));\r
-}\r
-\r
-void ArrayImpl::ResetId()\r
-{\r
- memset(&mId, 0, sizeof(mId));\r
- mIdAssigned = false;\r
-}\r
-\r
-void ArrayImpl::AllocArrayBuffer()\r
-{\r
- // Clean previous buffer if any\r
- if (mBuffer != 0) delete [] (char*)mBuffer;\r
- mBuffer = 0;\r
-\r
- // Computes total number of elements in the array or slice\r
- mElemCount = 1;\r
- for (int i = 0; i < mDesc.array_desc_dimensions; i++)\r
- {\r
- mElemCount = mElemCount *\r
- (mDesc.array_desc_bounds[i].array_bound_upper -\r
- mDesc.array_desc_bounds[i].array_bound_lower + 1);\r
- }\r
-\r
- // Allocates a buffer for this count of elements\r
- mElemSize = mDesc.array_desc_length;\r
- if (mDesc.array_desc_dtype == blr_varying) mElemSize += 2;\r
- else if (mDesc.array_desc_dtype == blr_cstring) mElemSize += 1;\r
- mBufferSize = mElemSize * mElemCount;\r
- mBuffer = (void*) new char[mBufferSize];\r
-}\r
-\r
-void ArrayImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
- if (database == 0) throw LogicExceptionImpl("Array::AttachDatabase",\r
- _("Can't attach a 0 Database object."));\r
-\r
- if (mDatabase != 0) mDatabase->DetachArrayImpl(this);\r
- mDatabase = database;\r
- mDatabase->AttachArrayImpl(this);\r
-}\r
-\r
-void ArrayImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
-{\r
- if (transaction == 0) throw LogicExceptionImpl("Array::AttachTransaction",\r
- _("Can't attach a 0 Transaction object."));\r
-\r
- if (mTransaction != 0) mTransaction->DetachArrayImpl(this);\r
- mTransaction = transaction;\r
- mTransaction->AttachArrayImpl(this);\r
-}\r
-\r
-void ArrayImpl::DetachDatabaseImpl()\r
-{\r
- if (mDatabase == 0) return;\r
-\r
- mDatabase->DetachArrayImpl(this);\r
- mDatabase = 0;\r
-}\r
-\r
-void ArrayImpl::DetachTransactionImpl()\r
-{\r
- if (mTransaction == 0) return;\r
-\r
- mTransaction->DetachArrayImpl(this);\r
- mTransaction = 0;\r
-}\r
-\r
-ArrayImpl::ArrayImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
- : mRefCount(0)\r
-{\r
- Init();\r
- AttachDatabaseImpl(database);\r
- if (transaction != 0) AttachTransactionImpl(transaction);\r
-}\r
-\r
-ArrayImpl::~ArrayImpl()\r
-{\r
- try { if (mTransaction != 0) mTransaction->DetachArrayImpl(this); }\r
- catch (...) {}\r
- try { if (mDatabase != 0) mDatabase->DetachArrayImpl(this); }\r
- catch (...) {}\r
- try { if (mBuffer != 0) delete [] (char*)mBuffer; }\r
- catch (...) {}\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Blob class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void BlobImpl::Open()\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Open", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Open", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached."));\r
- if (! mIdAssigned)\r
- throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed."));\r
- mWriteMode = false;\r
-}\r
-\r
-void BlobImpl::Create()\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Create", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Create", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Create",\r
- _("isc_create_blob failed."));\r
- mIdAssigned = true;\r
- mWriteMode = true;\r
-}\r
-\r
-void BlobImpl::Close()\r
-{\r
- if (mHandle == 0) return; // Not opened anyway\r
-\r
- IBS status;\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-void BlobImpl::Cancel()\r
-{\r
- if (mHandle == 0) return; // Not opened anyway\r
-\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read"));\r
-\r
- IBS status;\r
- (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed."));\r
- mHandle = 0;\r
- mIdAssigned = false;\r
-}\r
-\r
-int BlobImpl::Read(void* buffer, int size)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened"));\r
- if (mWriteMode)\r
- throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write"));\r
- if (size < 1 || size > (64*1024-1))\r
- throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)"));\r
-\r
- IBS status;\r
- unsigned short bytesread;\r
- ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread,\r
- (unsigned short)size, (char*)buffer);\r
- if (result == isc_segstr_eof) return 0; // Fin du blob\r
- if (result != isc_segment && status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed."));\r
- return (int)bytesread;\r
-}\r
-\r
-void BlobImpl::Write(const void* buffer, int size)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened"));\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read"));\r
- if (size < 1 || size > (64*1024-1))\r
- throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)"));\r
-\r
- IBS status;\r
- (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
- (unsigned short)size, (char*)buffer);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed."));\r
-}\r
-\r
-void BlobImpl::Info(int* Size, int* Largest, int* Segments)\r
-{\r
- char items[] = {isc_info_blob_total_length,\r
- isc_info_blob_max_segment,\r
- isc_info_blob_num_segments};\r
-\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened"));\r
-\r
- IBS status;\r
- RB result(100);\r
- (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items,\r
- (short)result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed."));\r
-\r
- if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length);\r
- if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment);\r
- if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments);\r
-}\r
-\r
-void BlobImpl::Save(const std::string& data)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Save", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Save", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save",\r
- _("isc_create_blob failed."));\r
- mIdAssigned = true;\r
- mWriteMode = true;\r
-\r
- size_t pos = 0;\r
- size_t len = data.size();\r
- while (len != 0)\r
- {\r
- size_t blklen = (len < 32*1024-1) ? len : 32*1024-1;\r
- status.Reset();\r
- (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
- (unsigned short)blklen, const_cast<char*>(data.data()+pos));\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save",\r
- _("isc_put_segment failed."));\r
- pos += blklen;\r
- len -= blklen;\r
- }\r
- \r
- status.Reset();\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-void BlobImpl::Load(std::string& data)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Load", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Load", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached."));\r
- if (! mIdAssigned)\r
- throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed."));\r
- mWriteMode = false;\r
-\r
- size_t blklen = 32*1024-1;\r
- data.resize(blklen);\r
-\r
- size_t size = 0;\r
- size_t pos = 0;\r
- for (;;)\r
- {\r
- status.Reset();\r
- unsigned short bytesread;\r
- ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle,\r
- &bytesread, (unsigned short)blklen,\r
- const_cast<char*>(data.data()+pos));\r
- if (result == isc_segstr_eof) break; // End of blob\r
- if (result != isc_segment && status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed."));\r
-\r
- pos += bytesread;\r
- size += bytesread;\r
- data.resize(size + blklen);\r
- }\r
- data.resize(size);\r
- \r
- status.Reset();\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-IBPP::Database BlobImpl::DatabasePtr() const\r
-{\r
- if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr",\r
- _("No Database is attached."));\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction BlobImpl::TransactionPtr() const\r
-{\r
- if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr",\r
- _("No Transaction is attached."));\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IBlob* BlobImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void BlobImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void BlobImpl::Init()\r
-{\r
- mIdAssigned = false;\r
- mWriteMode = false;\r
- mHandle = 0;\r
- mDatabase = 0;\r
- mTransaction = 0;\r
-}\r
-\r
-void BlobImpl::SetId(ISC_QUAD* quad)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl."));\r
- if (quad == 0)\r
- throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected."));\r
-\r
- memcpy(&mId, quad, sizeof(mId));\r
- mIdAssigned = true;\r
-}\r
-\r
-void BlobImpl::GetId(ISC_QUAD* quad)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl."));\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob."));\r
- if (quad == 0)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected."));\r
-\r
- memcpy(quad, &mId, sizeof(mId));\r
-}\r
-\r
-void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
- if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase",\r
- _("Can't attach a NULL Database object."));\r
-\r
- if (mDatabase != 0) mDatabase->DetachBlobImpl(this);\r
- mDatabase = database;\r
- mDatabase->AttachBlobImpl(this);\r
-}\r
-\r
-void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
-{\r
- if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction",\r
- _("Can't attach a NULL Transaction object."));\r
-\r
- if (mTransaction != 0) mTransaction->DetachBlobImpl(this);\r
- mTransaction = transaction;\r
- mTransaction->AttachBlobImpl(this);\r
-}\r
-\r
-void BlobImpl::DetachDatabaseImpl()\r
-{\r
- if (mDatabase == 0) return;\r
-\r
- mDatabase->DetachBlobImpl(this);\r
- mDatabase = 0;\r
-}\r
-\r
-void BlobImpl::DetachTransactionImpl()\r
-{\r
- if (mTransaction == 0) return;\r
-\r
- mTransaction->DetachBlobImpl(this);\r
- mTransaction = 0;\r
-}\r
-\r
-BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
- : mRefCount(0)\r
-{\r
- Init();\r
- AttachDatabaseImpl(database);\r
- if (transaction != 0) AttachTransactionImpl(transaction);\r
-}\r
-\r
-BlobImpl::~BlobImpl()\r
-{\r
- try\r
- {\r
- if (mHandle != 0)\r
- {\r
- if (mWriteMode) Cancel();\r
- else Close();\r
- }\r
- }\r
- catch (...) { }\r
- \r
- try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); }\r
- catch (...) { }\r
- try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: database.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : IBPP, Database class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <algorithm>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void DatabaseImpl::Create(int dialect)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Database::Create", _("Database is already connected."));\r
- if (mDatabaseName.empty())\r
- throw LogicExceptionImpl("Database::Create", _("Unspecified database name."));\r
- if (mUserName.empty())\r
- throw LogicExceptionImpl("Database::Create", _("Unspecified user name."));\r
- if (dialect != 1 && dialect != 3)\r
- throw LogicExceptionImpl("Database::Create", _("Only dialects 1 and 3 are supported."));\r
-\r
- // Build the SQL Create Statement\r
- std::string create;\r
- create.assign("CREATE DATABASE '");\r
- if (! mServerName.empty()) create.append(mServerName).append(":");\r
- create.append(mDatabaseName).append("' ");\r
-\r
- create.append("USER '").append(mUserName).append("' ");\r
- if (! mUserPassword.empty())\r
- create.append("PASSWORD '").append(mUserPassword).append("' ");\r
-\r
- if (! mCreateParams.empty()) create.append(mCreateParams);\r
-\r
- // Call ExecuteImmediate to create the database\r
- isc_tr_handle tr_handle = 0;\r
- IBS status;\r
- (*gds.Call()->m_dsql_execute_immediate)(status.Self(), &mHandle, &tr_handle,\r
- 0, const_cast<char*>(create.c_str()), short(dialect), NULL);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Database::Create", _("isc_dsql_execute_immediate failed"));\r
-\r
- Disconnect();\r
-}\r
-\r
-void DatabaseImpl::Connect()\r
-{\r
- if (mHandle != 0) return; // Already connected\r
-\r
- if (mDatabaseName.empty())\r
- throw LogicExceptionImpl("Database::Connect", _("Unspecified database name."));\r
- if (mUserName.empty())\r
- throw LogicExceptionImpl("Database::Connect", _("Unspecified user name."));\r
-\r
- // Build a DPB based on the properties\r
- DPB dpb;\r
- dpb.Insert(isc_dpb_user_name, mUserName.c_str());\r
- dpb.Insert(isc_dpb_password, mUserPassword.c_str());\r
- if (! mRoleName.empty()) dpb.Insert(isc_dpb_sql_role_name, mRoleName.c_str());\r
- if (! mCharSet.empty()) dpb.Insert(isc_dpb_lc_ctype, mCharSet.c_str());\r
-\r
- std::string connect;\r
- if (! mServerName.empty())\r
- connect.assign(mServerName).append(":");\r
- connect.append(mDatabaseName);\r
-\r
- IBS status;\r
- (*gds.Call()->m_attach_database)(status.Self(), (short)connect.size(),\r
- const_cast<char*>(connect.c_str()), &mHandle, dpb.Size(), dpb.Self());\r
- if (status.Errors())\r
- {\r
- mHandle = 0; // Should be, but better be sure...\r
- throw SQLExceptionImpl(status, "Database::Connect", _("isc_attach_database failed"));\r
- }\r
-\r
- // Now, get ODS version information and dialect.\r
- // If ODS major is lower of equal to 9, we reject the connection.\r
- // If ODS major is 10 or higher, this is at least an InterBase 6.x Server\r
- // OR FireBird 1.x Server.\r
-\r
- char items[] = {isc_info_ods_version,\r
- isc_info_db_SQL_dialect,\r
- isc_info_end};\r
- RB result(100);\r
-\r
- status.Reset();\r
- (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- {\r
- status.Reset();\r
- (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
- mHandle = 0; // Should be, but better be sure...\r
- throw SQLExceptionImpl(status, "Database::Connect", _("isc_database_info failed"));\r
- }\r
-\r
- int ODS = result.GetValue(isc_info_ods_version);\r
- if (ODS <= 9)\r
- {\r
- status.Reset();\r
- (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
- mHandle = 0; // Should be, but better be sure...\r
- throw LogicExceptionImpl("Database::Connect",\r
- _("Unsupported Server : wrong ODS version (%d), at least '10' required."), ODS);\r
- }\r
-\r
- mDialect = result.GetValue(isc_info_db_SQL_dialect);\r
- if (mDialect != 1 && mDialect != 3)\r
- {\r
- status.Reset();\r
- (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
- mHandle = 0; // Should be, but better be sure...\r
- throw LogicExceptionImpl("Database::Connect", _("Dialect 1 or 3 required"));\r
- }\r
-\r
- // Now, verify the GDS32.DLL we are using is compatible with the server\r
- if (ODS >= 10 && gds.Call()->mGDSVersion < 60)\r
- {\r
- status.Reset();\r
- (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
- mHandle = 0; // Should be, but better be sure...\r
- throw LogicExceptionImpl("Database::Connect", _("GDS32.DLL version 5 against IBSERVER 6"));\r
- }\r
-}\r
-\r
-void DatabaseImpl::Inactivate()\r
-{\r
- if (mHandle == 0) return; // Not connected anyway\r
-\r
- IBS status;\r
-\r
- // Rollback any started transaction...\r
- for (unsigned i = 0; i < mTransactions.size(); i++)\r
- {\r
- if (mTransactions[i]->Started())\r
- mTransactions[i]->Rollback();\r
- }\r
-\r
- // Cancel all pending event traps\r
- for (unsigned i = 0; i < mEvents.size(); i++)\r
- mEvents[i]->Clear();\r
-\r
- // Let's detach from all Blobs\r
- while (mBlobs.size() > 0)\r
- mBlobs.back()->DetachDatabaseImpl();\r
-\r
- // Let's detach from all Arrays\r
- while (mArrays.size() > 0)\r
- mArrays.back()->DetachDatabaseImpl();\r
-\r
- // Let's detach from all Statements\r
- while (mStatements.size() > 0)\r
- mStatements.back()->DetachDatabaseImpl();\r
-\r
- // Let's detach from all Transactions\r
- while (mTransactions.size() > 0)\r
- mTransactions.back()->DetachDatabaseImpl(this);\r
-\r
- // Let's detach from all Events\r
- while (mEvents.size() > 0)\r
- mEvents.back()->DetachDatabaseImpl();\r
-}\r
-\r
-void DatabaseImpl::Disconnect()\r
-{\r
- if (mHandle == 0) return; // Not connected anyway\r
-\r
- // Put the connection to rest\r
- Inactivate();\r
-\r
- // Detach from the server\r
- IBS status;\r
- (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
-\r
- // Should we throw, set mHandle to 0 first, because Disconnect() may\r
- // be called from Database destructor (keeps the object coherent).\r
- mHandle = 0;\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Database::Disconnect", _("isc_detach_database failed"));\r
-}\r
-\r
-void DatabaseImpl::Drop()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Database::Drop", _("Database must be connected."));\r
-\r
- // Put the connection to a rest\r
- Inactivate();\r
-\r
- IBS vector;\r
- (*gds.Call()->m_drop_database)(vector.Self(), &mHandle);\r
- if (vector.Errors())\r
- throw SQLExceptionImpl(vector, "Database::Drop", _("isc_drop_database failed"));\r
-\r
- mHandle = 0;\r
-}\r
-\r
-void DatabaseImpl::Info(int* ODSMajor, int* ODSMinor,\r
- int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
- bool* Sync, bool* Reserve)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Database::Info", _("Database is not connected."));\r
-\r
- char items[] = {isc_info_ods_version,\r
- isc_info_ods_minor_version,\r
- isc_info_page_size,\r
- isc_info_allocation,\r
- isc_info_num_buffers,\r
- isc_info_sweep_interval,\r
- isc_info_forced_writes,\r
- isc_info_no_reserve,\r
- isc_info_end};\r
- IBS status;\r
- RB result(256);\r
-\r
- status.Reset();\r
- (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Database::Info", _("isc_database_info failed"));\r
-\r
- if (ODSMajor != 0) *ODSMajor = result.GetValue(isc_info_ods_version);\r
- if (ODSMinor != 0) *ODSMinor = result.GetValue(isc_info_ods_minor_version);\r
- if (PageSize != 0) *PageSize = result.GetValue(isc_info_page_size);\r
- if (Pages != 0) *Pages = result.GetValue(isc_info_allocation);\r
- if (Buffers != 0) *Buffers = result.GetValue(isc_info_num_buffers);\r
- if (Sweep != 0) *Sweep = result.GetValue(isc_info_sweep_interval);\r
- if (Sync != 0)\r
- *Sync = result.GetValue(isc_info_forced_writes) == 1 ? true : false;\r
- if (Reserve != 0)\r
- *Reserve = result.GetValue(isc_info_no_reserve) == 1 ? false : true;\r
-}\r
-\r
-void DatabaseImpl::Statistics(int* Fetches, int* Marks, int* Reads, int* Writes)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Database::Statistics", _("Database is not connected."));\r
-\r
- char items[] = {isc_info_fetches,\r
- isc_info_marks,\r
- isc_info_reads,\r
- isc_info_writes,\r
- isc_info_end};\r
- IBS status;\r
- RB result(128);\r
-\r
- status.Reset();\r
- (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Database::Statistics", _("isc_database_info failed"));\r
-\r
- if (Fetches != 0) *Fetches = result.GetValue(isc_info_fetches);\r
- if (Marks != 0) *Marks = result.GetValue(isc_info_marks);\r
- if (Reads != 0) *Reads = result.GetValue(isc_info_reads);\r
- if (Writes != 0) *Writes = result.GetValue(isc_info_writes);\r
-}\r
-\r
-void DatabaseImpl::Counts(int* Insert, int* Update, int* Delete, \r
- int* ReadIdx, int* ReadSeq)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Database::Counts", _("Database is not connected."));\r
-\r
- char items[] = {isc_info_insert_count,\r
- isc_info_update_count,\r
- isc_info_delete_count,\r
- isc_info_read_idx_count,\r
- isc_info_read_seq_count,\r
- isc_info_end};\r
- IBS status;\r
- RB result(1024);\r
-\r
- status.Reset();\r
- (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Database::Counts", _("isc_database_info failed"));\r
-\r
- if (Insert != 0) *Insert = result.GetCountValue(isc_info_insert_count);\r
- if (Update != 0) *Update = result.GetCountValue(isc_info_update_count);\r
- if (Delete != 0) *Delete = result.GetCountValue(isc_info_delete_count);\r
- if (ReadIdx != 0) *ReadIdx = result.GetCountValue(isc_info_read_idx_count);\r
- if (ReadSeq != 0) *ReadSeq = result.GetCountValue(isc_info_read_seq_count);\r
-}\r
-\r
-void DatabaseImpl::Users(std::vector<std::string>& users)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Database::Users", _("Database is not connected."));\r
-\r
- char items[] = {isc_info_user_names,\r
- isc_info_end};\r
- IBS status;\r
- RB result(8000);\r
-\r
- status.Reset();\r
- (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- {\r
- status.Reset();\r
- throw SQLExceptionImpl(status, "Database::Users", _("isc_database_info failed"));\r
- }\r
-\r
- users.clear();\r
- char* p = result.Self();\r
- while (*p == isc_info_user_names)\r
- {\r
- p += 3; // Get to the length byte (there are two undocumented bytes which we skip)\r
- int len = (int)(*p);\r
- ++p; // Get to the first char of username\r
- if (len != 0) users.push_back(std::string().append(p, len));\r
- p += len; // Skip username\r
- }\r
- return;\r
-}\r
-\r
-IBPP::IDatabase* DatabaseImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void DatabaseImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void DatabaseImpl::AttachTransactionImpl(TransactionImpl* tr)\r
-{\r
- if (tr == 0)\r
- throw LogicExceptionImpl("Database::AttachTransaction",\r
- _("Transaction object is null."));\r
-\r
- mTransactions.push_back(tr);\r
-}\r
-\r
-void DatabaseImpl::DetachTransactionImpl(TransactionImpl* tr)\r
-{\r
- if (tr == 0)\r
- throw LogicExceptionImpl("Database::DetachTransaction",\r
- _("ITransaction object is null."));\r
-\r
- mTransactions.erase(std::find(mTransactions.begin(), mTransactions.end(), tr));\r
-}\r
-\r
-void DatabaseImpl::AttachStatementImpl(StatementImpl* st)\r
-{\r
- if (st == 0)\r
- throw LogicExceptionImpl("Database::AttachStatement",\r
- _("Can't attach a null Statement object."));\r
-\r
- mStatements.push_back(st);\r
-}\r
-\r
-void DatabaseImpl::DetachStatementImpl(StatementImpl* st)\r
-{\r
- if (st == 0)\r
- throw LogicExceptionImpl("Database::DetachStatement",\r
- _("Can't detach a null Statement object."));\r
-\r
- mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
-}\r
-\r
-void DatabaseImpl::AttachBlobImpl(BlobImpl* bb)\r
-{\r
- if (bb == 0)\r
- throw LogicExceptionImpl("Database::AttachBlob",\r
- _("Can't attach a null Blob object."));\r
-\r
- mBlobs.push_back(bb);\r
-}\r
-\r
-void DatabaseImpl::DetachBlobImpl(BlobImpl* bb)\r
-{\r
- if (bb == 0)\r
- throw LogicExceptionImpl("Database::DetachBlob",\r
- _("Can't detach a null Blob object."));\r
-\r
- mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
-}\r
-\r
-void DatabaseImpl::AttachArrayImpl(ArrayImpl* ar)\r
-{\r
- if (ar == 0)\r
- throw LogicExceptionImpl("Database::AttachArray",\r
- _("Can't attach a null Array object."));\r
-\r
- mArrays.push_back(ar);\r
-}\r
-\r
-void DatabaseImpl::DetachArrayImpl(ArrayImpl* ar)\r
-{\r
- if (ar == 0)\r
- throw LogicExceptionImpl("Database::DetachArray",\r
- _("Can't detach a null Array object."));\r
-\r
- mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
-}\r
-\r
-void DatabaseImpl::AttachEventsImpl(EventsImpl* ev)\r
-{\r
- if (ev == 0)\r
- throw LogicExceptionImpl("Database::AttachEventsImpl",\r
- _("Can't attach a null Events object."));\r
-\r
- mEvents.push_back(ev);\r
-}\r
-\r
-void DatabaseImpl::DetachEventsImpl(EventsImpl* ev)\r
-{\r
- if (ev == 0)\r
- throw LogicExceptionImpl("Database::DetachEventsImpl",\r
- _("Can't detach a null Events object."));\r
-\r
- mEvents.erase(std::find(mEvents.begin(), mEvents.end(), ev));\r
-}\r
-\r
-DatabaseImpl::DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
- const std::string& UserName, const std::string& UserPassword,\r
- const std::string& RoleName, const std::string& CharSet,\r
- const std::string& CreateParams) :\r
-\r
- mRefCount(0), mHandle(0),\r
- mServerName(ServerName), mDatabaseName(DatabaseName),\r
- mUserName(UserName), mUserPassword(UserPassword), mRoleName(RoleName),\r
- mCharSet(CharSet), mCreateParams(CreateParams),\r
- mDialect(3)\r
-{\r
-}\r
-\r
-DatabaseImpl::~DatabaseImpl()\r
-{\r
- try { if (Connected()) Disconnect(); }\r
- catch(...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: date.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : IBPP, Date class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
-\r
-using namespace ibpp_internals;\r
-\r
-void IBPP::Date::Today()\r
-{\r
- time_t systime = time(0);\r
- tm* loctime = localtime(&systime);\r
-\r
- if (! IBPP::itod(&mDate, loctime->tm_year + 1900,\r
- loctime->tm_mon + 1, loctime->tm_mday))\r
- throw LogicExceptionImpl("Date::Today", _("Out of range"));\r
-}\r
-\r
-void IBPP::Date::SetDate(int dt)\r
-{\r
- if (! IBPP::dtoi(dt, 0, 0, 0))\r
- throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
- mDate = dt;\r
-}\r
-\r
-void IBPP::Date::SetDate(int year, int month, int day)\r
-{\r
- if (! IBPP::itod(&mDate, year, month, day))\r
- throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
-}\r
-\r
-void IBPP::Date::GetDate(int& year, int& month, int& day) const\r
-{\r
- if (! IBPP::dtoi(mDate, &year, &month, &day))\r
- throw LogicExceptionImpl("Date::GetDate", _("Out of range"));\r
-}\r
-\r
-int IBPP::Date::Year() const\r
-{\r
- int year;\r
- if (! IBPP::dtoi(mDate, &year, 0, 0))\r
- throw LogicExceptionImpl("Date::Year", _("Out of range"));\r
- return year;\r
-}\r
-\r
-int IBPP::Date::Month() const\r
-{\r
- int month;\r
- if (! IBPP::dtoi(mDate, 0, &month, 0))\r
- throw LogicExceptionImpl("Date::Month", _("Out of range"));\r
- return month;\r
-}\r
-\r
-int IBPP::Date::Day() const\r
-{\r
- int day;\r
- if (! IBPP::dtoi(mDate, 0, 0, &day))\r
- throw LogicExceptionImpl("Date::Day", _("Out of range"));\r
- return day;\r
-}\r
-\r
-void IBPP::Date::Add(int days)\r
-{\r
- int newdate = mDate + days; // days can be signed\r
- if (! IBPP::dtoi(newdate, 0, 0, 0))\r
- throw LogicExceptionImpl("Date::Add()", _("Out of range"));\r
- mDate = newdate;\r
-}\r
-\r
-void IBPP::Date::StartOfMonth()\r
-{\r
- int year, month;\r
- if (! IBPP::dtoi(mDate, &year, &month, 0))\r
- throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
- if (! IBPP::itod(&mDate, year, month, 1)) // First of same month\r
- throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
-}\r
-\r
-void IBPP::Date::EndOfMonth()\r
-{\r
- int year, month;\r
- if (! IBPP::dtoi(mDate, &year, &month, 0))\r
- throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
- if (++month > 12) { month = 1; year++; }\r
- if (! IBPP::itod(&mDate, year, month, 1)) // First of next month\r
- throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
- mDate--; // Last day of original month, all weird cases accounted for\r
-}\r
-\r
-IBPP::Date::Date(int year, int month, int day)\r
-{\r
- SetDate(year, month, day);\r
-}\r
-\r
-IBPP::Date::Date(const IBPP::Date& copied)\r
-{\r
- mDate = copied.mDate;\r
-}\r
-\r
-IBPP::Date& IBPP::Date::operator=(const IBPP::Timestamp& assigned)\r
-{\r
- mDate = assigned.GetDate();\r
- return *this;\r
-}\r
-\r
-IBPP::Date& IBPP::Date::operator=(const IBPP::Date& assigned)\r
-{\r
- mDate = assigned.mDate;\r
- return *this;\r
-}\r
-\r
-// The following date calculations were inspired by web pages found on\r
-// Peter Baum web homepage at 'http://www.capecod.net/~pbaum/'.\r
-// His contact info is at : 'http://home.capecod.net/~pbaum/contact.htm'.\r
-// Please, understand that Peter Baum is not related to this IBPP project.\r
-// So __please__, do not contact him regarding IBPP matters.\r
-\r
-// Take a date, in its integer format as used in IBPP internals and splits\r
-// it in year (4 digits), month (1-12), day (1-31)\r
-\r
-bool IBPP::dtoi (int date, int *y, int *m, int *d)\r
-{\r
- int RataDie, Z, H, A, B, C;\r
- int year, month, day;\r
-\r
- // Validity control.\r
- if (date < IBPP::MinDate || date > IBPP::MaxDate)\r
- return false;\r
-\r
- // The "Rata Die" is the date specified as the number of days elapsed since\r
- // 31 Dec of year 0. So 1 Jan 0001 is 1.\r
-\r
- RataDie = date + ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899.\r
-\r
- Z = RataDie + 306;\r
- H = 100*Z - 25;\r
- A = H/3652425;\r
- B = A - A/4;\r
- year = (100*B + H) / 36525;\r
- C = B + Z - 365*year - year / 4;\r
- month = (5*C + 456) / 153;\r
- day = C - (153*month - 457) / 5;\r
- if (month > 12) { year += 1; month -= 12; }\r
-\r
- if (y != 0) *y = (int)year;\r
- if (m != 0) *m = (int)month;\r
- if (d != 0) *d = (int)day;\r
-\r
- return true;\r
-}\r
-\r
-// Take a date from its components year, month, day and convert it to the\r
-// integer representation used internally in IBPP.\r
-\r
-bool IBPP::itod (int *pdate, int year, int month, int day)\r
-{\r
- int RataDie, result;\r
- int y, m, d;\r
-\r
- d = day; m = month; y = year;\r
- if (m < 3) { m += 12; y -= 1; }\r
- RataDie = d + (153*m - 457) / 5 + 365*y + y/4 - y/100 + y/400 - 306;\r
-\r
- result = RataDie - ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899\r
-\r
- // Validity control\r
- if (result < IBPP::MinDate || result > IBPP::MaxDate)\r
- return false;\r
-\r
- *pdate = result;\r
- return true;\r
-}\r
-\r
-// Eof\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: dbkey.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : IBPP, DBKey class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <iostream>\r
-#include <sstream>\r
-#include <iomanip>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// Private implementation\r
-\r
-// Public implementation\r
-\r
-void IBPP::DBKey::Clear()\r
-{\r
- mDBKey.erase();\r
- mString.erase();\r
-}\r
-\r
-void IBPP::DBKey::SetKey(const void* key, int size)\r
-{\r
- if (key == 0)\r
- throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Null DBKey reference detected."));\r
- if (size <= 0 || ((size >> 3) << 3) != size)\r
- throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Invalid DBKey size."));\r
-\r
- mDBKey.assign((const char*)key, (size_t)size);\r
- mString.erase();\r
-}\r
-\r
-void IBPP::DBKey::GetKey(void* key, int size) const\r
-{\r
- if (mDBKey.empty())\r
- throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("DBKey not assigned."));\r
- if (key == 0)\r
- throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Null DBKey reference detected."));\r
- if (size != (int)mDBKey.size())\r
- throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Incompatible DBKey size detected."));\r
-\r
- mDBKey.copy((char*)key, mDBKey.size());\r
-}\r
-\r
-const char* IBPP::DBKey::AsString() const\r
-{\r
- if (mDBKey.empty())\r
- throw LogicExceptionImpl("IBPP::DBKey::GetString", _("DBKey not assigned."));\r
-\r
- if (mString.empty())\r
- {\r
- std::ostringstream hexkey;\r
- hexkey.setf(std::ios::hex, std::ios::basefield);\r
- hexkey.setf(std::ios::uppercase);\r
-\r
- const uint32_t* key = reinterpret_cast<const uint32_t*>(mDBKey.data());\r
- int n = (int)mDBKey.size() / 8;\r
- for (int i = 0; i < n; i++)\r
- {\r
- if (i != 0) hexkey<< "-";\r
- hexkey<< std::setw(4)<< key[i*2]<< ":";\r
- hexkey<< std::setw(8)<< key[i*2+1];\r
- }\r
-\r
- mString = hexkey.str();\r
- }\r
-\r
- return mString.c_str();\r
-}\r
-\r
-IBPP::DBKey::DBKey(const DBKey& copied)\r
-{\r
- mDBKey = copied.mDBKey;\r
- mString = copied.mString;\r
-}\r
-\r
-IBPP::DBKey& IBPP::DBKey::operator=(const IBPP::DBKey& assigned)\r
-{\r
- mDBKey = assigned.mDBKey;\r
- mString = assigned.mString;\r
- return *this;\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: events.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : IBPP, internal EventsImpl class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-// SPECIAL WARNING COMMENT (by Olivier Mascia, 2000 Nov 12)\r
-// The way this source file handles events is not publicly documented, in\r
-// the ibase.h header file or in the IB 6.0 documentation. This documentation\r
-// suggests to use the API isc_event_block to construct vectors of events.\r
-// Unfortunately, this API takes a variable number of parameters to specify\r
-// the list of event names. In addition, the documentation warn on not using\r
-// more than 15 names. This is a sad limitation, partly because the maximum\r
-// number of parameters safely processed in such an API is very compiler\r
-// dependant and also because isc_event_counts() is designed to return counts\r
-// through the IB status vector which is a vector of 20 32-bits integers !\r
-// From reverse engineering of the isc_event_block() API in\r
-// source file jrd/alt.c (as available on fourceforge.net/project/InterBase as\r
-// of 2000 Nov 12), it looks like the internal format of those EPB is simple.\r
-// An EPB starts by a byte with value 1. A version identifier of some sort.\r
-// Then a small cluster is used for each event name. The cluster starts with\r
-// a byte for the length of the event name (no final '\0'). Followed by the N\r
-// characters of the name itself (no final '\0'). The cluster ends with 4 bytes\r
-// preset to 0.\r
-//\r
-// SPECIAL CREDIT (July 2004) : this is a complete re-implementation of this\r
-// class, directly based on work by Val Samko.\r
-// The whole event handling has then be completely redesigned, based on the old\r
-// EPB class to bring up the current IBPP::Events implementation.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-using namespace ibpp_internals;\r
-\r
-const size_t EventsImpl::MAXEVENTNAMELEN = 127;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void EventsImpl::Add(const std::string& eventname, IBPP::EventInterface* objref)\r
-{\r
- if (eventname.size() == 0)\r
- throw LogicExceptionImpl("Events::Add", _("Zero length event names not permitted"));\r
- if (eventname.size() > MAXEVENTNAMELEN)\r
- throw LogicExceptionImpl("Events::Add", _("Event name is too long"));\r
- if ((mEventBuffer.size() + eventname.length() + 5) > 32766) // max signed 16 bits integer minus one\r
- throw LogicExceptionImpl("Events::Add",\r
- _("Can't add this event, the events list would overflow IB/FB limitation"));\r
-\r
- Cancel();\r
-\r
- // 1) Alloc or grow the buffers\r
- size_t prev_buffer_size = mEventBuffer.size();\r
- size_t needed = ((prev_buffer_size==0) ? 1 : 0) + eventname.length() + 5;\r
- // Initial alloc will require one more byte, we need 4 more bytes for\r
- // the count itself, and one byte for the string length prefix\r
-\r
- mEventBuffer.resize(mEventBuffer.size() + needed);\r
- mResultsBuffer.resize(mResultsBuffer.size() + needed);\r
- if (prev_buffer_size == 0)\r
- mEventBuffer[0] = mResultsBuffer[0] = 1; // First byte is a 'one'. Documentation ??\r
-\r
- // 2) Update the buffers (append)\r
- {\r
- Buffer::iterator it = mEventBuffer.begin() +\r
- ((prev_buffer_size==0) ? 1 : prev_buffer_size); // Byte after current content\r
- *(it++) = static_cast<char>(eventname.length());\r
- it = std::copy(eventname.begin(), eventname.end(), it);\r
- // We initialize the counts to (uint32_t)(-1) to initialize properly, see FireActions()\r
- *(it++) = -1; *(it++) = -1; *(it++) = -1; *it = -1;\r
- }\r
-\r
- // copying new event to the results buffer to keep event_buffer_ and results_buffer_ consistant,\r
- // otherwise we might get a problem in `FireActions`\r
- // Val Samko, val@digiways.com\r
- std::copy(mEventBuffer.begin() + prev_buffer_size,\r
- mEventBuffer.end(), mResultsBuffer.begin() + prev_buffer_size);\r
-\r
- // 3) Alloc or grow the objref array and update the objref array (append)\r
- mObjectReferences.push_back(objref);\r
-\r
- Queue();\r
-}\r
-\r
-void EventsImpl::Drop(const std::string& eventname)\r
-{\r
- if (eventname.size() == 0)\r
- throw LogicExceptionImpl("EventsImpl::Drop", _("Zero length event names not permitted"));\r
- if (eventname.size() > MAXEVENTNAMELEN)\r
- throw LogicExceptionImpl("EventsImpl::Drop", _("Event name is too long"));\r
-\r
- if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
-\r
- Cancel();\r
-\r
- // 1) Find the event in the buffers\r
- typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
- EventIterator eit(mEventBuffer.begin()+1);\r
- EventIterator rit(mResultsBuffer.begin()+1);\r
-\r
- for (ObjRefs::iterator oit = mObjectReferences.begin();\r
- oit != mObjectReferences.end();\r
- ++oit, ++eit, ++rit)\r
- {\r
- if (eventname != eit.get_name()) continue;\r
- \r
- // 2) Event found, remove it\r
- mEventBuffer.erase(eit.begin(), eit.end());\r
- mResultsBuffer.erase(rit.begin(), rit.end());\r
- mObjectReferences.erase(oit);\r
- break;\r
- }\r
-\r
- Queue();\r
-}\r
-\r
-void EventsImpl::List(std::vector<std::string>& events)\r
-{\r
- events.clear();\r
- \r
- if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
-\r
- typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
- EventIterator eit(mEventBuffer.begin()+1);\r
-\r
- for (ObjRefs::iterator oit = mObjectReferences.begin();\r
- oit != mObjectReferences.end();\r
- ++oit, ++eit)\r
- {\r
- events.push_back(eit.get_name());\r
- }\r
-}\r
-\r
-void EventsImpl::Clear()\r
-{\r
- Cancel();\r
- \r
- mObjectReferences.clear();\r
- mEventBuffer.clear();\r
- mResultsBuffer.clear();\r
-}\r
-\r
-void EventsImpl::Dispatch()\r
-{\r
- // If no events registered, nothing to do of course.\r
- if (mEventBuffer.size() == 0) return;\r
-\r
- // Let's fire the events actions for all the events which triggered, if any, and requeue.\r
- FireActions();\r
- Queue();\r
-}\r
-\r
-IBPP::Database EventsImpl::DatabasePtr() const\r
-{\r
- if (mDatabase == 0) throw LogicExceptionImpl("Events::DatabasePtr",\r
- _("No Database is attached."));\r
- return mDatabase;\r
-}\r
-\r
-IBPP::IEvents* EventsImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void EventsImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void EventsImpl::Queue()\r
-{\r
- if (! mQueued)\r
- {\r
- if (mDatabase->GetHandle() == 0)\r
- throw LogicExceptionImpl("EventsImpl::Queue",\r
- _("Database is not connected"));\r
-\r
- IBS vector;\r
- mTrapped = false;\r
- mQueued = true;\r
- (*gds.Call()->m_que_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId,\r
- short(mEventBuffer.size()), &mEventBuffer[0],\r
- (isc_callback)EventHandler, (char*)this);\r
-\r
- if (vector.Errors())\r
- {\r
- mId = 0; // Should be, but better be safe\r
- mQueued = false;\r
- throw SQLExceptionImpl(vector, "EventsImpl::Queue",\r
- _("isc_que_events failed"));\r
- }\r
- }\r
-}\r
-\r
-void EventsImpl::Cancel()\r
-{\r
- if (mQueued)\r
- {\r
- if (mDatabase->GetHandle() == 0) throw LogicExceptionImpl("EventsImpl::Cancel",\r
- _("Database is not connected"));\r
-\r
- IBS vector;\r
-\r
- // A call to cancel_events will call *once* the handler routine, even\r
- // though no events had fired. This is why we first set mEventsQueued\r
- // to false, so that we can be sure to dismiss those unwanted callbacks\r
- // subsequent to the execution of isc_cancel_events().\r
- mTrapped = false;\r
- mQueued = false;\r
- (*gds.Call()->m_cancel_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId);\r
-\r
- if (vector.Errors())\r
- {\r
- mQueued = true; // Need to restore this as cancel failed\r
- throw SQLExceptionImpl(vector, "EventsImpl::Cancel",\r
- _("isc_cancel_events failed"));\r
- }\r
-\r
- mId = 0; // Should be, but better be safe\r
- }\r
-}\r
-\r
-void EventsImpl::FireActions()\r
-{\r
- if (mTrapped)\r
- {\r
- typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
- EventIterator eit(mEventBuffer.begin()+1);\r
- EventIterator rit(mResultsBuffer.begin()+1);\r
-\r
- for (ObjRefs::iterator oit = mObjectReferences.begin();\r
- oit != mObjectReferences.end();\r
- ++oit, ++eit, ++rit)\r
- {\r
- if (eit == EventIterator(mEventBuffer.end())\r
- || rit == EventIterator(mResultsBuffer.end()))\r
- throw LogicExceptionImpl("EventsImpl::FireActions", _("Internal buffer size error"));\r
- uint32_t vnew = rit.get_count();\r
- uint32_t vold = eit.get_count();\r
- if (vnew > vold)\r
- {\r
- // Fire the action\r
- try\r
- {\r
- (*oit)->ibppEventHandler(this, eit.get_name(), (int)(vnew - vold));\r
- }\r
- catch (...)\r
- {\r
- std::copy(rit.begin(), rit.end(), eit.begin());\r
- throw;\r
- }\r
- std::copy(rit.begin(), rit.end(), eit.begin());\r
- }\r
- // This handles initialization too, where vold == (uint32_t)(-1)\r
- // Thanks to M. Hieke for this idea and related initialization to (-1)\r
- if (vnew != vold)\r
- std::copy(rit.begin(), rit.end(), eit.begin());\r
- }\r
- }\r
-}\r
-\r
-// This function must keep this prototype to stay compatible with\r
-// what isc_que_events() expects\r
-\r
-void EventsImpl::EventHandler(const char* object, short size, const char* tmpbuffer)\r
-{\r
- // >>>>> This method is a STATIC member !! <<<<<\r
- // Consider this method as a kind of "interrupt handler". It should do as\r
- // few work as possible as quickly as possible and then return.\r
- // Never forget: this is called by the Firebird client code, on *some*\r
- // thread which might not be (and won't probably be) any of your application\r
- // thread. This function is to be considered as an "interrupt-handler" of a\r
- // hardware driver.\r
-\r
- // There can be spurious calls to EventHandler from FB internal. We must\r
- // dismiss those calls.\r
- if (object == 0 || size == 0 || tmpbuffer == 0) return;\r
- \r
- EventsImpl* evi = (EventsImpl*)object; // Ugly, but wanted, c-style cast\r
-\r
- if (evi->mQueued)\r
- {\r
- try\r
- {\r
- char* rb = &evi->mResultsBuffer[0];\r
- if (evi->mEventBuffer.size() < (unsigned)size) size = (short)evi->mEventBuffer.size();\r
- for (int i = 0; i < size; i++)\r
- rb[i] = tmpbuffer[i];\r
- evi->mTrapped = true;\r
- evi->mQueued = false;\r
- }\r
- catch (...) { }\r
- }\r
-}\r
-\r
-void EventsImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
- if (database == 0) throw LogicExceptionImpl("EventsImpl::AttachDatabase",\r
- _("Can't attach a null Database object."));\r
-\r
- if (mDatabase != 0) mDatabase->DetachEventsImpl(this);\r
- mDatabase = database;\r
- mDatabase->AttachEventsImpl(this);\r
-}\r
-\r
-void EventsImpl::DetachDatabaseImpl()\r
-{\r
- if (mDatabase == 0) return;\r
-\r
- mDatabase->DetachEventsImpl(this);\r
- mDatabase = 0;\r
-}\r
-\r
-EventsImpl::EventsImpl(DatabaseImpl* database)\r
- : mRefCount(0)\r
-{\r
- mDatabase = 0;\r
- mId = 0;\r
- mQueued = mTrapped = false;\r
- AttachDatabaseImpl(database);\r
-}\r
-\r
-EventsImpl::~EventsImpl()\r
-{\r
- try { Clear(); }\r
- catch (...) { }\r
- \r
- try { if (mDatabase != 0) mDatabase->DetachEventsImpl(this); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: exception.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-// Subject : IBPP, Initialization of the library\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// None of the exception classes methods are implemented inline, because they\r
-// are all declared throw() and Borland compilers at least, but possibly some\r
-// others emit a warning like "W8026 - functions with exception specification\r
-// are not expanded inline". Nothing we have to worry about, but we don't want\r
-// people concerned by such warnings.\r
-\r
-IBPP::Exception::~Exception() throw()\r
-{\r
-}\r
-\r
-IBPP::LogicException::~LogicException() throw()\r
-{\r
-}\r
-\r
-IBPP::SQLException::~SQLException() throw()\r
-{\r
-}\r
-\r
-IBPP::WrongType::~WrongType() throw()\r
-{\r
-}\r
-\r
-//\r
-// (((((((( ExceptionBase Implementation ))))))))\r
-//\r
-\r
-void ExceptionBase::buildErrorMessage(const char* message)\r
-{\r
- if (! mContext.empty())\r
- mWhat.append(_("Context: ")).append(mContext).append("\n");\r
-\r
- if (message != 0 && *message != 0 )\r
- mWhat.append(_("Message: ")).append(message).append("\n");\r
- \r
- mWhat.append("\n");\r
-}\r
-\r
-void ExceptionBase::raise(const std::string& context, const char* message, va_list argptr)\r
-{\r
- mContext.assign(context);\r
-\r
- if (message != 0)\r
- {\r
- char buffer[1024];\r
-#if defined(_MSC_VER) || defined(__DMC__)\r
- _vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
-#else\r
- vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
-#endif\r
- buffer[sizeof(buffer)-1] = 0;\r
- \r
- buildErrorMessage(buffer);\r
- }\r
- else\r
- buildErrorMessage(0);\r
-}\r
-\r
-ExceptionBase::ExceptionBase() throw()\r
-{\r
-}\r
-\r
-ExceptionBase::ExceptionBase(const ExceptionBase& copied) throw()\r
-{\r
- mContext = copied.mContext;\r
- mWhat = copied.mWhat;\r
-}\r
-\r
-ExceptionBase& ExceptionBase::operator=(const ExceptionBase& copied) throw()\r
-{\r
- mContext = copied.mContext;\r
- mWhat = copied.mWhat;\r
- return *this;\r
-}\r
-\r
-ExceptionBase::ExceptionBase(const std::string& context,\r
- const char* message, ...) throw()\r
-{\r
- va_list argptr;\r
- va_start(argptr, message);\r
- mWhat.assign("*** IBPP::Exception ***\n");\r
- raise(context, message, argptr);\r
- va_end(argptr);\r
-}\r
-\r
-ExceptionBase::~ExceptionBase() throw()\r
-{\r
-}\r
-\r
-const char* ExceptionBase::Origin() const throw()\r
-{\r
- return mContext.c_str();\r
-}\r
-\r
-const char* ExceptionBase::ErrorMessage() const throw()\r
-{\r
- return mWhat.c_str();\r
-}\r
-\r
-const char* ExceptionBase::what() const throw()\r
-{\r
- return mWhat.c_str();\r
-}\r
-\r
-// (((((((( LogicExceptionImpl Implementation ))))))))\r
-\r
-// The following constructors are small and could be inlined, but for object\r
-// code compacity of the library it is much better to have them non-inlined.\r
-// The amount of code generated by compilers for a throw is well-enough.\r
-\r
-LogicExceptionImpl::LogicExceptionImpl() throw()\r
- : ExceptionBase()\r
-{\r
-}\r
-\r
-LogicExceptionImpl::LogicExceptionImpl(const LogicExceptionImpl& copied) throw()\r
- : IBPP::LogicException(), ExceptionBase(copied)\r
-{\r
-}\r
-\r
-LogicExceptionImpl& LogicExceptionImpl::operator=(const LogicExceptionImpl& copied) throw()\r
-{\r
- ExceptionBase::operator=(copied);\r
- return *this;\r
-}\r
-\r
-LogicExceptionImpl::LogicExceptionImpl(const std::string& context,\r
- const char* message, ...) throw()\r
-{\r
- va_list argptr;\r
- va_start(argptr, message);\r
- mWhat.assign("*** IBPP::LogicException ***\n");\r
- raise(context, message, argptr);\r
- va_end(argptr);\r
-}\r
-\r
-LogicExceptionImpl::~LogicExceptionImpl() throw ()\r
-{\r
-}\r
-\r
-const char* LogicExceptionImpl::Origin() const throw()\r
-{\r
- return ExceptionBase::Origin();\r
-}\r
-\r
-const char* LogicExceptionImpl::ErrorMessage() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-const char* LogicExceptionImpl::what() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-// (((((((( SQLExceptionImpl Implementation ))))))))\r
-\r
-SQLExceptionImpl::SQLExceptionImpl() throw()\r
- : ExceptionBase(), mSqlCode(0), mEngineCode(0)\r
-{\r
-}\r
-\r
-SQLExceptionImpl::SQLExceptionImpl(const SQLExceptionImpl& copied) throw()\r
- : IBPP::SQLException(), ExceptionBase(copied), mSqlCode(copied.mSqlCode),\r
- mEngineCode(copied.mEngineCode)\r
-{\r
-}\r
-\r
-SQLExceptionImpl& SQLExceptionImpl::operator=(const SQLExceptionImpl& copied) throw()\r
-{\r
- ExceptionBase::operator=(copied);\r
- mSqlCode = copied.mSqlCode;\r
- mEngineCode = copied.mEngineCode;\r
- return *this;\r
-}\r
-\r
-SQLExceptionImpl::SQLExceptionImpl(const IBS& status, const std::string& context,\r
- const char* message, ...) throw()\r
-{\r
- va_list argptr;\r
- va_start(argptr, message);\r
- mWhat.assign("*** IBPP::SQLException ***\n");\r
- raise(context, message, argptr);\r
- va_end(argptr);\r
- mSqlCode = status.SqlCode();\r
- mEngineCode = status.EngineCode();\r
- mWhat.append(status.ErrorMessage());\r
-}\r
-\r
-SQLExceptionImpl::~SQLExceptionImpl() throw ()\r
-{\r
-}\r
-\r
-const char* SQLExceptionImpl::Origin() const throw()\r
-{\r
- return ExceptionBase::Origin();\r
-}\r
-\r
-const char* SQLExceptionImpl::ErrorMessage() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-const char* SQLExceptionImpl::what() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-int SQLExceptionImpl::SqlCode() const throw()\r
-{\r
- return mSqlCode;\r
-}\r
-\r
-int SQLExceptionImpl::EngineCode() const throw()\r
-{\r
- return mEngineCode;\r
-}\r
-\r
-// (((((((( WrongTypeImpl Implementation ))))))))\r
-\r
-// The following constructors are small and could be inlined, but for object\r
-// code compacity of the library it is much better to have them non-inlined.\r
-// The amount of code generated by compilers for a throw is well-enough.\r
-\r
-WrongTypeImpl::WrongTypeImpl() throw()\r
- : IBPP::WrongType(), ExceptionBase()\r
-{\r
-}\r
-\r
-WrongTypeImpl::WrongTypeImpl(const WrongTypeImpl& copied) throw()\r
- : IBPP::WrongType(), ExceptionBase(copied)\r
-{\r
-}\r
-\r
-WrongTypeImpl& WrongTypeImpl::operator=(const WrongTypeImpl& copied) throw()\r
-{\r
- ExceptionBase::operator=(copied);\r
- return *this;\r
-}\r
-\r
-WrongTypeImpl::WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
- const char* message, ...) throw()\r
-{\r
- va_list argptr;\r
- va_start(argptr, message);\r
- mWhat.assign("*** IBPP::WrongType ***\n");\r
- raise(context, message, argptr);\r
- va_end(argptr);\r
-\r
- std::string info;\r
- switch (sqlType & ~1)\r
- {\r
- case SQL_TEXT : info.append("CHAR"); break;\r
- case SQL_VARYING : info.append("VARCHAR"); break;\r
- case SQL_SHORT : info.append("SMALLINT"); break;\r
- case SQL_LONG : info.append("INTEGER"); break;\r
- case SQL_INT64 : info.append("BIGINT"); break;\r
- case SQL_FLOAT : info.append("FLOAT"); break;\r
- case SQL_DOUBLE : info.append("DOUBLE"); break;\r
- case SQL_TIMESTAMP : info.append("TIMESTAMP"); break;\r
- case SQL_TYPE_DATE : info.append("DATE"); break;\r
- case SQL_TYPE_TIME : info.append("TIME"); break;\r
- case SQL_BLOB : info.append("BLOB"); break;\r
- case SQL_ARRAY : info.append("ARRAY"); break;\r
- }\r
- info.append(" ").append(_(" and ")).append(" ");\r
- switch (varType)\r
- {\r
- case ivArray : info.append("Array"); break;\r
- case ivBlob : info.append("Blob"); break;\r
- case ivDate : info.append("Date"); break;\r
- case ivTime : info.append("Time"); break;\r
- case ivTimestamp : info.append("Timestamp"); break;\r
- case ivString : info.append("std::string"); break;\r
- case ivInt16 : info.append("int16_t"); break;\r
- case ivInt32 : info.append("int32_t"); break;\r
- case ivInt64 : info.append("int64_t"); break;\r
- case ivFloat : info.append("float"); break;\r
- case ivDouble : info.append("double"); break;\r
- case ivBool : info.append("bool"); break;\r
- case ivDBKey : info.append("DBKey"); break;\r
- case ivByte : info.append("int8_t"); break;\r
- }\r
- mWhat.append(info).append("\n");\r
-}\r
-\r
-WrongTypeImpl::~WrongTypeImpl() throw ()\r
-{\r
-}\r
-\r
-const char* WrongTypeImpl::Origin() const throw()\r
-{\r
- return ExceptionBase::Origin();\r
-}\r
-\r
-const char* WrongTypeImpl::ErrorMessage() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-const char* WrongTypeImpl::what() const throw()\r
-{\r
- return ExceptionBase::what();\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-/*\r
- * MODULE: ibase.h\r
- * DESCRIPTION: OSRI entrypoints and defines\r
- *\r
- * The contents of this file are subject to the Interbase Public\r
- * License Version 1.0 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy\r
- * of the License at http://www.Inprise.com/IPL.html\r
- *\r
- * Software distributed under the License is distributed on an\r
- * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code was created by Inprise Corporation\r
- * and its predecessors. Portions created by Inprise Corporation are\r
- * Copyright (C) Inprise Corporation.\r
- *\r
- * All Rights Reserved.\r
- * Contributor(s): ______________________________________.\r
- * Added TCP_NO_DELAY option for superserver on Linux\r
- * FSG 16.03.2001\r
- * 2001.07.28: John Bellardo: Added blr_skip\r
- * 2001.09.18: Ann Harrison: New info codes\r
- * 17-Oct-2001 Mike Nordell: CPU affinity\r
- * 2001-04-16 Paul Beach: ISC_TIME_SECONDS_PRECISION_SCALE modified for HP10\r
- * Compiler Compatibility\r
- * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports:\r
- * - EPSON, XENIX, MAC (MAC_AUX), Cray and OS/2\r
- * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
- *\r
- * 2002.10.29 Sean Leyne - Removed support for obsolete IPX/SPX Protocol\r
- *\r
- */\r
-/*\r
-$Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
- */\r
-\r
-#ifndef JRD_IBASE_H\r
-#define JRD_IBASE_H\r
-\r
-\r
-/*\r
- *\r
- * The contents of this file are subject to the Mozilla Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/MPL/\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU General Public License Version 2 or later (the\r
- * "GPL"), in which case the provisions of the GPL are applicable\r
- * instead of those above. You may obtain a copy of the Licence at\r
- * http://www.gnu.org/copyleft/gpl.html\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * Relevant for more details.\r
- *\r
- * This file was created by members of the firebird development team.\r
- * All individual contributions remain the Copyright (C) of those\r
- * individuals. Contributors to this file are either listed here or\r
- * can be obtained from a CVS history command.\r
- *\r
- * All rights reserved.\r
- *\r
- * Contributor(s):\r
- * Mike Nordel <tamlin@algonet.se>\r
- * Mark O'Donohue <mark.odonohue@ludwig.edu.au>\r
- *\r
- *\r
- * $Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
- *\r
- * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "OS/2" port\r
- *\r
- */\r
-\r
-\r
-#ifndef INCLUDE_FB_TYPES_H\r
-#define INCLUDE_FB_TYPES_H\r
-\r
-\r
-/******************************************************************/\r
-/* Define type, export and other stuff based on c/c++ and Windows */\r
-/******************************************************************/\r
-\r
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
-#ifndef __GNUC__\r
-typedef __int64 ISC_INT64;\r
-typedef unsigned __int64 ISC_UINT64;\r
-#define ISC_INT64_DEFINED\r
-#endif\r
-#define ISC_EXPORT __stdcall\r
-#define ISC_EXPORT_VARARG __cdecl\r
-#else\r
-#define ISC_EXPORT\r
-#define ISC_EXPORT_VARARG\r
-#endif\r
-\r
-/*******************************************************************/\r
-/* 64 bit Integers */\r
-/*******************************************************************/\r
-\r
-#ifdef ISC_INT64_DEFINED\r
-#undef ISC_INT64_DEFINED\r
-#else\r
-//typedef long long int ISC_INT64;\r
-//typedef unsigned long long int ISC_UINT64;\r
-typedef int64_t ISC_INT64;\r
-typedef uint64_t ISC_UINT64;\r
-#endif\r
-\r
-// Nickolay: it is easier to assume that integer is at least 32-bit.\r
-// This comes from limitation that we cannot reliably detect datatype size at\r
-// compile time in cases when we do not control compilation (public headers) \r
-// We are not going to support 16-bit platforms, right?\r
-//\r
-// Temporarly restrict new definition until ULONG clash with Windows\r
-// type is solved. Win64 port is not possible before that point.\r
-// Cannot use SIZEOF_LONG define here because we are in a public header\r
-#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
- /* EKU: Firebird requires (S)LONG to be 32 bit */\r
-# define LONG_DEFINED\r
- typedef int SLONG;\r
- typedef unsigned int ULONG;\r
-#endif /* SIZEOF_LONG == 8 */\r
-\r
-\r
-\r
-/* Basic data types */\r
-\r
-\r
-#ifdef NOT_USED_OR_REPLACED\r
-typedef signed char SCHAR;\r
-#else\r
-/* TMN: TODO It seems SCHAR is used just about *everywhere* where a plain\r
- * "char" is really intended. This currently forces us to this bad definition.\r
- */\r
-typedef char SCHAR;\r
-#endif\r
-\r
-\r
-typedef unsigned char UCHAR;\r
-typedef short SSHORT;\r
-typedef unsigned short USHORT;\r
-\r
-\r
-#ifndef LONG_DEFINED /* 32 bit */\r
-typedef long SLONG;\r
-typedef unsigned long ULONG;\r
-#else\r
-#undef LONG_DEFINED\r
-#endif\r
-\r
-\r
-#ifndef SQUAD_DEFINED /* 64 bit */\r
-typedef struct {\r
- SLONG high;\r
- ULONG low;\r
-} SQUAD;\r
-#endif\r
-\r
-\r
-#ifndef DEFINED_GDS_QUAD\r
-#define DEFINED_GDS_QUAD\r
-struct GDS_QUAD_t {\r
- SLONG gds_quad_high;\r
- ULONG gds_quad_low;\r
-};\r
-\r
-typedef struct GDS_QUAD_t GDS_QUAD;\r
-\r
-#endif /* DEFINED_GDS_QUAD */\r
-\r
-//\r
-// TMN: some misc data types from all over the place\r
-//\r
-struct vary\r
-{\r
- USHORT vary_length;\r
- char vary_string[1];\r
-};\r
-// TMN: Currently we can't do this, since remote uses a different\r
-// definition of VARY than the rest of the code! :-<\r
-//typedef vary* VARY;\r
-\r
-struct lstring\r
-{\r
- ULONG lstr_length;\r
- ULONG lstr_allocated;\r
- UCHAR* lstr_address;\r
-};\r
-typedef struct lstring LSTRING;\r
-\r
-\r
-typedef unsigned char BOOLEAN;\r
-typedef char TEXT; // To be expunged over time\r
-//typedef unsigned char STEXT; Signed text - not used\r
-//typedef unsigned char UTEXT; Unsigned text - not used\r
-typedef unsigned char BYTE; // Unsigned byte - common\r
-//typedef char SBYTE; Signed byte - not used\r
-typedef long ISC_STATUS;\r
-typedef long IPTR;\r
-typedef unsigned long U_IPTR;\r
-typedef void (*FPTR_VOID) ();\r
-typedef void (*FPTR_VOID_PTR) (void *);\r
-typedef int (*FPTR_INT) ();\r
-typedef int (*FPTR_INT_VOID_PTR) (void *);\r
-typedef ULONG RCRD_OFFSET;\r
-typedef USHORT FLD_LENGTH;\r
-typedef int (*lock_ast_t)(void *);\r
-\r
-typedef IPTR FB_THREAD_ID;\r
-\r
-#define ISC_STATUS_LENGTH 20\r
-typedef ISC_STATUS ISC_STATUS_ARRAY[ISC_STATUS_LENGTH];\r
-\r
-/* Number of elements in an arry */\r
-#define FB_NELEM(x) ((int)(sizeof(x) / sizeof(x[0])))\r
-#define FB_ALIGN(n,b) ((n+b-1)&~(b-1))\r
-\r
-#endif /* INCLUDE_FB_TYPES_H */\r
-\r
-#define FB_API_VER 15\r
-#define isc_version4\r
-\r
-#define ISC_TRUE 1\r
-#define ISC_FALSE 0\r
-#if !(defined __cplusplus)\r
-#define ISC__TRUE ISC_TRUE\r
-#define ISC__FALSE ISC_FALSE\r
-#endif\r
-\r
-#define ISC_FAR\r
-\r
-// It is difficult to detect 64-bit long from the redistributable header\r
-// we do not care of 16-bit platforms anymore thus we may use plain "int"\r
-// which is 32-bit on all platforms we support\r
-#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
-typedef int ISC_LONG;\r
-typedef unsigned int ISC_ULONG;\r
-#else\r
-typedef signed long ISC_LONG;\r
-typedef unsigned long ISC_ULONG;\r
-#endif\r
-\r
-typedef signed short ISC_SHORT;\r
-typedef unsigned short ISC_USHORT;\r
-\r
-typedef unsigned char ISC_UCHAR;\r
-\r
-#define DSQL_close 1\r
-#define DSQL_drop 2\r
-\r
-\r
-/********************************/\r
-/* InterBase Handle Definitions */\r
-/********************************/\r
-\r
-#ifndef JRD_Y_REF_H\r
-#define FRBRD void\r
-#endif\r
-\r
-typedef FRBRD * isc_att_handle;\r
-typedef FRBRD * isc_blob_handle;\r
-typedef FRBRD * isc_db_handle;\r
-typedef FRBRD * isc_req_handle;\r
-typedef FRBRD * isc_stmt_handle;\r
-typedef FRBRD * isc_svc_handle;\r
-typedef FRBRD * isc_tr_handle;\r
-typedef void (* isc_callback) ();\r
-typedef ISC_LONG isc_resv_handle;\r
-\r
-/*******************************************************************/\r
-/* Time & Date Support */\r
-/*******************************************************************/\r
-\r
-#ifndef ISC_TIMESTAMP_DEFINED\r
-typedef int ISC_DATE;\r
-typedef unsigned int ISC_TIME;\r
-typedef struct\r
-{\r
- ISC_DATE timestamp_date;\r
- ISC_TIME timestamp_time;\r
-} ISC_TIMESTAMP;\r
-#define ISC_TIMESTAMP_DEFINED\r
-#endif /* ISC_TIMESTAMP_DEFINED */\r
-\r
-#define ISC_TIME_SECONDS_PRECISION 10000L\r
-#define ISC_TIME_SECONDS_PRECISION_SCALE (-4)\r
-\r
-/*******************************************************************/\r
-/* Blob id structure */\r
-/*******************************************************************/\r
-\r
-#if !(defined __cplusplus)\r
-typedef GDS_QUAD GDS__QUAD;\r
-#endif /* !(defined __cplusplus) */\r
-\r
-typedef struct GDS_QUAD_t ISC_QUAD;\r
-\r
-#define isc_quad_high gds_quad_high\r
-#define isc_quad_low gds_quad_low\r
-\r
-typedef struct\r
-{\r
- short array_bound_lower;\r
- short array_bound_upper;\r
-} ISC_ARRAY_BOUND;\r
-\r
-typedef struct\r
-{\r
- unsigned char array_desc_dtype;\r
- char array_desc_scale;\r
- unsigned short array_desc_length;\r
- char array_desc_field_name[32];\r
- char array_desc_relation_name[32];\r
- short array_desc_dimensions;\r
- short array_desc_flags;\r
- ISC_ARRAY_BOUND array_desc_bounds[16];\r
-} ISC_ARRAY_DESC;\r
-\r
-typedef struct\r
-{\r
- short blob_desc_subtype;\r
- short blob_desc_charset;\r
- short blob_desc_segment_size;\r
- unsigned char blob_desc_field_name[32];\r
- unsigned char blob_desc_relation_name[32];\r
-} ISC_BLOB_DESC;\r
-\r
-\r
-\r
-/***************************/\r
-/* Blob control structure */\r
-/***************************/\r
-\r
-typedef struct isc_blob_ctl\r
-{\r
- ISC_STATUS (* ctl_source)(); /* Source filter */\r
- struct isc_blob_ctl * ctl_source_handle; /* Argument to pass to source filter */\r
- short ctl_to_sub_type; /* Target type */\r
- short ctl_from_sub_type; /* Source type */\r
- unsigned short ctl_buffer_length; /* Length of buffer */\r
- unsigned short ctl_segment_length; /* Length of current segment */\r
- unsigned short ctl_bpb_length; /* Length of blob parameter block */\r
- char * ctl_bpb; /* Address of blob parameter block */\r
- unsigned char * ctl_buffer; /* Address of segment buffer */\r
- ISC_LONG ctl_max_segment; /* Length of longest segment */\r
- ISC_LONG ctl_number_segments; /* Total number of segments */\r
- ISC_LONG ctl_total_length; /* Total length of blob */\r
- ISC_STATUS * ctl_status; /* Address of status vector */\r
- long ctl_data[8]; /* Application specific data */\r
-} * ISC_BLOB_CTL;\r
-\r
-/***************************/\r
-/* Blob stream definitions */\r
-/***************************/\r
-\r
-typedef struct bstream\r
-{\r
- isc_blob_handle bstr_blob; /* Blob handle */\r
- char * bstr_buffer; /* Address of buffer */\r
- char * bstr_ptr; /* Next character */\r
- short bstr_length; /* Length of buffer */\r
- short bstr_cnt; /* Characters in buffer */\r
- char bstr_mode; /* (mode) ? OUTPUT : INPUT */\r
-} BSTREAM;\r
-\r
-/* Three ugly macros, one even using octal radix... sigh... */\r
-#define getb(p) (--(p)->bstr_cnt >= 0 ? *(p)->bstr_ptr++ & 0377: BLOB_get (p))\r
-#define putb(x,p) (((x) == '\n' || (!(--(p)->bstr_cnt))) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
-#define putbx(x,p) ((!(--(p)->bstr_cnt)) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
-\r
-\r
-/********************************************************************/\r
-/* CVC: Public blob interface definition held in val.h. */\r
-/* For some unknown reason, it was only documented in langRef */\r
-/* and being the structure passed by the engine to UDFs it never */\r
-/* made its way into this public definitions file. */\r
-/* Being its original name "blob", I renamed it blobcallback here. */\r
-/* I did the full definition with the proper parameters instead of */\r
-/* the weak C declaration with any number and type of parameters. */\r
-/* Since the first parameter -BLB- is unknown outside the engine, */\r
-/* it's more accurate to use void* than int* as the blob pointer */\r
-/********************************************************************/\r
-\r
-#if !defined(JRD_VAL_H) && !defined(REQUESTER)\r
-/* Blob passing structure */\r
-\r
-enum lseek_mode {blb_seek_relative = 1, blb_seek_from_tail = 2};\r
-\r
-typedef struct blobcallback {\r
- short ( *blob_get_segment)\r
- (void * hnd, unsigned char* buffer, ISC_USHORT buf_size, ISC_USHORT* result_len);\r
- void *blob_handle;\r
- ISC_LONG blob_number_segments;\r
- ISC_LONG blob_max_segment;\r
- ISC_LONG blob_total_length;\r
- void ( *blob_put_segment)\r
- (void * hnd, unsigned char* buffer, ISC_USHORT buf_size);\r
- ISC_LONG ( *blob_lseek)\r
- (void * hnd, ISC_USHORT mode, ISC_LONG offset);\r
-} *BLOBCALLBACK;\r
-#endif /* !defined(JRD_VAL_H) && !defined(REQUESTER) */\r
-\r
-\r
-\r
-/********************************************************************/\r
-/* CVC: Public descriptor interface held in dsc.h. */\r
-/* We need it documented to be able to recognize NULL in UDFs. */\r
-/* Being its original name "dsc", I renamed it paramdsc here. */\r
-/* Notice that I adjust to the original definition: contrary to */\r
-/* other cases, the typedef is the same struct not the pointer. */\r
-/* I included the enumeration of dsc_dtype possible values. */\r
-/* Ultimately, dsc.h should be part of the public interface. */\r
-/********************************************************************/\r
-\r
-#if !defined(JRD_DSC_H)\r
-/* This is the famous internal descriptor that UDFs can use, too. */\r
-typedef struct paramdsc {\r
- unsigned char dsc_dtype;\r
- signed char dsc_scale;\r
- ISC_USHORT dsc_length;\r
- short dsc_sub_type;\r
- ISC_USHORT dsc_flags;\r
- unsigned char *dsc_address;\r
-} PARAMDSC;\r
-\r
-#if !defined(JRD_VAL_H)\r
-/* This is a helper struct to work with varchars. */\r
-typedef struct paramvary {\r
- ISC_USHORT vary_length;\r
- unsigned char vary_string [1];\r
-} PARAMVARY;\r
-#endif /* !defined(JRD_VAL_H) */\r
-\r
-/* values for dsc_flags */\r
-/* Note: DSC_null is only reliably set for local variables\r
- (blr_variable) */\r
-#define DSC_null 1\r
-#define DSC_no_subtype 2 /* dsc has no sub type specified */\r
-#define DSC_nullable 4 /* not stored. instead, is derived\r
- from metadata primarily to flag\r
- SQLDA (in DSQL) */\r
-\r
-/* Overload text typing information into the dsc_sub_type field.\r
- See intl.h for definitions of text types */ \r
-\r
-#ifndef dsc_ttype\r
-#define dsc_ttype dsc_sub_type\r
-#endif\r
-\r
-\r
-/* Note that dtype_null actually means that we do not yet know the\r
- dtype for this descriptor. A nice cleanup item would be to globally\r
- change it to dtype_unknown. --chrisj 1999-02-17 */\r
-\r
-#define dtype_null 0\r
-#define dtype_text 1\r
-#define dtype_cstring 2\r
-#define dtype_varying 3\r
-\r
-#define dtype_packed 6\r
-#define dtype_byte 7\r
-#define dtype_short 8\r
-#define dtype_long 9\r
-#define dtype_quad 10\r
-#define dtype_real 11\r
-#define dtype_double 12\r
-#define dtype_d_float 13\r
-#define dtype_sql_date 14\r
-#define dtype_sql_time 15\r
-#define dtype_timestamp 16\r
-#define dtype_blob 17\r
-#define dtype_array 18\r
-#define dtype_int64 19\r
-#define DTYPE_TYPE_MAX 20\r
-#endif /* !defined(JRD_DSC_H) */\r
-\r
-\r
-/***************************/\r
-/* Dynamic SQL definitions */\r
-/***************************/\r
-\r
-/******************************/\r
-/* Declare the extended SQLDA */\r
-/******************************/\r
-\r
-#ifndef FB_SQLDA\r
-\r
-typedef struct\r
-{\r
- short sqltype; /* datatype of field */\r
- short sqlscale; /* scale factor */\r
- short sqlsubtype; /* datatype subtype - BLOBs & Text types only */\r
- short sqllen; /* length of data area */\r
- char * sqldata; /* address of data */\r
- short * sqlind; /* address of indicator variable */\r
- short sqlname_length; /* length of sqlname field */\r
- char sqlname[32]; /* name of field, name length + space for NULL */\r
- short relname_length; /* length of relation name */\r
- char relname[32]; /* field's relation name + space for NULL */\r
- short ownname_length; /* length of owner name */\r
- char ownname[32]; /* relation's owner name + space for NULL */\r
- short aliasname_length; /* length of alias name */\r
- char aliasname[32]; /* relation's alias name + space for NULL */\r
-} XSQLVAR;\r
-\r
-typedef struct\r
-{\r
- short version; /* version of this XSQLDA */\r
- char sqldaid[8]; /* XSQLDA name field */\r
- ISC_LONG sqldabc; /* length in bytes of SQLDA */\r
- short sqln; /* number of fields allocated */\r
- short sqld; /* actual number of fields */\r
- XSQLVAR sqlvar[1]; /* first field address */\r
-} XSQLDA;\r
-\r
-#define XSQLDA_LENGTH(n) (sizeof (XSQLDA) + ((n)-1) * sizeof (XSQLVAR))\r
-\r
-#define SQLDA_VERSION1 1\r
-\r
-#define SQL_DIALECT_V5 1 /* meaning is same as DIALECT_xsqlda */\r
-#define SQL_DIALECT_V6_TRANSITION 2 /* flagging anything that is delimited\r
- by double quotes as an error and\r
- flagging keyword DATE as an error */\r
-#define SQL_DIALECT_V6 3 /* supports SQL delimited identifier,\r
- SQLDATE/DATE, TIME, TIMESTAMP,\r
- CURRENT_DATE, CURRENT_TIME,\r
- CURRENT_TIMESTAMP, and 64-bit exact\r
- numeric type */\r
-#define SQL_DIALECT_CURRENT SQL_DIALECT_V6 /* latest IB DIALECT */\r
-\r
-\r
-#define FB_SQLDA\r
-#endif\r
-\r
-/***************************/\r
-/* OSRI database functions */\r
-/***************************/\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-ISC_STATUS ISC_EXPORT isc_attach_database(ISC_STATUS *,\r
- short,\r
- char *,\r
- isc_db_handle *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_gen_sdl(ISC_STATUS *,\r
- ISC_ARRAY_DESC *,\r
- short *,\r
- char *,\r
- short *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_get_slice(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- ISC_ARRAY_DESC *,\r
- void *,\r
- ISC_LONG *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_lookup_bounds(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- char *,\r
- char *,\r
- ISC_ARRAY_DESC *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_lookup_desc(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- char *,\r
- char *,\r
- ISC_ARRAY_DESC *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_set_desc(ISC_STATUS *,\r
- char *,\r
- char *,\r
- short *,\r
- short *,\r
- short *,\r
- ISC_ARRAY_DESC *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_array_put_slice(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- ISC_ARRAY_DESC *,\r
- void *,\r
- ISC_LONG *);\r
-\r
-void ISC_EXPORT isc_blob_default_desc(ISC_BLOB_DESC *,\r
- unsigned char *,\r
- unsigned char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_blob_gen_bpb(ISC_STATUS *,\r
- ISC_BLOB_DESC *,\r
- ISC_BLOB_DESC *,\r
- unsigned short,\r
- unsigned char *,\r
- unsigned short *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_blob_info(ISC_STATUS *,\r
- isc_blob_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_blob_lookup_desc(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned char *,\r
- unsigned char *,\r
- ISC_BLOB_DESC *,\r
- unsigned char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_blob_set_desc(ISC_STATUS *,\r
- unsigned char *,\r
- unsigned char *,\r
- short,\r
- short,\r
- short,\r
- ISC_BLOB_DESC *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_cancel_blob(ISC_STATUS *,\r
- isc_blob_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_cancel_events(ISC_STATUS *,\r
- isc_db_handle *,\r
- ISC_LONG *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_close_blob(ISC_STATUS *,\r
- isc_blob_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_commit_retaining(ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_commit_transaction(ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_create_blob(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_create_blob2(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_create_database(ISC_STATUS *,\r
- short,\r
- char *,\r
- isc_db_handle *,\r
- short,\r
- char *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_database_info(ISC_STATUS *,\r
- isc_db_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-void ISC_EXPORT isc_decode_date(ISC_QUAD *,\r
- void *);\r
-\r
-void ISC_EXPORT isc_decode_sql_date(ISC_DATE *,\r
- void *);\r
-\r
-void ISC_EXPORT isc_decode_sql_time(ISC_TIME *,\r
- void *);\r
-\r
-void ISC_EXPORT isc_decode_timestamp(ISC_TIMESTAMP *,\r
- void *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_detach_database(ISC_STATUS *,\r
- isc_db_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_drop_database(ISC_STATUS *,\r
- isc_db_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_allocate_statement(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_stmt_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_alloc_statement2(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_stmt_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_describe(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_describe_bind(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_exec_immed2(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute2(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_fetch(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_finish(isc_db_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_free_statement(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_insert(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_prepare(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_set_cursor_name(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- char *,\r
- unsigned short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_sql_info(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- short,\r
- const char *,\r
- short,\r
- char *);\r
-\r
-void ISC_EXPORT isc_encode_date(void *,\r
- ISC_QUAD *);\r
-\r
-void ISC_EXPORT isc_encode_sql_date(void *,\r
- ISC_DATE *);\r
-\r
-void ISC_EXPORT isc_encode_sql_time(void *,\r
- ISC_TIME *);\r
-\r
-void ISC_EXPORT isc_encode_timestamp(void *,\r
- ISC_TIMESTAMP *);\r
-\r
-ISC_LONG ISC_EXPORT_VARARG isc_event_block(char * *,\r
- char * *,\r
- unsigned short, ...);\r
-\r
-void ISC_EXPORT isc_event_counts(ISC_ULONG *,\r
- short,\r
- char *,\r
- char *);\r
-\r
-/* 17 May 2001 - isc_expand_dpb is DEPRECATED */\r
-void ISC_EXPORT_VARARG isc_expand_dpb(char * *,\r
- short *, ...);\r
-\r
-int ISC_EXPORT isc_modify_dpb(char * *,\r
- short *,\r
- unsigned short,\r
- char *,\r
- short);\r
-\r
-ISC_LONG ISC_EXPORT isc_free(char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_get_segment(ISC_STATUS *,\r
- isc_blob_handle *,\r
- unsigned short *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_get_slice(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- short,\r
- char *,\r
- short,\r
- ISC_LONG *,\r
- ISC_LONG,\r
- void *,\r
- ISC_LONG *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_interprete(char *,\r
- ISC_STATUS * *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_open_blob(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_open_blob2(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- isc_blob_handle *,\r
- ISC_QUAD *,\r
- ISC_USHORT,\r
- ISC_UCHAR *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_prepare_transaction2(ISC_STATUS *,\r
- isc_tr_handle *,\r
- ISC_USHORT,\r
- ISC_UCHAR *);\r
-\r
-void ISC_EXPORT isc_print_sqlerror(ISC_SHORT,\r
- ISC_STATUS *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_print_status(ISC_STATUS *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_put_segment(ISC_STATUS *,\r
- isc_blob_handle *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_put_slice(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- ISC_QUAD *,\r
- short,\r
- char *,\r
- short,\r
- ISC_LONG *,\r
- ISC_LONG,\r
- void *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_que_events(ISC_STATUS *,\r
- isc_db_handle *,\r
- ISC_LONG *,\r
- short,\r
- char *,\r
- isc_callback,\r
- void *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_rollback_retaining(ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_rollback_transaction(ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_start_multiple(ISC_STATUS *,\r
- isc_tr_handle *,\r
- short,\r
- void *);\r
-\r
-ISC_STATUS ISC_EXPORT_VARARG isc_start_transaction(ISC_STATUS *,\r
- isc_tr_handle *,\r
- short, ...);\r
-\r
-ISC_LONG ISC_EXPORT isc_sqlcode(ISC_STATUS *);\r
-\r
-void ISC_EXPORT isc_sql_interprete(short,\r
- char *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_transaction_info(ISC_STATUS *,\r
- isc_tr_handle *,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_transact_request(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_LONG ISC_EXPORT isc_vax_integer(char *,\r
- short);\r
-\r
-ISC_INT64 ISC_EXPORT isc_portable_integer(unsigned char *,\r
- short);\r
-\r
-/*************************************/\r
-/* Security Functions and structures */\r
-/*************************************/\r
-\r
-#define sec_uid_spec 0x01\r
-#define sec_gid_spec 0x02\r
-#define sec_server_spec 0x04\r
-#define sec_password_spec 0x08\r
-#define sec_group_name_spec 0x10\r
-#define sec_first_name_spec 0x20\r
-#define sec_middle_name_spec 0x40\r
-#define sec_last_name_spec 0x80\r
-#define sec_dba_user_name_spec 0x100\r
-#define sec_dba_password_spec 0x200\r
-\r
-#define sec_protocol_tcpip 1\r
-#define sec_protocol_netbeui 2\r
-#define sec_protocol_spx 3 /* -- Deprecated Protocol. Declaration retained for compatibility */\r
-#define sec_protocol_local 4\r
-\r
-typedef struct {\r
- short sec_flags; /* which fields are specified */\r
- int uid; /* the user's id */\r
- int gid; /* the user's group id */\r
- int protocol; /* protocol to use for connection */\r
- char *server; /* server to administer */\r
- char *user_name; /* the user's name */\r
- char *password; /* the user's password */\r
- char *group_name; /* the group name */\r
- char *first_name; /* the user's first name */\r
- char *middle_name; /* the user's middle name */\r
- char *last_name; /* the user's last name */\r
- char *dba_user_name; /* the dba user name */\r
- char *dba_password; /* the dba password */\r
-} USER_SEC_DATA;\r
-\r
-int ISC_EXPORT isc_add_user(ISC_STATUS *, USER_SEC_DATA *);\r
-\r
-int ISC_EXPORT isc_delete_user(ISC_STATUS *, USER_SEC_DATA *);\r
-\r
-int ISC_EXPORT isc_modify_user(ISC_STATUS *, USER_SEC_DATA *);\r
-\r
-/**********************************/\r
-/* Other OSRI functions */\r
-/**********************************/\r
-\r
-ISC_STATUS ISC_EXPORT isc_compile_request(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_req_handle *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_compile_request2(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_req_handle *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_ddl(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_prepare_transaction(ISC_STATUS *,\r
- isc_tr_handle *);\r
-\r
-\r
-ISC_STATUS ISC_EXPORT isc_receive(ISC_STATUS *,\r
- isc_req_handle *,\r
- short,\r
- short,\r
- void *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_reconnect_transaction(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_release_request(ISC_STATUS *,\r
- isc_req_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_request_info(ISC_STATUS *,\r
- isc_req_handle *,\r
- short,\r
- short,\r
- char *,\r
- short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_seek_blob(ISC_STATUS *,\r
- isc_blob_handle *,\r
- short,\r
- ISC_LONG,\r
- ISC_LONG *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_send(ISC_STATUS *,\r
- isc_req_handle *,\r
- short,\r
- short,\r
- void *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_start_and_send(ISC_STATUS *,\r
- isc_req_handle *,\r
- isc_tr_handle *,\r
- short,\r
- short,\r
- void *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_start_request(ISC_STATUS *,\r
- isc_req_handle *,\r
- isc_tr_handle *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_unwind_request(ISC_STATUS *,\r
- isc_tr_handle *,\r
- short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_wait_for_event(ISC_STATUS *,\r
- isc_db_handle *,\r
- short,\r
- char *,\r
- char *);\r
-\r
-\r
-/*****************************/\r
-/* Other Sql functions */\r
-/*****************************/\r
-\r
-ISC_STATUS ISC_EXPORT isc_close(ISC_STATUS *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_declare(ISC_STATUS *,\r
- char *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_describe(ISC_STATUS *,\r
- char *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_describe_bind(ISC_STATUS *,\r
- char *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_execute(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_execute_immediate(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- short *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_fetch(ISC_STATUS *,\r
- char *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_open(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_prepare(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- char *,\r
- short *,\r
- char *,\r
- XSQLDA *);\r
-\r
-\r
-/*************************************/\r
-/* Other Dynamic sql functions */\r
-/*************************************/\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute_m(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute2_m(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate_m(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_exec_immed3_m(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_fetch_m(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_insert_m(ISC_STATUS *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_prepare_m(ISC_STATUS *,\r
- isc_tr_handle *,\r
- isc_stmt_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_dsql_release(ISC_STATUS *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_close(ISC_STATUS *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_declare(ISC_STATUS *,\r
- char *,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_describe(ISC_STATUS *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_describe_bind(ISC_STATUS *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_execute(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_execute2(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_execute_immed(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_fetch(ISC_STATUS *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_open(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_open2(ISC_STATUS *,\r
- isc_tr_handle *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_insert(ISC_STATUS *,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_prepare(ISC_STATUS *,\r
- isc_db_handle *,\r
- isc_tr_handle *,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- XSQLDA *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_embed_dsql_release(ISC_STATUS *,\r
- char *);\r
-\r
-\r
-/******************************/\r
-/* Other Blob functions */\r
-/******************************/\r
-\r
-BSTREAM *ISC_EXPORT BLOB_open(isc_blob_handle,\r
- char *,\r
- int);\r
-\r
-int ISC_EXPORT BLOB_put(char,\r
- BSTREAM *);\r
-\r
-int ISC_EXPORT BLOB_close(BSTREAM *);\r
-\r
-int ISC_EXPORT BLOB_get(BSTREAM *);\r
-\r
-int ISC_EXPORT BLOB_display(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-int ISC_EXPORT BLOB_dump(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-int ISC_EXPORT BLOB_edit(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-int ISC_EXPORT BLOB_load(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-int ISC_EXPORT BLOB_text_dump(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-int ISC_EXPORT BLOB_text_load(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-BSTREAM *ISC_EXPORT Bopen(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *);\r
-\r
-BSTREAM *ISC_EXPORT Bopen2(ISC_QUAD *,\r
- isc_db_handle,\r
- isc_tr_handle,\r
- char *,\r
- unsigned short);\r
-\r
-\r
-/******************************/\r
-/* Other Misc functions */\r
-/******************************/\r
-\r
-ISC_LONG ISC_EXPORT isc_ftof(char *,\r
- unsigned short,\r
- char *,\r
- unsigned short);\r
-\r
-ISC_STATUS ISC_EXPORT isc_print_blr(char *,\r
- isc_callback,\r
- void *,\r
- short);\r
-\r
-void ISC_EXPORT isc_set_debug(int);\r
-\r
-void ISC_EXPORT isc_qtoq(ISC_QUAD *,\r
- ISC_QUAD *);\r
-\r
-void ISC_EXPORT isc_vtof(char *,\r
- char *,\r
- unsigned short);\r
-\r
-void ISC_EXPORT isc_vtov(char *,\r
- char *,\r
- short);\r
-\r
-int ISC_EXPORT isc_version(isc_db_handle *,\r
- isc_callback,\r
- void *);\r
-\r
-ISC_LONG ISC_EXPORT isc_reset_fpe(unsigned short);\r
-\r
-\r
-/*****************************************/\r
-/* Service manager functions */\r
-/*****************************************/\r
-\r
-#define ADD_SPB_LENGTH(p, length) {*(p)++ = (length); *(p)++ = (length) >> 8;}\r
-\r
-#define ADD_SPB_NUMERIC(p, data) {*(p)++ = (SCHAR) (data); *(p)++ = (SCHAR) ((data) >> 8); *(p)++ = (SCHAR) ((data) >> 16); *(p)++ = (SCHAR) ((data) >> 24);}\r
-\r
-ISC_STATUS ISC_EXPORT isc_service_attach(ISC_STATUS *,\r
- unsigned short,\r
- char *,\r
- isc_svc_handle *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_service_detach(ISC_STATUS *,\r
- isc_svc_handle *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_service_query(ISC_STATUS *,\r
- isc_svc_handle *,\r
- isc_resv_handle *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *,\r
- unsigned short,\r
- char *);\r
-\r
-ISC_STATUS ISC_EXPORT isc_service_start(ISC_STATUS *,\r
- isc_svc_handle *,\r
- isc_resv_handle *,\r
- unsigned short,\r
- char *);\r
-\r
-\r
-/********************************/\r
-/* Client information functions */\r
-/********************************/\r
-\r
-void ISC_EXPORT isc_get_client_version ( char *);\r
-int ISC_EXPORT isc_get_client_major_version ();\r
-int ISC_EXPORT isc_get_client_minor_version ();\r
-\r
-#ifdef __cplusplus\r
-} /* extern "C" */\r
-#endif\r
-\r
-\r
-/***************************************************/\r
-/* Actions to pass to the blob filter (ctl_source) */\r
-/***************************************************/\r
-\r
-#define isc_blob_filter_open 0\r
-#define isc_blob_filter_get_segment 1\r
-#define isc_blob_filter_close 2\r
-#define isc_blob_filter_create 3\r
-#define isc_blob_filter_put_segment 4\r
-#define isc_blob_filter_alloc 5\r
-#define isc_blob_filter_free 6\r
-#define isc_blob_filter_seek 7\r
-\r
-/*******************/\r
-/* Blr definitions */\r
-/*******************/\r
-\r
-/*\r
- * PROGRAM: C preprocessor\r
- * MODULE: blr.h\r
- * DESCRIPTION: BLR constants\r
- *\r
- * The contents of this file are subject to the Interbase Public\r
- * License Version 1.0 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy\r
- * of the License at http://www.Inprise.com/IPL.html\r
- *\r
- * Software distributed under the License is distributed on an\r
- * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code was created by Inprise Corporation\r
- * and its predecessors. Portions created by Inprise Corporation are\r
- * Copyright (C) Inprise Corporation.\r
- *\r
- * All Rights Reserved.\r
- * Contributor(s): ______________________________________.\r
- *\r
- * Claudio Valderrama: 2001.6.18: Add blr_current_role.\r
- * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced\r
- * exception handling in SPs/triggers,\r
- * implemented ROWS_AFFECTED system variable\r
- * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks\r
- * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
- */\r
-\r
-#ifndef _JRD_BLR_H_\r
-#define _JRD_BLR_H_\r
-\r
-/* WARNING: if you add a new BLR representing a data type, and the value\r
- * is greater than the numerically greatest value which now\r
- * represents a data type, you must change the define for\r
- * DTYPE_BLR_MAX in jrd/align.h, and add the necessary entries\r
- * to all the arrays in that file.\r
- */\r
-\r
-#define blr_text (unsigned char)14\r
-#define blr_text2 (unsigned char)15 /* added in 3.2 JPN */\r
-#define blr_short (unsigned char)7\r
-#define blr_long (unsigned char)8\r
-#define blr_quad (unsigned char)9\r
-#define blr_float (unsigned char)10\r
-#define blr_double (unsigned char)27\r
-#define blr_d_float (unsigned char)11\r
-#define blr_timestamp (unsigned char)35\r
-#define blr_varying (unsigned char)37\r
-#define blr_varying2 (unsigned char)38 /* added in 3.2 JPN */\r
-#define blr_blob (unsigned short)261\r
-#define blr_cstring (unsigned char)40 \r
-#define blr_cstring2 (unsigned char)41 /* added in 3.2 JPN */\r
-#define blr_blob_id (unsigned char)45 /* added from gds.h */\r
-#define blr_sql_date (unsigned char)12\r
-#define blr_sql_time (unsigned char)13\r
-#define blr_int64 (unsigned char)16\r
-\r
-/* Historical alias for pre V6 applications */\r
-#define blr_date blr_timestamp\r
-\r
-#define blr_inner (unsigned char)0\r
-#define blr_left (unsigned char)1\r
-#define blr_right (unsigned char)2\r
-#define blr_full (unsigned char)3\r
-\r
-#define blr_gds_code (unsigned char)0\r
-#define blr_sql_code (unsigned char)1\r
-#define blr_exception (unsigned char)2\r
-#define blr_trigger_code (unsigned char)3\r
-#define blr_default_code (unsigned char)4\r
-#define blr_raise (unsigned char)5\r
-#define blr_exception_msg (unsigned char)6\r
-\r
-#define blr_version4 (unsigned char)4\r
-#define blr_version5 (unsigned char)5\r
-#define blr_eoc (unsigned char)76\r
-#define blr_end (unsigned char)255 /* note: defined as -1 in gds.h */\r
-\r
-#define blr_assignment (unsigned char)1\r
-#define blr_begin (unsigned char)2\r
-#define blr_dcl_variable (unsigned char)3 /* added from gds.h */\r
-#define blr_message (unsigned char)4\r
-#define blr_erase (unsigned char)5\r
-#define blr_fetch (unsigned char)6\r
-#define blr_for (unsigned char)7\r
-#define blr_if (unsigned char)8\r
-#define blr_loop (unsigned char)9\r
-#define blr_modify (unsigned char)10\r
-#define blr_handler (unsigned char)11\r
-#define blr_receive (unsigned char)12\r
-#define blr_select (unsigned char)13\r
-#define blr_send (unsigned char)14\r
-#define blr_store (unsigned char)15\r
-#define blr_label (unsigned char)17\r
-#define blr_leave (unsigned char)18\r
-#define blr_store2 (unsigned char)19\r
-#define blr_post (unsigned char)20\r
-#define blr_literal (unsigned char)21\r
-#define blr_dbkey (unsigned char)22\r
-#define blr_field (unsigned char)23\r
-#define blr_fid (unsigned char)24\r
-#define blr_parameter (unsigned char)25\r
-#define blr_variable (unsigned char)26\r
-#define blr_average (unsigned char)27\r
-#define blr_count (unsigned char)28\r
-#define blr_maximum (unsigned char)29\r
-#define blr_minimum (unsigned char)30\r
-#define blr_total (unsigned char)31\r
-/* count 2\r
-#define blr_count2 32\r
-*/\r
-#define blr_add (unsigned char)34\r
-#define blr_subtract (unsigned char)35\r
-#define blr_multiply (unsigned char)36\r
-#define blr_divide (unsigned char)37\r
-#define blr_negate (unsigned char)38\r
-#define blr_concatenate (unsigned char)39\r
-#define blr_substring (unsigned char)40\r
-#define blr_parameter2 (unsigned char)41\r
-#define blr_from (unsigned char)42\r
-#define blr_via (unsigned char)43\r
-#define blr_parameter2_old (unsigned char)44 /* Confusion */\r
-#define blr_user_name (unsigned char)44 /* added from gds.h */\r
-#define blr_null (unsigned char)45\r
-\r
-#define blr_eql (unsigned char)47\r
-#define blr_neq (unsigned char)48\r
-#define blr_gtr (unsigned char)49\r
-#define blr_geq (unsigned char)50\r
-#define blr_lss (unsigned char)51\r
-#define blr_leq (unsigned char)52\r
-#define blr_containing (unsigned char)53\r
-#define blr_matching (unsigned char)54\r
-#define blr_starting (unsigned char)55\r
-#define blr_between (unsigned char)56\r
-#define blr_or (unsigned char)57\r
-#define blr_and (unsigned char)58\r
-#define blr_not (unsigned char)59\r
-#define blr_any (unsigned char)60\r
-#define blr_missing (unsigned char)61\r
-#define blr_unique (unsigned char)62\r
-#define blr_like (unsigned char)63\r
-\r
-#define blr_stream (unsigned char)65 /* added from gds.h */\r
-#define blr_set_index (unsigned char)66 /* added from gds.h */\r
-\r
-#define blr_rse (unsigned char)67\r
-#define blr_first (unsigned char)68\r
-#define blr_project (unsigned char)69\r
-#define blr_sort (unsigned char)70\r
-#define blr_boolean (unsigned char)71\r
-#define blr_ascending (unsigned char)72\r
-#define blr_descending (unsigned char)73\r
-#define blr_relation (unsigned char)74\r
-#define blr_rid (unsigned char)75\r
-#define blr_union (unsigned char)76\r
-#define blr_map (unsigned char)77\r
-#define blr_group_by (unsigned char)78\r
-#define blr_aggregate (unsigned char)79\r
-#define blr_join_type (unsigned char)80\r
-\r
-#define blr_agg_count (unsigned char)83\r
-#define blr_agg_max (unsigned char)84\r
-#define blr_agg_min (unsigned char)85\r
-#define blr_agg_total (unsigned char)86\r
-#define blr_agg_average (unsigned char)87\r
-#define blr_parameter3 (unsigned char)88 /* same as Rdb definition */\r
-#define blr_run_max (unsigned char)89\r
-#define blr_run_min (unsigned char)90\r
-#define blr_run_total (unsigned char)91\r
-#define blr_run_average (unsigned char)92\r
-#define blr_agg_count2 (unsigned char)93\r
-#define blr_agg_count_distinct (unsigned char)94\r
-#define blr_agg_total_distinct (unsigned char)95\r
-#define blr_agg_average_distinct (unsigned char)96\r
-\r
-#define blr_function (unsigned char)100\r
-#define blr_gen_id (unsigned char)101\r
-#define blr_prot_mask (unsigned char)102\r
-#define blr_upcase (unsigned char)103\r
-#define blr_lock_state (unsigned char)104\r
-#define blr_value_if (unsigned char)105\r
-#define blr_matching2 (unsigned char)106\r
-#define blr_index (unsigned char)107\r
-#define blr_ansi_like (unsigned char)108\r
-#define blr_bookmark (unsigned char)109\r
-#define blr_crack (unsigned char)110\r
-#define blr_force_crack (unsigned char)111\r
-#define blr_seek (unsigned char)112\r
-#define blr_find (unsigned char)113\r
- \r
-/* these indicate directions for blr_seek and blr_find */\r
-\r
-#define blr_continue (unsigned char)0\r
-#define blr_forward (unsigned char)1\r
-#define blr_backward (unsigned char)2\r
-#define blr_bof_forward (unsigned char)3\r
-#define blr_eof_backward (unsigned char)4\r
-\r
-#define blr_lock_relation (unsigned char)114\r
-#define blr_lock_record (unsigned char)115\r
-#define blr_set_bookmark (unsigned char)116\r
-#define blr_get_bookmark (unsigned char)117\r
-\r
-#define blr_run_count (unsigned char)118 /* changed from 88 to avoid conflict with blr_parameter3 */\r
-#define blr_rs_stream (unsigned char)119\r
-#define blr_exec_proc (unsigned char)120\r
-#define blr_begin_range (unsigned char)121\r
-#define blr_end_range (unsigned char)122\r
-#define blr_delete_range (unsigned char)123\r
-#define blr_procedure (unsigned char)124\r
-#define blr_pid (unsigned char)125\r
-#define blr_exec_pid (unsigned char)126\r
-#define blr_singular (unsigned char)127\r
-#define blr_abort (unsigned char)128\r
-#define blr_block (unsigned char)129\r
-#define blr_error_handler (unsigned char)130\r
-\r
-#define blr_cast (unsigned char)131\r
-#define blr_release_lock (unsigned char)132\r
-#define blr_release_locks (unsigned char)133\r
-#define blr_start_savepoint (unsigned char)134\r
-#define blr_end_savepoint (unsigned char)135\r
-#define blr_find_dbkey (unsigned char)136\r
-#define blr_range_relation (unsigned char)137\r
-#define blr_delete_ranges (unsigned char)138\r
-\r
-#define blr_plan (unsigned char)139 /* access plan items */\r
-#define blr_merge (unsigned char)140\r
-#define blr_join (unsigned char)141\r
-#define blr_sequential (unsigned char)142\r
-#define blr_navigational (unsigned char)143\r
-#define blr_indices (unsigned char)144\r
-#define blr_retrieve (unsigned char)145\r
-\r
-#define blr_relation2 (unsigned char)146\r
-#define blr_rid2 (unsigned char)147\r
-#define blr_reset_stream (unsigned char)148\r
-#define blr_release_bookmark (unsigned char)149\r
-\r
-#define blr_set_generator (unsigned char)150\r
-\r
-#define blr_ansi_any (unsigned char)151 /* required for NULL handling */\r
-#define blr_exists (unsigned char)152 /* required for NULL handling */\r
-#define blr_cardinality (unsigned char)153\r
-\r
-#define blr_record_version (unsigned char)154 /* get tid of record */\r
-#define blr_stall (unsigned char)155 /* fake server stall */\r
-\r
-#define blr_seek_no_warn (unsigned char)156 \r
-#define blr_find_dbkey_version (unsigned char)157 /* find dbkey with record version */\r
-#define blr_ansi_all (unsigned char)158 /* required for NULL handling */\r
-\r
-#define blr_extract (unsigned char)159\r
-\r
-/* sub parameters for blr_extract */\r
-\r
-#define blr_extract_year (unsigned char)0\r
-#define blr_extract_month (unsigned char)1\r
-#define blr_extract_day (unsigned char)2\r
-#define blr_extract_hour (unsigned char)3\r
-#define blr_extract_minute (unsigned char)4\r
-#define blr_extract_second (unsigned char)5\r
-#define blr_extract_weekday (unsigned char)6\r
-#define blr_extract_yearday (unsigned char)7\r
-\r
-#define blr_current_date (unsigned char)160\r
-#define blr_current_timestamp (unsigned char)161\r
-#define blr_current_time (unsigned char)162\r
-\r
-/* FB 1.0 specific BLR */\r
-\r
-#define blr_current_role (unsigned char)174\r
-#define blr_skip (unsigned char)175\r
-\r
-/* FB 1.5 specific BLR */\r
-\r
-#define blr_exec_sql (unsigned char)176\r
-#define blr_internal_info (unsigned char)177\r
-#define blr_nullsfirst (unsigned char)178\r
-#define blr_writelock (unsigned char)179\r
-#define blr_nullslast (unsigned char)180\r
-\r
-/* These codes reuse BLR code space */\r
-\r
-#define blr_post_arg (unsigned char)163\r
-#define blr_exec_into (unsigned char)164\r
-#define blr_user_savepoint (unsigned char)165\r
-\r
-/* These codes are actions for user-defined savepoints */\r
-\r
-#define blr_savepoint_set (unsigned char)0\r
-#define blr_savepoint_release (unsigned char)1\r
-#define blr_savepoint_undo (unsigned char)2\r
-#define blr_savepoint_release_single (unsigned char)3\r
-\r
-#endif /* _JRD_BLR_H_ */\r
-\r
-\r
-/**********************************/\r
-/* Database parameter block stuff */\r
-/**********************************/\r
-\r
-#define isc_dpb_version1 1\r
-#define isc_dpb_cdd_pathname 1\r
-#define isc_dpb_allocation 2\r
-#define isc_dpb_journal 3\r
-#define isc_dpb_page_size 4\r
-#define isc_dpb_num_buffers 5\r
-#define isc_dpb_buffer_length 6\r
-#define isc_dpb_debug 7\r
-#define isc_dpb_garbage_collect 8\r
-#define isc_dpb_verify 9\r
-#define isc_dpb_sweep 10\r
-#define isc_dpb_enable_journal 11\r
-#define isc_dpb_disable_journal 12\r
-#define isc_dpb_dbkey_scope 13\r
-#define isc_dpb_number_of_users 14\r
-#define isc_dpb_trace 15\r
-#define isc_dpb_no_garbage_collect 16\r
-#define isc_dpb_damaged 17\r
-#define isc_dpb_license 18\r
-#define isc_dpb_sys_user_name 19\r
-#define isc_dpb_encrypt_key 20\r
-#define isc_dpb_activate_shadow 21\r
-#define isc_dpb_sweep_interval 22\r
-#define isc_dpb_delete_shadow 23\r
-#define isc_dpb_force_write 24\r
-#define isc_dpb_begin_log 25\r
-#define isc_dpb_quit_log 26\r
-#define isc_dpb_no_reserve 27\r
-#define isc_dpb_user_name 28\r
-#define isc_dpb_password 29\r
-#define isc_dpb_password_enc 30\r
-#define isc_dpb_sys_user_name_enc 31\r
-#define isc_dpb_interp 32\r
-#define isc_dpb_online_dump 33\r
-#define isc_dpb_old_file_size 34\r
-#define isc_dpb_old_num_files 35\r
-#define isc_dpb_old_file 36\r
-#define isc_dpb_old_start_page 37\r
-#define isc_dpb_old_start_seqno 38\r
-#define isc_dpb_old_start_file 39\r
-#define isc_dpb_drop_walfile 40\r
-#define isc_dpb_old_dump_id 41\r
-#define isc_dpb_wal_backup_dir 42\r
-#define isc_dpb_wal_chkptlen 43\r
-#define isc_dpb_wal_numbufs 44\r
-#define isc_dpb_wal_bufsize 45\r
-#define isc_dpb_wal_grp_cmt_wait 46\r
-#define isc_dpb_lc_messages 47\r
-#define isc_dpb_lc_ctype 48\r
-#define isc_dpb_cache_manager 49\r
-#define isc_dpb_shutdown 50\r
-#define isc_dpb_online 51\r
-#define isc_dpb_shutdown_delay 52\r
-#define isc_dpb_reserved 53\r
-#define isc_dpb_overwrite 54\r
-#define isc_dpb_sec_attach 55\r
-#define isc_dpb_disable_wal 56\r
-#define isc_dpb_connect_timeout 57\r
-#define isc_dpb_dummy_packet_interval 58\r
-#define isc_dpb_gbak_attach 59\r
-#define isc_dpb_sql_role_name 60\r
-#define isc_dpb_set_page_buffers 61\r
-#define isc_dpb_working_directory 62\r
-#define isc_dpb_sql_dialect 63\r
-#define isc_dpb_set_db_readonly 64\r
-#define isc_dpb_set_db_sql_dialect 65\r
-#define isc_dpb_gfix_attach 66\r
-#define isc_dpb_gstat_attach 67\r
-#define isc_dpb_set_db_charset 68\r
-\r
-/*********************************/\r
-/* isc_dpb_verify specific flags */\r
-/*********************************/\r
-\r
-#define isc_dpb_pages 1\r
-#define isc_dpb_records 2\r
-#define isc_dpb_indices 4\r
-#define isc_dpb_transactions 8\r
-#define isc_dpb_no_update 16\r
-#define isc_dpb_repair 32\r
-#define isc_dpb_ignore 64\r
-\r
-/***********************************/\r
-/* isc_dpb_shutdown specific flags */\r
-/***********************************/\r
-\r
-#define isc_dpb_shut_cache 1\r
-#define isc_dpb_shut_attachment 2\r
-#define isc_dpb_shut_transaction 4\r
-#define isc_dpb_shut_force 8\r
-\r
-/**************************************/\r
-/* Bit assignments in RDB$SYSTEM_FLAG */\r
-/**************************************/\r
-\r
-#define RDB_system 1\r
-#define RDB_id_assigned 2\r
-\r
-\r
-/*************************************/\r
-/* Transaction parameter block stuff */\r
-/*************************************/\r
-\r
-#define isc_tpb_version1 1\r
-#define isc_tpb_version3 3\r
-#define isc_tpb_consistency 1\r
-#define isc_tpb_concurrency 2\r
-#define isc_tpb_shared 3\r
-#define isc_tpb_protected 4\r
-#define isc_tpb_exclusive 5\r
-#define isc_tpb_wait 6\r
-#define isc_tpb_nowait 7\r
-#define isc_tpb_read 8\r
-#define isc_tpb_write 9\r
-#define isc_tpb_lock_read 10\r
-#define isc_tpb_lock_write 11\r
-#define isc_tpb_verb_time 12\r
-#define isc_tpb_commit_time 13\r
-#define isc_tpb_ignore_limbo 14\r
-#define isc_tpb_read_committed 15\r
-#define isc_tpb_autocommit 16\r
-#define isc_tpb_rec_version 17\r
-#define isc_tpb_no_rec_version 18\r
-#define isc_tpb_restart_requests 19\r
-#define isc_tpb_no_auto_undo 20\r
-\r
-\r
-/************************/\r
-/* Blob Parameter Block */\r
-/************************/\r
-\r
-#define isc_bpb_version1 1\r
-#define isc_bpb_source_type 1\r
-#define isc_bpb_target_type 2\r
-#define isc_bpb_type 3\r
-#define isc_bpb_source_interp 4\r
-#define isc_bpb_target_interp 5\r
-#define isc_bpb_filter_parameter 6\r
-\r
-#define isc_bpb_type_segmented 0\r
-#define isc_bpb_type_stream 1\r
-\r
-\r
-/*********************************/\r
-/* Service parameter block stuff */\r
-/*********************************/\r
-\r
-#define isc_spb_version1 1\r
-#define isc_spb_current_version 2\r
-#define isc_spb_version isc_spb_current_version\r
-#define isc_spb_user_name isc_dpb_user_name\r
-#define isc_spb_sys_user_name isc_dpb_sys_user_name\r
-#define isc_spb_sys_user_name_enc isc_dpb_sys_user_name_enc\r
-#define isc_spb_password isc_dpb_password\r
-#define isc_spb_password_enc isc_dpb_password_enc\r
-#define isc_spb_command_line 105\r
-#define isc_spb_dbname 106\r
-#define isc_spb_verbose 107\r
-#define isc_spb_options 108\r
-\r
-#define isc_spb_connect_timeout isc_dpb_connect_timeout\r
-#define isc_spb_dummy_packet_interval isc_dpb_dummy_packet_interval\r
-#define isc_spb_sql_role_name isc_dpb_sql_role_name\r
-\r
-\r
-/*********************************/\r
-/* Information call declarations */\r
-/*********************************/\r
-\r
-/****************************/\r
-/* Common, structural codes */\r
-/****************************/\r
-\r
-#define isc_info_end 1\r
-#define isc_info_truncated 2\r
-#define isc_info_error 3\r
-#define isc_info_data_not_ready 4\r
-#define isc_info_flag_end 127\r
-\r
-/******************************/\r
-/* Database information items */\r
-/******************************/\r
-\r
-enum db_info_types\r
- {\r
- isc_info_db_id = 4,\r
- isc_info_reads = 5,\r
- isc_info_writes = 6,\r
- isc_info_fetches = 7,\r
- isc_info_marks = 8,\r
-\r
- isc_info_implementation = 11,\r
- isc_info_isc_version = 12,\r
- isc_info_base_level = 13,\r
- isc_info_page_size = 14,\r
- isc_info_num_buffers = 15,\r
- isc_info_limbo = 16,\r
- isc_info_current_memory = 17,\r
- isc_info_max_memory = 18,\r
- isc_info_window_turns = 19,\r
- isc_info_license = 20, \r
-\r
- isc_info_allocation = 21,\r
- isc_info_attachment_id = 22,\r
- isc_info_read_seq_count = 23,\r
- isc_info_read_idx_count = 24,\r
- isc_info_insert_count = 25,\r
- isc_info_update_count = 26,\r
- isc_info_delete_count = 27,\r
- isc_info_backout_count = 28,\r
- isc_info_purge_count = 29,\r
- isc_info_expunge_count = 30, \r
-\r
- isc_info_sweep_interval = 31,\r
- isc_info_ods_version = 32,\r
- isc_info_ods_minor_version = 33,\r
- isc_info_no_reserve = 34,\r
- isc_info_logfile = 35,\r
- isc_info_cur_logfile_name = 36,\r
- isc_info_cur_log_part_offset = 37,\r
- isc_info_num_wal_buffers = 38,\r
- isc_info_wal_buffer_size = 39,\r
- isc_info_wal_ckpt_length = 40, \r
-\r
- isc_info_wal_cur_ckpt_interval = 41, \r
- isc_info_wal_prv_ckpt_fname = 42,\r
- isc_info_wal_prv_ckpt_poffset = 43,\r
- isc_info_wal_recv_ckpt_fname = 44,\r
- isc_info_wal_recv_ckpt_poffset = 45,\r
- isc_info_wal_grpc_wait_usecs = 47,\r
- isc_info_wal_num_io = 48,\r
- isc_info_wal_avg_io_size = 49,\r
- isc_info_wal_num_commits = 50, \r
-\r
- isc_info_wal_avg_grpc_size = 51,\r
- isc_info_forced_writes = 52,\r
- isc_info_user_names = 53,\r
- isc_info_page_errors = 54,\r
- isc_info_record_errors = 55,\r
- isc_info_bpage_errors = 56,\r
- isc_info_dpage_errors = 57,\r
- isc_info_ipage_errors = 58,\r
- isc_info_ppage_errors = 59,\r
- isc_info_tpage_errors = 60,\r
-\r
- isc_info_set_page_buffers = 61,\r
- isc_info_db_sql_dialect = 62, \r
- isc_info_db_read_only = 63,\r
- isc_info_db_size_in_pages = 64,\r
-\r
- /* Values 65 -100 unused to avoid conflict with InterBase */\r
- \r
- frb_info_att_charset = 101,\r
- isc_info_db_class = 102,\r
- isc_info_firebird_version = 103,\r
- isc_info_oldest_transaction = 104,\r
- isc_info_oldest_active = 105,\r
- isc_info_oldest_snapshot = 106,\r
- isc_info_next_transaction = 107,\r
- isc_info_db_provider = 108,\r
- isc_info_active_transactions = 109,\r
-\r
- isc_info_db_last_value /* Leave this LAST! */\r
- };\r
-\r
-#define isc_info_version isc_info_isc_version\r
-\r
-\r
-/**************************************/\r
-/* Database information return values */\r
-/**************************************/\r
-\r
-enum info_db_implementations\r
- {\r
- isc_info_db_impl_rdb_vms = 1,\r
- isc_info_db_impl_rdb_eln = 2,\r
- isc_info_db_impl_rdb_eln_dev = 3,\r
- isc_info_db_impl_rdb_vms_y = 4,\r
- isc_info_db_impl_rdb_eln_y = 5,\r
- isc_info_db_impl_jri = 6,\r
- isc_info_db_impl_jsv = 7,\r
-\r
- isc_info_db_impl_isc_apl_68K = 25,\r
- isc_info_db_impl_isc_vax_ultr = 26,\r
- isc_info_db_impl_isc_vms = 27,\r
- isc_info_db_impl_isc_sun_68k = 28,\r
- isc_info_db_impl_isc_os2 = 29,\r
- isc_info_db_impl_isc_sun4 = 30, /* 30 */\r
- \r
- isc_info_db_impl_isc_hp_ux = 31,\r
- isc_info_db_impl_isc_sun_386i = 32,\r
- isc_info_db_impl_isc_vms_orcl = 33,\r
- isc_info_db_impl_isc_mac_aux = 34,\r
- isc_info_db_impl_isc_rt_aix = 35,\r
- isc_info_db_impl_isc_mips_ult = 36,\r
- isc_info_db_impl_isc_xenix = 37,\r
- isc_info_db_impl_isc_dg = 38,\r
- isc_info_db_impl_isc_hp_mpexl = 39,\r
- isc_info_db_impl_isc_hp_ux68K = 40, /* 40 */\r
-\r
- isc_info_db_impl_isc_sgi = 41,\r
- isc_info_db_impl_isc_sco_unix = 42,\r
- isc_info_db_impl_isc_cray = 43,\r
- isc_info_db_impl_isc_imp = 44,\r
- isc_info_db_impl_isc_delta = 45,\r
- isc_info_db_impl_isc_next = 46,\r
- isc_info_db_impl_isc_dos = 47,\r
- isc_info_db_impl_m88K = 48,\r
- isc_info_db_impl_unixware = 49,\r
- isc_info_db_impl_isc_winnt_x86 = 50,\r
-\r
- isc_info_db_impl_isc_epson = 51,\r
- isc_info_db_impl_alpha_osf = 52,\r
- isc_info_db_impl_alpha_vms = 53,\r
- isc_info_db_impl_netware_386 = 54, \r
- isc_info_db_impl_win_only = 55,\r
- isc_info_db_impl_ncr_3000 = 56,\r
- isc_info_db_impl_winnt_ppc = 57,\r
- isc_info_db_impl_dg_x86 = 58,\r
- isc_info_db_impl_sco_ev = 59,\r
- isc_info_db_impl_i386 = 60,\r
-\r
- isc_info_db_impl_freebsd = 61,\r
- isc_info_db_impl_netbsd = 62,\r
- isc_info_db_impl_darwin = 63,\r
- isc_info_db_impl_sinixz = 64,\r
-\r
- isc_info_db_impl_linux_sparc = 65,\r
- isc_info_db_impl_linux_amd64 = 66,\r
-\r
- isc_info_db_impl_last_value /* Leave this LAST! */\r
- };\r
-\r
-#define isc_info_db_impl_isc_a isc_info_db_impl_isc_apl_68K\r
-#define isc_info_db_impl_isc_u isc_info_db_impl_isc_vax_ultr\r
-#define isc_info_db_impl_isc_v isc_info_db_impl_isc_vms\r
-#define isc_info_db_impl_isc_s isc_info_db_impl_isc_sun_68k\r
-\r
-\r
-enum info_db_class\r
- {\r
- isc_info_db_class_access = 1,\r
- isc_info_db_class_y_valve = 2,\r
- isc_info_db_class_rem_int = 3,\r
- isc_info_db_class_rem_srvr = 4,\r
- isc_info_db_class_pipe_int = 7,\r
- isc_info_db_class_pipe_srvr = 8,\r
- isc_info_db_class_sam_int = 9,\r
- isc_info_db_class_sam_srvr = 10,\r
- isc_info_db_class_gateway = 11,\r
- isc_info_db_class_cache = 12,\r
- isc_info_db_class_classic_access = 13,\r
- isc_info_db_class_server_access = 14,\r
-\r
- isc_info_db_class_last_value /* Leave this LAST! */\r
- };\r
-\r
-enum info_db_provider\r
- {\r
- isc_info_db_code_rdb_eln = 1,\r
- isc_info_db_code_rdb_vms = 2,\r
- isc_info_db_code_interbase = 3,\r
- isc_info_db_code_firebird = 4,\r
-\r
- isc_info_db_code_last_value /* Leave this LAST! */\r
- };\r
-\r
-\r
-/*****************************/\r
-/* Request information items */\r
-/*****************************/\r
-\r
-#define isc_info_number_messages 4\r
-#define isc_info_max_message 5\r
-#define isc_info_max_send 6\r
-#define isc_info_max_receive 7\r
-#define isc_info_state 8\r
-#define isc_info_message_number 9\r
-#define isc_info_message_size 10\r
-#define isc_info_request_cost 11\r
-#define isc_info_access_path 12\r
-#define isc_info_req_select_count 13\r
-#define isc_info_req_insert_count 14\r
-#define isc_info_req_update_count 15\r
-#define isc_info_req_delete_count 16\r
-\r
-\r
-/*********************/\r
-/* Access path items */\r
-/*********************/\r
-\r
-#define isc_info_rsb_end 0\r
-#define isc_info_rsb_begin 1\r
-#define isc_info_rsb_type 2\r
-#define isc_info_rsb_relation 3\r
-#define isc_info_rsb_plan 4\r
-\r
-/*************/\r
-/* Rsb types */\r
-/*************/\r
-\r
-#define isc_info_rsb_unknown 1\r
-#define isc_info_rsb_indexed 2\r
-#define isc_info_rsb_navigate 3\r
-#define isc_info_rsb_sequential 4\r
-#define isc_info_rsb_cross 5\r
-#define isc_info_rsb_sort 6\r
-#define isc_info_rsb_first 7\r
-#define isc_info_rsb_boolean 8\r
-#define isc_info_rsb_union 9\r
-#define isc_info_rsb_aggregate 10\r
-#define isc_info_rsb_merge 11\r
-#define isc_info_rsb_ext_sequential 12\r
-#define isc_info_rsb_ext_indexed 13\r
-#define isc_info_rsb_ext_dbkey 14\r
-#define isc_info_rsb_left_cross 15\r
-#define isc_info_rsb_select 16\r
-#define isc_info_rsb_sql_join 17\r
-#define isc_info_rsb_simulate 18\r
-#define isc_info_rsb_sim_cross 19\r
-#define isc_info_rsb_once 20\r
-#define isc_info_rsb_procedure 21\r
-\r
-/**********************/\r
-/* Bitmap expressions */\r
-/**********************/\r
-\r
-#define isc_info_rsb_and 1\r
-#define isc_info_rsb_or 2\r
-#define isc_info_rsb_dbkey 3\r
-#define isc_info_rsb_index 4\r
-\r
-#define isc_info_req_active 2\r
-#define isc_info_req_inactive 3\r
-#define isc_info_req_send 4\r
-#define isc_info_req_receive 5\r
-#define isc_info_req_select 6\r
-#define isc_info_req_sql_stall 7\r
-\r
-/**************************/\r
-/* Blob information items */\r
-/**************************/\r
-\r
-#define isc_info_blob_num_segments 4\r
-#define isc_info_blob_max_segment 5\r
-#define isc_info_blob_total_length 6\r
-#define isc_info_blob_type 7\r
-\r
-/*********************************/\r
-/* Transaction information items */\r
-/*********************************/\r
-\r
-#define isc_info_tra_id 4\r
-\r
-/*****************************\r
- * Service action items *\r
- *****************************/\r
-\r
-#define isc_action_svc_backup 1 /* Starts database backup process on the server */\r
-#define isc_action_svc_restore 2 /* Starts database restore process on the server */\r
-#define isc_action_svc_repair 3 /* Starts database repair process on the server */\r
-#define isc_action_svc_add_user 4 /* Adds a new user to the security database */\r
-#define isc_action_svc_delete_user 5 /* Deletes a user record from the security database */\r
-#define isc_action_svc_modify_user 6 /* Modifies a user record in the security database */\r
-#define isc_action_svc_display_user 7 /* Displays a user record from the security database */\r
-#define isc_action_svc_properties 8 /* Sets database properties */\r
-#define isc_action_svc_add_license 9 /* Adds a license to the license file */\r
-#define isc_action_svc_remove_license 10 /* Removes a license from the license file */\r
-#define isc_action_svc_db_stats 11 /* Retrieves database statistics */\r
-#define isc_action_svc_get_ib_log 12 /* Retrieves the InterBase log file from the server */\r
-\r
-/*****************************\r
- * Service information items *\r
- *****************************/\r
-\r
-#define isc_info_svc_svr_db_info 50 /* Retrieves the number of attachments and databases */\r
-#define isc_info_svc_get_license 51 /* Retrieves all license keys and IDs from the license file */\r
-#define isc_info_svc_get_license_mask 52 /* Retrieves a bitmask representing licensed options on the server */\r
-#define isc_info_svc_get_config 53 /* Retrieves the parameters and values for IB_CONFIG */\r
-#define isc_info_svc_version 54 /* Retrieves the version of the services manager */\r
-#define isc_info_svc_server_version 55 /* Retrieves the version of the InterBase server */\r
-#define isc_info_svc_implementation 56 /* Retrieves the implementation of the InterBase server */\r
-#define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */\r
-#define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */\r
-#define isc_info_svc_get_env 59 /* Retrieves the setting of $INTERBASE */\r
-#define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $INTERBASE_LCK */\r
-#define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $INTERBASE_MSG */\r
-#define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */\r
-#define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */\r
-#define isc_info_svc_timeout 64 /* Sets / signifies a timeout value for reading service information */\r
-#define isc_info_svc_get_licensed_users 65 /* Retrieves the number of users licensed for accessing the server */\r
-#define isc_info_svc_limbo_trans 66 /* Retrieve the limbo transactions */\r
-#define isc_info_svc_running 67 /* Checks to see if a service is running on an attachment */\r
-#define isc_info_svc_get_users 68 /* Returns the user information from isc_action_svc_display_users */\r
-\r
-/******************************************************\r
- * Parameters for isc_action_{add|delete|modify)_user *\r
- ******************************************************/\r
-\r
-#define isc_spb_sec_userid 5\r
-#define isc_spb_sec_groupid 6\r
-#define isc_spb_sec_username 7\r
-#define isc_spb_sec_password 8\r
-#define isc_spb_sec_groupname 9\r
-#define isc_spb_sec_firstname 10\r
-#define isc_spb_sec_middlename 11\r
-#define isc_spb_sec_lastname 12\r
-\r
-/*******************************************************\r
- * Parameters for isc_action_svc_(add|remove)_license, *\r
- * isc_info_svc_get_license *\r
- *******************************************************/\r
-\r
-#define isc_spb_lic_key 5\r
-#define isc_spb_lic_id 6\r
-#define isc_spb_lic_desc 7\r
-\r
-\r
-/*****************************************\r
- * Parameters for isc_action_svc_backup *\r
- *****************************************/\r
-\r
-#define isc_spb_bkp_file 5\r
-#define isc_spb_bkp_factor 6\r
-#define isc_spb_bkp_length 7\r
-#define isc_spb_bkp_ignore_checksums 0x01\r
-#define isc_spb_bkp_ignore_limbo 0x02\r
-#define isc_spb_bkp_metadata_only 0x04\r
-#define isc_spb_bkp_no_garbage_collect 0x08\r
-#define isc_spb_bkp_old_descriptions 0x10\r
-#define isc_spb_bkp_non_transportable 0x20\r
-#define isc_spb_bkp_convert 0x40\r
-#define isc_spb_bkp_expand 0x80\r
-\r
-/********************************************\r
- * Parameters for isc_action_svc_properties *\r
- ********************************************/\r
-\r
-#define isc_spb_prp_page_buffers 5\r
-#define isc_spb_prp_sweep_interval 6\r
-#define isc_spb_prp_shutdown_db 7\r
-#define isc_spb_prp_deny_new_attachments 9\r
-#define isc_spb_prp_deny_new_transactions 10\r
-#define isc_spb_prp_reserve_space 11\r
-#define isc_spb_prp_write_mode 12\r
-#define isc_spb_prp_access_mode 13\r
-#define isc_spb_prp_set_sql_dialect 14\r
-#define isc_spb_prp_activate 0x0100\r
-#define isc_spb_prp_db_online 0x0200\r
-\r
-/********************************************\r
- * Parameters for isc_spb_prp_reserve_space *\r
- ********************************************/\r
-\r
-#define isc_spb_prp_res_use_full 35\r
-#define isc_spb_prp_res 36\r
-\r
-/******************************************\r
- * Parameters for isc_spb_prp_write_mode *\r
- ******************************************/\r
-\r
-#define isc_spb_prp_wm_async 37\r
-#define isc_spb_prp_wm_sync 38\r
-\r
-/******************************************\r
- * Parameters for isc_spb_prp_access_mode *\r
- ******************************************/\r
-\r
-#define isc_spb_prp_am_readonly 39\r
-#define isc_spb_prp_am_readwrite 40\r
-\r
-/*****************************************\r
- * Parameters for isc_action_svc_repair *\r
- *****************************************/\r
-\r
-#define isc_spb_rpr_commit_trans 15\r
-#define isc_spb_rpr_rollback_trans 34\r
-#define isc_spb_rpr_recover_two_phase 17\r
-#define isc_spb_tra_id 18\r
-#define isc_spb_single_tra_id 19\r
-#define isc_spb_multi_tra_id 20\r
-#define isc_spb_tra_state 21\r
-#define isc_spb_tra_state_limbo 22\r
-#define isc_spb_tra_state_commit 23\r
-#define isc_spb_tra_state_rollback 24\r
-#define isc_spb_tra_state_unknown 25\r
-#define isc_spb_tra_host_site 26\r
-#define isc_spb_tra_remote_site 27\r
-#define isc_spb_tra_db_path 28\r
-#define isc_spb_tra_advise 29\r
-#define isc_spb_tra_advise_commit 30\r
-#define isc_spb_tra_advise_rollback 31\r
-#define isc_spb_tra_advise_unknown 33\r
-\r
-#define isc_spb_rpr_validate_db 0x01\r
-#define isc_spb_rpr_sweep_db 0x02\r
-#define isc_spb_rpr_mend_db 0x04\r
-#define isc_spb_rpr_list_limbo_trans 0x08\r
-#define isc_spb_rpr_check_db 0x10\r
-#define isc_spb_rpr_ignore_checksum 0x20\r
-#define isc_spb_rpr_kill_shadows 0x40\r
-#define isc_spb_rpr_full 0x80\r
-\r
-/*****************************************\r
- * Parameters for isc_action_svc_restore *\r
- *****************************************/\r
-\r
-#define isc_spb_res_buffers 9\r
-#define isc_spb_res_page_size 10\r
-#define isc_spb_res_length 11\r
-#define isc_spb_res_access_mode 12\r
-#define isc_spb_res_deactivate_idx 0x0100\r
-#define isc_spb_res_no_shadow 0x0200\r
-#define isc_spb_res_no_validity 0x0400\r
-#define isc_spb_res_one_at_a_time 0x0800\r
-#define isc_spb_res_replace 0x1000\r
-#define isc_spb_res_create 0x2000\r
-#define isc_spb_res_use_all_space 0x4000\r
-\r
-/******************************************\r
- * Parameters for isc_spb_res_access_mode *\r
- ******************************************/\r
-\r
-#define isc_spb_res_am_readonly isc_spb_prp_am_readonly\r
-#define isc_spb_res_am_readwrite isc_spb_prp_am_readwrite\r
-\r
-/*******************************************\r
- * Parameters for isc_info_svc_svr_db_info *\r
- *******************************************/\r
-\r
-#define isc_spb_num_att 5\r
-#define isc_spb_num_db 6\r
-\r
-/*****************************************\r
- * Parameters for isc_info_svc_db_stats *\r
- *****************************************/\r
-\r
-#define isc_spb_sts_data_pages 0x01\r
-#define isc_spb_sts_db_log 0x02\r
-#define isc_spb_sts_hdr_pages 0x04\r
-#define isc_spb_sts_idx_pages 0x08\r
-#define isc_spb_sts_sys_relations 0x10\r
-#define isc_spb_sts_record_versions 0x20\r
-#define isc_spb_sts_table 0x40\r
-\r
-/*************************/\r
-/* SQL information items */\r
-/*************************/\r
-\r
-#define isc_info_sql_select 4\r
-#define isc_info_sql_bind 5\r
-#define isc_info_sql_num_variables 6\r
-#define isc_info_sql_describe_vars 7\r
-#define isc_info_sql_describe_end 8\r
-#define isc_info_sql_sqlda_seq 9\r
-#define isc_info_sql_message_seq 10\r
-#define isc_info_sql_type 11\r
-#define isc_info_sql_sub_type 12\r
-#define isc_info_sql_scale 13\r
-#define isc_info_sql_length 14\r
-#define isc_info_sql_null_ind 15\r
-#define isc_info_sql_field 16\r
-#define isc_info_sql_relation 17\r
-#define isc_info_sql_owner 18\r
-#define isc_info_sql_alias 19\r
-#define isc_info_sql_sqlda_start 20\r
-#define isc_info_sql_stmt_type 21\r
-#define isc_info_sql_get_plan 22\r
-#define isc_info_sql_records 23\r
-#define isc_info_sql_batch_fetch 24\r
-\r
-/*********************************/\r
-/* SQL information return values */\r
-/*********************************/\r
-\r
-#define isc_info_sql_stmt_select 1\r
-#define isc_info_sql_stmt_insert 2\r
-#define isc_info_sql_stmt_update 3\r
-#define isc_info_sql_stmt_delete 4\r
-#define isc_info_sql_stmt_ddl 5\r
-#define isc_info_sql_stmt_get_segment 6\r
-#define isc_info_sql_stmt_put_segment 7\r
-#define isc_info_sql_stmt_exec_procedure 8\r
-#define isc_info_sql_stmt_start_trans 9\r
-#define isc_info_sql_stmt_commit 10\r
-#define isc_info_sql_stmt_rollback 11\r
-#define isc_info_sql_stmt_select_for_upd 12\r
-#define isc_info_sql_stmt_set_generator 13\r
-#define isc_info_sql_stmt_savepoint 14\r
-\r
-\r
-/***********************************/\r
-/* Server configuration key values */\r
-/***********************************/\r
-\r
-/* Not available in Firebird 1.5 */\r
-\r
-\r
-/**********************************************/\r
-/* Dynamic Data Definition Language operators */\r
-/**********************************************/\r
-\r
-/******************/\r
-/* Version number */\r
-/******************/\r
-\r
-#define isc_dyn_version_1 1\r
-#define isc_dyn_eoc 255\r
-\r
-/******************************/\r
-/* Operations (may be nested) */\r
-/******************************/\r
-\r
-#define isc_dyn_begin 2\r
-#define isc_dyn_end 3\r
-#define isc_dyn_if 4\r
-#define isc_dyn_def_database 5\r
-#define isc_dyn_def_global_fld 6\r
-#define isc_dyn_def_local_fld 7\r
-#define isc_dyn_def_idx 8\r
-#define isc_dyn_def_rel 9\r
-#define isc_dyn_def_sql_fld 10\r
-#define isc_dyn_def_view 12\r
-#define isc_dyn_def_trigger 15\r
-#define isc_dyn_def_security_class 120\r
-#define isc_dyn_def_dimension 140\r
-#define isc_dyn_def_generator 24\r
-#define isc_dyn_def_function 25\r
-#define isc_dyn_def_filter 26\r
-#define isc_dyn_def_function_arg 27\r
-#define isc_dyn_def_shadow 34\r
-#define isc_dyn_def_trigger_msg 17\r
-#define isc_dyn_def_file 36\r
-#define isc_dyn_mod_database 39\r
-#define isc_dyn_mod_rel 11\r
-#define isc_dyn_mod_global_fld 13\r
-#define isc_dyn_mod_idx 102\r
-#define isc_dyn_mod_local_fld 14\r
-#define isc_dyn_mod_sql_fld 216\r
-#define isc_dyn_mod_view 16\r
-#define isc_dyn_mod_security_class 122\r
-#define isc_dyn_mod_trigger 113\r
-#define isc_dyn_mod_trigger_msg 28\r
-#define isc_dyn_delete_database 18\r
-#define isc_dyn_delete_rel 19\r
-#define isc_dyn_delete_global_fld 20\r
-#define isc_dyn_delete_local_fld 21\r
-#define isc_dyn_delete_idx 22\r
-#define isc_dyn_delete_security_class 123\r
-#define isc_dyn_delete_dimensions 143\r
-#define isc_dyn_delete_trigger 23\r
-#define isc_dyn_delete_trigger_msg 29\r
-#define isc_dyn_delete_filter 32\r
-#define isc_dyn_delete_function 33\r
-#define isc_dyn_delete_shadow 35\r
-#define isc_dyn_grant 30\r
-#define isc_dyn_revoke 31\r
-#define isc_dyn_def_primary_key 37\r
-#define isc_dyn_def_foreign_key 38\r
-#define isc_dyn_def_unique 40\r
-#define isc_dyn_def_procedure 164\r
-#define isc_dyn_delete_procedure 165\r
-#define isc_dyn_def_parameter 135\r
-#define isc_dyn_delete_parameter 136\r
-#define isc_dyn_mod_procedure 175\r
-#define isc_dyn_def_log_file 176\r
-#define isc_dyn_def_cache_file 180\r
-#define isc_dyn_def_exception 181\r
-#define isc_dyn_mod_exception 182\r
-#define isc_dyn_del_exception 183\r
-#define isc_dyn_drop_log 194\r
-#define isc_dyn_drop_cache 195\r
-#define isc_dyn_def_default_log 202\r
-\r
-/***********************/\r
-/* View specific stuff */\r
-/***********************/\r
-\r
-#define isc_dyn_view_blr 43\r
-#define isc_dyn_view_source 44\r
-#define isc_dyn_view_relation 45\r
-#define isc_dyn_view_context 46\r
-#define isc_dyn_view_context_name 47\r
-\r
-/**********************/\r
-/* Generic attributes */\r
-/**********************/\r
-\r
-#define isc_dyn_rel_name 50\r
-#define isc_dyn_fld_name 51\r
-#define isc_dyn_new_fld_name 215\r
-#define isc_dyn_idx_name 52\r
-#define isc_dyn_description 53\r
-#define isc_dyn_security_class 54\r
-#define isc_dyn_system_flag 55\r
-#define isc_dyn_update_flag 56\r
-#define isc_dyn_prc_name 166\r
-#define isc_dyn_prm_name 137\r
-#define isc_dyn_sql_object 196\r
-#define isc_dyn_fld_character_set_name 174\r
-\r
-/********************************/\r
-/* Relation specific attributes */\r
-/********************************/\r
-\r
-#define isc_dyn_rel_dbkey_length 61\r
-#define isc_dyn_rel_store_trig 62\r
-#define isc_dyn_rel_modify_trig 63\r
-#define isc_dyn_rel_erase_trig 64\r
-#define isc_dyn_rel_store_trig_source 65\r
-#define isc_dyn_rel_modify_trig_source 66\r
-#define isc_dyn_rel_erase_trig_source 67\r
-#define isc_dyn_rel_ext_file 68\r
-#define isc_dyn_rel_sql_protection 69\r
-#define isc_dyn_rel_constraint 162\r
-#define isc_dyn_delete_rel_constraint 163\r
-\r
-/************************************/\r
-/* Global field specific attributes */\r
-/************************************/\r
-\r
-#define isc_dyn_fld_type 70\r
-#define isc_dyn_fld_length 71\r
-#define isc_dyn_fld_scale 72\r
-#define isc_dyn_fld_sub_type 73\r
-#define isc_dyn_fld_segment_length 74\r
-#define isc_dyn_fld_query_header 75\r
-#define isc_dyn_fld_edit_string 76\r
-#define isc_dyn_fld_validation_blr 77\r
-#define isc_dyn_fld_validation_source 78\r
-#define isc_dyn_fld_computed_blr 79\r
-#define isc_dyn_fld_computed_source 80\r
-#define isc_dyn_fld_missing_value 81\r
-#define isc_dyn_fld_default_value 82\r
-#define isc_dyn_fld_query_name 83\r
-#define isc_dyn_fld_dimensions 84\r
-#define isc_dyn_fld_not_null 85\r
-#define isc_dyn_fld_precision 86\r
-#define isc_dyn_fld_char_length 172\r
-#define isc_dyn_fld_collation 173\r
-#define isc_dyn_fld_default_source 193\r
-#define isc_dyn_del_default 197\r
-#define isc_dyn_del_validation 198\r
-#define isc_dyn_single_validation 199\r
-#define isc_dyn_fld_character_set 203\r
-\r
-/***********************************/\r
-/* Local field specific attributes */\r
-/***********************************/\r
-\r
-#define isc_dyn_fld_source 90\r
-#define isc_dyn_fld_base_fld 91\r
-#define isc_dyn_fld_position 92\r
-#define isc_dyn_fld_update_flag 93\r
-\r
-/*****************************/\r
-/* Index specific attributes */\r
-/*****************************/\r
-\r
-#define isc_dyn_idx_unique 100\r
-#define isc_dyn_idx_inactive 101\r
-#define isc_dyn_idx_type 103\r
-#define isc_dyn_idx_foreign_key 104\r
-#define isc_dyn_idx_ref_column 105\r
-#define isc_dyn_idx_statistic 204\r
-\r
-/*******************************/\r
-/* Trigger specific attributes */\r
-/*******************************/\r
-\r
-#define isc_dyn_trg_type 110\r
-#define isc_dyn_trg_blr 111\r
-#define isc_dyn_trg_source 112\r
-#define isc_dyn_trg_name 114\r
-#define isc_dyn_trg_sequence 115\r
-#define isc_dyn_trg_inactive 116\r
-#define isc_dyn_trg_msg_number 117\r
-#define isc_dyn_trg_msg 118\r
-\r
-/**************************************/\r
-/* Security Class specific attributes */\r
-/**************************************/\r
-\r
-#define isc_dyn_scl_acl 121\r
-#define isc_dyn_grant_user 130\r
-#define isc_dyn_grant_user_explicit 219\r
-#define isc_dyn_grant_proc 186\r
-#define isc_dyn_grant_trig 187\r
-#define isc_dyn_grant_view 188\r
-#define isc_dyn_grant_options 132\r
-#define isc_dyn_grant_user_group 205\r
-#define isc_dyn_grant_role 218\r
-\r
-\r
-/**********************************/\r
-/* Dimension specific information */\r
-/**********************************/\r
-\r
-#define isc_dyn_dim_lower 141\r
-#define isc_dyn_dim_upper 142\r
-\r
-/****************************/\r
-/* File specific attributes */\r
-/****************************/\r
-\r
-#define isc_dyn_file_name 125\r
-#define isc_dyn_file_start 126\r
-#define isc_dyn_file_length 127\r
-#define isc_dyn_shadow_number 128\r
-#define isc_dyn_shadow_man_auto 129\r
-#define isc_dyn_shadow_conditional 130\r
-\r
-/********************************/\r
-/* Log file specific attributes */\r
-/********************************/\r
-\r
-#define isc_dyn_log_file_sequence 177\r
-#define isc_dyn_log_file_partitions 178\r
-#define isc_dyn_log_file_serial 179\r
-#define isc_dyn_log_file_overflow 200\r
-#define isc_dyn_log_file_raw 201\r
-\r
-/***************************/\r
-/* Log specific attributes */\r
-/***************************/\r
-\r
-#define isc_dyn_log_group_commit_wait 189\r
-#define isc_dyn_log_buffer_size 190\r
-#define isc_dyn_log_check_point_length 191\r
-#define isc_dyn_log_num_of_buffers 192\r
-\r
-/********************************/\r
-/* Function specific attributes */\r
-/********************************/\r
-\r
-#define isc_dyn_function_name 145\r
-#define isc_dyn_function_type 146\r
-#define isc_dyn_func_module_name 147\r
-#define isc_dyn_func_entry_point 148\r
-#define isc_dyn_func_return_argument 149\r
-#define isc_dyn_func_arg_position 150\r
-#define isc_dyn_func_mechanism 151\r
-#define isc_dyn_filter_in_subtype 152\r
-#define isc_dyn_filter_out_subtype 153\r
-\r
-\r
-#define isc_dyn_description2 154\r
-#define isc_dyn_fld_computed_source2 155\r
-#define isc_dyn_fld_edit_string2 156\r
-#define isc_dyn_fld_query_header2 157\r
-#define isc_dyn_fld_validation_source2 158\r
-#define isc_dyn_trg_msg2 159\r
-#define isc_dyn_trg_source2 160\r
-#define isc_dyn_view_source2 161\r
-#define isc_dyn_xcp_msg2 184\r
-\r
-/*********************************/\r
-/* Generator specific attributes */\r
-/*********************************/\r
-\r
-#define isc_dyn_generator_name 95\r
-#define isc_dyn_generator_id 96\r
-\r
-/*********************************/\r
-/* Procedure specific attributes */\r
-/*********************************/\r
-\r
-#define isc_dyn_prc_inputs 167\r
-#define isc_dyn_prc_outputs 168\r
-#define isc_dyn_prc_source 169\r
-#define isc_dyn_prc_blr 170\r
-#define isc_dyn_prc_source2 171\r
-\r
-/*********************************/\r
-/* Parameter specific attributes */\r
-/*********************************/\r
-\r
-#define isc_dyn_prm_number 138\r
-#define isc_dyn_prm_type 139\r
-\r
-/********************************/\r
-/* Relation specific attributes */\r
-/********************************/\r
-\r
-#define isc_dyn_xcp_msg 185\r
-\r
-/**********************************************/\r
-/* Cascading referential integrity values */\r
-/**********************************************/\r
-#define isc_dyn_foreign_key_update 205\r
-#define isc_dyn_foreign_key_delete 206\r
-#define isc_dyn_foreign_key_cascade 207\r
-#define isc_dyn_foreign_key_default 208\r
-#define isc_dyn_foreign_key_null 209\r
-#define isc_dyn_foreign_key_none 210\r
-\r
-/***********************/\r
-/* SQL role values */\r
-/***********************/\r
-#define isc_dyn_def_sql_role 211\r
-#define isc_dyn_sql_role_name 212\r
-#define isc_dyn_grant_admin_options 213\r
-#define isc_dyn_del_sql_role 214\r
-/* 215 & 216 are used some lines above. */\r
-\r
-/**********************************************/\r
-/* Generators again */\r
-/**********************************************/\r
-\r
-#ifndef __cplusplus /* c definitions */\r
-#define gds_dyn_delete_generator 217\r
-#else /* c++ definitions */\r
-const unsigned char gds_dyn_delete_generator = 217;\r
-#endif\r
-\r
-/****************************/\r
-/* Last $dyn value assigned */\r
-/****************************/\r
-\r
-#define isc_dyn_last_dyn_value 219\r
-\r
-/******************************************/\r
-/* Array slice description language (SDL) */\r
-/******************************************/\r
-\r
-#define isc_sdl_version1 1\r
-#define isc_sdl_eoc 255\r
-#define isc_sdl_relation 2\r
-#define isc_sdl_rid 3\r
-#define isc_sdl_field 4\r
-#define isc_sdl_fid 5\r
-#define isc_sdl_struct 6\r
-#define isc_sdl_variable 7\r
-#define isc_sdl_scalar 8\r
-#define isc_sdl_tiny_integer 9\r
-#define isc_sdl_short_integer 10\r
-#define isc_sdl_long_integer 11\r
-#define isc_sdl_literal 12\r
-#define isc_sdl_add 13\r
-#define isc_sdl_subtract 14\r
-#define isc_sdl_multiply 15\r
-#define isc_sdl_divide 16\r
-#define isc_sdl_negate 17\r
-#define isc_sdl_eql 18\r
-#define isc_sdl_neq 19\r
-#define isc_sdl_gtr 20\r
-#define isc_sdl_geq 21\r
-#define isc_sdl_lss 22\r
-#define isc_sdl_leq 23\r
-#define isc_sdl_and 24\r
-#define isc_sdl_or 25\r
-#define isc_sdl_not 26\r
-#define isc_sdl_while 27\r
-#define isc_sdl_assignment 28\r
-#define isc_sdl_label 29\r
-#define isc_sdl_leave 30\r
-#define isc_sdl_begin 31\r
-#define isc_sdl_end 32\r
-#define isc_sdl_do3 33\r
-#define isc_sdl_do2 34\r
-#define isc_sdl_do1 35\r
-#define isc_sdl_element 36\r
-\r
-/********************************************/\r
-/* International text interpretation values */\r
-/********************************************/\r
-\r
-#define isc_interp_eng_ascii 0\r
-#define isc_interp_jpn_sjis 5\r
-#define isc_interp_jpn_euc 6\r
-\r
-/*******************/\r
-/* SQL definitions */\r
-/*******************/\r
-\r
-#define SQL_TEXT 452\r
-#define SQL_VARYING 448\r
-#define SQL_SHORT 500\r
-#define SQL_LONG 496\r
-#define SQL_FLOAT 482\r
-#define SQL_DOUBLE 480\r
-#define SQL_D_FLOAT 530\r
-#define SQL_TIMESTAMP 510\r
-#define SQL_BLOB 520\r
-#define SQL_ARRAY 540\r
-#define SQL_QUAD 550\r
-#define SQL_TYPE_TIME 560\r
-#define SQL_TYPE_DATE 570\r
-#define SQL_INT64 580\r
-\r
-/* Historical alias for pre V6 applications */\r
-#define SQL_DATE SQL_TIMESTAMP\r
-\r
-/*****************/\r
-/* Blob Subtypes */\r
-/*****************/\r
-\r
-/* types less than zero are reserved for customer use */\r
-\r
-#define isc_blob_untyped 0\r
-\r
-/* internal subtypes */\r
-\r
-#define isc_blob_text 1\r
-#define isc_blob_blr 2\r
-#define isc_blob_acl 3\r
-#define isc_blob_ranges 4\r
-#define isc_blob_summary 5\r
-#define isc_blob_format 6\r
-#define isc_blob_tra 7\r
-#define isc_blob_extfile 8\r
-\r
-/* the range 20-30 is reserved for dBASE and Paradox types */\r
-\r
-#define isc_blob_formatted_memo 20\r
-#define isc_blob_paradox_ole 21\r
-#define isc_blob_graphic 22\r
-#define isc_blob_dbase_ole 23\r
-#define isc_blob_typed_binary 24\r
-\r
-/* Deprecated definitions maintained for compatibility only */\r
-\r
-#define isc_info_db_SQL_dialect 62\r
-#define isc_dpb_SQL_dialect 63\r
-#define isc_dpb_set_db_SQL_dialect 65\r
-\r
-\r
-#include "iberror.h"\r
-\r
-#endif /* JRD_IBASE_H */\r
-\r
+++ /dev/null
-\r
-#ifndef _JRD_GEN_IBERROR_H\r
-#define _JRD_GEN_IBERROR_H\r
-/*\r
- * The contents of this file are subject to the Interbase Public\r
- * License Version 1.0 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy\r
- * of the License at http://www.Inprise.com/IPL.html\r
- * \r
- * Software distributed under the License is distributed on an\r
- * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- * \r
- * The content of this file was generated by the Firebird project\r
- * using the program jrd/codes.epp\r
- */\r
-/*\r
- * \r
- * *** WARNING *** - This file is automatically generated by codes.e - do not edit!\r
- * \r
- */\r
-/*\r
- * MODULE: iberror.h\r
- * DESCRIPTION: ISC error codes\r
- *\r
- */\r
-\r
-\r
-\r
-/***********************/\r
-/* ISC Error Codes */\r
-/***********************/\r
-\r
-#define isc_facility 20\r
-#define isc_base 335544320L\r
-#define isc_factor 1\r
-\r
-#define isc_arg_end 0 /* end of argument list */\r
-#define isc_arg_gds 1 /* generic DSRI status value */\r
-#define isc_arg_string 2 /* string argument */\r
-#define isc_arg_cstring 3 /* count & string argument */\r
-#define isc_arg_number 4 /* numeric argument (long) */\r
-#define isc_arg_interpreted 5 /* interpreted status code (string) */\r
-#define isc_arg_vms 6 /* VAX/VMS status code (long) */\r
-#define isc_arg_unix 7 /* UNIX error code */\r
-#define isc_arg_domain 8 /* Apollo/Domain error code */\r
-#define isc_arg_dos 9 /* MSDOS/OS2 error code */\r
-#define isc_arg_mpexl 10 /* HP MPE/XL error code */\r
-#define isc_arg_mpexl_ipc 11 /* HP MPE/XL IPC error code */\r
-#define isc_arg_next_mach 15 /* NeXT/Mach error code */\r
-#define isc_arg_netware 16 /* NetWare error code */\r
-#define isc_arg_win32 17 /* Win32 error code */\r
-#define isc_arg_warning 18 /* warning argument */\r
-\r
-#define isc_arith_except 335544321L\r
-#define isc_bad_dbkey 335544322L\r
-#define isc_bad_db_format 335544323L\r
-#define isc_bad_db_handle 335544324L\r
-#define isc_bad_dpb_content 335544325L\r
-#define isc_bad_dpb_form 335544326L\r
-#define isc_bad_req_handle 335544327L\r
-#define isc_bad_segstr_handle 335544328L\r
-#define isc_bad_segstr_id 335544329L\r
-#define isc_bad_tpb_content 335544330L\r
-#define isc_bad_tpb_form 335544331L\r
-#define isc_bad_trans_handle 335544332L\r
-#define isc_bug_check 335544333L\r
-#define isc_convert_error 335544334L\r
-#define isc_db_corrupt 335544335L\r
-#define isc_deadlock 335544336L\r
-#define isc_excess_trans 335544337L\r
-#define isc_from_no_match 335544338L\r
-#define isc_infinap 335544339L\r
-#define isc_infona 335544340L\r
-#define isc_infunk 335544341L\r
-#define isc_integ_fail 335544342L\r
-#define isc_invalid_blr 335544343L\r
-#define isc_io_error 335544344L\r
-#define isc_lock_conflict 335544345L\r
-#define isc_metadata_corrupt 335544346L\r
-#define isc_not_valid 335544347L\r
-#define isc_no_cur_rec 335544348L\r
-#define isc_no_dup 335544349L\r
-#define isc_no_finish 335544350L\r
-#define isc_no_meta_update 335544351L\r
-#define isc_no_priv 335544352L\r
-#define isc_no_recon 335544353L\r
-#define isc_no_record 335544354L\r
-#define isc_no_segstr_close 335544355L\r
-#define isc_obsolete_metadata 335544356L\r
-#define isc_open_trans 335544357L\r
-#define isc_port_len 335544358L\r
-#define isc_read_only_field 335544359L\r
-#define isc_read_only_rel 335544360L\r
-#define isc_read_only_trans 335544361L\r
-#define isc_read_only_view 335544362L\r
-#define isc_req_no_trans 335544363L\r
-#define isc_req_sync 335544364L\r
-#define isc_req_wrong_db 335544365L\r
-#define isc_segment 335544366L\r
-#define isc_segstr_eof 335544367L\r
-#define isc_segstr_no_op 335544368L\r
-#define isc_segstr_no_read 335544369L\r
-#define isc_segstr_no_trans 335544370L\r
-#define isc_segstr_no_write 335544371L\r
-#define isc_segstr_wrong_db 335544372L\r
-#define isc_sys_request 335544373L\r
-#define isc_stream_eof 335544374L\r
-#define isc_unavailable 335544375L\r
-#define isc_unres_rel 335544376L\r
-#define isc_uns_ext 335544377L\r
-#define isc_wish_list 335544378L\r
-#define isc_wrong_ods 335544379L\r
-#define isc_wronumarg 335544380L\r
-#define isc_imp_exc 335544381L\r
-#define isc_random 335544382L\r
-#define isc_fatal_conflict 335544383L\r
-#define isc_badblk 335544384L\r
-#define isc_invpoolcl 335544385L\r
-#define isc_nopoolids 335544386L\r
-#define isc_relbadblk 335544387L\r
-#define isc_blktoobig 335544388L\r
-#define isc_bufexh 335544389L\r
-#define isc_syntaxerr 335544390L\r
-#define isc_bufinuse 335544391L\r
-#define isc_bdbincon 335544392L\r
-#define isc_reqinuse 335544393L\r
-#define isc_badodsver 335544394L\r
-#define isc_relnotdef 335544395L\r
-#define isc_fldnotdef 335544396L\r
-#define isc_dirtypage 335544397L\r
-#define isc_waifortra 335544398L\r
-#define isc_doubleloc 335544399L\r
-#define isc_nodnotfnd 335544400L\r
-#define isc_dupnodfnd 335544401L\r
-#define isc_locnotmar 335544402L\r
-#define isc_badpagtyp 335544403L\r
-#define isc_corrupt 335544404L\r
-#define isc_badpage 335544405L\r
-#define isc_badindex 335544406L\r
-#define isc_dbbnotzer 335544407L\r
-#define isc_tranotzer 335544408L\r
-#define isc_trareqmis 335544409L\r
-#define isc_badhndcnt 335544410L\r
-#define isc_wrotpbver 335544411L\r
-#define isc_wroblrver 335544412L\r
-#define isc_wrodpbver 335544413L\r
-#define isc_blobnotsup 335544414L\r
-#define isc_badrelation 335544415L\r
-#define isc_nodetach 335544416L\r
-#define isc_notremote 335544417L\r
-#define isc_trainlim 335544418L\r
-#define isc_notinlim 335544419L\r
-#define isc_traoutsta 335544420L\r
-#define isc_connect_reject 335544421L\r
-#define isc_dbfile 335544422L\r
-#define isc_orphan 335544423L\r
-#define isc_no_lock_mgr 335544424L\r
-#define isc_ctxinuse 335544425L\r
-#define isc_ctxnotdef 335544426L\r
-#define isc_datnotsup 335544427L\r
-#define isc_badmsgnum 335544428L\r
-#define isc_badparnum 335544429L\r
-#define isc_virmemexh 335544430L\r
-#define isc_blocking_signal 335544431L\r
-#define isc_lockmanerr 335544432L\r
-#define isc_journerr 335544433L\r
-#define isc_keytoobig 335544434L\r
-#define isc_nullsegkey 335544435L\r
-#define isc_sqlerr 335544436L\r
-#define isc_wrodynver 335544437L\r
-#define isc_funnotdef 335544438L\r
-#define isc_funmismat 335544439L\r
-#define isc_bad_msg_vec 335544440L\r
-#define isc_bad_detach 335544441L\r
-#define isc_noargacc_read 335544442L\r
-#define isc_noargacc_write 335544443L\r
-#define isc_read_only 335544444L\r
-#define isc_ext_err 335544445L\r
-#define isc_non_updatable 335544446L\r
-#define isc_no_rollback 335544447L\r
-#define isc_bad_sec_info 335544448L\r
-#define isc_invalid_sec_info 335544449L\r
-#define isc_misc_interpreted 335544450L\r
-#define isc_update_conflict 335544451L\r
-#define isc_unlicensed 335544452L\r
-#define isc_obj_in_use 335544453L\r
-#define isc_nofilter 335544454L\r
-#define isc_shadow_accessed 335544455L\r
-#define isc_invalid_sdl 335544456L\r
-#define isc_out_of_bounds 335544457L\r
-#define isc_invalid_dimension 335544458L\r
-#define isc_rec_in_limbo 335544459L\r
-#define isc_shadow_missing 335544460L\r
-#define isc_cant_validate 335544461L\r
-#define isc_cant_start_journal 335544462L\r
-#define isc_gennotdef 335544463L\r
-#define isc_cant_start_logging 335544464L\r
-#define isc_bad_segstr_type 335544465L\r
-#define isc_foreign_key 335544466L\r
-#define isc_high_minor 335544467L\r
-#define isc_tra_state 335544468L\r
-#define isc_trans_invalid 335544469L\r
-#define isc_buf_invalid 335544470L\r
-#define isc_indexnotdefined 335544471L\r
-#define isc_login 335544472L\r
-#define isc_invalid_bookmark 335544473L\r
-#define isc_bad_lock_level 335544474L\r
-#define isc_relation_lock 335544475L\r
-#define isc_record_lock 335544476L\r
-#define isc_max_idx 335544477L\r
-#define isc_jrn_enable 335544478L\r
-#define isc_old_failure 335544479L\r
-#define isc_old_in_progress 335544480L\r
-#define isc_old_no_space 335544481L\r
-#define isc_no_wal_no_jrn 335544482L\r
-#define isc_num_old_files 335544483L\r
-#define isc_wal_file_open 335544484L\r
-#define isc_bad_stmt_handle 335544485L\r
-#define isc_wal_failure 335544486L\r
-#define isc_walw_err 335544487L\r
-#define isc_logh_small 335544488L\r
-#define isc_logh_inv_version 335544489L\r
-#define isc_logh_open_flag 335544490L\r
-#define isc_logh_open_flag2 335544491L\r
-#define isc_logh_diff_dbname 335544492L\r
-#define isc_logf_unexpected_eof 335544493L\r
-#define isc_logr_incomplete 335544494L\r
-#define isc_logr_header_small 335544495L\r
-#define isc_logb_small 335544496L\r
-#define isc_wal_illegal_attach 335544497L\r
-#define isc_wal_invalid_wpb 335544498L\r
-#define isc_wal_err_rollover 335544499L\r
-#define isc_no_wal 335544500L\r
-#define isc_drop_wal 335544501L\r
-#define isc_stream_not_defined 335544502L\r
-#define isc_wal_subsys_error 335544503L\r
-#define isc_wal_subsys_corrupt 335544504L\r
-#define isc_no_archive 335544505L\r
-#define isc_shutinprog 335544506L\r
-#define isc_range_in_use 335544507L\r
-#define isc_range_not_found 335544508L\r
-#define isc_charset_not_found 335544509L\r
-#define isc_lock_timeout 335544510L\r
-#define isc_prcnotdef 335544511L\r
-#define isc_prcmismat 335544512L\r
-#define isc_wal_bugcheck 335544513L\r
-#define isc_wal_cant_expand 335544514L\r
-#define isc_codnotdef 335544515L\r
-#define isc_xcpnotdef 335544516L\r
-#define isc_except 335544517L\r
-#define isc_cache_restart 335544518L\r
-#define isc_bad_lock_handle 335544519L\r
-#define isc_jrn_present 335544520L\r
-#define isc_wal_err_rollover2 335544521L\r
-#define isc_wal_err_logwrite 335544522L\r
-#define isc_wal_err_jrn_comm 335544523L\r
-#define isc_wal_err_expansion 335544524L\r
-#define isc_wal_err_setup 335544525L\r
-#define isc_wal_err_ww_sync 335544526L\r
-#define isc_wal_err_ww_start 335544527L\r
-#define isc_shutdown 335544528L\r
-#define isc_existing_priv_mod 335544529L\r
-#define isc_primary_key_ref 335544530L\r
-#define isc_primary_key_notnull 335544531L\r
-#define isc_ref_cnstrnt_notfound 335544532L\r
-#define isc_foreign_key_notfound 335544533L\r
-#define isc_ref_cnstrnt_update 335544534L\r
-#define isc_check_cnstrnt_update 335544535L\r
-#define isc_check_cnstrnt_del 335544536L\r
-#define isc_integ_index_seg_del 335544537L\r
-#define isc_integ_index_seg_mod 335544538L\r
-#define isc_integ_index_del 335544539L\r
-#define isc_integ_index_mod 335544540L\r
-#define isc_check_trig_del 335544541L\r
-#define isc_check_trig_update 335544542L\r
-#define isc_cnstrnt_fld_del 335544543L\r
-#define isc_cnstrnt_fld_rename 335544544L\r
-#define isc_rel_cnstrnt_update 335544545L\r
-#define isc_constaint_on_view 335544546L\r
-#define isc_invld_cnstrnt_type 335544547L\r
-#define isc_primary_key_exists 335544548L\r
-#define isc_systrig_update 335544549L\r
-#define isc_not_rel_owner 335544550L\r
-#define isc_grant_obj_notfound 335544551L\r
-#define isc_grant_fld_notfound 335544552L\r
-#define isc_grant_nopriv 335544553L\r
-#define isc_nonsql_security_rel 335544554L\r
-#define isc_nonsql_security_fld 335544555L\r
-#define isc_wal_cache_err 335544556L\r
-#define isc_shutfail 335544557L\r
-#define isc_check_constraint 335544558L\r
-#define isc_bad_svc_handle 335544559L\r
-#define isc_shutwarn 335544560L\r
-#define isc_wrospbver 335544561L\r
-#define isc_bad_spb_form 335544562L\r
-#define isc_svcnotdef 335544563L\r
-#define isc_no_jrn 335544564L\r
-#define isc_transliteration_failed 335544565L\r
-#define isc_start_cm_for_wal 335544566L\r
-#define isc_wal_ovflow_log_required 335544567L\r
-#define isc_text_subtype 335544568L\r
-#define isc_dsql_error 335544569L\r
-#define isc_dsql_command_err 335544570L\r
-#define isc_dsql_constant_err 335544571L\r
-#define isc_dsql_cursor_err 335544572L\r
-#define isc_dsql_datatype_err 335544573L\r
-#define isc_dsql_decl_err 335544574L\r
-#define isc_dsql_cursor_update_err 335544575L\r
-#define isc_dsql_cursor_open_err 335544576L\r
-#define isc_dsql_cursor_close_err 335544577L\r
-#define isc_dsql_field_err 335544578L\r
-#define isc_dsql_internal_err 335544579L\r
-#define isc_dsql_relation_err 335544580L\r
-#define isc_dsql_procedure_err 335544581L\r
-#define isc_dsql_request_err 335544582L\r
-#define isc_dsql_sqlda_err 335544583L\r
-#define isc_dsql_var_count_err 335544584L\r
-#define isc_dsql_stmt_handle 335544585L\r
-#define isc_dsql_function_err 335544586L\r
-#define isc_dsql_blob_err 335544587L\r
-#define isc_collation_not_found 335544588L\r
-#define isc_collation_not_for_charset 335544589L\r
-#define isc_dsql_dup_option 335544590L\r
-#define isc_dsql_tran_err 335544591L\r
-#define isc_dsql_invalid_array 335544592L\r
-#define isc_dsql_max_arr_dim_exceeded 335544593L\r
-#define isc_dsql_arr_range_error 335544594L\r
-#define isc_dsql_trigger_err 335544595L\r
-#define isc_dsql_subselect_err 335544596L\r
-#define isc_dsql_crdb_prepare_err 335544597L\r
-#define isc_specify_field_err 335544598L\r
-#define isc_num_field_err 335544599L\r
-#define isc_col_name_err 335544600L\r
-#define isc_where_err 335544601L\r
-#define isc_table_view_err 335544602L\r
-#define isc_distinct_err 335544603L\r
-#define isc_key_field_count_err 335544604L\r
-#define isc_subquery_err 335544605L\r
-#define isc_expression_eval_err 335544606L\r
-#define isc_node_err 335544607L\r
-#define isc_command_end_err 335544608L\r
-#define isc_index_name 335544609L\r
-#define isc_exception_name 335544610L\r
-#define isc_field_name 335544611L\r
-#define isc_token_err 335544612L\r
-#define isc_union_err 335544613L\r
-#define isc_dsql_construct_err 335544614L\r
-#define isc_field_aggregate_err 335544615L\r
-#define isc_field_ref_err 335544616L\r
-#define isc_order_by_err 335544617L\r
-#define isc_return_mode_err 335544618L\r
-#define isc_extern_func_err 335544619L\r
-#define isc_alias_conflict_err 335544620L\r
-#define isc_procedure_conflict_error 335544621L\r
-#define isc_relation_conflict_err 335544622L\r
-#define isc_dsql_domain_err 335544623L\r
-#define isc_idx_seg_err 335544624L\r
-#define isc_node_name_err 335544625L\r
-#define isc_table_name 335544626L\r
-#define isc_proc_name 335544627L\r
-#define isc_idx_create_err 335544628L\r
-#define isc_wal_shadow_err 335544629L\r
-#define isc_dependency 335544630L\r
-#define isc_idx_key_err 335544631L\r
-#define isc_dsql_file_length_err 335544632L\r
-#define isc_dsql_shadow_number_err 335544633L\r
-#define isc_dsql_token_unk_err 335544634L\r
-#define isc_dsql_no_relation_alias 335544635L\r
-#define isc_indexname 335544636L\r
-#define isc_no_stream_plan 335544637L\r
-#define isc_stream_twice 335544638L\r
-#define isc_stream_not_found 335544639L\r
-#define isc_collation_requires_text 335544640L\r
-#define isc_dsql_domain_not_found 335544641L\r
-#define isc_index_unused 335544642L\r
-#define isc_dsql_self_join 335544643L\r
-#define isc_stream_bof 335544644L\r
-#define isc_stream_crack 335544645L\r
-#define isc_db_or_file_exists 335544646L\r
-#define isc_invalid_operator 335544647L\r
-#define isc_conn_lost 335544648L\r
-#define isc_bad_checksum 335544649L\r
-#define isc_page_type_err 335544650L\r
-#define isc_ext_readonly_err 335544651L\r
-#define isc_sing_select_err 335544652L\r
-#define isc_psw_attach 335544653L\r
-#define isc_psw_start_trans 335544654L\r
-#define isc_invalid_direction 335544655L\r
-#define isc_dsql_var_conflict 335544656L\r
-#define isc_dsql_no_blob_array 335544657L\r
-#define isc_dsql_base_table 335544658L\r
-#define isc_duplicate_base_table 335544659L\r
-#define isc_view_alias 335544660L\r
-#define isc_index_root_page_full 335544661L\r
-#define isc_dsql_blob_type_unknown 335544662L\r
-#define isc_req_max_clones_exceeded 335544663L\r
-#define isc_dsql_duplicate_spec 335544664L\r
-#define isc_unique_key_violation 335544665L\r
-#define isc_srvr_version_too_old 335544666L\r
-#define isc_drdb_completed_with_errs 335544667L\r
-#define isc_dsql_procedure_use_err 335544668L\r
-#define isc_dsql_count_mismatch 335544669L\r
-#define isc_blob_idx_err 335544670L\r
-#define isc_array_idx_err 335544671L\r
-#define isc_key_field_err 335544672L\r
-#define isc_no_delete 335544673L\r
-#define isc_del_last_field 335544674L\r
-#define isc_sort_err 335544675L\r
-#define isc_sort_mem_err 335544676L\r
-#define isc_version_err 335544677L\r
-#define isc_inval_key_posn 335544678L\r
-#define isc_no_segments_err 335544679L\r
-#define isc_crrp_data_err 335544680L\r
-#define isc_rec_size_err 335544681L\r
-#define isc_dsql_field_ref 335544682L\r
-#define isc_req_depth_exceeded 335544683L\r
-#define isc_no_field_access 335544684L\r
-#define isc_no_dbkey 335544685L\r
-#define isc_jrn_format_err 335544686L\r
-#define isc_jrn_file_full 335544687L\r
-#define isc_dsql_open_cursor_request 335544688L\r
-#define isc_ib_error 335544689L\r
-#define isc_cache_redef 335544690L\r
-#define isc_cache_too_small 335544691L\r
-#define isc_log_redef 335544692L\r
-#define isc_log_too_small 335544693L\r
-#define isc_partition_too_small 335544694L\r
-#define isc_partition_not_supp 335544695L\r
-#define isc_log_length_spec 335544696L\r
-#define isc_precision_err 335544697L\r
-#define isc_scale_nogt 335544698L\r
-#define isc_expec_short 335544699L\r
-#define isc_expec_long 335544700L\r
-#define isc_expec_ushort 335544701L\r
-#define isc_like_escape_invalid 335544702L\r
-#define isc_svcnoexe 335544703L\r
-#define isc_net_lookup_err 335544704L\r
-#define isc_service_unknown 335544705L\r
-#define isc_host_unknown 335544706L\r
-#define isc_grant_nopriv_on_base 335544707L\r
-#define isc_dyn_fld_ambiguous 335544708L\r
-#define isc_dsql_agg_ref_err 335544709L\r
-#define isc_complex_view 335544710L\r
-#define isc_unprepared_stmt 335544711L\r
-#define isc_expec_positive 335544712L\r
-#define isc_dsql_sqlda_value_err 335544713L\r
-#define isc_invalid_array_id 335544714L\r
-#define isc_extfile_uns_op 335544715L\r
-#define isc_svc_in_use 335544716L\r
-#define isc_err_stack_limit 335544717L\r
-#define isc_invalid_key 335544718L\r
-#define isc_net_init_error 335544719L\r
-#define isc_loadlib_failure 335544720L\r
-#define isc_network_error 335544721L\r
-#define isc_net_connect_err 335544722L\r
-#define isc_net_connect_listen_err 335544723L\r
-#define isc_net_event_connect_err 335544724L\r
-#define isc_net_event_listen_err 335544725L\r
-#define isc_net_read_err 335544726L\r
-#define isc_net_write_err 335544727L\r
-#define isc_integ_index_deactivate 335544728L\r
-#define isc_integ_deactivate_primary 335544729L\r
-#define isc_cse_not_supported 335544730L\r
-#define isc_tra_must_sweep 335544731L\r
-#define isc_unsupported_network_drive 335544732L\r
-#define isc_io_create_err 335544733L\r
-#define isc_io_open_err 335544734L\r
-#define isc_io_close_err 335544735L\r
-#define isc_io_read_err 335544736L\r
-#define isc_io_write_err 335544737L\r
-#define isc_io_delete_err 335544738L\r
-#define isc_io_access_err 335544739L\r
-#define isc_udf_exception 335544740L\r
-#define isc_lost_db_connection 335544741L\r
-#define isc_no_write_user_priv 335544742L\r
-#define isc_token_too_long 335544743L\r
-#define isc_max_att_exceeded 335544744L\r
-#define isc_login_same_as_role_name 335544745L\r
-#define isc_reftable_requires_pk 335544746L\r
-#define isc_usrname_too_long 335544747L\r
-#define isc_password_too_long 335544748L\r
-#define isc_usrname_required 335544749L\r
-#define isc_password_required 335544750L\r
-#define isc_bad_protocol 335544751L\r
-#define isc_dup_usrname_found 335544752L\r
-#define isc_usrname_not_found 335544753L\r
-#define isc_error_adding_sec_record 335544754L\r
-#define isc_error_modifying_sec_record 335544755L\r
-#define isc_error_deleting_sec_record 335544756L\r
-#define isc_error_updating_sec_db 335544757L\r
-#define isc_sort_rec_size_err 335544758L\r
-#define isc_bad_default_value 335544759L\r
-#define isc_invalid_clause 335544760L\r
-#define isc_too_many_handles 335544761L\r
-#define isc_optimizer_blk_exc 335544762L\r
-#define isc_invalid_string_constant 335544763L\r
-#define isc_transitional_date 335544764L\r
-#define isc_read_only_database 335544765L\r
-#define isc_must_be_dialect_2_and_up 335544766L\r
-#define isc_blob_filter_exception 335544767L\r
-#define isc_exception_access_violation 335544768L\r
-#define isc_exception_datatype_missalignment 335544769L\r
-#define isc_exception_array_bounds_exceeded 335544770L\r
-#define isc_exception_float_denormal_operand 335544771L\r
-#define isc_exception_float_divide_by_zero 335544772L\r
-#define isc_exception_float_inexact_result 335544773L\r
-#define isc_exception_float_invalid_operand 335544774L\r
-#define isc_exception_float_overflow 335544775L\r
-#define isc_exception_float_stack_check 335544776L\r
-#define isc_exception_float_underflow 335544777L\r
-#define isc_exception_integer_divide_by_zero 335544778L\r
-#define isc_exception_integer_overflow 335544779L\r
-#define isc_exception_unknown 335544780L\r
-#define isc_exception_stack_overflow 335544781L\r
-#define isc_exception_sigsegv 335544782L\r
-#define isc_exception_sigill 335544783L\r
-#define isc_exception_sigbus 335544784L\r
-#define isc_exception_sigfpe 335544785L\r
-#define isc_ext_file_delete 335544786L\r
-#define isc_ext_file_modify 335544787L\r
-#define isc_adm_task_denied 335544788L\r
-#define isc_extract_input_mismatch 335544789L\r
-#define isc_insufficient_svc_privileges 335544790L\r
-#define isc_file_in_use 335544791L\r
-#define isc_service_att_err 335544792L\r
-#define isc_ddl_not_allowed_by_db_sql_dial 335544793L\r
-#define isc_cancelled 335544794L\r
-#define isc_unexp_spb_form 335544795L\r
-#define isc_sql_dialect_datatype_unsupport 335544796L\r
-#define isc_svcnouser 335544797L\r
-#define isc_depend_on_uncommitted_rel 335544798L\r
-#define isc_svc_name_missing 335544799L\r
-#define isc_too_many_contexts 335544800L\r
-#define isc_datype_notsup 335544801L\r
-#define isc_dialect_reset_warning 335544802L\r
-#define isc_dialect_not_changed 335544803L\r
-#define isc_database_create_failed 335544804L\r
-#define isc_inv_dialect_specified 335544805L\r
-#define isc_valid_db_dialects 335544806L\r
-#define isc_sqlwarn 335544807L\r
-#define isc_dtype_renamed 335544808L\r
-#define isc_extern_func_dir_error 335544809L\r
-#define isc_date_range_exceeded 335544810L\r
-#define isc_inv_client_dialect_specified 335544811L\r
-#define isc_valid_client_dialects 335544812L\r
-#define isc_optimizer_between_err 335544813L\r
-#define isc_service_not_supported 335544814L\r
-#define isc_generator_name 335544815L\r
-#define isc_udf_name 335544816L\r
-#define isc_bad_limit_param 335544817L\r
-#define isc_bad_skip_param 335544818L\r
-#define isc_io_32bit_exceeded_err 335544819L\r
-#define isc_invalid_savepoint 335544820L\r
-#define isc_dsql_column_pos_err 335544821L\r
-#define isc_dsql_agg_where_err 335544822L\r
-#define isc_dsql_agg_group_err 335544823L\r
-#define isc_dsql_agg_column_err 335544824L\r
-#define isc_dsql_agg_having_err 335544825L\r
-#define isc_dsql_agg_nested_err 335544826L\r
-#define isc_exec_sql_invalid_arg 335544827L\r
-#define isc_exec_sql_invalid_req 335544828L\r
-#define isc_exec_sql_invalid_var 335544829L\r
-#define isc_exec_sql_max_call_exceeded 335544830L\r
-#define isc_conf_access_denied 335544831L\r
-#define isc_gfix_db_name 335740929L\r
-#define isc_gfix_invalid_sw 335740930L\r
-#define isc_gfix_incmp_sw 335740932L\r
-#define isc_gfix_replay_req 335740933L\r
-#define isc_gfix_pgbuf_req 335740934L\r
-#define isc_gfix_val_req 335740935L\r
-#define isc_gfix_pval_req 335740936L\r
-#define isc_gfix_trn_req 335740937L\r
-#define isc_gfix_full_req 335740940L\r
-#define isc_gfix_usrname_req 335740941L\r
-#define isc_gfix_pass_req 335740942L\r
-#define isc_gfix_subs_name 335740943L\r
-#define isc_gfix_wal_req 335740944L\r
-#define isc_gfix_sec_req 335740945L\r
-#define isc_gfix_nval_req 335740946L\r
-#define isc_gfix_type_shut 335740947L\r
-#define isc_gfix_retry 335740948L\r
-#define isc_gfix_retry_db 335740951L\r
-#define isc_gfix_exceed_max 335740991L\r
-#define isc_gfix_corrupt_pool 335740992L\r
-#define isc_gfix_mem_exhausted 335740993L\r
-#define isc_gfix_bad_pool 335740994L\r
-#define isc_gfix_trn_not_valid 335740995L\r
-#define isc_gfix_unexp_eoi 335741012L\r
-#define isc_gfix_recon_fail 335741018L\r
-#define isc_gfix_trn_unknown 335741036L\r
-#define isc_gfix_mode_req 335741038L\r
-#define isc_gfix_opt_SQL_dialect 335741039L\r
-#define isc_dsql_dbkey_from_non_table 336003074L\r
-#define isc_dsql_transitional_numeric 336003075L\r
-#define isc_dsql_dialect_warning_expr 336003076L\r
-#define isc_sql_db_dialect_dtype_unsupport 336003077L\r
-#define isc_isc_sql_dialect_conflict_num 336003079L\r
-#define isc_dsql_warning_number_ambiguous 336003080L\r
-#define isc_dsql_warning_number_ambiguous1 336003081L\r
-#define isc_dsql_warn_precision_ambiguous 336003082L\r
-#define isc_dsql_warn_precision_ambiguous1 336003083L\r
-#define isc_dsql_warn_precision_ambiguous2 336003084L\r
-#define isc_dsql_ambiguous_field_name 336003085L\r
-#define isc_dsql_udf_return_pos_err 336003086L\r
-#define isc_dsql_invalid_label 336003087L\r
-#define isc_dsql_datatypes_not_comparable 336003088L\r
-#define isc_dyn_role_does_not_exist 336068796L\r
-#define isc_dyn_no_grant_admin_opt 336068797L\r
-#define isc_dyn_user_not_role_member 336068798L\r
-#define isc_dyn_delete_role_failed 336068799L\r
-#define isc_dyn_grant_role_to_user 336068800L\r
-#define isc_dyn_inv_sql_role_name 336068801L\r
-#define isc_dyn_dup_sql_role 336068802L\r
-#define isc_dyn_kywd_spec_for_role 336068803L\r
-#define isc_dyn_roles_not_supported 336068804L\r
-#define isc_dyn_domain_name_exists 336068812L\r
-#define isc_dyn_field_name_exists 336068813L\r
-#define isc_dyn_dependency_exists 336068814L\r
-#define isc_dyn_dtype_invalid 336068815L\r
-#define isc_dyn_char_fld_too_small 336068816L\r
-#define isc_dyn_invalid_dtype_conversion 336068817L\r
-#define isc_dyn_dtype_conv_invalid 336068818L\r
-#define isc_dyn_zero_len_id 336068820L\r
-#define isc_gbak_unknown_switch 336330753L\r
-#define isc_gbak_page_size_missing 336330754L\r
-#define isc_gbak_page_size_toobig 336330755L\r
-#define isc_gbak_redir_ouput_missing 336330756L\r
-#define isc_gbak_switches_conflict 336330757L\r
-#define isc_gbak_unknown_device 336330758L\r
-#define isc_gbak_no_protection 336330759L\r
-#define isc_gbak_page_size_not_allowed 336330760L\r
-#define isc_gbak_multi_source_dest 336330761L\r
-#define isc_gbak_filename_missing 336330762L\r
-#define isc_gbak_dup_inout_names 336330763L\r
-#define isc_gbak_inv_page_size 336330764L\r
-#define isc_gbak_db_specified 336330765L\r
-#define isc_gbak_db_exists 336330766L\r
-#define isc_gbak_unk_device 336330767L\r
-#define isc_gbak_blob_info_failed 336330772L\r
-#define isc_gbak_unk_blob_item 336330773L\r
-#define isc_gbak_get_seg_failed 336330774L\r
-#define isc_gbak_close_blob_failed 336330775L\r
-#define isc_gbak_open_blob_failed 336330776L\r
-#define isc_gbak_put_blr_gen_id_failed 336330777L\r
-#define isc_gbak_unk_type 336330778L\r
-#define isc_gbak_comp_req_failed 336330779L\r
-#define isc_gbak_start_req_failed 336330780L\r
-#define isc_gbak_rec_failed 336330781L\r
-#define isc_gbak_rel_req_failed 336330782L\r
-#define isc_gbak_db_info_failed 336330783L\r
-#define isc_gbak_no_db_desc 336330784L\r
-#define isc_gbak_db_create_failed 336330785L\r
-#define isc_gbak_decomp_len_error 336330786L\r
-#define isc_gbak_tbl_missing 336330787L\r
-#define isc_gbak_blob_col_missing 336330788L\r
-#define isc_gbak_create_blob_failed 336330789L\r
-#define isc_gbak_put_seg_failed 336330790L\r
-#define isc_gbak_rec_len_exp 336330791L\r
-#define isc_gbak_inv_rec_len 336330792L\r
-#define isc_gbak_exp_data_type 336330793L\r
-#define isc_gbak_gen_id_failed 336330794L\r
-#define isc_gbak_unk_rec_type 336330795L\r
-#define isc_gbak_inv_bkup_ver 336330796L\r
-#define isc_gbak_missing_bkup_desc 336330797L\r
-#define isc_gbak_string_trunc 336330798L\r
-#define isc_gbak_cant_rest_record 336330799L\r
-#define isc_gbak_send_failed 336330800L\r
-#define isc_gbak_no_tbl_name 336330801L\r
-#define isc_gbak_unexp_eof 336330802L\r
-#define isc_gbak_db_format_too_old 336330803L\r
-#define isc_gbak_inv_array_dim 336330804L\r
-#define isc_gbak_xdr_len_expected 336330807L\r
-#define isc_gbak_open_bkup_error 336330817L\r
-#define isc_gbak_open_error 336330818L\r
-#define isc_gbak_missing_block_fac 336330934L\r
-#define isc_gbak_inv_block_fac 336330935L\r
-#define isc_gbak_block_fac_specified 336330936L\r
-#define isc_gbak_missing_username 336330940L\r
-#define isc_gbak_missing_password 336330941L\r
-#define isc_gbak_missing_skipped_bytes 336330952L\r
-#define isc_gbak_inv_skipped_bytes 336330953L\r
-#define isc_gbak_err_restore_charset 336330965L\r
-#define isc_gbak_err_restore_collation 336330967L\r
-#define isc_gbak_read_error 336330972L\r
-#define isc_gbak_write_error 336330973L\r
-#define isc_gbak_db_in_use 336330985L\r
-#define isc_gbak_sysmemex 336330990L\r
-#define isc_gbak_restore_role_failed 336331002L\r
-#define isc_gbak_role_op_missing 336331005L\r
-#define isc_gbak_page_buffers_missing 336331010L\r
-#define isc_gbak_page_buffers_wrong_param 336331011L\r
-#define isc_gbak_page_buffers_restore 336331012L\r
-#define isc_gbak_inv_size 336331014L\r
-#define isc_gbak_file_outof_sequence 336331015L\r
-#define isc_gbak_join_file_missing 336331016L\r
-#define isc_gbak_stdin_not_supptd 336331017L\r
-#define isc_gbak_stdout_not_supptd 336331018L\r
-#define isc_gbak_bkup_corrupt 336331019L\r
-#define isc_gbak_unk_db_file_spec 336331020L\r
-#define isc_gbak_hdr_write_failed 336331021L\r
-#define isc_gbak_disk_space_ex 336331022L\r
-#define isc_gbak_size_lt_min 336331023L\r
-#define isc_gbak_svc_name_missing 336331025L\r
-#define isc_gbak_not_ownr 336331026L\r
-#define isc_gbak_mode_req 336331031L\r
-#define isc_gbak_just_data 336331033L\r
-#define isc_gbak_data_only 336331034L\r
-#define isc_gsec_cant_open_db 336723983L\r
-#define isc_gsec_switches_error 336723984L\r
-#define isc_gsec_no_op_spec 336723985L\r
-#define isc_gsec_no_usr_name 336723986L\r
-#define isc_gsec_err_add 336723987L\r
-#define isc_gsec_err_modify 336723988L\r
-#define isc_gsec_err_find_mod 336723989L\r
-#define isc_gsec_err_rec_not_found 336723990L\r
-#define isc_gsec_err_delete 336723991L\r
-#define isc_gsec_err_find_del 336723992L\r
-#define isc_gsec_err_find_disp 336723996L\r
-#define isc_gsec_inv_param 336723997L\r
-#define isc_gsec_op_specified 336723998L\r
-#define isc_gsec_pw_specified 336723999L\r
-#define isc_gsec_uid_specified 336724000L\r
-#define isc_gsec_gid_specified 336724001L\r
-#define isc_gsec_proj_specified 336724002L\r
-#define isc_gsec_org_specified 336724003L\r
-#define isc_gsec_fname_specified 336724004L\r
-#define isc_gsec_mname_specified 336724005L\r
-#define isc_gsec_lname_specified 336724006L\r
-#define isc_gsec_inv_switch 336724008L\r
-#define isc_gsec_amb_switch 336724009L\r
-#define isc_gsec_no_op_specified 336724010L\r
-#define isc_gsec_params_not_allowed 336724011L\r
-#define isc_gsec_incompat_switch 336724012L\r
-#define isc_gsec_inv_username 336724044L\r
-#define isc_gsec_inv_pw_length 336724045L\r
-#define isc_gsec_db_specified 336724046L\r
-#define isc_gsec_db_admin_specified 336724047L\r
-#define isc_gsec_db_admin_pw_specified 336724048L\r
-#define isc_gsec_sql_role_specified 336724049L\r
-#define isc_license_no_file 336789504L\r
-#define isc_license_op_specified 336789523L\r
-#define isc_license_op_missing 336789524L\r
-#define isc_license_inv_switch 336789525L\r
-#define isc_license_inv_switch_combo 336789526L\r
-#define isc_license_inv_op_combo 336789527L\r
-#define isc_license_amb_switch 336789528L\r
-#define isc_license_inv_parameter 336789529L\r
-#define isc_license_param_specified 336789530L\r
-#define isc_license_param_req 336789531L\r
-#define isc_license_syntx_error 336789532L\r
-#define isc_license_dup_id 336789534L\r
-#define isc_license_inv_id_key 336789535L\r
-#define isc_license_err_remove 336789536L\r
-#define isc_license_err_update 336789537L\r
-#define isc_license_err_convert 336789538L\r
-#define isc_license_err_unk 336789539L\r
-#define isc_license_svc_err_add 336789540L\r
-#define isc_license_svc_err_remove 336789541L\r
-#define isc_license_eval_exists 336789563L\r
-#define isc_gstat_unknown_switch 336920577L\r
-#define isc_gstat_retry 336920578L\r
-#define isc_gstat_wrong_ods 336920579L\r
-#define isc_gstat_unexpected_eof 336920580L\r
-#define isc_gstat_open_err 336920605L\r
-#define isc_gstat_read_err 336920606L\r
-#define isc_gstat_sysmemex 336920607L\r
-#define isc_err_max 713\r
-\r
-#endif /* JRD_GEN_IBERROR_H */\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: ibpp.h,v 1.3 2007/10/28 11:17:44 nobunaga Exp $\r
-// Subject : IBPP public header file. This is _the_ only file you include in\r
-// your application files when developing with IBPP.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-// Contributor(s):\r
-//\r
-// Olivier Mascia, main coding\r
-// Matt Hortman, initial linux port\r
-// Mark Jordan, design contributions\r
-// Maxim Abrashkin, enhancement patches\r
-// Torsten Martinsen, enhancement patches\r
-// Michael Hieke, darwin (OS X) port, enhancement patches\r
-// Val Samko, enhancement patches and debugging\r
-// Mike Nordell, invaluable C++ advices\r
-// Claudio Valderrama, help with not-so-well documented IB/FB features\r
-// Many others, excellent suggestions, bug finding, and support\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// Tabulations should be set every four characters when editing this file.\r
-//\r
-// When compiling a project using IBPP, the following defines should be made\r
-// on the command-line (or in makefiles) according to the OS platform and\r
-// compiler used.\r
-//\r
-// Select the platform: IBPP_WINDOWS | IBPP_LINUX | IBPP_DARWIN\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifndef __IBPP_H__\r
-#define __IBPP_H__\r
-\r
-#if !defined(IBPP_WINDOWS) && !defined(IBPP_LINUX) && !defined(IBPP_DARWIN)\r
-#error Please define IBPP_WINDOWS/IBPP_LINUX/IBPP_DARWIN before compiling !\r
-#endif\r
-\r
-#if !defined(__BCPLUSPLUS__) && !defined(__GNUC__) && !defined(_MSC_VER) && !defined(__DMC__)
-#error Your compiler is not recognized.\r
-#endif\r
-\r
-#if defined(IBPP_LINUX) || defined(IBPP_DARWIN)\r
-#define IBPP_UNIX // IBPP_UNIX stands as a common denominator to *NIX flavours\r
-#endif\r
-\r
-// IBPP is written for 32 bits systems or higher.\r
-// The standard type 'int' is assumed to be at least 32 bits.\r
-// And the standard type 'short' is assumed to be exactly 16 bits.\r
-// Everywhere possible, where the exact size of an integer does not matter,\r
-// the standard type 'int' is used. And where an exact integer size is required\r
-// the standard exact precision types definitions of C 99 standard are used.\r
-\r
-#if defined(_MSC_VER) || defined(__DMC__) || defined(__BCPLUSPLUS__)\r
-// C99 §7.18.1.1 Exact-width integer types (only those used by IBPP)\r
-#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
- typedef short int16_t;\r
- typedef int int32_t;\r
- typedef unsigned int uint32_t;\r
-#else\r
- typedef __int16 int16_t;\r
- typedef __int32 int32_t;\r
- typedef unsigned __int32 uint32_t;\r
-#endif\r
- typedef __int64 int64_t;\r
-#else\r
- #include <stg/os_int.h> // C99 (§7.18) integer types definitions\r
-#endif\r
-\r
-#if !defined(_)\r
-#define _(s) s\r
-#endif\r
-\r
-#include <exception>\r
-#include <string>\r
-#include <vector>\r
-\r
-namespace IBPP\r
-{\r
- // Typically you use this constant in a call IBPP::CheckVersion as in:\r
- // if (! IBPP::CheckVersion(IBPP::Version)) { throw .... ; }\r
- const uint32_t Version = (2<<24) + (5<<16) + (3<<8) + 0; // Version == 2.5.3.0\r
-\r
- // Dates range checking\r
- const int MinDate = -693594; // 1 JAN 0001\r
- const int MaxDate = 2958464; // 31 DEC 9999\r
- \r
- // Transaction Access Modes\r
- enum TAM {amWrite, amRead};\r
-\r
- // Transaction Isolation Levels\r
- enum TIL {ilConcurrency, ilReadDirty, ilReadCommitted, ilConsistency};\r
-\r
- // Transaction Lock Resolution\r
- enum TLR {lrWait, lrNoWait};\r
-\r
- // Transaction Table Reservation\r
- enum TTR {trSharedWrite, trSharedRead, trProtectedWrite, trProtectedRead};\r
-\r
- // Prepared Statement Types\r
- enum STT {stUnknown, stUnsupported,\r
- stSelect, stInsert, stUpdate, stDelete, stDDL, stExecProcedure,\r
- stSelectUpdate, stSetGenerator, stSavePoint};\r
-\r
- // SQL Data Types\r
- enum SDT {sdArray, sdBlob, sdDate, sdTime, sdTimestamp, sdString,\r
- sdSmallint, sdInteger, sdLargeint, sdFloat, sdDouble};\r
-\r
- // Array Data Types\r
- enum ADT {adDate, adTime, adTimestamp, adString,\r
- adBool, adInt16, adInt32, adInt64, adFloat, adDouble};\r
-\r
- // Database::Shutdown Modes\r
- enum DSM {dsForce, dsDenyTrans, dsDenyAttach};\r
-\r
- // Service::StartBackup && Service::StartRestore Flags\r
- enum BRF {\r
- brVerbose = 0x1,\r
- // Backup flags\r
- brIgnoreChecksums = 0x100, brIgnoreLimbo = 0x200,\r
- brMetadataOnly = 0x400, brNoGarbageCollect = 0x800,\r
- brNonTransportable = 0x1000, brConvertExtTables = 0x2000,\r
- // Restore flags\r
- brReplace = 0x10000, brDeactivateIdx = 0x20000,\r
- brNoShadow = 0x40000, brNoValidity = 0x80000,\r
- brPerTableCommit = 0x100000, brUseAllSpace = 0x200000\r
- };\r
-\r
- // Service::Repair Flags\r
- enum RPF\r
- {\r
- // Mandatory and mutually exclusives\r
- rpMendRecords = 0x1, rpValidatePages = 0x2, rpValidateFull = 0x4,\r
- // Options\r
- rpReadOnly = 0x100, rpIgnoreChecksums = 0x200, rpKillShadows = 0x400\r
- };\r
-\r
- // TransactionFactory Flags\r
- enum TFF {tfIgnoreLimbo = 0x1, tfAutoCommit = 0x2, tfNoAutoUndo = 0x4};\r
-\r
- /* IBPP never return any error codes. It throws exceptions.\r
- * On database engine reported errors, an IBPP::SQLException is thrown.\r
- * In all other cases, IBPP throws IBPP::LogicException.\r
- * Also note that the runtime and the language might also throw exceptions\r
- * while executing some IBPP methods. A failing new operator will throw\r
- * std::bad_alloc, IBPP does nothing to alter the standard behaviour.\r
- *\r
- * std::exception\r
- * |\r
- * IBPP::Exception\r
- * / \\r
- * IBPP::LogicException IBPP::SQLException\r
- * |\r
- * IBPP::WrongType\r
- */\r
-\r
- class Exception : public std::exception\r
- {\r
- public:\r
- virtual const char* Origin() const throw() = 0;\r
- virtual const char* ErrorMessage() const throw() = 0; // Deprecated, use what()\r
- virtual const char* what() const throw() = 0;\r
- virtual ~Exception() throw();\r
- };\r
-\r
- class LogicException : public Exception\r
- {\r
- public:\r
- virtual ~LogicException() throw();\r
- };\r
-\r
- class SQLException : public Exception\r
- {\r
- public:\r
- virtual int SqlCode() const throw() = 0;\r
- virtual int EngineCode() const throw() = 0;\r
- \r
- virtual ~SQLException() throw();\r
- };\r
-\r
- class WrongType : public LogicException\r
- {\r
- public:\r
- virtual ~WrongType() throw();\r
- };\r
- \r
- /* Classes Date, Time, Timestamp and DBKey are 'helper' classes. They help\r
- * in retrieving or setting some special SQL types. Dates, times and dbkeys\r
- * are often read and written as strings in SQL scripts. When programming\r
- * with IBPP, we handle those data with these specific classes, which\r
- * enhance their usefullness and free us of format problems (M/D/Y, D/M/Y,\r
- * Y-M-D ?, and so on...). */\r
-\r
- /* Class Date represent purely a Date (no time part specified). It is\r
- * usefull in interactions with the SQL DATE type of Interbase. You can add\r
- * or substract a number from a Date, that will modify it to represent the\r
- * correct date, X days later or sooner. All the Y2K details taken into\r
- * account.\r
- * The full range goes from integer values IBPP::MinDate to IBPP::MaxDate\r
- * which means from 01 Jan 0001 to 31 Dec 9999. ( Which is inherently\r
- * incorrect as this assumes Gregorian calendar. ) */\r
- \r
- class Timestamp; // Cross-reference between Timestamp, Date and Time\r
- \r
- class Date\r
- {\r
- protected:\r
- int mDate; // The date : 1 == 1 Jan 1900\r
-\r
- public:\r
- void Clear() { mDate = MinDate - 1; }\r
- void Today();\r
- void SetDate(int year, int month, int day);\r
- void SetDate(int dt);\r
- void GetDate(int& year, int& month, int& day) const;\r
- int GetDate() const { return mDate; }\r
- int Year() const;\r
- int Month() const;\r
- int Day() const;\r
- void Add(int days);\r
- void StartOfMonth();\r
- void EndOfMonth();\r
- \r
- Date() { Clear(); }\r
- Date(int dt) { SetDate(dt); }\r
- Date(int year, int month, int day);\r
- Date(const Date&); // Copy Constructor\r
- Date& operator=(const Timestamp&); // Timestamp Assignment operator\r
- Date& operator=(const Date&); // Date Assignment operator\r
-\r
- bool operator==(const Date& rv) const { return mDate == rv.GetDate(); }\r
- bool operator!=(const Date& rv) const { return mDate != rv.GetDate(); }\r
- bool operator<(const Date& rv) const { return mDate < rv.GetDate(); }\r
- bool operator>(const Date& rv) const { return mDate > rv.GetDate(); }\r
-\r
- virtual ~Date() { }\r
- };\r
-\r
- /* Class Time represent purely a Time. It is usefull in interactions\r
- * with the SQL TIME type of Interbase. */\r
-\r
- class Time\r
- {\r
- protected:\r
- int mTime; // The time, in ten-thousandths of seconds since midnight\r
-\r
- public:\r
- void Clear() { mTime = 0; }\r
- void Now();\r
- void SetTime(int hour, int minute, int second, int tenthousandths = 0);\r
- void SetTime(int tm);\r
- void GetTime(int& hour, int& minute, int& second) const;\r
- void GetTime(int& hour, int& minute, int& second, int& tenthousandths) const;\r
- int GetTime() const { return mTime; }\r
- int Hours() const;\r
- int Minutes() const;\r
- int Seconds() const;\r
- int SubSeconds() const; // Actually tenthousandths of seconds\r
- Time() { Clear(); }\r
- Time(int tm) { SetTime(tm); }\r
- Time(int hour, int minute, int second, int tenthousandths = 0);\r
- Time(const Time&); // Copy Constructor\r
- Time& operator=(const Timestamp&); // Timestamp Assignment operator\r
- Time& operator=(const Time&); // Time Assignment operator\r
-\r
- bool operator==(const Time& rv) const { return mTime == rv.GetTime(); }\r
- bool operator!=(const Time& rv) const { return mTime != rv.GetTime(); }\r
- bool operator<(const Time& rv) const { return mTime < rv.GetTime(); }\r
- bool operator>(const Time& rv) const { return mTime > rv.GetTime(); }\r
-\r
- virtual ~Time() { }\r
- };\r
-\r
- /* Class Timestamp represent a date AND a time. It is usefull in\r
- * interactions with the SQL TIMESTAMP type of Interbase. This class\r
- * inherits from Date and Time and completely inline implements its small\r
- * specific details. */\r
-\r
- class Timestamp : public Date, public Time\r
- {\r
- public:\r
- void Clear() { Date::Clear(); Time::Clear(); }\r
- void Today() { Date::Today(); Time::Clear(); }\r
- void Now() { Date::Today(); Time::Now(); }\r
-\r
- Timestamp() { Clear(); }\r
-\r
- Timestamp(int y, int m, int d)\r
- { Date::SetDate(y, m, d); Time::Clear(); }\r
-\r
- Timestamp(int y, int mo, int d, int h, int mi, int s, int t = 0)\r
- { Date::SetDate(y, mo, d); Time::SetTime(h, mi, s, t); }\r
-\r
- Timestamp(const Timestamp& rv)\r
- : Date(rv.mDate), Time(rv.mTime) {} // Copy Constructor\r
-\r
- Timestamp(const Date& rv)\r
- { mDate = rv.GetDate(); mTime = 0; }\r
-\r
- Timestamp(const Time& rv)\r
- { mDate = 0; mTime = rv.GetTime(); }\r
-\r
- Timestamp& operator=(const Timestamp& rv) // Timestamp Assignment operator\r
- { mDate = rv.mDate; mTime = rv.mTime; return *this; }\r
-\r
- Timestamp& operator=(const Date& rv) // Date Assignment operator\r
- { mDate = rv.GetDate(); return *this; }\r
-\r
- Timestamp& operator=(const Time& rv) // Time Assignment operator\r
- { mTime = rv.GetTime(); return *this; }\r
-\r
- bool operator==(const Timestamp& rv) const\r
- { return (mDate == rv.GetDate()) && (mTime == rv.GetTime()); }\r
-\r
- bool operator!=(const Timestamp& rv) const\r
- { return (mDate != rv.GetDate()) || (mTime != rv.GetTime()); }\r
-\r
- bool operator<(const Timestamp& rv) const\r
- { return (mDate < rv.GetDate()) ||\r
- (mDate == rv.GetDate() && mTime < rv.GetTime()); }\r
-\r
- bool operator>(const Timestamp& rv) const\r
- { return (mDate > rv.GetDate()) ||\r
- (mDate == rv.GetDate() && mTime > rv.GetTime()); }\r
-\r
- ~Timestamp() { }\r
- };\r
-\r
- /* Class DBKey can store a DBKEY, that special value which the hidden\r
- * RDB$DBKEY can give you from a select statement. A DBKey is nothing\r
- * specific to IBPP. It's a feature of the Firebird database engine. See its\r
- * documentation for more information. */\r
-\r
- class DBKey\r
- {\r
- private:\r
- std::string mDBKey; // Stores the binary DBKey\r
- mutable std::string mString;// String (temporary) representation of it\r
-\r
- public:\r
- void Clear();\r
- int Size() const { return (int)mDBKey.size(); }\r
- void SetKey(const void*, int size);\r
- void GetKey(void*, int size) const;\r
- const char* AsString() const;\r
-\r
- DBKey& operator=(const DBKey&); // Assignment operator\r
- DBKey(const DBKey&); // Copy Constructor\r
- DBKey() { }\r
- ~DBKey() { }\r
- };\r
-\r
- /* Class User wraps all the information about a user that the engine can manage. */\r
-\r
- class User\r
- {\r
- public:\r
- std::string username;\r
- std::string password;\r
- std::string firstname;\r
- std::string middlename;\r
- std::string lastname;\r
- uint32_t userid; // Only relevant on unixes\r
- uint32_t groupid; // Only relevant on unixes\r
-\r
- private:\r
- void copyfrom(const User& r);\r
-\r
- public:\r
- void clear();\r
- User& operator=(const User& r) { copyfrom(r); return *this; }\r
- User(const User& r) { copyfrom(r); }\r
- User() : userid(0), groupid(0) { }\r
- ~User() { }\r
- };\r
-\r
- // Interface Wrapper\r
- template <class T>\r
- class Ptr\r
- {\r
- private:\r
- T* mObject;\r
-\r
- public:\r
- void clear()\r
- {\r
- if (mObject != 0) { mObject->Release(); mObject = 0; }\r
- }\r
-\r
- T* intf() const { return mObject; }\r
- T* operator->() const { return mObject; }\r
-\r
- bool operator==(const T* p) const { return mObject == p; }\r
- bool operator==(const Ptr& r) const { return mObject == r.mObject; }\r
- bool operator!=(const T* p) const { return mObject != p; }\r
- bool operator!=(const Ptr& r) const { return mObject != r.mObject; }\r
-\r
- Ptr& operator=(T* p)\r
- {\r
- // AddRef _before_ Release gives correct behaviour on self-assigns\r
- T* tmp = (p == 0 ? 0 : p->AddRef()); // Take care of 0\r
- if (mObject != 0) mObject->Release();\r
- mObject = tmp; return *this;\r
- }\r
-\r
- Ptr& operator=(const Ptr& r)\r
- {\r
- // AddRef _before_ Release gives correct behaviour on self-assigns\r
- T* tmp = (r.intf() == 0 ? 0 : r->AddRef());// Take care of 0\r
- if (mObject != 0) mObject->Release();\r
- mObject = tmp; return *this;\r
- }\r
-\r
- Ptr(T* p) : mObject(p == 0 ? 0 : p->AddRef()) { }\r
- Ptr(const Ptr& r) : mObject(r.intf() == 0 ? 0 : r->AddRef()) { }\r
-\r
- Ptr() : mObject(0) { }\r
- ~Ptr() { clear(); }\r
- };\r
-\r
- // --- Interface Classes --- //\r
-\r
- /* Interfaces IBlob, IArray, IService, IDatabase, ITransaction and\r
- * IStatement are at the core of IBPP. Though it is possible to program your\r
- * applications by using theses interfaces directly (as was the case with\r
- * IBPP 1.x), you should refrain from using them and prefer the new IBPP\r
- * Objects Blob, Array, ... (without the I in front). Those new objects are\r
- * typedef'd right after each interface class definition as you can read\r
- * below. If you program using the Blob (instead of the IBlob interface\r
- * itself), you'll never have to care about AddRef/Release and you'll never\r
- * have to care about deleting your objects. */\r
-\r
- class IBlob; typedef Ptr<IBlob> Blob;\r
- class IArray; typedef Ptr<IArray> Array;\r
- class IService; typedef Ptr<IService> Service;\r
- class IDatabase; typedef Ptr<IDatabase> Database;\r
- class ITransaction; typedef Ptr<ITransaction> Transaction;\r
- class IStatement; typedef Ptr<IStatement> Statement;\r
- class IEvents; typedef Ptr<IEvents> Events;\r
- class IRow; typedef Ptr<IRow> Row;\r
-\r
- /* IBlob is the interface to the blob capabilities of IBPP. Blob is the\r
- * object class you actually use in your programming. In Firebird, at the\r
- * row level, a blob is merely a handle to a blob, stored elsewhere in the\r
- * database. Blob allows you to retrieve such a handle and then read from or\r
- * write to the blob, much in the same manner than you would do with a file. */\r
-\r
- class IBlob\r
- {\r
- public:\r
- virtual void Create() = 0;\r
- virtual void Open() = 0;\r
- virtual void Close() = 0;\r
- virtual void Cancel() = 0;\r
- virtual int Read(void*, int size) = 0;\r
- virtual void Write(const void*, int size) = 0;\r
- virtual void Info(int* Size, int* Largest, int* Segments) = 0;\r
- \r
- virtual void Save(const std::string& data) = 0;\r
- virtual void Load(std::string& data) = 0;\r
-\r
- virtual Database DatabasePtr() const = 0;\r
- virtual Transaction TransactionPtr() const = 0;\r
-\r
- virtual IBlob* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IBlob() { }\r
- };\r
-\r
- /* IArray is the interface to the array capabilities of IBPP. Array is the\r
- * object class you actually use in your programming. With an Array object, you\r
- * can create, read and write Interbase Arrays, as a whole or in slices. */\r
-\r
- class IArray\r
- {\r
- public:\r
- virtual void Describe(const std::string& table, const std::string& column) = 0;\r
- virtual void ReadTo(ADT, void* buffer, int elemcount) = 0;\r
- virtual void WriteFrom(ADT, const void* buffer, int elemcount) = 0;\r
- virtual SDT ElementType() = 0;\r
- virtual int ElementSize() = 0;\r
- virtual int ElementScale() = 0;\r
- virtual int Dimensions() = 0;\r
- virtual void Bounds(int dim, int* low, int* high) = 0;\r
- virtual void SetBounds(int dim, int low, int high) = 0;\r
-\r
- virtual Database DatabasePtr() const = 0;\r
- virtual Transaction TransactionPtr() const = 0;\r
-\r
- virtual IArray* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IArray() { }\r
- };\r
-\r
- /* IService is the interface to the service capabilities of IBPP. Service is\r
- * the object class you actually use in your programming. With a Service\r
- * object, you can do some maintenance work of databases and servers\r
- * (backup, restore, create/update users, ...) */\r
-\r
- class IService\r
- {\r
- public:\r
- virtual void Connect() = 0;\r
- virtual bool Connected() = 0;\r
- virtual void Disconnect() = 0;\r
-\r
- virtual void GetVersion(std::string& version) = 0;\r
-\r
- virtual void AddUser(const User&) = 0;\r
- virtual void GetUser(User&) = 0;\r
- virtual void GetUsers(std::vector<User>&) = 0;\r
- virtual void ModifyUser(const User&) = 0;\r
- virtual void RemoveUser(const std::string& username) = 0;\r
-\r
- virtual void SetPageBuffers(const std::string& dbfile, int buffers) = 0;\r
- virtual void SetSweepInterval(const std::string& dbfile, int sweep) = 0;\r
- virtual void SetSyncWrite(const std::string& dbfile, bool) = 0;\r
- virtual void SetReadOnly(const std::string& dbfile, bool) = 0;\r
- virtual void SetReserveSpace(const std::string& dbfile, bool) = 0;\r
-\r
- virtual void Shutdown(const std::string& dbfile, DSM mode, int sectimeout) = 0;\r
- virtual void Restart(const std::string& dbfile) = 0;\r
- virtual void Sweep(const std::string& dbfile) = 0;\r
- virtual void Repair(const std::string& dbfile, RPF flags) = 0;\r
-\r
- virtual void StartBackup(const std::string& dbfile,\r
- const std::string& bkfile, BRF flags = BRF(0)) = 0;\r
- virtual void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
- int pagesize = 0, BRF flags = BRF(0)) = 0;\r
-\r
- virtual const char* WaitMsg() = 0; // With reporting (does not block)\r
- virtual void Wait() = 0; // Without reporting (does block)\r
-\r
- virtual IService* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IService() { }\r
- };\r
-\r
- /* IDatabase is the interface to the database connections in IBPP. Database\r
- * is the object class you actually use in your programming. With a Database\r
- * object, you can create/drop/connect databases. */\r
-\r
- class EventInterface; // Cross-reference between EventInterface and IDatabase\r
- \r
- class IDatabase\r
- {\r
- public:\r
- virtual const char* ServerName() const = 0;\r
- virtual const char* DatabaseName() const = 0;\r
- virtual const char* Username() const = 0;\r
- virtual const char* UserPassword() const = 0;\r
- virtual const char* RoleName() const = 0;\r
- virtual const char* CharSet() const = 0;\r
- virtual const char* CreateParams() const = 0;\r
-\r
- virtual void Info(int* ODS, int* ODSMinor, int* PageSize,\r
- int* Pages, int* Buffers, int* Sweep, bool* Sync,\r
- bool* Reserve) = 0;\r
- virtual void Statistics(int* Fetches, int* Marks,\r
- int* Reads, int* Writes) = 0;\r
- virtual void Counts(int* Insert, int* Update, int* Delete, \r
- int* ReadIdx, int* ReadSeq) = 0;\r
- virtual void Users(std::vector<std::string>& users) = 0;\r
- virtual int Dialect() = 0;\r
-\r
- virtual void Create(int dialect) = 0;\r
- virtual void Connect() = 0;\r
- virtual bool Connected() = 0;\r
- virtual void Inactivate() = 0;\r
- virtual void Disconnect() = 0;\r
- virtual void Drop() = 0;\r
-\r
- virtual IDatabase* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IDatabase() { }\r
- };\r
-\r
- /* ITransaction is the interface to the transaction connections in IBPP.\r
- * Transaction is the object class you actually use in your programming. A\r
- * Transaction object can be associated with more than one Database,\r
- * allowing for distributed transactions spanning multiple databases,\r
- * possibly located on different servers. IBPP is one among the few\r
- * programming interfaces to Firebird that allows you to support distributed\r
- * transactions. */\r
-\r
- class ITransaction\r
- {\r
- public:\r
- virtual void AttachDatabase(Database db, TAM am = amWrite,\r
- TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)) = 0;\r
- virtual void DetachDatabase(Database db) = 0;\r
- virtual void AddReservation(Database db,\r
- const std::string& table, TTR tr) = 0;\r
-\r
- virtual void Start() = 0;\r
- virtual bool Started() = 0;\r
- virtual void Commit() = 0;\r
- virtual void Rollback() = 0;\r
- virtual void CommitRetain() = 0;\r
- virtual void RollbackRetain() = 0;\r
-\r
- virtual ITransaction* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~ITransaction() { }\r
- };\r
-\r
- /*\r
- * Class Row can hold all the values of a row (from a SELECT for instance).\r
- */\r
-\r
- class IRow\r
- {\r
- public:\r
- virtual void SetNull(int) = 0;\r
- virtual void Set(int, bool) = 0;\r
- virtual void Set(int, const void*, int) = 0; // byte buffers\r
- virtual void Set(int, const char*) = 0; // c-string\r
- virtual void Set(int, const std::string&) = 0;\r
- virtual void Set(int, int16_t) = 0;\r
- virtual void Set(int, int32_t) = 0;\r
- virtual void Set(int, int64_t) = 0;\r
- virtual void Set(int, float) = 0;\r
- virtual void Set(int, double) = 0;\r
- virtual void Set(int, const Timestamp&) = 0;\r
- virtual void Set(int, const Date&) = 0;\r
- virtual void Set(int, const Time&) = 0;\r
- virtual void Set(int, const DBKey&) = 0;\r
- virtual void Set(int, const Blob&) = 0;\r
- virtual void Set(int, const Array&) = 0;\r
-\r
- virtual bool IsNull(int) = 0;\r
- virtual bool Get(int, bool&) = 0;\r
- virtual bool Get(int, void*, int&) = 0; // byte buffers\r
- virtual bool Get(int, std::string&) = 0;\r
- virtual bool Get(int, int16_t&) = 0;\r
- virtual bool Get(int, int32_t&) = 0;\r
- virtual bool Get(int, int64_t&) = 0;\r
- virtual bool Get(int, float&) = 0;\r
- virtual bool Get(int, double&) = 0;\r
- virtual bool Get(int, Timestamp&) = 0;\r
- virtual bool Get(int, Date&) = 0;\r
- virtual bool Get(int, Time&) = 0;\r
- virtual bool Get(int, DBKey&) = 0;\r
- virtual bool Get(int, Blob&) = 0;\r
- virtual bool Get(int, Array&) = 0;\r
-\r
- virtual bool IsNull(const std::string&) = 0;\r
- virtual bool Get(const std::string&, bool&) = 0;\r
- virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
- virtual bool Get(const std::string&, std::string&) = 0;\r
- virtual bool Get(const std::string&, int16_t&) = 0;\r
- virtual bool Get(const std::string&, int32_t&) = 0;\r
- virtual bool Get(const std::string&, int64_t&) = 0;\r
- virtual bool Get(const std::string&, float&) = 0;\r
- virtual bool Get(const std::string&, double&) = 0;\r
- virtual bool Get(const std::string&, Timestamp&) = 0;\r
- virtual bool Get(const std::string&, Date&) = 0;\r
- virtual bool Get(const std::string&, Time&) = 0;\r
- virtual bool Get(const std::string&, DBKey&) = 0;\r
- virtual bool Get(const std::string&, Blob&) = 0;\r
- virtual bool Get(const std::string&, Array&) = 0;\r
-\r
- virtual int ColumnNum(const std::string&) = 0;\r
- virtual const char* ColumnName(int) = 0;\r
- virtual const char* ColumnAlias(int) = 0;\r
- virtual const char* ColumnTable(int) = 0;\r
- virtual SDT ColumnType(int) = 0;\r
- virtual int ColumnSubtype(int) = 0;\r
- virtual int ColumnSize(int) = 0;\r
- virtual int ColumnScale(int) = 0;\r
- virtual int Columns() = 0;\r
- \r
- virtual bool ColumnUpdated(int) = 0;\r
- virtual bool Updated() = 0;\r
-\r
- virtual Database DatabasePtr() const = 0;\r
- virtual Transaction TransactionPtr() const = 0;\r
-\r
- virtual IRow* Clone() = 0;\r
- virtual IRow* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IRow() {}\r
- };\r
-\r
- /* IStatement is the interface to the statements execution in IBPP.\r
- * Statement is the object class you actually use in your programming. A\r
- * Statement object is the work horse of IBPP. All your data manipulation\r
- * statements will be done through it. It is also used to access the result\r
- * set of a query (when the statement is such), one row at a time and in\r
- * strict forward direction. */\r
-\r
- class IStatement\r
- {\r
- public:\r
- virtual void Prepare(const std::string&) = 0;\r
- virtual void Execute() = 0;\r
- virtual void Execute(const std::string&) = 0;\r
- virtual void ExecuteImmediate(const std::string&) = 0;\r
- virtual void CursorExecute(const std::string& cursor) = 0;\r
- virtual void CursorExecute(const std::string& cursor, const std::string&) = 0;\r
- virtual bool Fetch() = 0;\r
- virtual bool Fetch(Row&) = 0;\r
- virtual int AffectedRows() = 0;\r
- virtual void Close() = 0;\r
- virtual std::string& Sql() = 0;\r
- virtual STT Type() = 0;\r
-\r
- virtual void SetNull(int) = 0;\r
- virtual void Set(int, bool) = 0;\r
- virtual void Set(int, const void*, int) = 0; // byte buffers\r
- virtual void Set(int, const char*) = 0; // c-string\r
- virtual void Set(int, const std::string&) = 0;\r
- virtual void Set(int, int16_t value) = 0;\r
- virtual void Set(int, int32_t value) = 0;\r
- virtual void Set(int, int64_t value) = 0;\r
- virtual void Set(int, float value) = 0;\r
- virtual void Set(int, double value) = 0;\r
- virtual void Set(int, const Timestamp& value) = 0;\r
- virtual void Set(int, const Date& value) = 0;\r
- virtual void Set(int, const Time& value) = 0;\r
- virtual void Set(int, const DBKey& value) = 0;\r
- virtual void Set(int, const Blob& value) = 0;\r
- virtual void Set(int, const Array& value) = 0;\r
-\r
- virtual bool IsNull(int) = 0;\r
- virtual bool Get(int, bool&) = 0;\r
- virtual bool Get(int, void*, int&) = 0; // byte buffers\r
- virtual bool Get(int, std::string&) = 0;\r
- virtual bool Get(int, int16_t&) = 0;\r
- virtual bool Get(int, int32_t&) = 0;\r
- virtual bool Get(int, int64_t&) = 0;\r
- virtual bool Get(int, float&) = 0;\r
- virtual bool Get(int, double&) = 0;\r
- virtual bool Get(int, Timestamp& value) = 0;\r
- virtual bool Get(int, Date& value) = 0;\r
- virtual bool Get(int, Time& value) = 0;\r
- virtual bool Get(int, DBKey& value) = 0;\r
- virtual bool Get(int, Blob& value) = 0;\r
- virtual bool Get(int, Array& value) = 0;\r
-\r
- virtual bool IsNull(const std::string&) = 0;\r
- virtual bool Get(const std::string&, bool&) = 0;\r
- virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
- virtual bool Get(const std::string&, std::string&) = 0;\r
- virtual bool Get(const std::string&, int16_t&) = 0;\r
- virtual bool Get(const std::string&, int32_t&) = 0;\r
- virtual bool Get(const std::string&, int64_t&) = 0;\r
- virtual bool Get(const std::string&, float&) = 0;\r
- virtual bool Get(const std::string&, double&) = 0;\r
- virtual bool Get(const std::string&, Timestamp& value) = 0;\r
- virtual bool Get(const std::string&, Date& value) = 0;\r
- virtual bool Get(const std::string&, Time& value) = 0;\r
- virtual bool Get(const std::string&, DBKey& value) = 0;\r
- virtual bool Get(const std::string&, Blob& value) = 0;\r
- virtual bool Get(const std::string&, Array& value) = 0;\r
-\r
- virtual int ColumnNum(const std::string&) = 0;\r
- virtual const char* ColumnName(int) = 0;\r
- virtual const char* ColumnAlias(int) = 0;\r
- virtual const char* ColumnTable(int) = 0;\r
- virtual SDT ColumnType(int) = 0;\r
- virtual int ColumnSubtype(int) = 0;\r
- virtual int ColumnSize(int) = 0;\r
- virtual int ColumnScale(int) = 0;\r
- virtual int Columns() = 0;\r
-\r
- virtual SDT ParameterType(int) = 0;\r
- virtual int ParameterSubtype(int) = 0;\r
- virtual int ParameterSize(int) = 0;\r
- virtual int ParameterScale(int) = 0;\r
- virtual int Parameters() = 0;\r
-\r
- virtual void Plan(std::string&) = 0;\r
-\r
- virtual Database DatabasePtr() const = 0;\r
- virtual Transaction TransactionPtr() const = 0;\r
-\r
- virtual IStatement* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IStatement() { }\r
-\r
- // DEPRECATED METHODS (WON'T BE AVAILABLE IN VERSIONS 3.x)\r
- virtual bool Get(int, char*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, char*) = 0; // DEPRECATED\r
- virtual bool Get(int, bool*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, bool*) = 0; // DEPRECATED\r
- virtual bool Get(int, int16_t*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, int16_t*) = 0; // DEPRECATED\r
- virtual bool Get(int, int32_t*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, int32_t*) = 0; // DEPRECATED\r
- virtual bool Get(int, int64_t*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, int64_t*) = 0; // DEPRECATED\r
- virtual bool Get(int, float*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, float*) = 0; // DEPRECATED\r
- virtual bool Get(int, double*) = 0; // DEPRECATED\r
- virtual bool Get(const std::string&, double*) = 0; // DEPRECATED\r
- };\r
- \r
- class IEvents\r
- {\r
- public:\r
- virtual void Add(const std::string&, EventInterface*) = 0;\r
- virtual void Drop(const std::string&) = 0;\r
- virtual void List(std::vector<std::string>&) = 0;\r
- virtual void Clear() = 0; // Drop all events\r
- virtual void Dispatch() = 0; // Dispatch events (calls handlers)\r
-\r
- virtual Database DatabasePtr() const = 0;\r
-\r
- virtual IEvents* AddRef() = 0;\r
- virtual void Release() = 0;\r
-\r
- virtual ~IEvents() { }\r
- };\r
- \r
- /* Class EventInterface is merely a pure interface.\r
- * It is _not_ implemented by IBPP. It is only a base class definition from\r
- * which your own event interface classes have to derive from.\r
- * Please read the reference guide at http://www.ibpp.org for more info. */\r
-\r
- class EventInterface\r
- {\r
- public:\r
- virtual void ibppEventHandler(Events, const std::string&, int) = 0;\r
- virtual ~EventInterface() { }\r
- };\r
-\r
- // --- Factories ---\r
- // These methods are the only way to get one of the above\r
- // Interfaces. They are at the heart of how you program using IBPP. For\r
- // instance, to get access to a database, you'll write code similar to this:\r
- // {\r
- // Database db = DatabaseFactory("server", "databasename",\r
- // "user", "password");\r
- // db->Connect();\r
- // ...\r
- // db->Disconnect();\r
- // }\r
-\r
- Service ServiceFactory(const std::string& ServerName,\r
- const std::string& UserName, const std::string& UserPassword);\r
-\r
- Database DatabaseFactory(const std::string& ServerName,\r
- const std::string& DatabaseName, const std::string& UserName,\r
- const std::string& UserPassword, const std::string& RoleName,\r
- const std::string& CharSet, const std::string& CreateParams);\r
-\r
- inline Database DatabaseFactory(const std::string& ServerName,\r
- const std::string& DatabaseName, const std::string& UserName,\r
- const std::string& UserPassword)\r
- { return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); }\r
-\r
- Transaction TransactionFactory(Database db, TAM am = amWrite,\r
- TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0));\r
-\r
- Statement StatementFactory(Database db, Transaction tr,\r
- const std::string& sql);\r
-\r
- inline Statement StatementFactory(Database db, Transaction tr)\r
- { return StatementFactory(db, tr, ""); }\r
-\r
- Blob BlobFactory(Database db, Transaction tr);\r
- \r
- Array ArrayFactory(Database db, Transaction tr);\r
- \r
- Events EventsFactory(Database db);\r
-\r
- /* IBPP uses a self initialization system. Each time an object that may\r
- * require the usage of the Interbase client C-API library is used, the\r
- * library internal handling details are automatically initialized, if not\r
- * already done. You can kick this initialization at the start of an\r
- * application by calling IBPP::CheckVersion(). This is recommended, because\r
- * IBPP::CheckVersion will assure you that YOUR code has been compiled\r
- * against a compatible version of the library. */\r
-\r
- bool CheckVersion(uint32_t);\r
- int GDSVersion();\r
- \r
- /* On Win32 platform, ClientLibSearchPaths() allows to setup\r
- * one or multiple additional paths (separated with a ';') where IBPP\r
- * will look for the client library (before the default implicit search\r
- * locations). This is usefull for applications distributed with a 'private'\r
- * copy of Firebird, when the registry is useless to identify the location\r
- * from where to attempt loading the fbclient.dll / gds32.dll.\r
- * If called, this function must be called *early* by the application,\r
- * before *any* other function or object methods of IBPP.\r
- * Currently, this is a NO-OP on platforms other than Win32. */\r
- \r
- void ClientLibSearchPaths(const std::string&);\r
-\r
- /* Finally, here are some date and time conversion routines used by IBPP and\r
- * that may be helpful at the application level. They do not depend on\r
- * anything related to Firebird/Interbase. Just a bonus. dtoi and itod\r
- * return false on invalid parameters or out of range conversions. */\r
-\r
- bool dtoi(int date, int* py, int* pm, int* pd);\r
- bool itod(int* pdate, int year, int month, int day);\r
- void ttoi(int itime, int* phour, int* pminute, int* psecond, int* ptt);\r
- void itot(int* ptime, int hour, int minute, int second = 0, int tenthousandths = 0);\r
-\r
-}\r
-\r
-#endif\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Row class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <math.h>\r
-#include <time.h>\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void RowImpl::SetNull(int param)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized."));\r
- if (param < 1 || param > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[param-1]);\r
- if (! (var->sqltype & 1))\r
- throw LogicExceptionImpl("Row::SetNull", _("This column can't be null."));\r
-\r
- *var->sqlind = -1; // Set the column to SQL NULL\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, bool value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivBool, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const char* cstring)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized."));\r
- if (cstring == 0)\r
- throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected."));\r
-\r
- SetValue(param, ivByte, cstring, (int)strlen(cstring));\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const void* bindata, int len)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized."));\r
- if (bindata == 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected."));\r
- if (len < 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0"));\r
- \r
- SetValue(param, ivByte, bindata, len);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const std::string& s)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivString, (void*)&s);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int16_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized."));\r
- \r
- SetValue(param, ivInt16, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int32_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivInt32, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int64_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivInt64, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, float value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivFloat, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, double value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivDouble, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Timestamp& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivTimestamp, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Date& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized."));\r
-\r
- if (mDialect == 1)\r
- {\r
- // In dialect 1, IBPP::Date is supposed to work with old 'DATE'\r
- // fields which are actually ISC_TIMESTAMP.\r
- IBPP::Timestamp timestamp(value);\r
- SetValue(param, ivTimestamp, ×tamp);\r
- }\r
- else\r
- {\r
- // Dialect 3\r
- SetValue(param, ivDate, (void*)&value);\r
- }\r
-\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Time& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized."));\r
- if (mDialect == 1)\r
- throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database."));\r
-\r
- SetValue(param, ivTime, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Blob& blob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized."));\r
- if (mDatabase != 0 && blob->DatabasePtr() != mDatabase)\r
- throw LogicExceptionImpl("Row::Set[Blob]",\r
- _("IBlob and Row attached to different databases"));\r
- if (mTransaction != 0 && blob->TransactionPtr() != mTransaction)\r
- throw LogicExceptionImpl("Row::Set[Blob]",\r
- _("IBlob and Row attached to different transactions"));\r
-\r
- SetValue(param, ivBlob, blob.intf());\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Array& array)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized."));\r
- if (mDatabase != 0 && array->DatabasePtr() != mDatabase)\r
- throw LogicExceptionImpl("Row::Set[Array]",\r
- _("IArray and Row attached to different databases"));\r
- if (mTransaction != 0 && array->TransactionPtr() != mTransaction)\r
- throw LogicExceptionImpl("Row::Set[Array]",\r
- _("IArray and Row attached to different transactions"));\r
-\r
- SetValue(param, ivArray, (void*)array.intf());\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::DBKey& key)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivDBKey, (void*)&key);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-/*\r
-void RowImpl::Set(int param, const IBPP::Value& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized."));\r
-\r
- //SetValue(param, ivDBKey, (void*)&key);\r
- //mUpdated[param-1] = true;\r
-}\r
-*/\r
-\r
-bool RowImpl::IsNull(int column)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
- if (column < 1 || column > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[column-1]);\r
- return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, bool& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivBool);\r
- if (pvalue != 0)\r
- retvalue = (*(char*)pvalue == 0 ? false : true);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, char* retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
-\r
- int sqllen;\r
- void* pvalue = GetValue(column, ivByte, &sqllen);\r
- if (pvalue != 0)\r
- {\r
- memcpy(retvalue, pvalue, sqllen);\r
- retvalue[sqllen] = '\0';\r
- }\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, void* bindata, int& userlen)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
- if (bindata == 0)\r
- throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
- if (userlen < 0)\r
- throw LogicExceptionImpl("Row::Get", _("Length must be >= 0"));\r
-\r
- int sqllen;\r
- void* pvalue = GetValue(column, ivByte, &sqllen);\r
- if (pvalue != 0)\r
- {\r
- // userlen says how much bytes the user can accept\r
- // let's shorten it, if there is less bytes available\r
- if (sqllen < userlen) userlen = sqllen;\r
- memcpy(bindata, pvalue, userlen);\r
- }\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, std::string& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivString, &retvalue);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int16_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt16);\r
- if (pvalue != 0)\r
- retvalue = *(int16_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int32_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt32);\r
- if (pvalue != 0)\r
- retvalue = *(int32_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int64_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt64);\r
- if (pvalue != 0)\r
- retvalue = *(int64_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, float& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivFloat);\r
- if (pvalue != 0)\r
- retvalue = *(float*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, double& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivDouble);\r
- if (pvalue != 0)\r
- retvalue = *(double*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Timestamp& timestamp)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Date& date)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- if (mDialect == 1)\r
- {\r
- // Dialect 1. IBPP::Date is supposed to work with old 'DATE'\r
- // fields which are actually ISC_TIMESTAMP.\r
- IBPP::Timestamp timestamp;\r
- void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
- if (pvalue != 0) date = timestamp;\r
- return pvalue == 0 ? true : false;\r
- }\r
- else\r
- {\r
- void* pvalue = GetValue(column, ivDate, (void*)&date);\r
- return pvalue == 0 ? true : false;\r
- }\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Time& time)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivTime, (void*)&time);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Blob& retblob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf());\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::DBKey& retkey)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivDBKey, (void*)&retkey);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Array& retarray)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivArray, (void*)retarray.intf());\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-/*\r
-const IBPP::Value RowImpl::Get(int column)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- //void* value = GetValue(column, ivArray, (void*)retarray.intf());\r
- //return value == 0 ? true : false;\r
- return IBPP::Value();\r
-}\r
-*/\r
-\r
-bool RowImpl::IsNull(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
-\r
- return IsNull(ColumnNum(name));\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, bool& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, char* retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, void* retvalue, int& count)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue, count);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, std::string& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::GetString", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int16_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int32_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int64_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, float& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, double& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retblob);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Array& retarray)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retarray);\r
-}\r
-\r
-/*\r
-const IBPP::Value RowImpl::Get(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name));\r
-}\r
-*/\r
-\r
-int RowImpl::Columns()\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Columns", _("The row is not initialized."));\r
-\r
- return mDescrArea->sqld;\r
-}\r
-\r
-int RowImpl::ColumnNum(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized."));\r
- if (name.empty())\r
- throw LogicExceptionImpl("Row::ColumnNum", _("Column name <empty> not found."));\r
-\r
- XSQLVAR* var;\r
- char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0'\r
-\r
- // Local upper case copy of the column name\r
- size_t len = name.length();\r
- if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname);\r
- strncpy(Uname, name.c_str(), len);\r
- Uname[len] = '\0';\r
- char* p = Uname;\r
- while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
-\r
- // Loop through the columns of the descriptor\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- var = &(mDescrArea->sqlvar[i]);\r
- if (var->sqlname_length != (int16_t)len) continue;\r
- if (strncmp(Uname, var->sqlname, len) == 0) return i+1;\r
- }\r
-\r
- // Failed finding the column name, let's retry using the aliases\r
- char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0'\r
-\r
- // Local upper case copy of the column name\r
- len = name.length();\r
- if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname);\r
- strncpy(Ualias, name.c_str(), len);\r
- Ualias[len] = '\0';\r
- p = Ualias;\r
- while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
-\r
- // Loop through the columns of the descriptor\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- var = &(mDescrArea->sqlvar[i]);\r
- if (var->aliasname_length != (int16_t)len) continue;\r
- if (strncmp(Ualias, var->aliasname, len) == 0) return i+1;\r
- }\r
-\r
- throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column."));\r
-#ifdef __DMC__\r
- return 0; // DMC errronously warns here about a missing return\r
-#endif\r
-}\r
-\r
-/*\r
-ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake.\r
-Ideally, the strings should be stored elsewhere (like _Numerics and so on) to\r
-take into account the final '\0' which needs to be added. For now, we insert\r
-the '\0' in the original data, which will cut the 32th character. Not terribly\r
-bad, but should be cleanly rewritten.\r
-*/\r
-\r
-const char* RowImpl::ColumnName(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->sqlname_length >= 31) var->sqlname_length = 31;\r
- var->sqlname[var->sqlname_length] = '\0';\r
- return var->sqlname;\r
-}\r
-\r
-const char* RowImpl::ColumnAlias(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->aliasname_length >= 31) var->aliasname_length = 31;\r
- var->aliasname[var->aliasname_length] = '\0';\r
- return var->aliasname;\r
-}\r
-\r
-const char* RowImpl::ColumnTable(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->relname_length >= 31) var->relname_length = 31;\r
- var->relname[var->relname_length] = '\0';\r
- return var->relname;\r
-}\r
-\r
-IBPP::SDT RowImpl::ColumnType(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range."));\r
-\r
- IBPP::SDT value;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
-\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT : value = IBPP::sdString; break;\r
- case SQL_VARYING : value = IBPP::sdString; break;\r
- case SQL_SHORT : value = IBPP::sdSmallint; break;\r
- case SQL_LONG : value = IBPP::sdInteger; break;\r
- case SQL_INT64 : value = IBPP::sdLargeint; break;\r
- case SQL_FLOAT : value = IBPP::sdFloat; break;\r
- case SQL_DOUBLE : value = IBPP::sdDouble; break;\r
- case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break;\r
- case SQL_TYPE_DATE : value = IBPP::sdDate; break;\r
- case SQL_TYPE_TIME : value = IBPP::sdTime; break;\r
- case SQL_BLOB : value = IBPP::sdBlob; break;\r
- case SQL_ARRAY : value = IBPP::sdArray; break;\r
- default : throw LogicExceptionImpl("Row::ColumnType",\r
- _("Found an unknown sqltype !"));\r
- }\r
-\r
- return value;\r
-}\r
-\r
-int RowImpl::ColumnSubtype(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return (int)var->sqlsubtype;\r
-}\r
-\r
-int RowImpl::ColumnSize(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return var->sqllen;\r
-}\r
-\r
-int RowImpl::ColumnScale(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return -var->sqlscale;\r
-}\r
-\r
-bool RowImpl::ColumnUpdated(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range."));\r
-\r
- return mUpdated[varnum-1];\r
-}\r
-\r
-bool RowImpl::Updated()\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
-\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- if (mUpdated[i]) return true;\r
- return false;\r
-}\r
-\r
-IBPP::Database RowImpl::DatabasePtr() const\r
-{\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction RowImpl::TransactionPtr() const\r
-{\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IRow* RowImpl::Clone()\r
-{\r
- // By definition the clone of an IBPP Row is a new row (so refcount=0).\r
-\r
- RowImpl* clone = new RowImpl(*this);\r
- return clone;\r
-}\r
-\r
-IBPP::IRow* RowImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void RowImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)\r
-{\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));\r
- if (value == 0)\r
- throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));\r
-\r
- int16_t len;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT :\r
- if (ivType == ivString)\r
- {\r
- std::string* svalue = (std::string*)value;\r
- len = (int16_t)svalue->length();\r
- if (len > var->sqllen) len = var->sqllen;\r
- strncpy(var->sqldata, svalue->c_str(), len);\r
- while (len < var->sqllen) var->sqldata[len++] = ' ';\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- if (userlen > var->sqllen) userlen = var->sqllen;\r
- memcpy(var->sqldata, value, userlen);\r
- while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';\r
- }\r
- else if (ivType == ivDBKey)\r
- {\r
- IBPP::DBKey* key = (IBPP::DBKey*)value;\r
- key->GetKey(var->sqldata, var->sqllen);\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- var->sqldata[0] = *(bool*)value ? 'T' : 'F';\r
- len = 1;\r
- while (len < var->sqllen) var->sqldata[len++] = ' ';\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_VARYING :\r
- if (ivType == ivString)\r
- {\r
- std::string* svalue = (std::string*)value;\r
- len = (int16_t)svalue->length();\r
- if (len > var->sqllen) len = var->sqllen;\r
- *(int16_t*)var->sqldata = (int16_t)len;\r
- strncpy(var->sqldata+2, svalue->c_str(), len);\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- if (userlen > var->sqllen) userlen = var->sqllen;\r
- *(int16_t*)var->sqldata = (int16_t)userlen;\r
- memcpy(var->sqldata+2, value, userlen);\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- *(int16_t*)var->sqldata = (int16_t)1;\r
- var->sqldata[2] = *(bool*)value ? 'T' : 'F';\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_SHORT :\r
- if (ivType == ivBool)\r
- {\r
- *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(int16_t*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int16_t*)var->sqldata =\r
- (int16_t)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int16_t*)var->sqldata =\r
- (int16_t)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_LONG :\r
- if (ivType == ivBool)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(ISC_LONG*)var->sqldata =\r
- (ISC_LONG)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(ISC_LONG*)var->sqldata =\r
- (ISC_LONG)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_INT64 :\r
- if (ivType == ivBool)\r
- {\r
- *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(int64_t*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- *(int64_t*)var->sqldata = *(int32_t*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- *(int64_t*)var->sqldata = *(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int64_t*)var->sqldata =\r
- (int64_t)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int64_t*)var->sqldata =\r
- (int64_t)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_FLOAT :\r
- if (ivType != ivFloat || var->sqlscale != 0)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- *(float*)var->sqldata = *(float*)value;\r
- break;\r
-\r
- case SQL_DOUBLE :\r
- if (ivType != ivDouble)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- if (var->sqlscale != 0)\r
- {\r
- // Round to scale of NUMERIC(x,y)\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(double*)var->sqldata =\r
- floor(*(double*)value * multiplier + 0.5) / multiplier;\r
- }\r
- else *(double*)var->sqldata = *(double*)value;\r
- break;\r
-\r
- case SQL_TIMESTAMP :\r
- if (ivType != ivTimestamp)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);\r
- break;\r
-\r
- case SQL_TYPE_DATE :\r
- if (ivType != ivDate)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);\r
- break;\r
-\r
- case SQL_TYPE_TIME :\r
- if (ivType != ivTime)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);\r
- break;\r
-\r
- case SQL_BLOB :\r
- if (ivType == ivBlob)\r
- {\r
- BlobImpl* blob = (BlobImpl*)value;\r
- blob->GetId((ISC_QUAD*)var->sqldata);\r
- }\r
- else if (ivType == ivString)\r
- {\r
- BlobImpl blob(mDatabase, mTransaction);\r
- blob.Save(*(std::string*)value);\r
- blob.GetId((ISC_QUAD*)var->sqldata);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_ARRAY :\r
- if (ivType != ivArray)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- {\r
- ArrayImpl* array = (ArrayImpl*)value;\r
- array->GetId((ISC_QUAD*)var->sqldata);\r
- // When an array has been affected to a column, we want to reset\r
- // its ID. This way, the next WriteFrom() on the same Array object\r
- // will allocate a new ID. This protects against storing the same\r
- // array ID in multiple columns or rows.\r
- array->ResetId();\r
- }\r
- break;\r
-\r
- default : throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("The field uses an unsupported SQL type !"));\r
- }\r
-\r
- if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag\r
-}\r
-\r
-void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)\r
-{\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));\r
-\r
- void* value;\r
- int len;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
-\r
- // When there is no value (SQL NULL)\r
- if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;\r
-\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT :\r
- if (ivType == ivString)\r
- {\r
- // In case of ivString, 'void* retvalue' points to a std::string where we\r
- // will directly store the data.\r
- std::string* str = (std::string*)retvalue;\r
- str->erase();\r
- str->append(var->sqldata, var->sqllen);\r
- value = retvalue; // value != 0 means 'not null'\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- // In case of ivByte, void* retvalue points to an int where we\r
- // will store the len of the available data\r
- if (retvalue != 0) *(int*)retvalue = var->sqllen;\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivDBKey)\r
- {\r
- IBPP::DBKey* key = (IBPP::DBKey*)retvalue;\r
- key->SetKey(var->sqldata, var->sqllen);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- mBools[varnum-1] = 0;\r
- if (var->sqllen >= 1)\r
- {\r
- char c = var->sqldata[0];\r
- if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
- mBools[varnum-1] = 1;\r
- }\r
- value = &mBools[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_VARYING :\r
- if (ivType == ivString)\r
- {\r
- // In case of ivString, 'void* retvalue' points to a std::string where we\r
- // will directly store the data.\r
- std::string* str = (std::string*)retvalue;\r
- str->erase();\r
- str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- // In case of ivByte, void* retvalue points to an int where we\r
- // will store the len of the available data\r
- if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;\r
- value = var->sqldata+2;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- mBools[varnum-1] = 0;\r
- len = *(int16_t*)var->sqldata;\r
- if (len >= 1)\r
- {\r
- char c = var->sqldata[2];\r
- if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
- mBools[varnum-1] = 1;\r
- }\r
- value = &mBools[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_SHORT :\r
- if (ivType == ivInt16)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- mInt32s[varnum-1] = *(int16_t*)var->sqldata;\r
- value = &mInt32s[varnum-1];\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- mInt64s[varnum-1] = *(int16_t*)var->sqldata;\r
- value = &mInt64s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);\r
-\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_LONG :\r
- if (ivType == ivInt32)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- int32_t tmp = *(int32_t*)var->sqldata;\r
- if (tmp < consts::min16 || tmp > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt16s[varnum-1] = (int16_t)tmp;\r
- value = &mInt16s[varnum-1];\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- mInt64s[varnum-1] = *(int32_t*)var->sqldata;\r
- value = &mInt64s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_INT64 :\r
- if (ivType == ivInt64)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- int64_t tmp = *(int64_t*)var->sqldata;\r
- if (tmp < consts::min16 || tmp > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt16s[varnum-1] = (int16_t)tmp;\r
- value = &mInt16s[varnum-1];\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- int64_t tmp = *(int64_t*)var->sqldata;\r
- if (tmp < consts::min32 || tmp > consts::max32)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt32s[varnum-1] = (int32_t)tmp;\r
- value = &mInt32s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_FLOAT :\r
- if (ivType != ivFloat)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- value = var->sqldata;\r
- break;\r
-\r
- case SQL_DOUBLE :\r
- if (ivType != ivDouble)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- if (var->sqlscale != 0)\r
- {\r
- // Round to scale y of NUMERIC(x,y)\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] =\r
- floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else value = var->sqldata;\r
- break;\r
-\r
- case SQL_TIMESTAMP :\r
- if (ivType != ivTimestamp)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_TYPE_DATE :\r
- if (ivType != ivDate)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_TYPE_TIME :\r
- if (ivType != ivTime)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_BLOB :\r
- if (ivType == ivBlob)\r
- {\r
- BlobImpl* blob = (BlobImpl*)retvalue;\r
- blob->SetId((ISC_QUAD*)var->sqldata);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivString)\r
- {\r
- BlobImpl blob(mDatabase, mTransaction);\r
- blob.SetId((ISC_QUAD*)var->sqldata);\r
- std::string* str = (std::string*)retvalue;\r
- blob.Load(*str);\r
- value = retvalue;\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
- \r
- case SQL_ARRAY :\r
- if (ivType != ivArray)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- {\r
- ArrayImpl* array = (ArrayImpl*)retvalue;\r
- array->SetId((ISC_QUAD*)var->sqldata);\r
- value = retvalue;\r
- }\r
- break;\r
-\r
- default : throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Found an unknown sqltype !"));\r
- }\r
-\r
- return value;\r
-}\r
-\r
-void RowImpl::Free()\r
-{\r
- if (mDescrArea != 0)\r
- {\r
- for (int i = 0; i < mDescrArea->sqln; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- if (var->sqldata != 0)\r
- {\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break;\r
- case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break;\r
- case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break;\r
- case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break;\r
- case SQL_TEXT :\r
- case SQL_VARYING : delete [] var->sqldata; break;\r
- case SQL_SHORT : delete (int16_t*) var->sqldata; break;\r
- case SQL_LONG : delete (int32_t*) var->sqldata; break;\r
- case SQL_INT64 : delete (int64_t*) var->sqldata; break;\r
- case SQL_FLOAT : delete (float*) var->sqldata; break;\r
- case SQL_DOUBLE : delete (double*) var->sqldata; break;\r
- default : throw LogicExceptionImpl("RowImpl::Free",\r
- _("Found an unknown sqltype !"));\r
- }\r
- }\r
- if (var->sqlind != 0) delete var->sqlind;\r
- }\r
- delete [] (char*)mDescrArea;\r
- mDescrArea = 0;\r
- }\r
-\r
- mNumerics.clear();\r
- mFloats.clear();\r
- mInt64s.clear();\r
- mInt32s.clear();\r
- mInt16s.clear();\r
- mBools.clear();\r
- mStrings.clear();\r
- mUpdated.clear();\r
-\r
- mDialect = 0;\r
- mDatabase = 0;\r
- mTransaction = 0;\r
-}\r
-\r
-void RowImpl::Resize(int n)\r
-{\r
- const int size = XSQLDA_LENGTH(n);\r
-\r
- Free();\r
- mDescrArea = (XSQLDA*) new char[size];\r
-\r
- memset(mDescrArea, 0, size);\r
- mNumerics.resize(n);\r
- mFloats.resize(n);\r
- mInt64s.resize(n);\r
- mInt32s.resize(n);\r
- mInt16s.resize(n);\r
- mBools.resize(n);\r
- mStrings.resize(n);\r
- mUpdated.resize(n);\r
- for (int i = 0; i < n; i++)\r
- {\r
- mNumerics[i] = 0.0;\r
- mFloats[i] = 0.0;\r
- mInt64s[i] = 0;\r
- mInt32s[i] = 0;\r
- mInt16s[i] = 0;\r
- mBools[i] = 0;\r
- mStrings[i].erase();\r
- mUpdated[i] = false;\r
- }\r
-\r
- mDescrArea->version = SQLDA_VERSION1;\r
- mDescrArea->sqln = (int16_t)n;\r
-}\r
-\r
-void RowImpl::AllocVariables()\r
-{\r
- int i;\r
- for (i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
- memset(var->sqldata, 0, sizeof(ISC_QUAD));\r
- break;\r
- case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
- memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP));\r
- break;\r
- case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
- memset(var->sqldata, 0, sizeof(ISC_TIME));\r
- break;\r
- case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
- memset(var->sqldata, 0, sizeof(ISC_DATE));\r
- break;\r
- case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
- memset(var->sqldata, ' ', var->sqllen);\r
- var->sqldata[var->sqllen] = '\0';\r
- break;\r
- case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
- memset(var->sqldata, 0, 2);\r
- memset(var->sqldata+2, ' ', var->sqllen);\r
- var->sqldata[var->sqllen+2] = '\0';\r
- break;\r
- case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break;\r
- case SQL_LONG : var->sqldata = (char*) new int32_t(0); break;\r
- case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break;\r
- case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break;\r
- case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break;\r
- default : throw LogicExceptionImpl("RowImpl::AllocVariables",\r
- _("Found an unknown sqltype !"));\r
- }\r
- if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator\r
- }\r
-}\r
-\r
-bool RowImpl::MissingValues()\r
-{\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- if (! mUpdated[i]) return true;\r
- return false;\r
-}\r
-\r
-RowImpl& RowImpl::operator=(const RowImpl& copied)\r
-{\r
- Free();\r
-\r
- const int n = copied.mDescrArea->sqln;\r
- const int size = XSQLDA_LENGTH(n);\r
-\r
- // Initial brute copy\r
- mDescrArea = (XSQLDA*) new char[size];\r
- memcpy(mDescrArea, copied.mDescrArea, size);\r
-\r
- // Copy of the columns data\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD));\r
- break;\r
- case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP));\r
- break;\r
- case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME));\r
- break;\r
- case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE));\r
- break;\r
- case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
- memcpy(var->sqldata, org->sqldata, var->sqllen+1);\r
- break;\r
- case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
- memcpy(var->sqldata, org->sqldata, var->sqllen+3);\r
- break;\r
- case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break;\r
- case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break;\r
- case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break;\r
- case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break;\r
- case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break;\r
- default : throw LogicExceptionImpl("RowImpl::Ctor",\r
- _("Found an unknown sqltype !"));\r
- }\r
- if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator\r
- }\r
-\r
- // Pointers init, real data copy\r
- mNumerics = copied.mNumerics;\r
- mFloats = copied.mFloats;\r
- mInt64s = copied.mInt64s;\r
- mInt32s = copied.mInt32s;\r
- mInt16s = copied.mInt16s;\r
- mBools = copied.mBools;\r
- mStrings = copied.mStrings;\r
-\r
- mDialect = copied.mDialect;\r
- mDatabase = copied.mDatabase;\r
- mTransaction = copied.mTransaction;\r
- \r
- return *this;\r
-}\r
-\r
-RowImpl::RowImpl(const RowImpl& copied)\r
- : IBPP::IRow(), mRefCount(0), mDescrArea(0)\r
-{\r
- // mRefCount and mDescrArea are set to 0 before using the assignment operator\r
- *this = copied; // The assignment operator does the real copy\r
-}\r
-\r
-RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr)\r
- : mRefCount(0), mDescrArea(0)\r
-{\r
- Resize(n);\r
- mDialect = dialect;\r
- mDatabase = db;\r
- mTransaction = tr;\r
-}\r
-\r
-RowImpl::~RowImpl()\r
-{\r
- try { Free(); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: service.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
-// Subject : IBPP, Service class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-using namespace ibpp_internals;\r
-\r
-#ifdef IBPP_UNIX\r
-#include <unistd.h>\r
-#define Sleep(x) usleep(x)\r
-#endif\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void ServiceImpl::Connect()\r
-{\r
- if (mHandle != 0) return; // Already connected\r
- \r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mUserName.empty())\r
- throw LogicExceptionImpl("Service::Connect", _("Unspecified user name."));\r
- if (mUserPassword.empty())\r
- throw LogicExceptionImpl("Service::Connect", _("Unspecified user password."));\r
-\r
- // Attach to the Service Manager\r
- IBS status;\r
- SPB spb;\r
- std::string connect;\r
-\r
- // Build a SPB based on the properties\r
- spb.Insert(isc_spb_version);\r
- spb.Insert(isc_spb_current_version);\r
- spb.InsertString(isc_spb_user_name, 1, mUserName.c_str());\r
- spb.InsertString(isc_spb_password, 1, mUserPassword.c_str());\r
-\r
- if (! mServerName.empty())\r
- {\r
- connect = mServerName;\r
- connect += ":";\r
- }\r
-\r
- connect += "service_mgr";\r
-\r
- (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(),\r
- &mHandle, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- {\r
- mHandle = 0; // Should be, but better be sure...\r
- throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));\r
- }\r
-}\r
-\r
-void ServiceImpl::Disconnect()\r
-{\r
- if (mHandle == 0) return; // Already disconnected\r
- \r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
-\r
- IBS status;\r
-\r
- // Detach from the service manager\r
- (*gds.Call()->m_service_detach)(status.Self(), &mHandle);\r
-\r
- // Set mHandle to 0 now, just in case we need to throw, because Disconnect()\r
- // is called from Service destructor and we want to maintain a coherent state.\r
- mHandle = 0;\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed"));\r
-}\r
-\r
-void ServiceImpl::GetVersion(std::string& version)\r
-{\r
- // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock')\r
-\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected."));\r
-\r
- IBS status;\r
- SPB spb;\r
- RB result(250);\r
-\r
- spb.Insert(isc_info_svc_server_version);\r
-\r
- (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(),\r
- result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed"));\r
-\r
- result.GetString(isc_info_svc_server_version, version);\r
-}\r
-\r
-void ServiceImpl::AddUser(const IBPP::User& user)\r
-{\r
- if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
- throw LogicExceptionImpl("Service::AddUser", _("Service is not connected."));\r
- if (user.username.empty())\r
- throw LogicExceptionImpl("Service::AddUser", _("Username required."));\r
- if (user.password.empty())\r
- throw LogicExceptionImpl("Service::AddUser", _("Password required."));\r
-\r
- IBS status;\r
- SPB spb;\r
- spb.Insert(isc_action_svc_add_user);\r
- spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
- spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
- if (! user.firstname.empty())\r
- spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
- if (! user.middlename.empty())\r
- spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
- if (! user.lastname.empty())\r
- spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
- if (user.userid != 0)\r
- spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
- if (user.groupid != 0)\r
- spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::ModifyUser(const IBPP::User& user)\r
-{\r
- if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
- throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected."));\r
- if (user.username.empty())\r
- throw LogicExceptionImpl("Service::ModifyUser", _("Username required."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_modify_user);\r
- spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
- if (! user.password.empty())\r
- spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
- if (! user.firstname.empty())\r
- spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
- if (! user.middlename.empty())\r
- spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
- if (! user.lastname.empty())\r
- spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
- if (user.userid != 0)\r
- spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
- if (user.groupid != 0)\r
- spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::RemoveUser(const std::string& username)\r
-{\r
-\r
- if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
- throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected."));\r
- if (username.empty())\r
- throw LogicExceptionImpl("Service::RemoveUser", _("Username required."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_delete_user);\r
- spb.InsertString(isc_spb_sec_username, 2, username.c_str());\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::GetUser(IBPP::User& user)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::GetUser", _("Service is not connected."));\r
- if (user.username.empty())\r
- throw LogicExceptionImpl("Service::GetUser", _("Username required."));\r
-\r
- SPB spb;\r
- spb.Insert(isc_action_svc_display_user);\r
- spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
-\r
- IBS status;\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed"));\r
-\r
- RB result(8000);\r
- char request[] = {isc_info_svc_get_users};\r
- status.Reset();\r
- (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
- sizeof(request), request, result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed"));\r
-\r
- char* p = result.Self();\r
- if (*p != isc_info_svc_get_users)\r
- throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer"));\r
-\r
- p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
- user.clear();\r
- while (*p != isc_info_end)\r
- {\r
- if (*p == isc_spb_sec_userid)\r
- {\r
- user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
- p += 5;\r
- }\r
- else if (*p == isc_spb_sec_groupid)\r
- {\r
- user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
- p += 5;\r
- }\r
- else\r
- {\r
- unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
- switch (*p)\r
- {\r
- case isc_spb_sec_username :\r
- // For each user, this is the first element returned\r
- if (len != 0) user.username.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_password :\r
- if (len != 0) user.password.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_firstname :\r
- if (len != 0) user.firstname.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_middlename :\r
- if (len != 0) user.middlename.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_lastname :\r
- if (len != 0) user.lastname.assign(p+3, len);\r
- break;\r
- }\r
- p += (3 + len);\r
- }\r
- }\r
-}\r
-\r
-void ServiceImpl::GetUsers(std::vector<IBPP::User>& users)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected."));\r
-\r
- SPB spb;\r
- spb.Insert(isc_action_svc_display_user);\r
-\r
- IBS status;\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed"));\r
-\r
- RB result(8000);\r
- char request[] = {isc_info_svc_get_users};\r
- status.Reset();\r
- (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
- sizeof(request), request, result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed"));\r
-\r
- users.clear();\r
- char* p = result.Self();\r
- if (*p != isc_info_svc_get_users)\r
- throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer"));\r
-\r
- p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
- IBPP::User user;\r
- while (*p != isc_info_end)\r
- {\r
- if (*p == isc_spb_sec_userid)\r
- {\r
- user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
- p += 5;\r
- }\r
- else if (*p == isc_spb_sec_groupid)\r
- {\r
- user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
- p += 5;\r
- }\r
- else\r
- {\r
- unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
- switch (*p)\r
- {\r
- case isc_spb_sec_username :\r
- // For each user, this is the first element returned\r
- if (! user.username.empty()) users.push_back(user); // Flush previous user\r
- user.clear();\r
- if (len != 0) user.username.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_password :\r
- if (len != 0) user.password.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_firstname :\r
- if (len != 0) user.firstname.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_middlename :\r
- if (len != 0) user.middlename.assign(p+3, len);\r
- break;\r
- case isc_spb_sec_lastname :\r
- if (len != 0) user.lastname.assign(p+3, len);\r
- break;\r
- }\r
- p += (3 + len);\r
- }\r
- }\r
- if (! user.username.empty()) users.push_back(user); // Flush last user\r
-}\r
-\r
-void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- spb.InsertQuad(isc_spb_prp_page_buffers, buffers);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- spb.InsertQuad(isc_spb_prp_sweep_interval, sweep);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync);\r
- else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly);\r
- else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res);\r
- else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- switch (mode)\r
- {\r
- case IBPP::dsDenyAttach :\r
- spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout);\r
- break;\r
- case IBPP::dsDenyTrans :\r
- spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout);\r
- break;\r
- case IBPP::dsForce :\r
- spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout);\r
- break;\r
- }\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::Restart(const std::string& dbfile)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Restart", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_properties);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::Sweep(const std::string& dbfile)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Sweep", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_repair);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Repair", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_repair);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
-\r
- unsigned int mask;\r
- if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db);\r
- else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db;\r
- else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db;\r
- else throw LogicExceptionImpl("Service::Repair",\r
- _("One of rpMendRecords, rpValidatePages, rpValidateFull is required."));\r
-\r
- if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db;\r
- if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum;\r
- if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows;\r
- \r
- spb.InsertQuad(isc_spb_options, mask);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed"));\r
-\r
- Wait();\r
-}\r
-\r
-void ServiceImpl::StartBackup(const std::string& dbfile,\r
- const std::string& bkfile, IBPP::BRF flags)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Backup", _("Service is not connected."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified."));\r
- if (bkfile.empty())\r
- throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_backup);\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
- if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
-\r
- unsigned int mask = 0;\r
- if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums;\r
- if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo;\r
- if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only;\r
- if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect;\r
- if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable;\r
- if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert;\r
- if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed"));\r
-}\r
-\r
-void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile,\r
- int pagesize, IBPP::BRF flags)\r
-{\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Service::Restore", _("Service is not connected."));\r
- if (bkfile.empty())\r
- throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified."));\r
- if (dbfile.empty())\r
- throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified."));\r
-\r
- IBS status;\r
- SPB spb;\r
-\r
- spb.Insert(isc_action_svc_restore);\r
- spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
- spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
- if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
- if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize);\r
-\r
- unsigned int mask;\r
- if (flags & IBPP::brReplace) mask = isc_spb_res_replace;\r
- else mask = isc_spb_res_create; // Safe default mode\r
-\r
- if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx;\r
- if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow;\r
- if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity;\r
- if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time;\r
- if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space;\r
- if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
-\r
- (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed"));\r
-}\r
-\r
-const char* ServiceImpl::WaitMsg()\r
-{\r
- IBS status;\r
- SPB req;\r
- RB result(1024);\r
-\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
-\r
- req.Insert(isc_info_svc_line); // Request one line of textual output\r
-\r
- // _service_query will only block until a line of result is available\r
- // (or until the end of the task if it does not report information)\r
- (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
- req.Size(), req.Self(), result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
-\r
- // If message length is zero bytes, task is finished\r
- if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;\r
-\r
- // Task is not finished, but we have something to report\r
- return mWaitMessage.c_str();\r
-}\r
-\r
-void ServiceImpl::Wait()\r
-{\r
- IBS status;\r
- SPB spb;\r
- RB result(1024);\r
- std::string msg;\r
-\r
- if (gds.Call()->mGDSVersion < 60)\r
- throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
-\r
- spb.Insert(isc_info_svc_line);\r
- for (;;)\r
- {\r
- // Sleeps 1 millisecond upfront. This will release the remaining\r
- // timeslot of the thread. Doing so will give a good chance for small\r
- // services tasks to finish before we check if they are still running.\r
- // The deal is to limit (in that particular case) the number of loops\r
- // polling _service_query that will happen.\r
-\r
- Sleep(1);\r
-\r
- // _service_query will only block until a line of result is available\r
- // (or until the end of the task if it does not report information) \r
- (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
- spb.Size(), spb.Self(), result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
-\r
- // If message length is zero bytes, task is finished\r
- if (result.GetString(isc_info_svc_line, msg) == 0) return;\r
-\r
- status.Reset();\r
- result.Reset();\r
- }\r
-}\r
-\r
-IBPP::IService* ServiceImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void ServiceImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void ServiceImpl::SetServerName(const char* newName)\r
-{\r
- if (newName == 0) mServerName.erase();\r
- else mServerName = newName;\r
-}\r
-\r
-void ServiceImpl::SetUserName(const char* newName)\r
-{\r
- if (newName == 0) mUserName.erase();\r
- else mUserName = newName;\r
-}\r
-\r
-void ServiceImpl::SetUserPassword(const char* newPassword)\r
-{\r
- if (newPassword == 0) mUserPassword.erase();\r
- else mUserPassword = newPassword;\r
-}\r
-\r
-ServiceImpl::ServiceImpl(const std::string& ServerName,\r
- const std::string& UserName, const std::string& UserPassword)\r
- : mRefCount(0), mHandle(0),\r
- mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword)\r
-{\r
-}\r
-\r
-ServiceImpl::~ServiceImpl()\r
-{\r
- try { if (Connected()) Disconnect(); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// Eof\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: statement.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Service class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void StatementImpl::Prepare(const std::string& sql)\r
-{\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Statement::Prepare", _("An IDatabase must be attached."));\r
- if (mDatabase->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::Prepare", _("IDatabase must be connected."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Statement::Prepare", _("An ITransaction must be attached."));\r
- if (mTransaction->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::Prepare", _("ITransaction must be started."));\r
- if (sql.empty())\r
- throw LogicExceptionImpl("Statement::Prepare", _("SQL statement can't be 0."));\r
-\r
- // Saves the SQL sentence, only for reporting reasons in case of errors\r
- mSql = sql;\r
-\r
- IBS status;\r
-\r
- // Free all resources currently attached to this Statement, then allocate\r
- // a new statement descriptor.\r
- Close();\r
- (*gds.Call()->m_dsql_allocate_statement)(status.Self(), mDatabase->GetHandlePtr(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Statement::Prepare",\r
- _("isc_dsql_allocate_statement failed"));\r
-\r
- // Empirical estimate of parameters count and output columns count.\r
- // This is by far not an exact estimation, which would require parsing the\r
- // SQL statement. If the SQL statement contains '?' and ',' in string\r
- // constants, this count will obviously be wrong, but it will be exagerated.\r
- // It won't hurt. We just try to not have to re-allocate those descriptors later.\r
- // So we prefer to get them a little bit larger than needed than the other way.\r
- int16_t inEstimate = 0;\r
- int16_t outEstimate = 1;\r
- for (size_t i = 0; i < strlen(sql.c_str()); i++)\r
- {\r
- if (sql[i] == '?') ++inEstimate;\r
- if (sql[i] == ',') ++outEstimate;\r
- }\r
-\r
- /*\r
- DebugStream()<< "Prepare(\""<< sql<< "\")"<< fds;\r
- DebugStream()<< _("Estimation: ")<< inEstimate<< _(" IN parameters and ")\r
- << outEstimate<< _(" OUT columns")<< fds;\r
- */\r
-\r
- // Allocates output descriptor and prepares the statement\r
- mOutRow = new RowImpl(mDatabase->Dialect(), outEstimate, mDatabase, mTransaction);\r
- mOutRow->AddRef();\r
-\r
- status.Reset();\r
- (*gds.Call()->m_dsql_prepare)(status.Self(), mTransaction->GetHandlePtr(),\r
- &mHandle, (short)sql.length(), const_cast<char*>(sql.c_str()),\r
- short(mDatabase->Dialect()), mOutRow->Self());\r
- if (status.Errors())\r
- {\r
- Close();\r
- std::string context = "Statement::Prepare( ";\r
- context.append(mSql).append(" )");\r
- throw SQLExceptionImpl(status, context.c_str(),\r
- _("isc_dsql_prepare failed"));\r
- }\r
-\r
- // Read what kind of statement was prepared\r
- status.Reset();\r
- char itemsReq[] = {isc_info_sql_stmt_type};\r
- char itemsRes[8];\r
- (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
- sizeof(itemsRes), itemsRes);\r
- if (status.Errors())\r
- {\r
- Close();\r
- throw SQLExceptionImpl(status, "Statement::Prepare",\r
- _("isc_dsql_sql_info failed"));\r
- }\r
- if (itemsRes[0] == isc_info_sql_stmt_type)\r
- {\r
- switch (itemsRes[3])\r
- {\r
- case isc_info_sql_stmt_select : mType = IBPP::stSelect; break;\r
- case isc_info_sql_stmt_insert : mType = IBPP::stInsert; break;\r
- case isc_info_sql_stmt_update : mType = IBPP::stUpdate; break;\r
- case isc_info_sql_stmt_delete : mType = IBPP::stDelete; break;\r
- case isc_info_sql_stmt_ddl : mType = IBPP::stDDL; break;\r
- case isc_info_sql_stmt_exec_procedure : mType = IBPP::stExecProcedure; break;\r
- case isc_info_sql_stmt_select_for_upd : mType = IBPP::stSelectUpdate; break;\r
- case isc_info_sql_stmt_set_generator : mType = IBPP::stSetGenerator; break;\r
- case isc_info_sql_stmt_savepoint : mType = IBPP::stSavePoint; break;\r
- default : mType = IBPP::stUnsupported;\r
- }\r
- }\r
- if (mType == IBPP::stUnknown || mType == IBPP::stUnsupported)\r
- {\r
- Close();\r
- throw LogicExceptionImpl("Statement::Prepare",\r
- _("Unknown or unsupported statement type"));\r
- }\r
-\r
- if (mOutRow->Columns() == 0)\r
- {\r
- // Get rid of the output descriptor, if it wasn't required (no output)\r
- mOutRow->Release();\r
- mOutRow = 0;\r
- /*\r
- DebugStream()<< _("Dropped output descriptor which was not required")<< fds;\r
- */\r
- }\r
- else if (mOutRow->Columns() > mOutRow->AllocatedSize())\r
- {\r
- // Resize the output descriptor (which is too small).\r
- // The statement does not need to be prepared again, though the\r
- // output columns must be described again.\r
-\r
- /*\r
- DebugStream()<< _("Resize output descriptor from ")\r
- << mOutRow->AllocatedSize()<< _(" to ")<< mOutRow->Columns()<< fds;\r
- */\r
-\r
- mOutRow->Resize(mOutRow->Columns());\r
- status.Reset();\r
- (*gds.Call()->m_dsql_describe)(status.Self(), &mHandle, 1, mOutRow->Self());\r
- if (status.Errors())\r
- {\r
- Close();\r
- throw SQLExceptionImpl(status, "Statement::Prepare",\r
- _("isc_dsql_describe failed"));\r
- }\r
- }\r
-\r
- if (inEstimate > 0)\r
- {\r
- // Ready an input descriptor\r
- mInRow = new RowImpl(mDatabase->Dialect(), inEstimate, mDatabase, mTransaction);\r
- mInRow->AddRef();\r
-\r
- status.Reset();\r
- (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
- if (status.Errors())\r
- {\r
- Close();\r
- throw SQLExceptionImpl(status, "Statement::Prepare",\r
- _("isc_dsql_describe_bind failed"));\r
- }\r
-\r
- if (mInRow->Columns() == 0)\r
- {\r
- // Get rid of the input descriptor, if it wasn't required (no parameters)\r
- mInRow->Release();\r
- mInRow = 0;\r
- /*\r
- DebugStream()<< _("Dropped input descriptor which was not required")<< fds;\r
- */\r
- }\r
- else if (mInRow->Columns() > mInRow->AllocatedSize())\r
- {\r
- // Resize the input descriptor (which is too small).\r
- // The statement does not need to be prepared again, though the\r
- // parameters must be described again.\r
-\r
- /*\r
- DebugStream()<< _("Resize input descriptor from ")\r
- << mInRow->AllocatedSize()<< _(" to ")\r
- << mInRow->Columns()<< fds;\r
- */\r
-\r
- mInRow->Resize(mInRow->Columns());\r
- status.Reset();\r
- (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
- if (status.Errors())\r
- {\r
- Close();\r
- throw SQLExceptionImpl(status, "Statement::Prepare",\r
- _("isc_dsql_describe_bind failed"));\r
- }\r
- }\r
- }\r
-\r
- // Allocates variables of the input descriptor\r
- if (mInRow != 0)\r
- {\r
- // Turn on 'can be NULL' on each input parameter\r
- for (int i = 0; i < mInRow->Columns(); i++)\r
- {\r
- XSQLVAR* var = &(mInRow->Self()->sqlvar[i]);\r
- if (! (var->sqltype & 1)) var->sqltype += short(1);\r
- }\r
- mInRow->AllocVariables();\r
- }\r
-\r
- // Allocates variables of the output descriptor\r
- if (mOutRow != 0) mOutRow->AllocVariables();\r
-}\r
-\r
-void StatementImpl::Plan(std::string& plan)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Plan", _("No statement has been prepared."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Statement::Plan", _("A Database must be attached."));\r
- if (mDatabase->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::Plan", _("Database must be connected."));\r
-\r
- IBS status;\r
- RB result(4096);\r
- char itemsReq[] = {isc_info_sql_get_plan};\r
-\r
- (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
- result.Size(), result.Self());\r
- if (status.Errors()) throw SQLExceptionImpl(status,\r
- "Statement::Plan", _("isc_dsql_sql_info failed."));\r
-\r
- result.GetString(isc_info_sql_get_plan, plan);\r
- if (plan[0] == '\n') plan.erase(0, 1);\r
-}\r
-\r
-void StatementImpl::Execute(const std::string& sql)\r
-{\r
- if (! sql.empty()) Prepare(sql);\r
-\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Execute",\r
- _("No statement has been prepared."));\r
-\r
- // Check that a value has been set for each input parameter\r
- if (mInRow != 0 && mInRow->MissingValues())\r
- throw LogicExceptionImpl("Statement::Execute",\r
- _("All parameters must be specified."));\r
-\r
- CursorFree(); // Free a previous 'cursor' if any\r
-\r
- IBS status;\r
- if (mType == IBPP::stSelect)\r
- {\r
- // Could return a result set (none, single or multi rows)\r
- (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
- &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
- if (status.Errors())\r
- {\r
- //Close(); Commented because Execute error should not free the statement\r
- std::string context = "Statement::Execute( ";\r
- context.append(mSql).append(" )");\r
- throw SQLExceptionImpl(status, context.c_str(),\r
- _("isc_dsql_execute failed"));\r
- }\r
- if (mOutRow != 0)\r
- {\r
- mResultSetAvailable = true;\r
- mCursorOpened = true;\r
- }\r
- }\r
- else\r
- {\r
- // Should return at most a single row\r
- (*gds.Call()->m_dsql_execute2)(status.Self(), mTransaction->GetHandlePtr(),\r
- &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self(),\r
- mOutRow == 0 ? 0 : mOutRow->Self());\r
- if (status.Errors())\r
- {\r
- //Close(); Commented because Execute error should not free the statement\r
- std::string context = "Statement::Execute( ";\r
- context.append(mSql).append(" )");\r
- throw SQLExceptionImpl(status, context.c_str(),\r
- _("isc_dsql_execute2 failed"));\r
- }\r
- }\r
-}\r
-\r
-void StatementImpl::CursorExecute(const std::string& cursor, const std::string& sql)\r
-{\r
- if (cursor.empty())\r
- throw LogicExceptionImpl("Statement::CursorExecute", _("Cursor name can't be 0."));\r
-\r
- if (! sql.empty()) Prepare(sql);\r
-\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::CursorExecute", _("No statement has been prepared."));\r
- if (mType != IBPP::stSelectUpdate)\r
- throw LogicExceptionImpl("Statement::CursorExecute", _("Statement must be a SELECT FOR UPDATE."));\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::CursorExecute", _("Statement would return no rows."));\r
-\r
- // Check that a value has been set for each input parameter\r
- if (mInRow != 0 && mInRow->MissingValues())\r
- throw LogicExceptionImpl("Statement::CursorExecute",\r
- _("All parameters must be specified."));\r
-\r
- CursorFree(); // Free a previous 'cursor' if any\r
-\r
- IBS status;\r
- (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
- &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
- if (status.Errors())\r
- {\r
- //Close(); Commented because Execute error should not free the statement\r
- std::string context = "Statement::CursorExecute( ";\r
- context.append(mSql).append(" )");\r
- throw SQLExceptionImpl(status, context.c_str(),\r
- _("isc_dsql_execute failed"));\r
- }\r
-\r
- status.Reset();\r
- (*gds.Call()->m_dsql_set_cursor_name)(status.Self(), &mHandle, const_cast<char*>(cursor.c_str()), 0);\r
- if (status.Errors())\r
- {\r
- //Close(); Commented because Execute error should not free the statement\r
- throw SQLExceptionImpl(status, "Statement::CursorExecute",\r
- _("isc_dsql_set_cursor_name failed"));\r
- }\r
-\r
- mResultSetAvailable = true;\r
- mCursorOpened = true;\r
-}\r
-\r
-void StatementImpl::ExecuteImmediate(const std::string& sql)\r
-{\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An IDatabase must be attached."));\r
- if (mDatabase->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::ExecuteImmediate", _("IDatabase must be connected."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An ITransaction must be attached."));\r
- if (mTransaction->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::ExecuteImmediate", _("ITransaction must be started."));\r
- if (sql.empty())\r
- throw LogicExceptionImpl("Statement::ExecuteImmediate", _("SQL statement can't be 0."));\r
-\r
- IBS status;\r
- Close();\r
- (*gds.Call()->m_dsql_execute_immediate)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), 0, const_cast<char*>(sql.c_str()),\r
- short(mDatabase->Dialect()), 0);\r
- if (status.Errors())\r
- {\r
- std::string context = "Statement::ExecuteImmediate( ";\r
- context.append(sql).append(" )");\r
- throw SQLExceptionImpl(status, context.c_str(),\r
- _("isc_dsql_execute_immediate failed"));\r
- }\r
-}\r
-\r
-int StatementImpl::AffectedRows()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::AffectedRows", _("No statement has been prepared."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Statement::AffectedRows", _("A Database must be attached."));\r
- if (mDatabase->GetHandle() == 0)\r
- throw LogicExceptionImpl("Statement::AffectedRows", _("Database must be connected."));\r
-\r
- int count;\r
- IBS status;\r
- RB result;\r
- char itemsReq[] = {isc_info_sql_records};\r
-\r
- (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
- result.Size(), result.Self());\r
- if (status.Errors()) throw SQLExceptionImpl(status,\r
- "Statement::AffectedRows", _("isc_dsql_sql_info failed."));\r
-\r
- if (mType == IBPP::stInsert)\r
- count = result.GetValue(isc_info_sql_records, isc_info_req_insert_count);\r
- else if (mType == IBPP::stUpdate)\r
- count = result.GetValue(isc_info_sql_records, isc_info_req_update_count);\r
- else if (mType == IBPP::stDelete)\r
- count = result.GetValue(isc_info_sql_records, isc_info_req_delete_count);\r
- else if (mType == IBPP::stSelect)\r
- count = result.GetValue(isc_info_sql_records, isc_info_req_select_count);\r
- else count = 0; // Returns zero count for unknown cases\r
-\r
- return count;\r
-}\r
-\r
-bool StatementImpl::Fetch()\r
-{\r
- if (! mResultSetAvailable)\r
- throw LogicExceptionImpl("Statement::Fetch",\r
- _("No statement has been executed or no result set available."));\r
-\r
- IBS status;\r
- ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, mOutRow->Self());\r
- if (code == 100) // This special code means "no more rows"\r
- {\r
- mResultSetAvailable = false;\r
- // Oddly enough, fetching rows up to the last one seems to open\r
- // an 'implicit' cursor that needs to be closed.\r
- mCursorOpened = true;\r
- CursorFree(); // Free the explicit or implicit cursor/result-set\r
- return false;\r
- }\r
- if (status.Errors())\r
- {\r
- Close();\r
- throw SQLExceptionImpl(status, "Statement::Fetch",\r
- _("isc_dsql_fetch failed."));\r
- }\r
-\r
- return true;\r
-}\r
-\r
-bool StatementImpl::Fetch(IBPP::Row& row)\r
-{\r
- if (! mResultSetAvailable)\r
- throw LogicExceptionImpl("Statement::Fetch(row)",\r
- _("No statement has been executed or no result set available."));\r
-\r
- RowImpl* rowimpl = new RowImpl(*mOutRow);\r
- row = rowimpl;\r
-\r
- IBS status;\r
- ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1,\r
- rowimpl->Self());\r
- if (code == 100) // This special code means "no more rows"\r
- {\r
- mResultSetAvailable = false;\r
- // Oddly enough, fetching rows up to the last one seems to open\r
- // an 'implicit' cursor that needs to be closed.\r
- mCursorOpened = true;\r
- CursorFree(); // Free the explicit or implicit cursor/result-set\r
- row.clear();\r
- return false;\r
- }\r
- if (status.Errors())\r
- {\r
- Close();\r
- row.clear();\r
- throw SQLExceptionImpl(status, "Statement::Fetch(row)",\r
- _("isc_dsql_fetch failed."));\r
- }\r
-\r
- return true;\r
-}\r
-\r
-void StatementImpl::Close()\r
-{\r
- // Free all statement resources.\r
- // Used before preparing a new statement or from destructor.\r
-\r
- if (mInRow != 0) { mInRow->Release(); mInRow = 0; }\r
- if (mOutRow != 0) { mOutRow->Release(); mOutRow = 0; }\r
-\r
- mResultSetAvailable = false;\r
- mCursorOpened = false;\r
- mType = IBPP::stUnknown;\r
-\r
- if (mHandle != 0)\r
- {\r
- IBS status;\r
- (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_drop);\r
- mHandle = 0;\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Statement::Close(DSQL_drop)",\r
- _("isc_dsql_free_statement failed."));\r
- }\r
-}\r
-\r
-void StatementImpl::SetNull(int param)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::SetNull", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::SetNull", _("The statement does not take parameters."));\r
-\r
- mInRow->SetNull(param);\r
-}\r
-\r
-void StatementImpl::Set(int param, bool value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[bool]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[bool]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, const char* cstring)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[char*]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[char*]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, cstring);\r
-}\r
-\r
-void StatementImpl::Set(int param, const void* bindata, int len)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[void*]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[void*]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, bindata, len);\r
-}\r
-\r
-void StatementImpl::Set(int param, const std::string& s)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[string]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[string]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, s);\r
-}\r
-\r
-void StatementImpl::Set(int param, int16_t value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[int16_t]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[int16_t]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, int32_t value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[int32_t]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[int32_t]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, int64_t value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[int64_t]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[int64_t]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, float value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[float]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[float]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, double value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[double]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[double]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::Timestamp& value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Timestamp]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Timestamp]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::Date& value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Date]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Date]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::Time& value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Time]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Time]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::Blob& blob)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Blob]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Blob]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, blob);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::Array& array)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Array]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Array]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, array);\r
-}\r
-\r
-void StatementImpl::Set(int param, const IBPP::DBKey& key)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[DBKey]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[DBKey]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, key);\r
-}\r
-\r
-/*\r
-void StatementImpl::Set(int param, const IBPP::Value& value)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Set[Value]", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Set[Value]", _("The statement does not take parameters."));\r
-\r
- mInRow->Set(param, value);\r
-}\r
-*/\r
-\r
-bool StatementImpl::IsNull(int column)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
-\r
- return mOutRow->IsNull(column);\r
-}\r
-\r
-bool StatementImpl::Get(int column, bool* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, bool& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, char* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, void* bindata, int& userlen)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, bindata, userlen);\r
-}\r
-\r
-bool StatementImpl::Get(int column, std::string& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int16_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int16_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int32_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int32_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int64_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, int64_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, float* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, float& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, double* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(column, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, double& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::Timestamp& timestamp)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, timestamp);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::Date& date)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, date);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::Time& time)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, time);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::Blob& blob)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, blob);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::DBKey& key)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, key);\r
-}\r
-\r
-bool StatementImpl::Get(int column, IBPP::Array& array)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column, array);\r
-}\r
-\r
-/*\r
-const IBPP::Value StatementImpl::Get(int column)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(column);\r
-}\r
-*/\r
-\r
-bool StatementImpl::IsNull(const std::string& name)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
-\r
- return mOutRow->IsNull(name);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, bool* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, bool& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, char* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get[char*]", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, void* retvalue, int& count)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get[void*,int]", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue, count);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, std::string& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::GetString", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int16_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int16_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int32_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int32_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int64_t* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, int64_t& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, float* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, float& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, double* retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
-\r
- return mOutRow->Get(name, *retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, double& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retblob);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retvalue);\r
-}\r
-\r
-bool StatementImpl::Get(const std::string& name, IBPP::Array& retarray)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name, retarray);\r
-}\r
-\r
-/*\r
-const IBPP::Value StatementImpl::Get(const std::string& name)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
-\r
- return mOutRow->Get(name);\r
-}\r
-*/\r
-\r
-int StatementImpl::Columns()\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
-\r
- return mOutRow->Columns();\r
-}\r
-\r
-int StatementImpl::ColumnNum(const std::string& name)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::ColumnNum", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnNum(name);\r
-}\r
-\r
-const char* StatementImpl::ColumnName(int varnum)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnName(varnum);\r
-}\r
-\r
-const char* StatementImpl::ColumnAlias(int varnum)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnAlias(varnum);\r
-}\r
-\r
-const char* StatementImpl::ColumnTable(int varnum)\r
-{\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnTable(varnum);\r
-}\r
-\r
-IBPP::SDT StatementImpl::ColumnType(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ColumnType", _("No statement has been prepared."));\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::ColumnType", _("The statement does not return results."));\r
-\r
- return mOutRow->ColumnType(varnum);\r
-}\r
-\r
-int StatementImpl::ColumnSubtype(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ColumnSubtype", _("No statement has been prepared."));\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::ColumnSubtype", _("The statement does not return results."));\r
-\r
- return mOutRow->ColumnSubtype(varnum);\r
-}\r
-\r
-int StatementImpl::ColumnSize(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ColumnSize", _("No statement has been prepared."));\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::ColumnSize", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnSize(varnum);\r
-}\r
-\r
-int StatementImpl::ColumnScale(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ColumnScale", _("No statement has been prepared."));\r
- if (mOutRow == 0)\r
- throw LogicExceptionImpl("Statement::ColumnScale", _("The row is not initialized."));\r
-\r
- return mOutRow->ColumnScale(varnum);\r
-}\r
-\r
-int StatementImpl::Parameters()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::Parameters", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::Parameters", _("The statement uses no parameters."));\r
-\r
- return mInRow->Columns();\r
-}\r
-\r
-IBPP::SDT StatementImpl::ParameterType(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ParameterType", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::ParameterType", _("The statement uses no parameters."));\r
-\r
- return mInRow->ColumnType(varnum);\r
-}\r
-\r
-int StatementImpl::ParameterSubtype(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ParameterSubtype", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::ParameterSubtype", _("The statement uses no parameters."));\r
-\r
- return mInRow->ColumnSubtype(varnum);\r
-}\r
-\r
-int StatementImpl::ParameterSize(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ParameterSize", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::ParameterSize", _("The statement uses no parameters."));\r
-\r
- return mInRow->ColumnSize(varnum);\r
-}\r
-\r
-int StatementImpl::ParameterScale(int varnum)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Statement::ParameterScale", _("No statement has been prepared."));\r
- if (mInRow == 0)\r
- throw LogicExceptionImpl("Statement::ParameterScale", _("The statement uses no parameters."));\r
-\r
- return mInRow->ColumnScale(varnum);\r
-}\r
-\r
-IBPP::Database StatementImpl::DatabasePtr() const\r
-{\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction StatementImpl::TransactionPtr() const\r
-{\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IStatement* StatementImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
-\r
- return this;\r
-}\r
-\r
-void StatementImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void StatementImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
- if (database == 0)\r
- throw LogicExceptionImpl("Statement::AttachDatabase",\r
- _("Can't attach a 0 IDatabase object."));\r
-\r
- if (mDatabase != 0) mDatabase->DetachStatementImpl(this);\r
- mDatabase = database;\r
- mDatabase->AttachStatementImpl(this);\r
-}\r
-\r
-void StatementImpl::DetachDatabaseImpl()\r
-{\r
- if (mDatabase == 0) return;\r
-\r
- Close();\r
- mDatabase->DetachStatementImpl(this);\r
- mDatabase = 0;\r
-}\r
-\r
-void StatementImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
-{\r
- if (transaction == 0)\r
- throw LogicExceptionImpl("Statement::AttachTransaction",\r
- _("Can't attach a 0 ITransaction object."));\r
-\r
- if (mTransaction != 0) mTransaction->DetachStatementImpl(this);\r
- mTransaction = transaction;\r
- mTransaction->AttachStatementImpl(this);\r
-}\r
-\r
-void StatementImpl::DetachTransactionImpl()\r
-{\r
- if (mTransaction == 0) return;\r
-\r
- Close();\r
- mTransaction->DetachStatementImpl(this);\r
- mTransaction = 0;\r
-}\r
-\r
-void StatementImpl::CursorFree()\r
-{\r
- if (mCursorOpened)\r
- {\r
- mCursorOpened = false;\r
- if (mHandle != 0)\r
- {\r
- IBS status;\r
- (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_close);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "StatementImpl::CursorFree(DSQL_close)",\r
- _("isc_dsql_free_statement failed."));\r
- }\r
- }\r
-}\r
-\r
-StatementImpl::StatementImpl(DatabaseImpl* database, TransactionImpl* transaction,\r
- const std::string& sql)\r
- : mRefCount(0), mHandle(0), mDatabase(0), mTransaction(0),\r
- mInRow(0), mOutRow(0),\r
- mResultSetAvailable(false), mCursorOpened(false), mType(IBPP::stUnknown)\r
-{\r
- AttachDatabaseImpl(database);\r
- if (transaction != 0) AttachTransactionImpl(transaction);\r
- if (! sql.empty()) Prepare(sql);\r
-}\r
-\r
-StatementImpl::~StatementImpl()\r
-{\r
- try { Close(); }\r
- catch (...) { }\r
- try { if (mTransaction != 0) mTransaction->DetachStatementImpl(this); }\r
- catch (...) { }\r
- try { if (mDatabase != 0) mDatabase->DetachStatementImpl(this); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: time.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
-// Subject : IBPP, Time class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
-\r
-using namespace ibpp_internals;\r
-\r
-void IBPP::Time::Now()\r
-{\r
- time_t systime = time(0);\r
- tm* loctime = localtime(&systime);\r
- IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0);\r
-}\r
-\r
-void IBPP::Time::SetTime(int tm)\r
-{\r
- if (tm < 0 || tm > 863999999)\r
- throw LogicExceptionImpl("Time::SetTime", _("Invalid time value"));\r
- mTime = tm;\r
-}\r
-\r
-void IBPP::Time::SetTime(int hour, int minute, int second, int tenthousandths)\r
-{\r
- if (hour < 0 || hour > 23 ||\r
- minute < 0 || minute > 59 ||\r
- second < 0 || second > 59 ||\r
- tenthousandths < 0 || tenthousandths > 9999)\r
- throw LogicExceptionImpl("Time::SetTime",\r
- _("Invalid hour, minute, second values"));\r
- IBPP::itot(&mTime, hour, minute, second, tenthousandths);\r
-}\r
-\r
-void IBPP::Time::GetTime(int& hour, int& minute, int& second) const\r
-{\r
- IBPP::ttoi(mTime, &hour, &minute, &second, 0);\r
-}\r
-\r
-void IBPP::Time::GetTime(int& hour, int& minute, int& second, int& tenthousandths) const\r
-{\r
- IBPP::ttoi(mTime, &hour, &minute, &second, &tenthousandths);\r
-}\r
-\r
-int IBPP::Time::Hours() const\r
-{\r
- int hours;\r
- IBPP::ttoi(mTime, &hours, 0, 0, 0);\r
- return hours;\r
-}\r
-\r
-int IBPP::Time::Minutes() const\r
-{\r
- int minutes;\r
- IBPP::ttoi(mTime, 0, &minutes, 0, 0);\r
- return minutes;\r
-}\r
-\r
-int IBPP::Time::Seconds() const\r
-{\r
- int seconds;\r
- IBPP::ttoi(mTime, 0, 0, &seconds, 0);\r
- return seconds;\r
-}\r
-\r
-int IBPP::Time::SubSeconds() const // Actually tenthousandths of seconds\r
-{\r
- int tenthousandths;\r
- IBPP::ttoi(mTime, 0, 0, 0, &tenthousandths);\r
- return tenthousandths;\r
-}\r
-\r
-IBPP::Time::Time(int hour, int minute, int second, int tenthousandths)\r
-{\r
- SetTime(hour, minute, second, tenthousandths);\r
-}\r
-\r
-IBPP::Time::Time(const IBPP::Time& copied)\r
-{\r
- mTime = copied.mTime;\r
-}\r
-\r
-IBPP::Time& IBPP::Time::operator=(const IBPP::Timestamp& assigned)\r
-{\r
- mTime = assigned.GetTime();\r
- return *this;\r
-}\r
-\r
-IBPP::Time& IBPP::Time::operator=(const IBPP::Time& assigned)\r
-{\r
- mTime = assigned.mTime;\r
- return *this;\r
-}\r
-\r
-// Time calculations. Internal format is the number of seconds elapsed since\r
-// midnight. Splits such a time in its hours, minutes, seconds components.\r
-\r
-void IBPP::ttoi(int itime, int *h, int *m, int *s, int* t)\r
-{\r
- int hh, mm, ss, tt;\r
-\r
- hh = (int) (itime / 36000000); itime = itime - hh * 36000000;\r
- mm = (int) (itime / 600000); itime = itime - mm * 600000;\r
- ss = (int) (itime / 10000);\r
- tt = (int) (itime - ss * 10000);\r
-\r
- if (h != 0) *h = hh;\r
- if (m != 0) *m = mm;\r
- if (s != 0) *s = ss;\r
- if (t != 0) *t = tt;\r
-\r
- return;\r
-}\r
-\r
-// Get the internal time format, given hour, minute, second.\r
-\r
-void IBPP::itot (int *ptime, int hour, int minute, int second, int tenthousandths)\r
-{\r
- *ptime = hour * 36000000 + minute * 600000 + second * 10000 + tenthousandths;\r
- return;\r
-}\r
-\r
-namespace ibpp_internals\r
-{\r
-\r
-//\r
-// The following functions are helper conversions functions between IBPP\r
-// Date, Time, Timestamp and ISC_DATE, ISC_TIME and ISC_TIMESTAMP.\r
-// (They must be maintained if the encoding used by Firebird evolve.)\r
-// These helper functions are used from row.cpp and from array.cpp.\r
-//\r
-\r
-void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt)\r
-{\r
- // There simply has a shift of 15019 between the native Firebird\r
- // date model and the IBPP model.\r
- isc_dt = (ISC_DATE)(dt.GetDate() + 15019);\r
-}\r
-\r
-void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt)\r
-{\r
- // There simply has a shift of 15019 between the native Firebird\r
- // date model and the IBPP model.\r
- dt.SetDate((int)isc_dt - 15019);\r
-}\r
-\r
-void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm)\r
-{\r
- isc_tm = (ISC_TIME)tm.GetTime();\r
-}\r
-\r
-void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm)\r
-{\r
- tm.SetTime((int)isc_tm);\r
-}\r
-\r
-void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts)\r
-{\r
- encodeDate(isc_ts.timestamp_date, ts);\r
- encodeTime(isc_ts.timestamp_time, ts);\r
-}\r
-\r
-void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts)\r
-{\r
- decodeDate(ts, isc_ts.timestamp_date);\r
- decodeTime(ts, isc_ts.timestamp_time);\r
-}\r
-\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
-\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: transaction.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
-// Subject : IBPP, Database class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <algorithm>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void TransactionImpl::AttachDatabase(IBPP::Database db,\r
- IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
-{\r
- if (db.intf() == 0)\r
- throw LogicExceptionImpl("Transaction::AttachDatabase",\r
- _("Can't attach an unbound Database."));\r
-\r
- AttachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()), am, il, lr, flags);\r
-}\r
-\r
-void TransactionImpl::DetachDatabase(IBPP::Database db)\r
-{\r
- if (db.intf() == 0)\r
- throw LogicExceptionImpl("Transaction::DetachDatabase",\r
- _("Can't detach an unbound Database."));\r
-\r
- DetachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
-}\r
-\r
-void TransactionImpl::AddReservation(IBPP::Database db,\r
- const std::string& table, IBPP::TTR tr)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Transaction::AddReservation",\r
- _("Can't add table reservation if Transaction started."));\r
- if (db.intf() == 0)\r
- throw LogicExceptionImpl("Transaction::AddReservation",\r
- _("Can't add table reservation on an unbound Database."));\r
-\r
- // Find the TPB associated with this database\r
- std::vector<DatabaseImpl*>::iterator pos =\r
- std::find(mDatabases.begin(), mDatabases.end(), dynamic_cast<DatabaseImpl*>(db.intf()));\r
- if (pos != mDatabases.end())\r
- {\r
- size_t index = pos - mDatabases.begin();\r
- TPB* tpb = mTPBs[index];\r
- \r
- // Now add the reservations to the TPB\r
- switch (tr)\r
- {\r
- case IBPP::trSharedWrite :\r
- tpb->Insert(isc_tpb_lock_write);\r
- tpb->Insert(table);\r
- tpb->Insert(isc_tpb_shared);\r
- break;\r
- case IBPP::trSharedRead :\r
- tpb->Insert(isc_tpb_lock_read);\r
- tpb->Insert(table);\r
- tpb->Insert(isc_tpb_shared);\r
- break;\r
- case IBPP::trProtectedWrite :\r
- tpb->Insert(isc_tpb_lock_write);\r
- tpb->Insert(table);\r
- tpb->Insert(isc_tpb_protected);\r
- break;\r
- case IBPP::trProtectedRead :\r
- tpb->Insert(isc_tpb_lock_read);\r
- tpb->Insert(table);\r
- tpb->Insert(isc_tpb_protected);\r
- break;\r
- /*default :\r
- throw LogicExceptionImpl("Transaction::AddReservation",\r
- _("Illegal TTR value detected."));*/\r
- }\r
- }\r
- else throw LogicExceptionImpl("Transaction::AddReservation",\r
- _("The database connection you specified is not attached to this transaction."));\r
-}\r
-\r
-void TransactionImpl::Start()\r
-{\r
- if (mHandle != 0) return; // Already started anyway\r
-\r
- if (mDatabases.empty())\r
- throw LogicExceptionImpl("Transaction::Start", _("No Database is attached."));\r
-\r
- struct ISC_TEB\r
- {\r
- ISC_LONG* db_ptr;\r
- ISC_LONG tpb_len;\r
- char* tpb_ptr;\r
- } * teb = new ISC_TEB[mDatabases.size()];\r
-\r
- unsigned i;\r
- for (i = 0; i < mDatabases.size(); i++)\r
- {\r
- if (mDatabases[i]->GetHandle() == 0)\r
- {\r
- // All Databases must be connected to Start the transaction !\r
- delete [] teb;\r
- throw LogicExceptionImpl("Transaction::Start",\r
- _("All attached Database should have been connected."));\r
- }\r
- teb[i].db_ptr = (ISC_LONG*) mDatabases[i]->GetHandlePtr();\r
- teb[i].tpb_len = mTPBs[i]->Size();\r
- teb[i].tpb_ptr = mTPBs[i]->Self();\r
- }\r
-\r
- IBS status;\r
- (*gds.Call()->m_start_multiple)(status.Self(), &mHandle, (short)mDatabases.size(), teb);\r
- delete [] teb;\r
- if (status.Errors())\r
- {\r
- mHandle = 0; // Should be, but better be sure...\r
- throw SQLExceptionImpl(status, "Transaction::Start");\r
- }\r
-}\r
-\r
-void TransactionImpl::Commit()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Transaction::Commit", _("Transaction is not started."));\r
- \r
- IBS status;\r
-\r
- (*gds.Call()->m_commit_transaction)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Transaction::Commit");\r
- mHandle = 0; // Should be, better be sure\r
-}\r
-\r
-void TransactionImpl::CommitRetain()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Transaction::CommitRetain", _("Transaction is not started."));\r
-\r
- IBS status;\r
-\r
- (*gds.Call()->m_commit_retaining)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Transaction::CommitRetain");\r
-}\r
-\r
-void TransactionImpl::Rollback()\r
-{\r
- if (mHandle == 0) return; // Transaction not started anyway\r
-\r
- IBS status;\r
-\r
- (*gds.Call()->m_rollback_transaction)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Transaction::Rollback");\r
- mHandle = 0; // Should be, better be sure\r
-}\r
-\r
-void TransactionImpl::RollbackRetain()\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Transaction::RollbackRetain", _("Transaction is not started."));\r
-\r
- IBS status;\r
-\r
- (*gds.Call()->m_rollback_retaining)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Transaction::RollbackRetain");\r
-}\r
-\r
-IBPP::ITransaction* TransactionImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void TransactionImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void TransactionImpl::Init()\r
-{\r
- mHandle = 0;\r
- mDatabases.clear();\r
- mTPBs.clear();\r
- mStatements.clear();\r
- mBlobs.clear();\r
- mArrays.clear();\r
-}\r
-\r
-void TransactionImpl::AttachStatementImpl(StatementImpl* st)\r
-{\r
- if (st == 0)\r
- throw LogicExceptionImpl("Transaction::AttachStatement",\r
- _("Can't attach a 0 Statement object."));\r
-\r
- mStatements.push_back(st);\r
-}\r
-\r
-void TransactionImpl::DetachStatementImpl(StatementImpl* st)\r
-{\r
- if (st == 0)\r
- throw LogicExceptionImpl("Transaction::DetachStatement",\r
- _("Can't detach a 0 Statement object."));\r
-\r
- mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
-}\r
-\r
-void TransactionImpl::AttachBlobImpl(BlobImpl* bb)\r
-{\r
- if (bb == 0)\r
- throw LogicExceptionImpl("Transaction::AttachBlob",\r
- _("Can't attach a 0 BlobImpl object."));\r
-\r
- mBlobs.push_back(bb);\r
-}\r
-\r
-void TransactionImpl::DetachBlobImpl(BlobImpl* bb)\r
-{\r
- if (bb == 0)\r
- throw LogicExceptionImpl("Transaction::DetachBlob",\r
- _("Can't detach a 0 BlobImpl object."));\r
-\r
- mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
-}\r
-\r
-void TransactionImpl::AttachArrayImpl(ArrayImpl* ar)\r
-{\r
- if (ar == 0)\r
- throw LogicExceptionImpl("Transaction::AttachArray",\r
- _("Can't attach a 0 ArrayImpl object."));\r
-\r
- mArrays.push_back(ar);\r
-}\r
-\r
-void TransactionImpl::DetachArrayImpl(ArrayImpl* ar)\r
-{\r
- if (ar == 0)\r
- throw LogicExceptionImpl("Transaction::DetachArray",\r
- _("Can't detach a 0 ArrayImpl object."));\r
-\r
- mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
-}\r
-\r
-void TransactionImpl::AttachDatabaseImpl(DatabaseImpl* dbi,\r
- IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Transaction::AttachDatabase",\r
- _("Can't attach a Database if Transaction started."));\r
- if (dbi == 0)\r
- throw LogicExceptionImpl("Transaction::AttachDatabase",\r
- _("Can't attach a null Database."));\r
-\r
- mDatabases.push_back(dbi);\r
-\r
- // Prepare a new TPB\r
- TPB* tpb = new TPB;\r
- if (am == IBPP::amRead) tpb->Insert(isc_tpb_read);\r
- else tpb->Insert(isc_tpb_write);\r
-\r
- switch (il)\r
- {\r
- case IBPP::ilConsistency : tpb->Insert(isc_tpb_consistency); break;\r
- case IBPP::ilReadDirty : tpb->Insert(isc_tpb_read_committed);\r
- tpb->Insert(isc_tpb_rec_version); break;\r
- case IBPP::ilReadCommitted : tpb->Insert(isc_tpb_read_committed);\r
- tpb->Insert(isc_tpb_no_rec_version); break;\r
- case IBPP::ilConcurrency : tpb->Insert(isc_tpb_concurrency); break;\r
- }\r
-\r
- if (lr == IBPP::lrNoWait) tpb->Insert(isc_tpb_nowait);\r
- else tpb->Insert(isc_tpb_wait);\r
-\r
- if (flags & IBPP::tfIgnoreLimbo) tpb->Insert(isc_tpb_ignore_limbo);\r
- if (flags & IBPP::tfAutoCommit) tpb->Insert(isc_tpb_autocommit);\r
- if (flags & IBPP::tfNoAutoUndo) tpb->Insert(isc_tpb_no_auto_undo);\r
-\r
- mTPBs.push_back(tpb);\r
-\r
- // Signals the Database object that it has been attached to the Transaction\r
- dbi->AttachTransactionImpl(this);\r
-}\r
-\r
-void TransactionImpl::DetachDatabaseImpl(DatabaseImpl* dbi)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Transaction::DetachDatabase",\r
- _("Can't detach a Database if Transaction started."));\r
- if (dbi == 0)\r
- throw LogicExceptionImpl("Transaction::DetachDatabase",\r
- _("Can't detach a null Database."));\r
-\r
- std::vector<DatabaseImpl*>::iterator pos =\r
- std::find(mDatabases.begin(), mDatabases.end(), dbi);\r
- if (pos != mDatabases.end())\r
- {\r
- size_t index = pos - mDatabases.begin();\r
- TPB* tpb = mTPBs[index];\r
- mDatabases.erase(pos);\r
- mTPBs.erase(mTPBs.begin()+index);\r
- delete tpb;\r
- }\r
-\r
- // Signals the Database object that it has been detached from the Transaction\r
- dbi->DetachTransactionImpl(this);\r
-}\r
-\r
-TransactionImpl::TransactionImpl(DatabaseImpl* db,\r
- IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
- : mRefCount(0)\r
-{\r
- Init();\r
- AttachDatabaseImpl(db, am, il, lr, flags);\r
-}\r
-\r
-TransactionImpl::~TransactionImpl()\r
-{\r
- // Rollback the transaction if it was Started\r
- try { if (Started()) Rollback(); }\r
- catch (...) { }\r
-\r
- // Let's detach cleanly all Blobs from this Transaction.\r
- // No Blob object can still maintain pointers to this\r
- // Transaction which is disappearing.\r
- //\r
- // We use a reverse traversal of the array to avoid loops.\r
- // The array shrinks on each loop (mBbCount decreases).\r
- // And during the deletion, there is a packing of the array through a\r
- // copy of elements from the end to the beginning of the array.\r
- try {\r
- while (mBlobs.size() > 0)\r
- mBlobs.back()->DetachTransactionImpl();\r
- } catch (...) { }\r
-\r
- // Let's detach cleanly all Arrays from this Transaction.\r
- // No Array object can still maintain pointers to this\r
- // Transaction which is disappearing.\r
- try {\r
- while (mArrays.size() > 0)\r
- mArrays.back()->DetachTransactionImpl();\r
- } catch (...) { }\r
-\r
- // Let's detach cleanly all Statements from this Transaction.\r
- // No Statement object can still maintain pointers to this\r
- // Transaction which is disappearing.\r
- try {\r
- while (mStatements.size() > 0)\r
- mStatements.back()->DetachTransactionImpl();\r
- } catch (...) { }\r
-\r
- // Very important : let's detach cleanly all Databases from this\r
- // Transaction. No Database object can still maintain pointers to this\r
- // Transaction which is disappearing.\r
- try {\r
- while (mDatabases.size() > 0)\r
- {\r
- size_t i = mDatabases.size()-1;\r
- DetachDatabaseImpl(mDatabases[i]); // <-- remove link to database from mTPBs\r
- // array and destroy TPB object\r
- // Fixed : Maxim Abrashkin on 12 Jun 2002\r
- //mDatabases.back()->DetachTransaction(this);\r
- }\r
- } catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: user.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
-// Subject : IBPP, User class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <iostream>\r
-#include <sstream>\r
-#include <iomanip>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// Private implementation\r
-\r
-void IBPP::User::copyfrom(const IBPP::User& r)\r
-{\r
- username = r.username;\r
- password = r.password;\r
- firstname = r.firstname;\r
- middlename = r.middlename;\r
- lastname = r.lastname;\r
- userid = r.userid;\r
- groupid = r.groupid;\r
-}\r
-\r
-// Public implementation\r
-\r
-void IBPP::User::clear()\r
-{\r
- username.erase(); password.erase();\r
- firstname.erase(); middlename.erase(); lastname.erase();\r
- userid = groupid = 0;\r
-}\r
-\r
-//\r
-// EOF\r
-//\r
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "stg/json_generator.h"
-
-#include <yajl/yajl_gen.h>
-
-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<const unsigned char*>(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<const char*>(buf), size);
-
- yajl_gen_free(handle);
-
- return res;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_JSON_GENERATOR_H__
-#define __STG_STGLIBS_JSON_GENERATOR_H__
-
-#include <string>
-#include <map>
-#include <vector>
-#include <utility>
-
-#include <boost/scoped_ptr.hpp>
-
-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 <typename T>
- 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<Gen*, bool> SmartGen;
- typedef std::map<std::string, SmartGen> 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<Gen*, bool> SmartGen;
- typedef std::vector<SmartGen> Value;
- Value m_value;
-};
-
-typedef bool (*Callback)(void* /*data*/, const char* /*buf*/, size_t /*size*/);
-bool generate(Gen& gen, Callback callback, void* data);
-
-}
-}
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_JSON_PARSER_H__
-#define __STG_STGLIBS_JSON_PARSER_H__
-
-#include "stg/common.h"
-
-#include <string>
-#include <map>
-
-#include <boost/scoped_ptr.hpp>
-
-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<Impl> m_impl;
-};
-
-template <typename T>
-class EnumParser : public NodeParser
-{
- public:
- typedef std::map<std::string, T> 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<std::string, std::string> 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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "stg/json_parser.h"
-
-#include <yajl/yajl_parse.h>
-
-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<const unsigned char*>(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<const char*>(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<const char*>(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<Impl*>(ctx)->m_parser; }
- static bool runParser(void* ctx, NodeParser* (NodeParser::*func)())
- {
- Impl& p = *static_cast<Impl*>(ctx);
- NodeParser* next = (p.m_parser->*func)();
- if (next != NULL)
- p.m_parser = next;
- return next != NULL;
- }
- template <typename T>
- static bool runParser(void* ctx, NodeParser* (NodeParser::*func)(const T&), const T& value)
- {
- Impl& p = *static_cast<Impl*>(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();
-}
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#ifndef STG_LOGGER_H
-#define STG_LOGGER_H
-
-#include <string>
-
-#include <pthread.h>
-
-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
+++ /dev/null
-#include "stg/logger.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <syslog.h>
-
-#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);
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
- /*
- $Revision: 1.8 $
- $Date: 2008/05/10 11:59:53 $
- $Author: nobunaga $
- */
-
-#ifndef PINGER_H
-#define PINGER_H
-
-#include <ctime>
-#include <string>
-#include <list>
-#include <map>
-
-#ifdef LINUX
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/ip_icmp.h>
-#endif
-
-#if defined (FREE_BSD) || defined (FREE_BSD5) || defined(DARWIN)
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/ip_var.h>
-#include <arpa/inet.h>
-#endif
-
-#include "stg/os_int.h"
-
-//-----------------------------------------------------------------------------
-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<uint32_t, time_t> 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<uint32_t, time_t> pingIP;
- std::list<uint32_t> ipToAdd;
- std::list<uint32_t> ipToDel;
-
- mutable pthread_mutex_t mutex;
-};
-//-----------------------------------------------------------------------------
-#endif
+++ /dev/null
-#include <pthread.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <cstdlib>
-#include <csignal>
-#include <cstring>
-#include <cerrno>
-#include <cmath>
-#include <cstdio>
-
-#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<uint32_t>::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<uint32_t>::iterator iter;
-std::multimap<uint32_t, time_t>::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<uint32_t, time_t>::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<uint32_t, time_t>::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<uint16_t *>(data);
-uint32_t sum = 0;
-uint32_t result;
-
-for ( sum = 0; len > 1; len -= 2 )
- sum += *buf++;
-
-if ( len == 1 )
- sum += *reinterpret_cast<uint8_t*>(buf);
-
-sum = (sum >> 16) + (sum & 0xFFFF);
-sum += (sum >> 16);
-result = ~sum;
-return static_cast<uint16_t>(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<uint16_t>(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<struct sockaddr*>(&addr), &len))
- {
- struct IP_HDR * ip = static_cast<struct IP_HDR *>(static_cast<void *>(buf));
- struct ICMP_HDR *icmp = static_cast<struct ICMP_HDR *>(static_cast<void *>(buf + ip->ihl * 4));
-
- if (icmp->un.echo.id != pid)
- return 0;
-
- ipAddr = *static_cast<uint32_t*>(static_cast<void *>(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<STG_PINGER *>(d);
-
-pinger->isRunningSender = true;
-time_t lastPing = 0;
-while (pinger->nonstop)
- {
- pinger->RealAddIP();
- pinger->RealDelIP();
-
- std::multimap<uint32_t, time_t>::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<STG_PINGER *>(d);
-
-pinger->isRunningRecver = true;
-
-while (pinger->nonstop)
- {
- uint32_t ip = pinger->RecvPing();
-
- if (ip)
- {
- std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
- std::multimap<uint32_t, time_t>::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;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-#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
+++ /dev/null
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-
-#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
- }
- }
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <ANY.h>
-#include <errno.h>
-
-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;
-}
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <BIT_STRING.h>
-#include <asn_internal.h>
-
-/*
- * 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("<absent>", 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;
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_codecs_prim.h>
-#include <BOOLEAN.h>
-
-/*
- * 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:
- /* "<false/>" */
- *st = 0;
- break;
- case XCT_UNKNOWN_BO:
- if(xer_check_tag(chunk_buf, chunk_size, "true")
- != XCT_BOTH)
- return XPBD_BROKEN_ENCODING;
- /* "<true/>" */
- *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("<true/>", 7);
- er.encoded = 7;
- } else {
- _ASN_CALLBACK("<false/>", 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 = "<absent>";
- 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);
-}
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <INTEGER.h>
-#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
-#include <errno.h>
-
-/*
- * 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("<absent>", 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;
-}
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-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
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_codecs_prim.h>
-#include <NULL.h>
-#include <BOOLEAN.h> /* 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("<present>", 9, app_key) < 0) ? -1 : 0;
- } else {
- return (cb("<absent>", 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);
-}
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. 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 <asn_internal.h>
-#include <NativeEnumerated.h>
-
-/*
- * 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);
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * 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 <asn_internal.h>
-#include <NativeInteger.h>
-
-/*
- * 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("<absent>", 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);
- }
-}
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <OBJECT_IDENTIFIER.h>
-#include <limits.h> /* for CHAR_BIT */
-#include <errno.h>
-
-/*
- * 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("<absent>", 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<oid_end; oid_text++) {
- switch(*oid_text) {
- case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */
- if(state == ST_SKIPSPACE) {
- continue;
- } else {
- break; /* Finish */
- }
- case 0x2e: /* '.' */
- if(state != ST_DIGITS
- || (oid_text + 1) == oid_end) {
- state = ST_WAITDIGITS;
- break;
- }
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- state = ST_WAITDIGITS;
- continue;
- case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
- case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
- if(state != ST_DIGITS) {
- state = ST_DIGITS;
- value = 0;
- }
- if(1) {
- long new_value = value * 10;
- if(new_value / 10 != value
- || (value = new_value + (*oid_text - 0x30)) < 0) {
- /* Overflow */
- state = ST_WAITDIGITS;
- break;
- }
- continue;
- }
- default:
- /* Unexpected symbols */
- state = ST_WAITDIGITS;
- break;
- } /* switch() */
- break;
- } /* for() */
-
-
- if(opt_oid_text_end) *opt_oid_text_end = oid_text;
-
- /* Finalize last arc */
- switch(state) {
- case ST_WAITDIGITS:
- errno = EINVAL;
- return -1;
- case ST_DIGITS:
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- /* Fall through */
- default:
- return arcs_count;
- }
-}
-
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <OCTET_STRING.h>
-#include <BIT_STRING.h> /* for .bits_unused member */
-#include <errno.h>
-
-/*
- * 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 : "<data>",
- (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: [<tag>] 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"), /* <nul/> */
- OSXET("\074\163\157\150\057\076"), /* <soh/> */
- OSXET("\074\163\164\170\057\076"), /* <stx/> */
- OSXET("\074\145\164\170\057\076"), /* <etx/> */
- OSXET("\074\145\157\164\057\076"), /* <eot/> */
- OSXET("\074\145\156\161\057\076"), /* <enq/> */
- OSXET("\074\141\143\153\057\076"), /* <ack/> */
- OSXET("\074\142\145\154\057\076"), /* <bel/> */
- OSXET("\074\142\163\057\076"), /* <bs/> */
- OSXET("\011"), /* \t */
- OSXET("\012"), /* \n */
- OSXET("\074\166\164\057\076"), /* <vt/> */
- OSXET("\074\146\146\057\076"), /* <ff/> */
- OSXET("\015"), /* \r */
- OSXET("\074\163\157\057\076"), /* <so/> */
- OSXET("\074\163\151\057\076"), /* <si/> */
- OSXET("\074\144\154\145\057\076"), /* <dle/> */
- OSXET("\074\144\143\061\057\076"), /* <de1/> */
- OSXET("\074\144\143\062\057\076"), /* <de2/> */
- OSXET("\074\144\143\063\057\076"), /* <de3/> */
- OSXET("\074\144\143\064\057\076"), /* <de4/> */
- OSXET("\074\156\141\153\057\076"), /* <nak/> */
- OSXET("\074\163\171\156\057\076"), /* <syn/> */
- OSXET("\074\145\164\142\057\076"), /* <etb/> */
- OSXET("\074\143\141\156\057\076"), /* <can/> */
- OSXET("\074\145\155\057\076"), /* <em/> */
- OSXET("\074\163\165\142\057\076"), /* <sub/> */
- OSXET("\074\145\163\143\057\076"), /* <esc/> */
- OSXET("\074\151\163\064\057\076"), /* <is4/> */
- OSXET("\074\151\163\063\057\076"), /* <is3/> */
- OSXET("\074\151\163\062\057\076"), /* <is2/> */
- OSXET("\074\151\163\061\057\076"), /* <is1/> */
- { 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("<absent>", 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("<absent>", 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;
-}
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-
--- WinAgents MIB Extraction Wizard\r
--- Extracted from rfc1155.txt 17.03.2005 16:16:50\r
-\r
-RFC1155-SMI DEFINITIONS ::= BEGIN\r
-\r
---EXPORTS EVERYTHING\r
--- internet, directory, mgmt,\r
--- experimental, private, enterprises,\r
--- OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax,\r
--- ApplicationSyntax, NetworkAddress, IpAddress,\r
--- Counter, Gauge, TimeTicks, Opaque;\r
-\r
- -- the path to the root\r
-\r
- internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }\r
-\r
- directory OBJECT IDENTIFIER ::= { internet 1 }\r
-\r
- mgmt OBJECT IDENTIFIER ::= { internet 2 }\r
-\r
- experimental OBJECT IDENTIFIER ::= { internet 3 }\r
-\r
- private OBJECT IDENTIFIER ::= { internet 4 }\r
- enterprises OBJECT IDENTIFIER ::= { private 1 }\r
-\r
-\r
- -- definition of object types\r
-\r
--- MIB Extraction: All MACRO definitions are predefined by compiler\r
--- commented by MIB Extraction: OBJECT-TYPE MACRO ::=\r
--- commented by MIB Extraction: BEGIN\r
--- commented by MIB Extraction: TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax)\r
--- commented by MIB Extraction: "ACCESS" Access\r
--- commented by MIB Extraction: "STATUS" Status\r
--- commented by MIB Extraction: VALUE NOTATION ::= value (VALUE ObjectName)\r
--- commented by MIB Extraction: \r
--- commented by MIB Extraction: Access ::= "read-only"\r
--- commented by MIB Extraction: | "read-write"\r
--- commented by MIB Extraction: | "write-only"\r
--- commented by MIB Extraction: | "not-accessible"\r
--- commented by MIB Extraction: Status ::= "mandatory"\r
--- commented by MIB Extraction: | "optional"\r
--- commented by MIB Extraction: | "obsolete"\r
--- commented by MIB Extraction: END\r
-\r
- -- names of objects in the MIB\r
-\r
- ObjectName ::=\r
- OBJECT IDENTIFIER\r
-\r
-\r
- -- syntax of objects in the MIB\r
-\r
- ObjectSyntax ::=\r
- CHOICE {\r
- simple\r
- SimpleSyntax,\r
-\r
- -- note that simple SEQUENCEs are not directly\r
- -- mentioned here to keep things simple (i.e.,\r
- -- prevent mis-use). However, application-wide\r
- -- types which are IMPLICITly encoded simple\r
- -- SEQUENCEs may appear in the following CHOICE\r
-\r
- application-wide\r
- ApplicationSyntax\r
- }\r
-\r
- SimpleSyntax ::=\r
- CHOICE {\r
- number\r
- INTEGER,\r
-\r
- string\r
- OCTET STRING,\r
-\r
- object\r
- OBJECT IDENTIFIER,\r
-\r
- empty\r
- NULL\r
- }\r
-\r
- ApplicationSyntax ::=\r
- CHOICE {\r
- address\r
- NetworkAddress,\r
-\r
- counter\r
- Counter,\r
-\r
- gauge\r
- Gauge,\r
-\r
- ticks\r
- TimeTicks,\r
-\r
- arbitrary\r
- Opaque\r
-\r
- -- other application-wide types, as they are\r
- -- defined, will be added here\r
- }\r
-\r
-\r
- -- application-wide types\r
-\r
- NetworkAddress ::=\r
- CHOICE {\r
- internet\r
- IpAddress\r
- }\r
-\r
- IpAddress ::=\r
- [APPLICATION 0] -- in network-byte order\r
- IMPLICIT OCTET STRING (SIZE (4))\r
-\r
- Counter ::=\r
- [APPLICATION 1]\r
- IMPLICIT INTEGER (0..4294967295)\r
-\r
- Gauge ::=\r
- [APPLICATION 2]\r
- IMPLICIT INTEGER (0..4294967295)\r
-\r
- TimeTicks ::=\r
- [APPLICATION 3]\r
- IMPLICIT INTEGER (0..4294967295)\r
-\r
- Opaque ::=\r
- [APPLICATION 4] -- arbitrary ASN.1 value,\r
- IMPLICIT OCTET STRING -- "double-wrapped"\r
-\r
- END\r
+++ /dev/null
-
--- WinAgents MIB Extraction Wizard\r
--- Extracted from rfc1157.txt 16.03.2005 20:20:14\r
-\r
-RFC1157-SNMP DEFINITIONS ::= BEGIN\r
-\r
- IMPORTS\r
- ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks\r
- FROM RFC1155-SMI;\r
-\r
-\r
- -- top-level message\r
-\r
- Message ::=\r
- SEQUENCE {\r
- version -- version-1 for this RFC\r
- INTEGER {\r
- version-1(0)\r
- },\r
-\r
- community -- community name\r
- OCTET STRING,\r
-\r
- data -- e.g., PDUs if trivial\r
- ANY -- authentication is being used\r
- }\r
-\r
-\r
- -- protocol data units\r
-\r
- PDUs ::=\r
- CHOICE {\r
- get-request\r
- GetRequest-PDU,\r
-\r
- get-next-request\r
- GetNextRequest-PDU,\r
-\r
- get-response\r
- GetResponse-PDU,\r
-\r
- set-request\r
- SetRequest-PDU,\r
-\r
- trap\r
- Trap-PDU\r
- }\r
-\r
-\r
-\r
-\r
- -- PDUs\r
-\r
- GetRequest-PDU ::=\r
- [0]\r
- IMPLICIT PDU\r
-\r
- GetNextRequest-PDU ::=\r
- [1]\r
- IMPLICIT PDU\r
-\r
- GetResponse-PDU ::=\r
- [2]\r
- IMPLICIT PDU\r
-\r
- SetRequest-PDU ::=\r
- [3]\r
- IMPLICIT PDU\r
-\r
- PDU ::=\r
- SEQUENCE {\r
- request-id\r
- INTEGER,\r
-\r
- error-status -- sometimes ignored\r
- INTEGER {\r
- noError(0),\r
- tooBig(1),\r
- noSuchName(2),\r
- badValue(3),\r
- readOnly(4),\r
- genErr(5)\r
- },\r
-\r
- error-index -- sometimes ignored\r
- INTEGER,\r
-\r
- variable-bindings -- values are sometimes ignored\r
- VarBindList\r
- }\r
-\r
- Trap-PDU ::=\r
- [4]\r
- IMPLICIT SEQUENCE {\r
- enterprise -- type of object generating\r
- -- trap, see sysObjectID in [5]\r
-\r
-\r
- OBJECT IDENTIFIER,\r
-\r
- agent-addr -- address of object generating\r
- NetworkAddress, -- trap\r
-\r
- generic-trap -- generic trap type\r
- INTEGER {\r
- coldStart(0),\r
- warmStart(1),\r
- linkDown(2),\r
- linkUp(3),\r
- authenticationFailure(4),\r
- egpNeighborLoss(5),\r
- enterpriseSpecific(6)\r
- },\r
-\r
- specific-trap -- specific code, present even\r
- INTEGER, -- if generic-trap is not\r
- -- enterpriseSpecific\r
-\r
- time-stamp -- time elapsed between the last\r
- TimeTicks, -- (re)initialization of the network\r
- -- entity and the generation of the trap\r
-\r
- variable-bindings -- "interesting" information\r
- VarBindList\r
- }\r
-\r
-\r
- -- variable bindings\r
-\r
- VarBind ::=\r
- SEQUENCE {\r
- name\r
- ObjectName,\r
-\r
- value\r
- ObjectSyntax\r
- }\r
-\r
- VarBindList ::=\r
- SEQUENCE OF\r
- VarBind\r
-\r
- END
\ No newline at end of file
+++ /dev/null
-
--- WinAgents MIB Extraction Wizard\r
--- Extracted from rfc1213.txt 16.03.2005 20:20:14\r
-\r
-RFC1213-MIB DEFINITIONS ::= BEGIN\r
-\r
-IMPORTS\r
- mgmt, NetworkAddress, IpAddress, Counter, Gauge,\r
- TimeTicks\r
- FROM RFC1155-SMI\r
- OBJECT-TYPE\r
- FROM RFC-1212;\r
-\r
--- This MIB module uses the extended OBJECT-TYPE macro as\r
--- defined in [14];\r
-\r
-\r
--- MIB-II (same prefix as MIB-I)\r
-\r
-mib-2 OBJECT IDENTIFIER ::= { mgmt 1 }\r
-\r
--- textual conventions\r
-\r
-DisplayString ::=\r
- OCTET STRING\r
--- This data type is used to model textual information taken\r
--- from the NVT ASCII character set. By convention, objects\r
--- with this syntax are declared as having\r
-\r
---\r
--- SIZE (0..255)\r
-\r
-PhysAddress ::=\r
- OCTET STRING\r
--- This data type is used to model media addresses. For many\r
--- types of media, this will be in a binary representation.\r
--- For example, an ethernet address would be represented as\r
--- a string of 6 octets.\r
-\r
-\r
--- groups in MIB-II\r
-\r
-system OBJECT IDENTIFIER ::= { mib-2 1 }\r
-\r
-interfaces OBJECT IDENTIFIER ::= { mib-2 2 }\r
-\r
-at OBJECT IDENTIFIER ::= { mib-2 3 }\r
-\r
-ip OBJECT IDENTIFIER ::= { mib-2 4 }\r
-\r
-icmp OBJECT IDENTIFIER ::= { mib-2 5 }\r
-\r
-tcp OBJECT IDENTIFIER ::= { mib-2 6 }\r
-\r
-udp OBJECT IDENTIFIER ::= { mib-2 7 }\r
-\r
-egp OBJECT IDENTIFIER ::= { mib-2 8 }\r
-\r
--- historical (some say hysterical)\r
--- cmot OBJECT IDENTIFIER ::= { mib-2 9 }\r
-\r
-transmission OBJECT IDENTIFIER ::= { mib-2 10 }\r
-\r
-snmp OBJECT IDENTIFIER ::= { mib-2 11 }\r
-\r
-\r
--- the System group\r
-\r
--- Implementation of the System group is mandatory for all\r
--- systems. If an agent is not configured to have a value\r
--- for any of these variables, a string of length 0 is\r
--- returned.\r
-\r
-\r
-IfEntry ::=\r
- SEQUENCE {\r
- ifIndex\r
- INTEGER,\r
-\r
- ifDescr\r
- DisplayString,\r
- ifType\r
- INTEGER,\r
- ifMtu\r
- INTEGER,\r
- ifSpeed\r
- Gauge,\r
- ifPhysAddress\r
- PhysAddress,\r
- ifAdminStatus\r
- INTEGER,\r
- ifOperStatus\r
- INTEGER,\r
- ifLastChange\r
- TimeTicks,\r
- ifInOctets\r
- Counter,\r
- ifInUcastPkts\r
- Counter,\r
- ifInNUcastPkts\r
- Counter,\r
- ifInDiscards\r
- Counter,\r
- ifInErrors\r
- Counter,\r
- ifInUnknownProtos\r
- Counter,\r
- ifOutOctets\r
- Counter,\r
- ifOutUcastPkts\r
- Counter,\r
- ifOutNUcastPkts\r
- Counter,\r
- ifOutDiscards\r
- Counter,\r
- ifOutErrors\r
- Counter,\r
- ifOutQLen\r
- Gauge,\r
- ifSpecific\r
- OBJECT IDENTIFIER\r
- }\r
-\r
-\r
--- the Address Translation group\r
-\r
--- Implementation of the Address Translation group is\r
--- mandatory for all systems. Note however that this group\r
--- is deprecated by MIB-II. That is, it is being included\r
-\r
--- solely for compatibility with MIB-I nodes, and will most\r
--- likely be excluded from MIB-III nodes. From MIB-II and\r
--- onwards, each network protocol group contains its own\r
--- address translation tables.\r
-\r
--- The Address Translation group contains one table which is\r
--- the union across all interfaces of the translation tables\r
--- for converting a NetworkAddress (e.g., an IP address) into\r
--- a subnetwork-specific address. For lack of a better term,\r
--- this document refers to such a subnetwork-specific address\r
--- as a `physical' address.\r
-\r
--- Examples of such translation tables are: for broadcast\r
--- media where ARP is in use, the translation table is\r
--- equivalent to the ARP cache; or, on an X.25 network where\r
--- non-algorithmic translation to X.121 addresses is\r
--- required, the translation table contains the\r
--- NetworkAddress to X.121 address equivalences.\r
-\r
-\r
-AtEntry ::=\r
- SEQUENCE {\r
- atIfIndex\r
- INTEGER,\r
-\r
- atPhysAddress\r
- PhysAddress,\r
- atNetAddress\r
- NetworkAddress\r
- }\r
-\r
-\r
-\r
-\r
-\r
--- the IP address table\r
-\r
--- The IP address table contains this entity's IP addressing\r
--- information.\r
-\r
-\r
-IpAddrEntry ::=\r
- SEQUENCE {\r
- ipAdEntAddr\r
- IpAddress,\r
- ipAdEntIfIndex\r
- INTEGER,\r
- ipAdEntNetMask\r
- IpAddress,\r
- ipAdEntBcastAddr\r
- INTEGER,\r
- ipAdEntReasmMaxSize\r
- INTEGER (0..65535)\r
- }\r
-\r
-\r
-IpRouteEntry ::=\r
- SEQUENCE {\r
- ipRouteDest\r
- IpAddress,\r
- ipRouteIfIndex\r
- INTEGER,\r
- ipRouteMetric1\r
- INTEGER,\r
- ipRouteMetric2\r
- INTEGER,\r
- ipRouteMetric3\r
- INTEGER,\r
- ipRouteMetric4\r
- INTEGER,\r
- ipRouteNextHop\r
- IpAddress,\r
- ipRouteType\r
- INTEGER,\r
- ipRouteProto\r
- INTEGER,\r
- ipRouteAge\r
- INTEGER,\r
- ipRouteMask\r
- IpAddress,\r
- ipRouteMetric5\r
- INTEGER,\r
-\r
- ipRouteInfo\r
- OBJECT IDENTIFIER\r
- }\r
-\r
-\r
-IpNetToMediaEntry ::=\r
- SEQUENCE {\r
- ipNetToMediaIfIndex\r
- INTEGER,\r
- ipNetToMediaPhysAddress\r
- PhysAddress,\r
- ipNetToMediaNetAddress\r
- IpAddress,\r
- ipNetToMediaType\r
- INTEGER\r
- }\r
-\r
-\r
-\r
-TcpConnEntry ::=\r
- SEQUENCE {\r
- tcpConnState\r
- INTEGER,\r
- tcpConnLocalAddress\r
- IpAddress,\r
- tcpConnLocalPort\r
- INTEGER (0..65535),\r
- tcpConnRemAddress\r
- IpAddress,\r
- tcpConnRemPort\r
- INTEGER (0..65535)\r
- }\r
-\r
-\r
-UdpEntry ::=\r
- SEQUENCE {\r
- udpLocalAddress\r
- IpAddress,\r
- udpLocalPort\r
- INTEGER (0..65535)\r
- }\r
-\r
-\r
-\r
--- the EGP Neighbor table\r
-\r
--- The EGP neighbor table contains information about this\r
--- entity's EGP neighbors.\r
-\r
-\r
-EgpNeighEntry ::=\r
- SEQUENCE {\r
- egpNeighState\r
- INTEGER,\r
- egpNeighAddr\r
- IpAddress,\r
- egpNeighAs\r
- INTEGER,\r
- egpNeighInMsgs\r
- Counter,\r
- egpNeighInErrs\r
- Counter,\r
- egpNeighOutMsgs\r
- Counter,\r
- egpNeighOutErrs\r
- Counter,\r
-\r
- egpNeighInErrMsgs\r
- Counter,\r
- egpNeighOutErrMsgs\r
- Counter,\r
- egpNeighStateUps\r
- Counter,\r
- egpNeighStateDowns\r
- Counter,\r
- egpNeighIntervalHello\r
- INTEGER,\r
- egpNeighIntervalPoll\r
- INTEGER,\r
- egpNeighMode\r
- INTEGER,\r
- egpNeighEventTrigger\r
- INTEGER\r
- }\r
-\r
-\r
-\r
--- the Transmission group\r
-\r
--- Based on the transmission media underlying each interface\r
--- on a system, the corresponding portion of the Transmission\r
--- group is mandatory for that system.\r
-\r
--- When Internet-standard definitions for managing\r
--- transmission media are defined, the transmission group is\r
--- used to provide a prefix for the names of those objects.\r
-\r
--- Typically, such definitions reside in the experimental\r
--- portion of the MIB until they are "proven", then as a\r
--- part of the Internet standardization process, the\r
--- definitions are accordingly elevated and a new object\r
--- identifier, under the transmission group is defined. By\r
--- convention, the name assigned is:\r
---\r
--- type OBJECT IDENTIFIER ::= { transmission number }\r
---\r
--- where "type" is the symbolic value used for the media in\r
--- the ifType column of the ifTable object, and "number" is\r
--- the actual integer value corresponding to the symbol.\r
-\r
-\r
--- the SNMP group\r
-\r
--- Implementation of the SNMP group is mandatory for all\r
--- systems which support an SNMP protocol entity. Some of\r
--- the objects defined below will be zero-valued in those\r
--- SNMP implementations that are optimized to support only\r
--- those functions specific to either a management agent or\r
--- a management station. In particular, it should be\r
--- observed that the objects below refer to an SNMP entity,\r
--- and there may be several SNMP entities residing on a\r
--- managed node (e.g., if the node is hosting acting as\r
--- a management station).\r
-\r
-\r
-END\r
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-
--- WinAgents MIB Extraction Wizard\r
--- Extracted from rfc1227.txt 16.03.2005 20:20:14\r
-\r
-SMUX DEFINITIONS ::= BEGIN\r
-\r
-IMPORTS\r
- ObjectName\r
- FROM RFC1155-SMI\r
- DisplayString\r
- FROM RFC1213-MIB\r
-\r
- PDUs\r
- FROM RFC1157-SNMP;\r
-\r
-\r
--- tags for SMUX-specific PDUs are application-wide to\r
--- avoid conflict with tags for current (and future)\r
--- SNMP-generic PDUs\r
-\r
-SMUX-PDUs ::=\r
- CHOICE {\r
- open -- SMUX peer uses\r
- OpenPDU, -- immediately after TCP open\r
-\r
- close -- either uses immediately before TCP close\r
- ClosePDU,\r
-\r
- registerRequest -- SMUX peer uses\r
- RReqPDU,\r
-\r
- registerResponse -- SNMP agent uses\r
- RRspPDU,\r
-\r
- PDUs, -- note that roles are reversed:\r
- -- SNMP agent does get/get-next/set\r
- -- SMUX peer does get-response/trap\r
-\r
- commitOrRollback -- SNMP agent uses\r
- SOutPDU\r
- }\r
-\r
-\r
--- open PDU\r
--- currently only simple authentication\r
-\r
-OpenPDU ::=\r
- CHOICE {\r
- simple\r
-\r
- SimpleOpen\r
- }\r
-\r
-SimpleOpen ::=\r
- [APPLICATION 0] IMPLICIT\r
- SEQUENCE {\r
- version -- of SMUX protocol\r
- INTEGER {\r
- version-1(0)\r
- },\r
-\r
- identity -- of SMUX peer, authoritative\r
- OBJECT IDENTIFIER,\r
-\r
- description -- of SMUX peer, implementation-specific\r
- DisplayString,\r
-\r
- password -- zero length indicates no authentication\r
- OCTET STRING\r
- }\r
-\r
-\r
--- close PDU\r
-\r
-ClosePDU ::=\r
- [APPLICATION 1] IMPLICIT\r
- INTEGER {\r
- goingDown(0),\r
- unsupportedVersion(1),\r
- packetFormat(2),\r
- protocolError(3),\r
- internalError(4),\r
- authenticationFailure(5)\r
- }\r
-\r
-\r
--- insert PDU\r
-\r
-RReqPDU ::=\r
- [APPLICATION 2] IMPLICIT\r
- SEQUENCE {\r
- subtree\r
- ObjectName,\r
-\r
- priority -- the lower the better, "-1" means default\r
- INTEGER (-1..2147483647),\r
-\r
- operation\r
-\r
- INTEGER {\r
- delete(0), -- remove registration\r
- readOnly(1), -- add registration, objects are RO\r
- readWrite(2) -- .., objects are RW\r
- }\r
- }\r
-\r
-RRspPDU ::=\r
- [APPLICATION 3] IMPLICIT\r
- INTEGER {\r
- failure(-1)\r
-\r
- -- on success the non-negative priority is returned\r
- }\r
-\r
-SOutPDU ::=\r
- [APPLICATION 4] IMPLICIT\r
- INTEGER {\r
- commit(0),\r
- rollback(1)\r
- }\r
-\r
-END
\ No newline at end of file
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * Generated by asn1c-0.9.21 (http://lionet.info/asn1c)
- * From ASN.1 module "SMUX"
- * found in "SMUX.asn1"
- * `asn1c -fskeletons-copy`
- */
-
-#include <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*
- * 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 <asn_internal.h>
-
-#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 */
-};
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_SEQUENCE_OF.h>
-
-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);
- }
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_SET_OF.h>
-#include <errno.h>
-
-/*
- * 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;
- }
-
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_codecs_prim.h>
-#include <errno.h>
-
-/*
- * 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:
- * "1<tag_start..."
- */
- arg->want_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;
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-
-#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 <TL<TL<TL...>>> 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);
-}
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <ber_tlv_length.h>
-#include <ber_tlv_tag.h>
-
-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;
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <ber_tlv_tag.h>
-#include <errno.h>
-
-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;
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <constr_CHOICE.h>
-
-/*
- * 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 <TLV>'s L, even if the buffer size allows
- * reading more data.
- * For example, consider the buffer containing the following TLVs:
- * <T:5><L:1><V> <T:6>...
- * 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
- * <opening> tags.
- */
- if(tcv & XCT_CLOSING) {
- /* Found </extension> 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("</", 2, mname, mlen, ">", 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("<absent>", 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("<absent>", 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("<absent>", 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));
- }
-}
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <constr_SEQUENCE.h>
-
-/*
- * 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 <TLV>'s L, even if the buffer size allows
- * reading more data.
- * For example, consider the buffer containing the following TLVs:
- * <T:5><L:1><V> <T:6>...
- * 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 = (<member_number> * 2 + <microphase>).
- */
- 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
- * <opening> tags.
- */
- if(tcv & XCT_CLOSING) {
- /* Found </extension> 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("</", 2, mname, mlen, ">", 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("<absent>", 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 <absent> 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);
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <constr_SEQUENCE_OF.h>
-#include <asn_SEQUENCE_OF.h>
-
-/*
- * 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("</", 2, mname, mlen, ">", 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);
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <constr_SET_OF.h>
-#include <asn_SET_OF.h>
-
-/*
- * 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 <TLV>'s L, even if the buffer size allows
- * reading more data.
- * For example, consider the buffer containing the following TLVs:
- * <T:5><L:1><V> <T:6>...
- * 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("</", 2, mname, mlen, ">", 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("<absent>", 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;
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <constr_TYPE.h>
-#include <errno.h>
-
-/*
- * 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);
-}
+++ /dev/null
-#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("<broken vsnprintf>") - 1;
- maxlen--;
- arg->errlen = vlen < maxlen ? vlen : maxlen;
- memcpy(arg->errbuf, "<broken vsnprintf>", 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;
-}
-
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <errno.h>
-
-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;
-}
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef ASN_TYPE_ANY_H
-#define ASN_TYPE_ANY_H
-
-#include <OCTET_STRING.h> /* 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 */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "NetworkAddress.h"
-#include "Counter.h"
-#include "Gauge.h"
-#include "TimeTicks.h"
-#include "Opaque.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "PhysAddress.h"
-#include "NetworkAddress.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _BIT_STRING_H_
-#define _BIT_STRING_H_
-
-#include <OCTET_STRING.h> /* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _BOOLEAN_H_
-#define _BOOLEAN_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OCTET_STRING.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "IpAddress.h"
-#include "Counter.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* 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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* 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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _INTEGER_H_
-#define _INTEGER_H_
-
-#include <asn_application.h>
-#include <asn_codecs_prim.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
-
-extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
-
-/* Map with <tag> 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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "DisplayString.h"
-#include "Gauge.h"
-#include "PhysAddress.h"
-#include "TimeTicks.h"
-#include "Counter.h"
-#include <OBJECT_IDENTIFIER.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "IpAddress.h"
-#include <INTEGER.h>
-#include <NativeInteger.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OCTET_STRING.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "PhysAddress.h"
-#include "IpAddress.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "IpAddress.h"
-#include <INTEGER.h>
-#include <OBJECT_IDENTIFIER.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include <OCTET_STRING.h>
-#include <ANY.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef ASN_TYPE_NULL_H
-#define ASN_TYPE_NULL_H
-
-#include <asn_application.h>
-
-#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 */
+++ /dev/null
-/*-
- * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * 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 <NativeInteger.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. 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 <asn_application.h>
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "IpAddress.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _OBJECT_IDENTIFIER_H_
-#define _OBJECT_IDENTIFIER_H_
-
-#include <asn_application.h>
-#include <asn_codecs_prim.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _OCTET_STRING_H_
-#define _OCTET_STRING_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OBJECT_IDENTIFIER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "SimpleSyntax.h"
-#include "ApplicationSyntax.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OCTET_STRING.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "SimpleOpen.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "VarBindList.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "GetRequest-PDU.h"
-#include "GetNextRequest-PDU.h"
-#include "GetResponse-PDU.h"
-#include "SetRequest-PDU.h"
-#include "Trap-PDU.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OCTET_STRING.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "ObjectName.h"
-#include <NativeInteger.h>
-#include <INTEGER.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "OpenPDU.h"
-#include "ClosePDU.h"
-#include "RReqPDU.h"
-#include "RRspPDU.h"
-#include "PDUs.h"
-#include "SOutPDU.h"
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* 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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include <OBJECT_IDENTIFIER.h>
-#include "DisplayString.h"
-#include <OCTET_STRING.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include <OCTET_STRING.h>
-#include <OBJECT_IDENTIFIER.h>
-#include <NULL.h>
-#include <constr_CHOICE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-#include "IpAddress.h"
-#include <NativeInteger.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <INTEGER.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <OBJECT_IDENTIFIER.h>
-#include "NetworkAddress.h"
-#include <INTEGER.h>
-#include "TimeTicks.h"
-#include "VarBindList.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "IpAddress.h"
-#include <NativeInteger.h>
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include "ObjectName.h"
-#include "ObjectSyntax.h"
-#include <constr_SEQUENCE.h>
-
-#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_ */
+++ /dev/null
-/*
- * 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 <asn_application.h>
-
-/* Including external dependencies */
-#include <asn_SEQUENCE_OF.h>
-#include <constr_SEQUENCE_OF.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef ASN_SEQUENCE_OF_H
-#define ASN_SEQUENCE_OF_H
-
-#include <asn_SET_OF.h>
-
-#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 */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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 */
+++ /dev/null
-/*-
- * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef ASN_CODECS_PRIM_H
-#define ASN_CODECS_PRIM_H
-
-#include <asn_application.h>
-
-#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 */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * 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 <assert.h> /* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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 <stdio.h> /* For snprintf(3) */
-#include <stdlib.h> /* For *alloc(3) */
-#include <string.h> /* For memcpy(3) */
-#include <sys/types.h> /* For size_t */
-#include <stdarg.h> /* For va_start */
-#include <stddef.h> /* for offsetof and ptrdiff_t */
-
-#ifdef WIN32
-
-#include <malloc.h>
-#include <stdint.h>
-#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 <windows.h>
-#include <float.h>
-#define isnan _isnan
-#define finite _finite
-#define copysign _copysign
-#define ilogb _logb
-#endif /* _MSC_VER */
-
-#else /* !WIN32 */
-
-#if defined(__vxworks)
-#include <types/vxTypes.h>
-#else /* !defined(__vxworks) */
-
-#include <inttypes.h> /* C99 specifies this file */
-/*
- * 1. Earlier FreeBSD version didn't have <stdint.h>,
- * but <inttypes.h> was present.
- * 2. Sun Solaris requires <alloca.h> for alloca(3),
- * but does not have <stdint.h>.
- */
-#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
-#if defined(sun)
-#include <alloca.h> /* For alloca(3) */
-#include <ieeefp.h> /* for finite(3) */
-#elif defined(__hpux)
-#ifdef __GNUC__
-#include <alloca.h> /* For alloca(3) */
-#else /* !__GNUC__ */
-#define inline
-#endif /* __GNUC__ */
-#else
-#include <stdint.h> /* 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 <stddef.h> */
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _BER_DECODER_H_
-#define _BER_DECODER_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _CONSTR_CHOICE_H_
-#define _CONSTR_CHOICE_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _CONSTR_SEQUENCE_H_
-#define _CONSTR_SEQUENCE_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _CONSTR_SEQUENCE_OF_H_
-#define _CONSTR_SEQUENCE_OF_H_
-
-#include <asn_application.h>
-#include <constr_SET_OF.h> /* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _CONSTR_SET_OF_H_
-#define _CONSTR_SET_OF_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
- * 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 <ber_tlv_length.h>
-#include <ber_tlv_tag.h>
-
-#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 <ber_decoder.h> /* Basic Encoding Rules decoder */
-#include <der_encoder.h> /* Distinguished Encoding Rules encoder */
-#include <xer_decoder.h> /* Decoder of XER (XML, text) */
-#include <xer_encoder.h> /* Encoder into XER (XML, text) */
-#include <per_decoder.h> /* Packet Encoding Rules decoder */
-#include <per_encoder.h> /* Packet Encoding Rules encoder */
-#include <constraints.h> /* 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;
-
-\f
-/*
- * 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; /* <optional, internal> */
- 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 <value> */
- 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _ASN1_CONSTRAINTS_VALIDATOR_H_
-#define _ASN1_CONSTRAINTS_VALIDATOR_H_
-
-#include <asn_system.h> /* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _DER_ENCODER_H_
-#define _DER_ENCODER_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _PER_DECODER_H_
-#define _PER_DECODER_H_
-
-#include <asn_application.h>
-#include <per_support.h>
-
-#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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _PER_ENCODER_H_
-#define _PER_ENCODER_H_
-
-#include <asn_application.h>
-#include <per_support.h>
-
-#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_ */
+++ /dev/null
-/*
- * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _PER_SUPPORT_H_
-#define _PER_SUPPORT_H_
-
-#include <asn_system.h> /* 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _XER_DECODER_H_
-#define _XER_DECODER_H_
-
-#include <asn_application.h>
-
-#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 <opening> tag */
- XCT_CLOSING = 2, /* This is the </closing> tag */
- XCT_BOTH = 3, /* This is the <modified/> tag */
- XCT__UNK__MASK = 4, /* Mask of everything unexpected */
- XCT_UNKNOWN_OP = 5, /* Unexpected <opening> tag */
- XCT_UNKNOWN_CL = 6, /* Unexpected </closing> tag */
- XCT_UNKNOWN_BO = 7 /* Unexpected <modified/> 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_ */
+++ /dev/null
-/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _XER_ENCODER_H_
-#define _XER_ENCODER_H_
-
-#include <asn_application.h>
-
-#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_ */
+++ /dev/null
-/*
- * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#ifndef _XER_SUPPORT_H_
-#define _XER_SUPPORT_H_
-
-#include <asn_system.h> /* 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 "<!--" and "-->". */
- /*
- * 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_ */
+++ /dev/null
-#include <asn_application.h>
-#include <asn_internal.h>
-#include <per_decoder.h>
-
-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 <limits.h> */
- 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;
-}
-
+++ /dev/null
-#include <asn_application.h>
-#include <asn_internal.h>
-#include <per_encoder.h>
-
-/* 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);
-}
+++ /dev/null
-/*
- * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_system.h>
-#include <asn_internal.h>
-#include <per_support.h>
-
-/*
- * 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);
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_application.h>
-#include <asn_internal.h>
-#include <xer_support.h> /* 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 "</" */
- size -= 3; /* strip "</" and ">" */
- ct = XCT_CLOSING;
- if(size > 0 && buf[size-1] == CSLASH)
- return XCT_BROKEN; /* </abc/> */
- } 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:
- /* "<abc def/>": 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;
- }
-}
+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <stdio.h>
-#include <errno.h>
-
-/*
- * 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("</", 2, mname, mlen, ">\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);
-}
+++ /dev/null
-/*
- * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_system.h>
-#include <xer_support.h>
-
-/* 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, /* "<!--"[1] */
- ST_COMMENT_WAIT_DASH2, /* "<!--"[2] */
- ST_COMMENT,
- ST_COMMENT_CLO_DASH2, /* "-->"[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;
-}
-
+++ /dev/null
-###############################################################################
-# $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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SERVCONF_H__
-#define __STG_STGLIBS_SERVCONF_H__
-
-#include "stg/servconf_types.h"
-
-#include "stg/admin_conf.h"
-#include "stg/os_int.h"
-
-#include <string>
-
-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<GET_ADMIN::INFO>::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<GET_TARIFF::INFO>::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<GET_USER::INFO>::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<GET_SERVICE::INFO>::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<GET_CORP::INFO>::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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_TYPES_H__
-#define __STG_STGLIBS_SRVCONF_TYPES_H__
-
-#include "stg/array.h"
-#include "stg/const.h" // DIR_NUM
-#include "stg/os_int.h" // uint32_t, etc...
-
-#include <string>
-#include <vector>
-#include <ctime>
-
-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 <typename INFO>
-struct CALLBACK
-{
-typedef void (* TYPE)(bool result, const std::string & reason, const std::vector<INFO> & info, void * data);
-};
-
-} // namespace GET_CONTAINER
-
-namespace AUTH_BY
-{
-
-typedef std::vector<std::string> 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<std::string, DIR_NUM> 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<long long, DIR_NUM> su;
- ARRAY<long long, DIR_NUM> sd;
- ARRAY<long long, DIR_NUM> mu;
- ARRAY<long long, DIR_NUM> 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<std::string, USERDATA_NUM> userData;
- std::vector<std::string> services;
- std::vector<std::string> 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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#include "netunit.h"
-
-#include "stg/servconf_types.h"
-#include "stg/common.h"
-#include "stg/blowfish.h"
-#include "stg/bfstream.h"
-
-#include <algorithm> // std::min
-
-#include <cerrno>
-#include <cstring>
-#include <cassert>
-
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-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<size_t>(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<NETTRANSACT *>(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<ReadState *>(data);
-
-const char * buffer = static_cast<const char *>(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;
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- */
-
-#ifndef NetUnitH
-#define NetUnitH
-
-#include "stg/os_int.h"
-
-#include <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "auth_by.h"
-
-#include <strings.h> // 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();
- }
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_PARSER_H__
-#define __STG_STGLIBS_SRVCONF_PARSER_H__
-
-#include <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "chg_admin.h"
-
-#include "stg/admin_conf.h"
-#include "stg/common.h"
-
-#include <strings.h>
-
-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;
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "chg_corp.h"
-
-#include "resetable_utils.h"
-
-#include "stg/corp_conf.h"
-#include "stg/common.h"
-
-#include <sstream>
-
-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();
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "chg_service.h"
-
-#include "resetable_utils.h"
-
-#include "stg/service_conf.h"
-#include "stg/common.h"
-
-#include <sstream>
-
-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();
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "chg_tariff.h"
-
-#include "resetable_utils.h"
-
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-
-#include <sstream>
-
-#include <strings.h>
-
-using namespace STG;
-
-namespace
-{
-
-template <typename A, typename T>
-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 << "<traffType value=\"" + TARIFF::TraffTypeToString(data.tariffConf.traffType.data()) + "\"/>";
-
-if (!data.tariffConf.period.empty())
- switch (data.tariffConf.period.data())
- {
- case TARIFF::DAY: stream << "<period value=\"day\"/>"; break;
- case TARIFF::MONTH: stream << "<period value=\"month\"/>"; break;
- }
-
-if (!data.tariffConf.changePolicy.empty())
- switch (data.tariffConf.changePolicy.data())
- {
- case TARIFF::ALLOW: stream << "<changePolicy value=\"allow\"/>"; break;
- case TARIFF::TO_CHEAP: stream << "<changePolicy value=\"to_cheap\"/>"; break;
- case TARIFF::TO_EXPENSIVE: stream << "<changePolicy value=\"to_expensive\"/>"; break;
- case TARIFF::DENY: stream << "<changePolicy value=\"deny\"/>"; 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 << "<time" << i << " value=\"" << data.dirPrice[i].hDay.data() << ":"
- << data.dirPrice[i].mDay.data() << "-"
- << data.dirPrice[i].hNight.data() << ":"
- << data.dirPrice[i].mNight.data() << "\"/>";
-
-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();
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "chg_user.h"
-
-#include "resetable_utils.h"
-
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/common.h"
-
-#include <sstream>
-#include <iostream>
-
-#include <strings.h>
-
-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 << "<tariff delayed=\"" << conf.nextTariff.data() << "\"/>";
-else if (!conf.tariffName.empty())
- stream << "<tariff now=\"" << conf.tariffName.data() << "\"/>";
-
-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 << "<services>";
- for (size_t i = 0; i < conf.services.data().size(); ++i)
- stream << "<service name=\"" << conf.services.data()[i] << "\"/>";
- stream << "</services>";
- }
-
-// Stat
-
-if (!stat.cashAdd.empty())
- stream << "<cash add=\"" << stat.cashAdd.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashAdd.data().second), encoding, "koi8-ru") << "\"/>";
-else if (!stat.cashSet.empty())
- stream << "<cash set=\"" << stat.cashSet.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashSet.data().second), encoding, "koi8-ru") << "\"/>";
-
-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 << "<traff" << traffData << "/>";
-
-std::cerr << stream.str() << "\n";
-return stream.str();
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "get_admin.h"
-
-#include "stg/common.h"
-
-#include <map>
-#include <utility>
-
-#include <strings.h>
-
-using namespace STG;
-
-namespace STG
-{
-
-template <>
-inline
-bool GetValue<PRIV>(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.";
-}*/
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__
-#define __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__
-
-#include "base.h"
-
-#include <string>
-
-#include <strings.h>
-
-namespace STG
-{
-namespace GET_CONTAINER
-{
-
-template <typename ELEMENT_PARSER>
-class PARSER: public STG::PARSER
-{
-public:
- typedef std::vector<typename ELEMENT_PARSER::INFO> 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<ELEMENT_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<ELEMENT_PARSER> * parser = static_cast<PARSER<ELEMENT_PARSER> *>(data);
- if (!result)
- parser->SetError(reason);
- else
- parser->AddElement(info);
- }
-};
-
-} // namespace GET_CONTAINER
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "get_corp.h"
-
-#include "parsers/property.h"
-
-#include "stg/common.h"
-
-#include <strings.h>
-
-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.";
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "get_service.h"
-
-#include "parsers/property.h"
-
-#include "stg/common.h"
-
-#include <strings.h>
-
-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.";
-}*/
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "get_tariff.h"
-
-#include "parsers/property.h"
-
-#include "stg/common.h"
-
-#include <utility>
-
-#include <strings.h>
-
-using namespace STG;
-
-namespace
-{
-
-template <typename A, typename T>
-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 <typename A, typename T>
-inline
-void AddAOSParser(PROPERTY_PARSERS & parsers, const std::string & name, A & array, T A::value_type:: * field, const typename AOS_PARSER<A, T>::FUNC & func)
-{
- parsers.insert(std::make_pair(ToLower(name), new AOS_PARSER<A, T>(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 <typename T>
-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 <typename T>
-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 <typename T>
-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 <typename A, typename T>
-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 + "'.";
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "get_user.h"
-
-#include "stg/common.h"
-
-#include <map>
-#include <utility>
-
-#include <strings.h>
-
-using namespace STG;
-
-namespace STG
-{
-
-template <>
-bool GetValue<GET_USER::STAT>(const char ** attr, GET_USER::STAT & value, const std::string & /*attrName*/)
-{
-if (!attr)
- return false;
-std::map<std::string, long long *> props;
-for (size_t i = 0; i < DIR_NUM; ++i)
- {
- props.insert(std::pair<std::string, long long *>("su" + unsigned2str(i), &value.su[i]));
- props.insert(std::pair<std::string, long long *>("sd" + unsigned2str(i), &value.sd[i]));
- props.insert(std::pair<std::string, long long *>("mu" + unsigned2str(i), &value.mu[i]));
- props.insert(std::pair<std::string, long long *>("md" + unsigned2str(i), &value.md[i]));
- }
-size_t pos = 0;
-while (attr[pos])
- {
- std::string name(ToLower(attr[pos++]));
- std::map<std::string, long long *>::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]);
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "property.h"
-
-#include <strings.h>
-
-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.
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__
-#define __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__
-
-#include "stg/common.h"
-
-#include <map>
-#include <string>
-
-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 <typename T>
-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<std::string>::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<std::string, BASE_PROPERTY_PARSER *> PROPERTY_PARSERS;
-
-bool CheckValue(const char ** attr, const std::string & attrName);
-
-template <typename T>
-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<std::string>(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<double>(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 <typename T>
-inline
-void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
-{
- parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(value, func)));
-}
-
-template <typename T>
-inline
-void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const std::string & toEncoding, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
-{
- parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__
-#define __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__
-
-#include "stg/resetable.h"
-#include "stg/common.h"
-
-#include <string>
-#include <ostream>
-
-namespace STG
-{
-
-template <typename T>
-inline
-void appendTag(std::ostream & stream, const std::string & name, const T & value)
-{
- stream << "<" << name << " value=\"" << value << "\"/>";
-}
-
-template <typename T>
-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<uint8_t>(std::ostream & stream, const std::string & name, const uint8_t & value)
-{
- stream << "<" << name << " value=\"" << static_cast<unsigned>(value) << "\"/>";
-}
-
-template <>
-inline
-void appendTag<int8_t>(std::ostream & stream, const std::string & name, const int8_t & value)
-{
- stream << "<" << name << " value=\"" << static_cast<int>(value) << "\"/>";
-}
-
-template <typename T>
-inline
-void appendAttr(std::ostream & stream, const std::string & name, const T & value)
-{
- stream << " " << name << "=\"" << value << "\"";
-}
-
-template <typename T>
-inline
-void appendAttr(std::ostream & stream, const std::string & name, size_t suffix, const T & value)
-{
- stream << " " << name << suffix << "=\"" << value << "\"";
-}
-
-template <>
-inline
-void appendAttr<uint8_t>(std::ostream & stream, const std::string & name, const uint8_t & value)
-{
- stream << " " << name << "=\"" << static_cast<unsigned>(value) << "\"";
-}
-
-template <>
-inline
-void appendAttr<int8_t>(std::ostream & stream, const std::string & name, const int8_t & value)
-{
- stream << " " << name << "=\"" << static_cast<int>(value) << "\"";
-}
-
-template <typename T>
-inline
-void appendResetableTag(std::ostream & stream, const std::string & name, const T & value)
-{
-if (!value.empty())
- appendTag(stream, name, value.const_data());
-}
-
-template <typename T>
-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 <typename T>
-inline
-void appendResetableAttr(std::ostream & stream, const std::string & name, const T & value)
-{
-if (!value.empty())
- appendAttr(stream, name, value.const_data());
-}
-
-template <typename T>
-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<std::string> MaybeEncode(const RESETABLE<std::string> & value)
-{
-RESETABLE<std::string> res;
-if (!value.empty())
- res = Encode12str(value.data());
-return res;
-}
-
-inline
-RESETABLE<std::string> MaybeIconv(const RESETABLE<std::string> & value, const std::string & fromEncoding, const std::string & toEncoding)
-{
-RESETABLE<std::string> res;
-if (!value.empty())
- res = IconvString(value.data(), fromEncoding, toEncoding);
-return res;
-}
-
-} // namespace STG
-
-#endif
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "server_info.h"
-
-#include "stg/common.h"
-
-#include <cstdio> // sprintf
-
-#include <strings.h>
-
-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;
- }
-}
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#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 <string>
-
-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
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#include "simple.h"
-
-#include <strings.h>
-
-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);
-}
+++ /dev/null
-/*
- * 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 <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__
-#define __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__
-
-#include "base.h"
-
-#include "stg/servconf_types.h"
-
-#include <string>
-
-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
+++ /dev/null
-/*
- * 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 <stg34@stargazer.dp.ua>
- * Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#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 <cstdio>
-#include <cstring>
-#include <clocale>
-
-#include <expat.h>
-#include <langinfo.h>
-
-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 <class P, typename C>
- int Exec(const std::string & request, C callback, void * data)
- {
- P cp(callback, data, encoding);
- return ExecImpl(request, cp);
- }
-
- template <class P, typename C>
- 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<SERVCONF::IMPL *>(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<int>(XML_GetCurrentLineNumber(sc->parser)),
- static_cast<int>(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<std::string *>(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<SERVER_INFO::PARSER>("<GetServerInfo/>", 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<GET_ADMIN::INFO>::TYPE f, void * data)
-{
-return pImpl->Exec<GET_CONTAINER::PARSER<GET_ADMIN::PARSER> >("admins", "<GetAdmins/>", f, data);
-}
-
-int SERVCONF::GetAdmin(const std::string & login, GET_ADMIN::CALLBACK f, void * data)
-{
-return pImpl->Exec<GET_ADMIN::PARSER>("<GetAdmin login=\"" + login + "\"/>", f, data);
-}
-
-int SERVCONF::ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
-}
-
-int SERVCONF::AddAdmin(const std::string & login,
- const ADMIN_CONF_RES & conf,
- SIMPLE::CALLBACK f, void * data)
-{
-int res = pImpl->Exec<SIMPLE::PARSER>("AddAdmin", "<AddAdmin login=\"" + login + "\"/>", f, data);
-if (res != st_ok)
- return res;
-return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
-}
-
-int SERVCONF::DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("DelAdmin", "<DelAdmin login=\"" + login + "\"/>", f, data);
-}
-
-// -- Tariffs --
-
-int SERVCONF::GetTariffs(GET_CONTAINER::CALLBACK<GET_TARIFF::INFO>::TYPE f, void * data)
-{
-return pImpl->Exec<GET_CONTAINER::PARSER<GET_TARIFF::PARSER> >("tariffs", "<GetTariffs/>", f, data);
-}
-
-int SERVCONF::GetTariff(const std::string & name, GET_TARIFF::CALLBACK f, void * data)
-{
-return pImpl->Exec<GET_TARIFF::PARSER>("<GetTariff name=\"" + name + "\"/>", f, data);
-}
-
-int SERVCONF::ChgTariff(const TARIFF_DATA_RES & tariffData, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + tariffData.tariffConf.name.data() + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
-}
-
-int SERVCONF::AddTariff(const std::string & name,
- const TARIFF_DATA_RES & tariffData,
- SIMPLE::CALLBACK f, void * data)
-{
-int res = pImpl->Exec<SIMPLE::PARSER>("AddTariff", "<AddTariff name=\"" + name + "\"/>", f, data);
-if (res != st_ok)
- return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + name + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
-}
-
-int SERVCONF::DelTariff(const std::string & name, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("DelTariff", "<DelTariff name=\"" + name + "\"/>", f, data);
-}
-
-// -- Users --
-
-int SERVCONF::GetUsers(GET_CONTAINER::CALLBACK<GET_USER::INFO>::TYPE f, void * data)
-{
-return pImpl->Exec<GET_CONTAINER::PARSER<GET_USER::PARSER> >("users", "<GetUsers/>", f, data);
-}
-
-int SERVCONF::GetUser(const std::string & login, GET_USER::CALLBACK f, void * data)
-{
-return pImpl->Exec<GET_USER::PARSER>("<GetUser login=\"" + login + "\"/>", 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::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
-}
-
-int SERVCONF::DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("DelUser", "<DelUser login=\"" + login + "\"/>", 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<SIMPLE::PARSER>("AddUser", "<AddUser><Login value=\"" + login + "\"/></AddUser>", f, data);
-if (res != st_ok)
- return res;
-return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
-}
-
-int SERVCONF::AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data)
-{
-return pImpl->Exec<AUTH_BY::PARSER>("<GetUserAuthBy login=\"" + login + "\"/>", f, data);
-}
-
-int SERVCONF::SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("SendMessageResult", "<Message login=\"" + login + "\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"" + Encode12str(text) + "\"/>", f, data);
-}
-
-int SERVCONF::CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("CheckUser", "<CheckUser login=\"" + login + "\" password=\"" + password + "\"/>", f, data);
-}
-
-// -- Services --
-
-int SERVCONF::GetServices(GET_CONTAINER::CALLBACK<GET_SERVICE::INFO>::TYPE f, void * data)
-{
-return pImpl->Exec<GET_CONTAINER::PARSER<GET_SERVICE::PARSER> >("services", "<GetServices/>", f, data);
-}
-
-int SERVCONF::GetService(const std::string & name, GET_SERVICE::CALLBACK f, void * data)
-{
-return pImpl->Exec<GET_SERVICE::PARSER>("<GetService name=\"" + name + "\"/>", f, data);
-}
-
-int SERVCONF::ChgService(const SERVICE_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService " + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
-}
-
-int SERVCONF::AddService(const std::string & name,
- const SERVICE_CONF_RES & conf,
- SIMPLE::CALLBACK f, void * data)
-{
-int res = pImpl->Exec<SIMPLE::PARSER>("AddService", "<AddService name=\"" + name + "\"/>", f, data);
-if (res != st_ok)
- return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService " + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
-}
-
-int SERVCONF::DelService(const std::string & name, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("DelService", "<DelService name=\"" + name + "\"/>", f, data);
-}
-
-// -- Corporations --
-
-int SERVCONF::GetCorporations(GET_CONTAINER::CALLBACK<GET_CORP::INFO>::TYPE f, void * data)
-{
-return pImpl->Exec<GET_CONTAINER::PARSER<GET_CORP::PARSER> >("corporations", "<GetCorporations/>", f, data);
-}
-
-int SERVCONF::GetCorp(const std::string & name, GET_CORP::CALLBACK f, void * data)
-{
-return pImpl->Exec<GET_CORP::PARSER>("<GetCorp name=\"" + name + "\"/>", f, data);
-}
-
-int SERVCONF::ChgCorp(const CORP_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + conf.name.data() + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
-}
-
-int SERVCONF::AddCorp(const std::string & name,
- const CORP_CONF_RES & conf,
- SIMPLE::CALLBACK f, void * data)
-{
-int res = pImpl->Exec<SIMPLE::PARSER>("AddCorp", "<AddCorp name=\"" + name + "\"/>", f, data);
-if (res != st_ok)
- return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + name + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
-}
-
-int SERVCONF::DelCorp(const std::string & name, SIMPLE::CALLBACK f, void * data)
-{
-return pImpl->Exec<SIMPLE::PARSER>("DelCorp", "<DelCorp name=\"" + name + "\"/>", 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<PARSER *>(data);
-currParser->ParseStart(el, attr);
-}
-//-----------------------------------------------------------------------------
-void SERVCONF::IMPL::End(void * data, const char * el)
-{
-PARSER * currParser = static_cast<PARSER *>(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;
-}
--- /dev/null
+set ( CPP_FILES main.cpp
+ test_raw_ip.cpp
+ test_admin_conf.cpp
+ test_tariff.cpp
+ test_conffiles.cpp
+ test_fee_charge_rules.cpp
+ test_reconnect_on_tariff_change.cpp
+ test_disable_session_log.cpp
+ test_filter_params_log.cpp
+ test_crypto.cpp
+ test_bfstream.cpp
+ ../stargazer/tariff_impl.cpp
+ ../stargazer/user_impl.cpp
+ ../stargazer/user_property.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_definitions ( -DUSE_ABSTRACT_SETTINGS )
+
+add_executable ( tests ${CPP_FILES} )
+
+target_link_libraries ( tests conffiles crypto logger scriptexecuter common Threads::Threads )
+
+target_include_directories ( tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ../stargazer )
#include "longstring.h"
#include "stg/bfstream.h"
-#include "stg/os_int.h"
#include <algorithm>
#include <string>
#include <cstring>
+#include <cstdint>
namespace
{
{
std::ofstream f("/tmp/test.cf");
- ensure("Correct construction (part 3)", f);
+ ensure("Correct construction (part 3)", static_cast<bool>(f));
f << "\n"
<< "a=a-string# a string\n"
#include <arpa/inet.h>
#include <cstdlib>
+#include <cstdint>
#include <ctime>
#include <iostream>
#include "tut/tut.hpp"
-#include "stg/os_int.h"
#include "raw_ip_packet_old.h"
#include "stg/raw_ip_packet.h"
class TEST_TARIFFS : public TARIFFS {
public:
- TEST_TARIFFS() {}
+ TEST_TARIFFS() : testTariff("") {}
int ReadTariffs () { return 0; }
const TARIFF * FindByName(const std::string & /*name*/) const { return &testTariff; }