Merge branch 'main' of http://116.236.50.103:8789/Huijue-Network/emsApplication
# Conflicts: # .gitignoremain
|
@ -223,3 +223,110 @@ bool OpDatabase::queryUser(const std::string& user_id, const std::string& passwd
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool OpDatabase::queryInnerDevice(int dev_id, std::string& jsonResult)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// 数据库连接配置
|
||||||
|
std::string server = "tcp://127.0.0.1:3306";
|
||||||
|
std::string dbuser = "root";
|
||||||
|
std::string password = "Hj57471000";
|
||||||
|
std::string database = "hjems";
|
||||||
|
|
||||||
|
// 创建连接
|
||||||
|
sql::mysql::MySQL_Driver* driver;
|
||||||
|
driver = sql::mysql::get_mysql_driver_instance();
|
||||||
|
//m_pDbConnection.reset(driver->connect(server, dbuser, password));
|
||||||
|
sql::Connection* pDbConnection = driver->connect(server, dbuser, password);
|
||||||
|
|
||||||
|
if( !pDbConnection )
|
||||||
|
{
|
||||||
|
hloge("Failed to connect to database.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置为使用指定数据库
|
||||||
|
pDbConnection->setSchema(database);
|
||||||
|
hloge("%s : %s", user_id.c_str(), passwd_md5.c_str());
|
||||||
|
#endif
|
||||||
|
// 准备SQL查询语句
|
||||||
|
std::string sql = "SELECT uid,uname, upasswd,usalt,email,mobile1,mobile2,memo FROM tbl_user WHERE uid = ?";
|
||||||
|
|
||||||
|
// 创建预编译的prepared statement
|
||||||
|
std::unique_ptr<sql::PreparedStatement> pstmt(m_pDbConnection->prepareStatement(sql));
|
||||||
|
|
||||||
|
// 绑定参数
|
||||||
|
pstmt->setString(1, user_id); // 替换为你要查询的用户名
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
OpenJson json;
|
||||||
|
auto& nodeRoot = json["user"];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// 处理结果集
|
||||||
|
while( res->next() )
|
||||||
|
{
|
||||||
|
auto& node = nodeRoot[i++];
|
||||||
|
node["valid"] = 0;
|
||||||
|
node["uid"] = res->getString("uid");
|
||||||
|
|
||||||
|
// 假设username和password都是字符串类型
|
||||||
|
std::string pass = res->getString("upasswd");
|
||||||
|
std::string salt = res->getString("usalt");
|
||||||
|
|
||||||
|
//计算passwd和salt之间的关系
|
||||||
|
//!passwd=md5(passwd_md5+salt+salt)
|
||||||
|
// passwd_md5 是大写的,需要确保一下
|
||||||
|
std::string tmp2(passwd_md5);
|
||||||
|
std::transform(tmp2.begin(), tmp2.end(), tmp2.begin(),
|
||||||
|
[](unsigned char c)
|
||||||
|
{
|
||||||
|
return std::toupper(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::string tmp = tmp2 + salt + salt;
|
||||||
|
std::string smd5 = CalculateMD5(tmp);
|
||||||
|
|
||||||
|
if( pass == smd5 )
|
||||||
|
{
|
||||||
|
node["valid"] = 1;
|
||||||
|
|
||||||
|
node["uname"] = res->getString("uname");
|
||||||
|
node["email"] = res->getString("email");
|
||||||
|
node["mobile1"] = res->getString("mobile1");
|
||||||
|
node["mobile2"] = res->getString("mobile2");
|
||||||
|
node["memo"] = res->getString("memo");
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hloge("upass=[%s],calc=[%s],src=[%s]", pass.c_str(), smd5.c_str(), tmp.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResult = json.encode();
|
||||||
|
|
||||||
|
//pDbConnection->close();
|
||||||
|
//delete pDbConnection;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch( sql::SQLException& e )
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "SQLException: " << e.what();
|
||||||
|
ss << " (MySQL error code: " << e.getErrorCode();
|
||||||
|
ss << ", SQLState: " << e.getSQLState() << " )";
|
||||||
|
hloge("Failed to connect to database: %s", ss.str().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,9 @@ public:
|
||||||
void InsertMessage(const std::string& ts, const std::string& msg_type, const std::string& fsu, const std::string& content, int topic, int dev_id);
|
void InsertMessage(const std::string& ts, const std::string& msg_type, const std::string& fsu, const std::string& content, int topic, int dev_id);
|
||||||
|
|
||||||
bool queryUser(const std::string& user_id, const std::string& passwd_md5, std::string& jsonResult);
|
bool queryUser(const std::string& user_id, const std::string& passwd_md5, std::string& jsonResult);
|
||||||
|
|
||||||
|
//查询设备,dev_id=0则返回全部
|
||||||
|
bool queryInnerDevice(int dev_id, std::string& jsonResult);
|
||||||
protected:
|
protected:
|
||||||
//std::unique_ptr<sql::Connection> m_pDbConnection;
|
//std::unique_ptr<sql::Connection> m_pDbConnection;
|
||||||
sql::Connection* m_pDbConnection;
|
sql::Connection* m_pDbConnection;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
CMakeLists.txt.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
INSTALLATION INSTRUCTIONS
|
||||||
|
|
||||||
|
These instructions refer to the package you are installing as
|
||||||
|
some-package.tar.gz or some-package.zip. The .zip file is intended for use
|
||||||
|
on Windows.
|
||||||
|
|
||||||
|
The directory you choose for the installation will be referred to as
|
||||||
|
your-install-dir.
|
||||||
|
|
||||||
|
Note to Qt Visual Studio Integration users: In the instructions below,
|
||||||
|
instead of building from command line with nmake, you can use the menu
|
||||||
|
command 'Qt->Open Solution from .pro file' on the .pro files in the
|
||||||
|
example and plugin directories, and then build from within Visual
|
||||||
|
Studio.
|
||||||
|
|
||||||
|
Unpacking and installation
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
1. Unpacking the archive (if you have not done so already).
|
||||||
|
|
||||||
|
On Unix and Mac OS X (in a terminal window):
|
||||||
|
|
||||||
|
cd your-install-dir
|
||||||
|
gunzip some-package.tar.gz
|
||||||
|
tar xvf some-package.tar
|
||||||
|
|
||||||
|
This creates the subdirectory some-package containing the files.
|
||||||
|
|
||||||
|
On Windows:
|
||||||
|
|
||||||
|
Unpack the .zip archive by right-clicking it in explorer and
|
||||||
|
choosing "Extract All...". If your version of Windows does not
|
||||||
|
have zip support, you can use the infozip tools available
|
||||||
|
from www.info-zip.org.
|
||||||
|
|
||||||
|
If you are using the infozip tools (in a command prompt window):
|
||||||
|
cd your-install-dir
|
||||||
|
unzip some-package.zip
|
||||||
|
|
||||||
|
2. Configuring the package.
|
||||||
|
|
||||||
|
The configure script is called "configure" on unix/mac and
|
||||||
|
"configure.bat" on Windows. It should be run from a command line
|
||||||
|
after cd'ing to the package directory.
|
||||||
|
|
||||||
|
You can choose whether you want to use the component by including
|
||||||
|
its source code directly into your project, or build the component
|
||||||
|
as a dynamic shared library (DLL) that is loaded into the
|
||||||
|
application at run-time. The latter may be preferable for
|
||||||
|
technical or licensing (LGPL) reasons. If you want to build a DLL,
|
||||||
|
run the configure script with the argument "-library". Also see
|
||||||
|
the note about usage below.
|
||||||
|
|
||||||
|
(Components that are Qt plugins, e.g. styles and image formats,
|
||||||
|
are by default built as a plugin DLL.)
|
||||||
|
|
||||||
|
The configure script will prompt you in some cases for further
|
||||||
|
information. Answer these questions and carefully read the license text
|
||||||
|
before accepting the license conditions. The package cannot be used if
|
||||||
|
you do not accept the license conditions.
|
||||||
|
|
||||||
|
3. Building the component and examples (when required).
|
||||||
|
|
||||||
|
If a DLL is to be built, or if you would like to build the
|
||||||
|
examples, next give the commands
|
||||||
|
|
||||||
|
qmake
|
||||||
|
make [or nmake if your are using Microsoft Visual C++]
|
||||||
|
|
||||||
|
The example program(s) can be found in the directory called
|
||||||
|
"examples" or "example".
|
||||||
|
|
||||||
|
Components that are Qt plugins, e.g. styles and image formats, are
|
||||||
|
ready to be used as soon as they are built, so the rest of this
|
||||||
|
installation instruction can be skipped.
|
||||||
|
|
||||||
|
4. Building the Qt Designer plugin (optional).
|
||||||
|
|
||||||
|
Some of the widget components are provided with plugins for Qt
|
||||||
|
Designer. To build and install the plugin, cd into the
|
||||||
|
some-package/plugin directory and give the commands
|
||||||
|
|
||||||
|
qmake
|
||||||
|
make [or nmake if your are using Microsoft Visual C++]
|
||||||
|
|
||||||
|
Restart Qt Designer to make it load the new widget plugin.
|
||||||
|
|
||||||
|
Note: If you are using the built-in Qt Designer from the Qt Visual
|
||||||
|
Studio Integration, you will need to manually copy the plugin DLL
|
||||||
|
file, i.e. copy
|
||||||
|
%QTDIR%\plugins\designer\some-component.dll
|
||||||
|
to the Qt Visual Studio Integration plugin path, typically:
|
||||||
|
C:\Program Files\Trolltech\Qt VS Integration\plugins
|
||||||
|
|
||||||
|
Note: If you for some reason are using a Qt Designer that is built
|
||||||
|
in debug mode, you will need to build the plugin in debug mode
|
||||||
|
also. Edit the file plugin.pro in the plugin directory, changing
|
||||||
|
'release' to 'debug' in the CONFIG line, before running qmake.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Solutions components are intended to be used directly from the package
|
||||||
|
directory during development, so there is no 'make install' procedure.
|
||||||
|
|
||||||
|
|
||||||
|
Using a component in your project
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
To use this component in your project, add the following line to the
|
||||||
|
project's .pro file (or do the equivalent in your IDE):
|
||||||
|
|
||||||
|
include(your-install-dir/some-package/src/some-package.pri)
|
||||||
|
|
||||||
|
This adds the package's sources and headers to the SOURCES and HEADERS
|
||||||
|
project variables respectively (or, if the component has been
|
||||||
|
configured as a DLL, it adds that library to the LIBS variable), and
|
||||||
|
updates INCLUDEPATH to contain the package's src
|
||||||
|
directory. Additionally, the .pri file may include some dependencies
|
||||||
|
needed by the package.
|
||||||
|
|
||||||
|
To include a header file from the package in your sources, you can now
|
||||||
|
simply use:
|
||||||
|
|
||||||
|
#include <SomeClass>
|
||||||
|
|
||||||
|
or alternatively, in pre-Qt 4 style:
|
||||||
|
|
||||||
|
#include <some-class.h>
|
||||||
|
|
||||||
|
Refer to the documentation to see the classes and headers this
|
||||||
|
components provides.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Install documentation (optional)
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
The HTML documentation for the package's classes is located in the
|
||||||
|
your-install-dir/some-package/doc/html/index.html. You can open this
|
||||||
|
file and read the documentation with any web browser.
|
||||||
|
|
||||||
|
To install the documentation into Qt Assistant (for Qt version 4.4 and
|
||||||
|
later):
|
||||||
|
|
||||||
|
1. In Assistant, open the Edit->Preferences dialog and choose the
|
||||||
|
Documentation tab. Click the Add... button and select the file
|
||||||
|
your-install-dir/some-package/doc/html/some-package.qch
|
||||||
|
|
||||||
|
For Qt versions prior to 4.4, do instead the following:
|
||||||
|
|
||||||
|
1. The directory your-install-dir/some-package/doc/html contains a
|
||||||
|
file called some-package.dcf. Execute the following commands in a
|
||||||
|
shell, command prompt or terminal window:
|
||||||
|
|
||||||
|
cd your-install-dir/some-package/doc/html/
|
||||||
|
assistant -addContentFile some-package.dcf
|
||||||
|
|
||||||
|
The next time you start Qt Assistant, you can access the package's
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
|
||||||
|
Removing the documentation from assistant
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later:
|
||||||
|
|
||||||
|
1. In Assistant, open the Edit->Preferences dialog and choose the
|
||||||
|
Documentation tab. In the list of Registered Documentation, select
|
||||||
|
the item com.nokia.qtsolutions.some-package_version, and click
|
||||||
|
the Remove button.
|
||||||
|
|
||||||
|
For Qt versions prior to 4.4, do instead the following:
|
||||||
|
|
||||||
|
1. The directory your-install-dir/some-package/doc/html contains a
|
||||||
|
file called some-package.dcf. Execute the following commands in a
|
||||||
|
shell, command prompt or terminal window:
|
||||||
|
|
||||||
|
cd your-install-dir/some-package/doc/html/
|
||||||
|
assistant -removeContentFile some-package.dcf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Using the component as a DLL
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
1. Normal components
|
||||||
|
|
||||||
|
The shared library (DLL) is built and placed in the
|
||||||
|
some-package/lib directory. It is intended to be used directly
|
||||||
|
from there during development. When appropriate, both debug and
|
||||||
|
release versions are built, since the run-time linker will in some
|
||||||
|
cases refuse to load a debug-built DLL into a release-built
|
||||||
|
application or vice versa.
|
||||||
|
|
||||||
|
The following steps are taken by default to help the dynamic
|
||||||
|
linker to locate the DLL at run-time (during development):
|
||||||
|
|
||||||
|
Unix: The some-package.pri file will add linker instructions to
|
||||||
|
add the some-package/lib directory to the rpath of the
|
||||||
|
executable. (When distributing, or if your system does not support
|
||||||
|
rpath, you can copy the shared library to another place that is
|
||||||
|
searched by the dynamic linker, e.g. the "lib" directory of your
|
||||||
|
Qt installation.)
|
||||||
|
|
||||||
|
Mac: The full path to the library is hardcoded into the library
|
||||||
|
itself, from where it is copied into the executable at link time,
|
||||||
|
and ready by the dynamic linker at run-time. (When distributing,
|
||||||
|
you will want to edit these hardcoded paths in the same way as for
|
||||||
|
the Qt DLLs. Refer to the document "Deploying an Application on
|
||||||
|
Mac OS X" in the Qt Reference Documentation.)
|
||||||
|
|
||||||
|
Windows: the .dll file(s) are copied into the "bin" directory of
|
||||||
|
your Qt installation. The Qt installation will already have set up
|
||||||
|
that directory to be searched by the dynamic linker.
|
||||||
|
|
||||||
|
|
||||||
|
2. Plugins
|
||||||
|
|
||||||
|
For Qt Solutions plugins (e.g. image formats), both debug and
|
||||||
|
release versions of the plugin are built by default when
|
||||||
|
appropriate, since in some cases the release Qt library will not
|
||||||
|
load a debug plugin, and vice versa. The plugins are automatically
|
||||||
|
copied into the plugins directory of your Qt installation when
|
||||||
|
built, so no further setup is required.
|
||||||
|
|
||||||
|
Plugins may also be built statically, i.e. as a library that will be
|
||||||
|
linked into your application executable, and so will not need to
|
||||||
|
be redistributed as a separate plugin DLL to end users. Static
|
||||||
|
building is required if Qt itself is built statically. To do it,
|
||||||
|
just add "static" to the CONFIG variable in the plugin/plugin.pro
|
||||||
|
file before building. Refer to the "Static Plugins" section in the
|
||||||
|
chapter "How to Create Qt Plugins" for explanation of how to use a
|
||||||
|
static plugin in your application. The source code of the example
|
||||||
|
program(s) will also typically contain the relevant instructions
|
||||||
|
as comments.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Uninstalling
|
||||||
|
------------
|
||||||
|
|
||||||
|
The following command will remove any fils that have been
|
||||||
|
automatically placed outside the package directory itself during
|
||||||
|
installation and building
|
||||||
|
|
||||||
|
make distclean [or nmake if your are using Microsoft Visual C++]
|
||||||
|
|
||||||
|
If Qt Assistant documentation or Qt Designer plugins have been
|
||||||
|
installed, they can be uninstalled manually, ref. above.
|
||||||
|
|
||||||
|
|
||||||
|
Enjoy! :)
|
||||||
|
|
||||||
|
- The Qt Solutions Team.
|
|
@ -0,0 +1 @@
|
||||||
|
#include "qtlockedfile.h"
|
|
@ -0,0 +1,33 @@
|
||||||
|
Qt Solutions Component: Single Application
|
||||||
|
|
||||||
|
The QtSingleApplication component provides support for
|
||||||
|
applications that can be only started once per user.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Version history:
|
||||||
|
|
||||||
|
2.0: - Version 1.3 ported to Qt 4.
|
||||||
|
|
||||||
|
2.1: - Fix compilation problem on Mac.
|
||||||
|
|
||||||
|
2.2: - Really fix the Mac compilation problem.
|
||||||
|
- Mac: fix crash due to wrong object releasing.
|
||||||
|
- Mac: Fix memory leak.
|
||||||
|
|
||||||
|
2.3: - Windows: Force creation of internal widget to make it work
|
||||||
|
with Qt 4.2.
|
||||||
|
|
||||||
|
2.4: - Fix the system for automatic window raising on message
|
||||||
|
reception. NOTE: minor API change.
|
||||||
|
|
||||||
|
2.5: - Mac: Fix isRunning() to work and report correctly.
|
||||||
|
|
||||||
|
2.6: - - initialize() is now obsolete, no longer necessary to call
|
||||||
|
it
|
||||||
|
- - Fixed race condition where multiple instances migth be started
|
||||||
|
- - QtSingleCoreApplication variant provided for non-GUI (console)
|
||||||
|
usage
|
||||||
|
- Complete reimplementation. Visible changes:
|
||||||
|
- LGPL release.
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "qtlocalpeer.h"
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#include <QLibrary>
|
||||||
|
#include <qt_windows.h>
|
||||||
|
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
|
||||||
|
static PProcessIdToSessionId pProcessIdToSessionId = 0;
|
||||||
|
#endif
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace QtLP_Private {
|
||||||
|
#include "qtlockedfile.cpp"
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#include "qtlockedfile_win.cpp"
|
||||||
|
#else
|
||||||
|
#include "qtlockedfile_unix.cpp"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* QtLocalPeer::ack = "ack";
|
||||||
|
|
||||||
|
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
|
||||||
|
: QObject(parent), id(appId)
|
||||||
|
{
|
||||||
|
QString prefix = id;
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
id = QCoreApplication::applicationFilePath();
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
id = id.toLower();
|
||||||
|
#endif
|
||||||
|
prefix = id.section(QLatin1Char('/'), -1);
|
||||||
|
}
|
||||||
|
prefix.remove(QRegularExpression ("[^a-zA-Z]"));
|
||||||
|
prefix.truncate(6);
|
||||||
|
|
||||||
|
QByteArray idc = id.toUtf8();
|
||||||
|
quint16 idNum = qChecksum(idc.constData(), idc.size());
|
||||||
|
socketName = QLatin1String("qtsingleapp-") + prefix
|
||||||
|
+ QLatin1Char('-') + QString::number(idNum, 16);
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (!pProcessIdToSessionId) {
|
||||||
|
QLibrary lib("kernel32");
|
||||||
|
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
|
||||||
|
}
|
||||||
|
if (pProcessIdToSessionId) {
|
||||||
|
DWORD sessionId = 0;
|
||||||
|
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
|
||||||
|
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
server = new QLocalServer(this);
|
||||||
|
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
||||||
|
+ QLatin1Char('/') + socketName
|
||||||
|
+ QLatin1String("-lockfile");
|
||||||
|
lockFile.setFileName(lockName);
|
||||||
|
lockFile.open(QIODevice::ReadWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLocalPeer::isClient()
|
||||||
|
{
|
||||||
|
if (lockFile.isLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool res = server->listen(socketName);
|
||||||
|
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
|
||||||
|
// ### Workaround
|
||||||
|
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
|
||||||
|
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
|
||||||
|
res = server->listen(socketName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!res)
|
||||||
|
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
|
||||||
|
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
|
||||||
|
{
|
||||||
|
if (!isClient())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QLocalSocket socket;
|
||||||
|
bool connOk = false;
|
||||||
|
for(int i = 0; i < 2; i++) {
|
||||||
|
// Try twice, in case the other instance is just starting up
|
||||||
|
socket.connectToServer(socketName);
|
||||||
|
connOk = socket.waitForConnected(timeout/2);
|
||||||
|
if (connOk || i)
|
||||||
|
break;
|
||||||
|
int ms = 250;
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
Sleep(DWORD(ms));
|
||||||
|
#else
|
||||||
|
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (!connOk)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QByteArray uMsg(message.toUtf8());
|
||||||
|
QDataStream ds(&socket);
|
||||||
|
ds.writeBytes(uMsg.constData(), uMsg.size());
|
||||||
|
bool res = socket.waitForBytesWritten(timeout);
|
||||||
|
if (res) {
|
||||||
|
res &= socket.waitForReadyRead(timeout); // wait for ack
|
||||||
|
if (res)
|
||||||
|
res &= (socket.read(qstrlen(ack)) == ack);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QtLocalPeer::receiveConnection()
|
||||||
|
{
|
||||||
|
QLocalSocket* socket = server->nextPendingConnection();
|
||||||
|
if (!socket)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (socket->bytesAvailable() < (int)sizeof(quint32))
|
||||||
|
socket->waitForReadyRead();
|
||||||
|
QDataStream ds(socket);
|
||||||
|
QByteArray uMsg;
|
||||||
|
quint32 remaining;
|
||||||
|
ds >> remaining;
|
||||||
|
uMsg.resize(remaining);
|
||||||
|
int got = 0;
|
||||||
|
char* uMsgBuf = uMsg.data();
|
||||||
|
do {
|
||||||
|
got = ds.readRawData(uMsgBuf, remaining);
|
||||||
|
remaining -= got;
|
||||||
|
uMsgBuf += got;
|
||||||
|
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
|
||||||
|
if (got < 0) {
|
||||||
|
qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
|
||||||
|
delete socket;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString message(QString::fromUtf8(uMsg));
|
||||||
|
socket->write(ack, qstrlen(ack));
|
||||||
|
socket->waitForBytesWritten(1000);
|
||||||
|
socket->waitForDisconnected(1000); // make sure client reads ack
|
||||||
|
delete socket;
|
||||||
|
emit messageReceived(message); //### (might take a long time to return)
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTLOCALPEER_H
|
||||||
|
#define QTLOCALPEER_H
|
||||||
|
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include "qtlockedfile.h"
|
||||||
|
|
||||||
|
class QtLocalPeer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
|
||||||
|
bool isClient();
|
||||||
|
bool sendMessage(const QString &message, int timeout);
|
||||||
|
QString applicationId() const
|
||||||
|
{ return id; }
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void messageReceived(const QString &message);
|
||||||
|
|
||||||
|
protected Q_SLOTS:
|
||||||
|
void receiveConnection();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString id;
|
||||||
|
QString socketName;
|
||||||
|
QLocalServer* server;
|
||||||
|
QtLP_Private::QtLockedFile lockFile;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const char* ack;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTLOCALPEER_H
|
|
@ -0,0 +1,193 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qtlockedfile.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QtLockedFile
|
||||||
|
|
||||||
|
\brief The QtLockedFile class extends QFile with advisory locking
|
||||||
|
functions.
|
||||||
|
|
||||||
|
A file may be locked in read or write mode. Multiple instances of
|
||||||
|
\e QtLockedFile, created in multiple processes running on the same
|
||||||
|
machine, may have a file locked in read mode. Exactly one instance
|
||||||
|
may have it locked in write mode. A read and a write lock cannot
|
||||||
|
exist simultaneously on the same file.
|
||||||
|
|
||||||
|
The file locks are advisory. This means that nothing prevents
|
||||||
|
another process from manipulating a locked file using QFile or
|
||||||
|
file system functions offered by the OS. Serialization is only
|
||||||
|
guaranteed if all processes that access the file use
|
||||||
|
QLockedFile. Also, while holding a lock on a file, a process
|
||||||
|
must not open the same file again (through any API), or locks
|
||||||
|
can be unexpectedly lost.
|
||||||
|
|
||||||
|
The lock provided by an instance of \e QtLockedFile is released
|
||||||
|
whenever the program terminates. This is true even when the
|
||||||
|
program crashes and no destructors are called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \enum QtLockedFile::LockMode
|
||||||
|
|
||||||
|
This enum describes the available lock modes.
|
||||||
|
|
||||||
|
\value ReadLock A read lock.
|
||||||
|
\value WriteLock A write lock.
|
||||||
|
\value NoLock Neither a read lock nor a write lock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an unlocked \e QtLockedFile object. This constructor
|
||||||
|
behaves in the same way as \e QFile::QFile().
|
||||||
|
|
||||||
|
\sa QFile::QFile()
|
||||||
|
*/
|
||||||
|
QtLockedFile::QtLockedFile()
|
||||||
|
: QFile()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wmutex = 0;
|
||||||
|
rmutex = 0;
|
||||||
|
#endif
|
||||||
|
m_lock_mode = NoLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an unlocked QtLockedFile object with file \a name. This
|
||||||
|
constructor behaves in the same way as \e QFile::QFile(const
|
||||||
|
QString&).
|
||||||
|
|
||||||
|
\sa QFile::QFile()
|
||||||
|
*/
|
||||||
|
QtLockedFile::QtLockedFile(const QString &name)
|
||||||
|
: QFile(name)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wmutex = 0;
|
||||||
|
rmutex = 0;
|
||||||
|
#endif
|
||||||
|
m_lock_mode = NoLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file in OpenMode \a mode.
|
||||||
|
|
||||||
|
This is identical to QFile::open(), with the one exception that the
|
||||||
|
Truncate mode flag is disallowed. Truncation would conflict with the
|
||||||
|
advisory file locking, since the file would be modified before the
|
||||||
|
write lock is obtained. If truncation is required, use resize(0)
|
||||||
|
after obtaining the write lock.
|
||||||
|
|
||||||
|
Returns true if successful; otherwise false.
|
||||||
|
|
||||||
|
\sa QFile::open(), QFile::resize()
|
||||||
|
*/
|
||||||
|
bool QtLockedFile::open(OpenMode mode)
|
||||||
|
{
|
||||||
|
if (mode & QIODevice::Truncate) {
|
||||||
|
qWarning("QtLockedFile::open(): Truncate mode not allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return QFile::open(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns \e true if this object has a in read or write lock;
|
||||||
|
otherwise returns \e false.
|
||||||
|
|
||||||
|
\sa lockMode()
|
||||||
|
*/
|
||||||
|
bool QtLockedFile::isLocked() const
|
||||||
|
{
|
||||||
|
return m_lock_mode != NoLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the type of lock currently held by this object, or \e
|
||||||
|
QtLockedFile::NoLock.
|
||||||
|
|
||||||
|
\sa isLocked()
|
||||||
|
*/
|
||||||
|
QtLockedFile::LockMode QtLockedFile::lockMode() const
|
||||||
|
{
|
||||||
|
return m_lock_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QtLockedFile::lock(LockMode mode, bool block = true)
|
||||||
|
|
||||||
|
Obtains a lock of type \a mode. The file must be opened before it
|
||||||
|
can be locked.
|
||||||
|
|
||||||
|
If \a block is true, this function will block until the lock is
|
||||||
|
aquired. If \a block is false, this function returns \e false
|
||||||
|
immediately if the lock cannot be aquired.
|
||||||
|
|
||||||
|
If this object already has a lock of type \a mode, this function
|
||||||
|
returns \e true immediately. If this object has a lock of a
|
||||||
|
different type than \a mode, the lock is first released and then a
|
||||||
|
new lock is obtained.
|
||||||
|
|
||||||
|
This function returns \e true if, after it executes, the file is
|
||||||
|
locked by this object, and \e false otherwise.
|
||||||
|
|
||||||
|
\sa unlock(), isLocked(), lockMode()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QtLockedFile::unlock()
|
||||||
|
|
||||||
|
Releases a lock.
|
||||||
|
|
||||||
|
If the object has no lock, this function returns immediately.
|
||||||
|
|
||||||
|
This function returns \e true if, after it executes, the file is
|
||||||
|
not locked by this object, and \e false otherwise.
|
||||||
|
|
||||||
|
\sa lock(), isLocked(), lockMode()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QtLockedFile::~QtLockedFile()
|
||||||
|
|
||||||
|
Destroys the \e QtLockedFile object. If any locks were held, they
|
||||||
|
are released.
|
||||||
|
*/
|
|
@ -0,0 +1,97 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTLOCKEDFILE_H
|
||||||
|
#define QTLOCKEDFILE_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QVector>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
|
||||||
|
# define QT_QTLOCKEDFILE_EXPORT
|
||||||
|
# elif defined(QT_QTLOCKEDFILE_IMPORT)
|
||||||
|
# if defined(QT_QTLOCKEDFILE_EXPORT)
|
||||||
|
# undef QT_QTLOCKEDFILE_EXPORT
|
||||||
|
# endif
|
||||||
|
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
|
||||||
|
# elif defined(QT_QTLOCKEDFILE_EXPORT)
|
||||||
|
# undef QT_QTLOCKEDFILE_EXPORT
|
||||||
|
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define QT_QTLOCKEDFILE_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace QtLP_Private {
|
||||||
|
|
||||||
|
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum LockMode { NoLock = 0, ReadLock, WriteLock };
|
||||||
|
|
||||||
|
QtLockedFile();
|
||||||
|
QtLockedFile(const QString &name);
|
||||||
|
~QtLockedFile();
|
||||||
|
|
||||||
|
bool open(OpenMode mode);
|
||||||
|
|
||||||
|
bool lock(LockMode mode, bool block = true);
|
||||||
|
bool unlock();
|
||||||
|
bool isLocked() const;
|
||||||
|
LockMode lockMode() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
Qt::HANDLE wmutex;
|
||||||
|
Qt::HANDLE rmutex;
|
||||||
|
QVector<Qt::HANDLE> rmutexes;
|
||||||
|
QString mutexname;
|
||||||
|
|
||||||
|
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
|
||||||
|
bool waitMutex(Qt::HANDLE mutex, bool doBlock);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
LockMode m_lock_mode;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,115 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "qtlockedfile.h"
|
||||||
|
|
||||||
|
bool QtLockedFile::lock(LockMode mode, bool block)
|
||||||
|
{
|
||||||
|
if (!isOpen()) {
|
||||||
|
qWarning("QtLockedFile::lock(): file is not opened");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == NoLock)
|
||||||
|
return unlock();
|
||||||
|
|
||||||
|
if (mode == m_lock_mode)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m_lock_mode != NoLock)
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
struct flock fl;
|
||||||
|
fl.l_whence = SEEK_SET;
|
||||||
|
fl.l_start = 0;
|
||||||
|
fl.l_len = 0;
|
||||||
|
fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
|
||||||
|
int cmd = block ? F_SETLKW : F_SETLK;
|
||||||
|
int ret = fcntl(handle(), cmd, &fl);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_lock_mode = mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLockedFile::unlock()
|
||||||
|
{
|
||||||
|
if (!isOpen()) {
|
||||||
|
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLocked())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
struct flock fl;
|
||||||
|
fl.l_whence = SEEK_SET;
|
||||||
|
fl.l_start = 0;
|
||||||
|
fl.l_len = 0;
|
||||||
|
fl.l_type = F_UNLCK;
|
||||||
|
int ret = fcntl(handle(), F_SETLKW, &fl);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lock_mode = NoLock;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtLockedFile::~QtLockedFile()
|
||||||
|
{
|
||||||
|
if (isOpen())
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qtlockedfile.h"
|
||||||
|
#include <qt_windows.h>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
#define MUTEX_PREFIX "QtLockedFile mutex "
|
||||||
|
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
|
||||||
|
#define MAX_READERS MAXIMUM_WAIT_OBJECTS
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
#define QT_WA(unicode, ansi) unicode
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
||||||
|
{
|
||||||
|
if (mutexname.isEmpty()) {
|
||||||
|
QFileInfo fi(*this);
|
||||||
|
mutexname = QString::fromLatin1(MUTEX_PREFIX)
|
||||||
|
+ fi.absoluteFilePath().toLower();
|
||||||
|
}
|
||||||
|
QString mname(mutexname);
|
||||||
|
if (idx >= 0)
|
||||||
|
mname += QString::number(idx);
|
||||||
|
|
||||||
|
Qt::HANDLE mutex;
|
||||||
|
if (doCreate) {
|
||||||
|
QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
|
||||||
|
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
|
||||||
|
if (!mutex) {
|
||||||
|
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
|
||||||
|
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
|
||||||
|
if (!mutex) {
|
||||||
|
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
|
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
|
||||||
|
{
|
||||||
|
Q_ASSERT(mutex);
|
||||||
|
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
|
||||||
|
switch (res) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool QtLockedFile::lock(LockMode mode, bool block)
|
||||||
|
{
|
||||||
|
if (!isOpen()) {
|
||||||
|
qWarning("QtLockedFile::lock(): file is not opened");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == NoLock)
|
||||||
|
return unlock();
|
||||||
|
|
||||||
|
if (mode == m_lock_mode)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m_lock_mode != NoLock)
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!waitMutex(wmutex, block))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mode == ReadLock) {
|
||||||
|
int idx = 0;
|
||||||
|
for (; idx < MAX_READERS; idx++) {
|
||||||
|
rmutex = getMutexHandle(idx, false);
|
||||||
|
if (!rmutex || waitMutex(rmutex, false))
|
||||||
|
break;
|
||||||
|
CloseHandle(rmutex);
|
||||||
|
}
|
||||||
|
bool ok = true;
|
||||||
|
if (idx >= MAX_READERS) {
|
||||||
|
qWarning("QtLockedFile::lock(): too many readers");
|
||||||
|
rmutex = 0;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
else if (!rmutex) {
|
||||||
|
rmutex = getMutexHandle(idx, true);
|
||||||
|
if (!rmutex || !waitMutex(rmutex, false))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
if (!ok && rmutex) {
|
||||||
|
CloseHandle(rmutex);
|
||||||
|
rmutex = 0;
|
||||||
|
}
|
||||||
|
ReleaseMutex(wmutex);
|
||||||
|
if (!ok)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Q_ASSERT(rmutexes.isEmpty());
|
||||||
|
for (int i = 0; i < MAX_READERS; i++) {
|
||||||
|
Qt::HANDLE mutex = getMutexHandle(i, false);
|
||||||
|
if (mutex)
|
||||||
|
rmutexes.append(mutex);
|
||||||
|
}
|
||||||
|
if (rmutexes.size()) {
|
||||||
|
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
|
||||||
|
TRUE, block ? INFINITE : 0);
|
||||||
|
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
|
||||||
|
if (res != WAIT_TIMEOUT)
|
||||||
|
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
|
||||||
|
m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lock_mode = mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtLockedFile::unlock()
|
||||||
|
{
|
||||||
|
if (!isOpen()) {
|
||||||
|
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLocked())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m_lock_mode == ReadLock) {
|
||||||
|
ReleaseMutex(rmutex);
|
||||||
|
CloseHandle(rmutex);
|
||||||
|
rmutex = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach(Qt::HANDLE mutex, rmutexes) {
|
||||||
|
ReleaseMutex(mutex);
|
||||||
|
CloseHandle(mutex);
|
||||||
|
}
|
||||||
|
rmutexes.clear();
|
||||||
|
ReleaseMutex(wmutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lock_mode = QtLockedFile::NoLock;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtLockedFile::~QtLockedFile()
|
||||||
|
{
|
||||||
|
if (isOpen())
|
||||||
|
unlock();
|
||||||
|
if (wmutex)
|
||||||
|
CloseHandle(wmutex);
|
||||||
|
}
|
|
@ -0,0 +1,356 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "qtsingleapplication.h"
|
||||||
|
#include "qtlocalpeer.h"
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QtSingleApplication qtsingleapplication.h
|
||||||
|
\brief The QtSingleApplication class provides an API to detect and
|
||||||
|
communicate with running instances of an application.
|
||||||
|
|
||||||
|
This class allows you to create applications where only one
|
||||||
|
instance should be running at a time. I.e., if the user tries to
|
||||||
|
launch another instance, the already running instance will be
|
||||||
|
activated instead. Another usecase is a client-server system,
|
||||||
|
where the first started instance will assume the role of server,
|
||||||
|
and the later instances will act as clients of that server.
|
||||||
|
|
||||||
|
By default, the full path of the executable file is used to
|
||||||
|
determine whether two processes are instances of the same
|
||||||
|
application. You can also provide an explicit identifier string
|
||||||
|
that will be compared instead.
|
||||||
|
|
||||||
|
The application should create the QtSingleApplication object early
|
||||||
|
in the startup phase, and call isRunning() to find out if another
|
||||||
|
instance of this application is already running. If isRunning()
|
||||||
|
returns false, it means that no other instance is running, and
|
||||||
|
this instance has assumed the role as the running instance. In
|
||||||
|
this case, the application should continue with the initialization
|
||||||
|
of the application user interface before entering the event loop
|
||||||
|
with exec(), as normal.
|
||||||
|
|
||||||
|
The messageReceived() signal will be emitted when the running
|
||||||
|
application receives messages from another instance of the same
|
||||||
|
application. When a message is received it might be helpful to the
|
||||||
|
user to raise the application so that it becomes visible. To
|
||||||
|
facilitate this, QtSingleApplication provides the
|
||||||
|
setActivationWindow() function and the activateWindow() slot.
|
||||||
|
|
||||||
|
If isRunning() returns true, another instance is already
|
||||||
|
running. It may be alerted to the fact that another instance has
|
||||||
|
started by using the sendMessage() function. Also data such as
|
||||||
|
startup parameters (e.g. the name of the file the user wanted this
|
||||||
|
new instance to open) can be passed to the running instance with
|
||||||
|
this function. Then, the application should terminate (or enter
|
||||||
|
client mode).
|
||||||
|
|
||||||
|
If isRunning() returns true, but sendMessage() fails, that is an
|
||||||
|
indication that the running instance is frozen.
|
||||||
|
|
||||||
|
Here's an example that shows how to convert an existing
|
||||||
|
application to use QtSingleApplication. It is very simple and does
|
||||||
|
not make use of all QtSingleApplication's functionality (see the
|
||||||
|
examples for that).
|
||||||
|
|
||||||
|
\code
|
||||||
|
// Original
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
MyMainWidget mmw;
|
||||||
|
mmw.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single instance
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QtSingleApplication app(argc, argv);
|
||||||
|
|
||||||
|
if (app.isRunning())
|
||||||
|
return !app.sendMessage(someDataString);
|
||||||
|
|
||||||
|
MyMainWidget mmw;
|
||||||
|
app.setActivationWindow(&mmw);
|
||||||
|
mmw.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Once this QtSingleApplication instance is destroyed (normally when
|
||||||
|
the process exits or crashes), when the user next attempts to run the
|
||||||
|
application this instance will not, of course, be encountered. The
|
||||||
|
next instance to call isRunning() or sendMessage() will assume the
|
||||||
|
role as the new running instance.
|
||||||
|
|
||||||
|
For console (non-GUI) applications, QtSingleCoreApplication may be
|
||||||
|
used instead of this class, to avoid the dependency on the QtGui
|
||||||
|
library.
|
||||||
|
|
||||||
|
\sa QtSingleCoreApplication
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void QtSingleApplication::sysInit(const QString &appId)
|
||||||
|
{
|
||||||
|
actWin = 0;
|
||||||
|
peer = new QtLocalPeer(this, appId);
|
||||||
|
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QtSingleApplication object. The application identifier
|
||||||
|
will be QCoreApplication::applicationFilePath(). \a argc, \a
|
||||||
|
argv, and \a GUIenabled are passed on to the QAppliation constructor.
|
||||||
|
|
||||||
|
If you are creating a console application (i.e. setting \a
|
||||||
|
GUIenabled to false), you may consider using
|
||||||
|
QtSingleCoreApplication instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
|
||||||
|
: QApplication(argc, argv, GUIenabled)
|
||||||
|
{
|
||||||
|
sysInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QtSingleApplication object with the application
|
||||||
|
identifier \a appId. \a argc and \a argv are passed on to the
|
||||||
|
QAppliation constructor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
|
||||||
|
: QApplication(argc, argv),
|
||||||
|
peer(nullptr)
|
||||||
|
{
|
||||||
|
sysInit(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtSingleApplication::~QtSingleApplication()
|
||||||
|
{
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
delete peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QtSingleApplication object. The application identifier
|
||||||
|
will be QCoreApplication::applicationFilePath(). \a argc, \a
|
||||||
|
argv, and \a type are passed on to the QAppliation constructor.
|
||||||
|
*/
|
||||||
|
QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
|
||||||
|
: QApplication(argc, argv, type)
|
||||||
|
{
|
||||||
|
sysInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# if defined(Q_WS_X11)
|
||||||
|
/*!
|
||||||
|
Special constructor for X11, ref. the documentation of
|
||||||
|
QApplication's corresponding constructor. The application identifier
|
||||||
|
will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
|
||||||
|
and \a cmap are passed on to the QApplication constructor.
|
||||||
|
*/
|
||||||
|
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||||
|
: QApplication(dpy, visual, cmap)
|
||||||
|
{
|
||||||
|
sysInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Special constructor for X11, ref. the documentation of
|
||||||
|
QApplication's corresponding constructor. The application identifier
|
||||||
|
will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
|
||||||
|
argv, \a visual, and \a cmap are passed on to the QApplication
|
||||||
|
constructor.
|
||||||
|
*/
|
||||||
|
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||||
|
: QApplication(dpy, argc, argv, visual, cmap)
|
||||||
|
{
|
||||||
|
sysInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Special constructor for X11, ref. the documentation of
|
||||||
|
QApplication's corresponding constructor. The application identifier
|
||||||
|
will be \a appId. \a dpy, \a argc, \a
|
||||||
|
argv, \a visual, and \a cmap are passed on to the QApplication
|
||||||
|
constructor.
|
||||||
|
*/
|
||||||
|
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||||
|
: QApplication(dpy, argc, argv, visual, cmap)
|
||||||
|
{
|
||||||
|
sysInit(appId);
|
||||||
|
}
|
||||||
|
# endif // Q_WS_X11
|
||||||
|
#endif // QT_VERSION < 0x050000
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if another instance of this application is running;
|
||||||
|
otherwise false.
|
||||||
|
|
||||||
|
This function does not find instances of this application that are
|
||||||
|
being run by a different user (on Windows: that are running in
|
||||||
|
another session).
|
||||||
|
|
||||||
|
\sa sendMessage()
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QtSingleApplication::isRunning()
|
||||||
|
{
|
||||||
|
return peer->isClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tries to send the text \a message to the currently running
|
||||||
|
instance. The QtSingleApplication object in the running instance
|
||||||
|
will emit the messageReceived() signal when it receives the
|
||||||
|
message.
|
||||||
|
|
||||||
|
This function returns true if the message has been sent to, and
|
||||||
|
processed by, the current instance. If there is no instance
|
||||||
|
currently running, or if the running instance fails to process the
|
||||||
|
message within \a timeout milliseconds, this function return false.
|
||||||
|
|
||||||
|
\sa isRunning(), messageReceived()
|
||||||
|
*/
|
||||||
|
bool QtSingleApplication::sendMessage(const QString &message, int timeout)
|
||||||
|
{
|
||||||
|
return peer->sendMessage(message, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the application identifier. Two processes with the same
|
||||||
|
identifier will be regarded as instances of the same application.
|
||||||
|
*/
|
||||||
|
QString QtSingleApplication::id() const
|
||||||
|
{
|
||||||
|
return peer->applicationId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the activation window of this application to \a aw. The
|
||||||
|
activation window is the widget that will be activated by
|
||||||
|
activateWindow(). This is typically the application's main window.
|
||||||
|
|
||||||
|
If \a activateOnMessage is true (the default), the window will be
|
||||||
|
activated automatically every time a message is received, just prior
|
||||||
|
to the messageReceived() signal being emitted.
|
||||||
|
|
||||||
|
\sa activateWindow(), messageReceived()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
|
||||||
|
{
|
||||||
|
actWin = aw;
|
||||||
|
if (activateOnMessage)
|
||||||
|
connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
|
||||||
|
else
|
||||||
|
disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the applications activation window if one has been set by
|
||||||
|
calling setActivationWindow(), otherwise returns 0.
|
||||||
|
|
||||||
|
\sa setActivationWindow()
|
||||||
|
*/
|
||||||
|
QWidget* QtSingleApplication::activationWindow() const
|
||||||
|
{
|
||||||
|
return actWin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
De-minimizes, raises, and activates this application's activation window.
|
||||||
|
This function does nothing if no activation window has been set.
|
||||||
|
|
||||||
|
This is a convenience function to show the user that this
|
||||||
|
application instance has been activated when he has tried to start
|
||||||
|
another instance.
|
||||||
|
|
||||||
|
This function should typically be called in response to the
|
||||||
|
messageReceived() signal. By default, that will happen
|
||||||
|
automatically, if an activation window has been set.
|
||||||
|
|
||||||
|
\sa setActivationWindow(), messageReceived(), initialize()
|
||||||
|
*/
|
||||||
|
void QtSingleApplication::activateWindow()
|
||||||
|
{
|
||||||
|
if (actWin) {
|
||||||
|
actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
|
||||||
|
actWin->raise();
|
||||||
|
actWin->activateWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QtSingleApplication::messageReceived(const QString& message)
|
||||||
|
|
||||||
|
This signal is emitted when the current instance receives a \a
|
||||||
|
message from another instance of this application.
|
||||||
|
|
||||||
|
\sa sendMessage(), setActivationWindow(), activateWindow()
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QtSingleApplication::initialize(bool dummy = true)
|
||||||
|
|
||||||
|
\obsolete
|
||||||
|
*/
|
|
@ -0,0 +1,107 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTSINGLEAPPLICATION_H
|
||||||
|
#define QTSINGLEAPPLICATION_H
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
class QtLocalPeer;
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
|
||||||
|
# define QT_QTSINGLEAPPLICATION_EXPORT
|
||||||
|
# elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
|
||||||
|
# if defined(QT_QTSINGLEAPPLICATION_EXPORT)
|
||||||
|
# undef QT_QTSINGLEAPPLICATION_EXPORT
|
||||||
|
# endif
|
||||||
|
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport)
|
||||||
|
# elif defined(QT_QTSINGLEAPPLICATION_EXPORT)
|
||||||
|
# undef QT_QTSINGLEAPPLICATION_EXPORT
|
||||||
|
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define QT_QTSINGLEAPPLICATION_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
|
||||||
|
QtSingleApplication(const QString &id, int &argc, char **argv);
|
||||||
|
virtual ~QtSingleApplication();
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
QtSingleApplication(int &argc, char **argv, Type type);
|
||||||
|
# if defined(Q_WS_X11)
|
||||||
|
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||||
|
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
|
||||||
|
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||||
|
# endif // Q_WS_X11
|
||||||
|
#endif // QT_VERSION < 0x050000
|
||||||
|
|
||||||
|
bool isRunning();
|
||||||
|
QString id() const;
|
||||||
|
|
||||||
|
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
|
||||||
|
QWidget* activationWindow() const;
|
||||||
|
|
||||||
|
// Obsolete:
|
||||||
|
void initialize(bool dummy = true)
|
||||||
|
{ isRunning(); Q_UNUSED(dummy) }
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
bool sendMessage(const QString &message, int timeout = 5000);
|
||||||
|
void activateWindow();
|
||||||
|
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void messageReceived(const QString &message);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sysInit(const QString &appId = QString());
|
||||||
|
QtLocalPeer *peer;
|
||||||
|
QWidget *actWin;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTSINGLEAPPLICATION_H
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include(../common.pri)
|
||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
DEPENDPATH += $$PWD
|
||||||
|
QT *= network
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets
|
||||||
|
|
||||||
|
qtsingleapplication-uselib:!qtsingleapplication-buildlib {
|
||||||
|
LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME
|
||||||
|
} else {
|
||||||
|
SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp
|
||||||
|
HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h
|
||||||
|
}
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT
|
||||||
|
else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "qtsinglecoreapplication.h"
|
||||||
|
#include "qtlocalpeer.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QtSingleCoreApplication qtsinglecoreapplication.h
|
||||||
|
\brief A variant of the QtSingleApplication class for non-GUI applications.
|
||||||
|
|
||||||
|
This class is a variant of QtSingleApplication suited for use in
|
||||||
|
console (non-GUI) applications. It is an extension of
|
||||||
|
QCoreApplication (instead of QApplication). It does not require
|
||||||
|
the QtGui library.
|
||||||
|
|
||||||
|
The API and usage is identical to QtSingleApplication, except that
|
||||||
|
functions relating to the "activation window" are not present, for
|
||||||
|
obvious reasons. Please refer to the QtSingleApplication
|
||||||
|
documentation for explanation of the usage.
|
||||||
|
|
||||||
|
A QtSingleCoreApplication instance can communicate to a
|
||||||
|
QtSingleApplication instance if they share the same application
|
||||||
|
id. Hence, this class can be used to create a light-weight
|
||||||
|
command-line tool that sends commands to a GUI application.
|
||||||
|
|
||||||
|
\sa QtSingleApplication
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QtSingleCoreApplication object. The application identifier
|
||||||
|
will be QCoreApplication::applicationFilePath(). \a argc and \a
|
||||||
|
argv are passed on to the QCoreAppliation constructor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
|
||||||
|
: QCoreApplication(argc, argv)
|
||||||
|
{
|
||||||
|
peer = new QtLocalPeer(this);
|
||||||
|
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QtSingleCoreApplication object with the application
|
||||||
|
identifier \a appId. \a argc and \a argv are passed on to the
|
||||||
|
QCoreAppliation constructor.
|
||||||
|
*/
|
||||||
|
QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv)
|
||||||
|
: QCoreApplication(argc, argv)
|
||||||
|
{
|
||||||
|
peer = new QtLocalPeer(this, appId);
|
||||||
|
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if another instance of this application is running;
|
||||||
|
otherwise false.
|
||||||
|
|
||||||
|
This function does not find instances of this application that are
|
||||||
|
being run by a different user (on Windows: that are running in
|
||||||
|
another session).
|
||||||
|
|
||||||
|
\sa sendMessage()
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QtSingleCoreApplication::isRunning()
|
||||||
|
{
|
||||||
|
return peer->isClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tries to send the text \a message to the currently running
|
||||||
|
instance. The QtSingleCoreApplication object in the running instance
|
||||||
|
will emit the messageReceived() signal when it receives the
|
||||||
|
message.
|
||||||
|
|
||||||
|
This function returns true if the message has been sent to, and
|
||||||
|
processed by, the current instance. If there is no instance
|
||||||
|
currently running, or if the running instance fails to process the
|
||||||
|
message within \a timeout milliseconds, this function return false.
|
||||||
|
|
||||||
|
\sa isRunning(), messageReceived()
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout)
|
||||||
|
{
|
||||||
|
return peer->sendMessage(message, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the application identifier. Two processes with the same
|
||||||
|
identifier will be regarded as instances of the same application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QString QtSingleCoreApplication::id() const
|
||||||
|
{
|
||||||
|
return peer->applicationId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QtSingleCoreApplication::messageReceived(const QString& message)
|
||||||
|
|
||||||
|
This signal is emitted when the current instance receives a \a
|
||||||
|
message from another instance of this application.
|
||||||
|
|
||||||
|
\sa sendMessage()
|
||||||
|
*/
|
|
@ -0,0 +1,71 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Solutions component.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||||
|
** of its contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTSINGLECOREAPPLICATION_H
|
||||||
|
#define QTSINGLECOREAPPLICATION_H
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
class QtLocalPeer;
|
||||||
|
|
||||||
|
class QtSingleCoreApplication : public QCoreApplication
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QtSingleCoreApplication(int &argc, char **argv);
|
||||||
|
QtSingleCoreApplication(const QString &id, int &argc, char **argv);
|
||||||
|
|
||||||
|
bool isRunning();
|
||||||
|
QString id() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
bool sendMessage(const QString &message, int timeout = 5000);
|
||||||
|
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void messageReceived(const QString &message);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
QtLocalPeer* peer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTSINGLECOREAPPLICATION_H
|
|
@ -0,0 +1,10 @@
|
||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
DEPENDPATH += $$PWD
|
||||||
|
HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h
|
||||||
|
SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp
|
||||||
|
|
||||||
|
QT *= network
|
||||||
|
|
||||||
|
win32:contains(TEMPLATE, lib):contains(CONFIG, shared) {
|
||||||
|
DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport)
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "datafetcher.h"
|
||||||
|
#include "globalparameters.h"
|
||||||
|
|
||||||
|
DataFetcher::DataFetcher()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DataFetcher::~DataFetcher()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataFetcher::Fetch(TableData& tbl_data)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataFetcher::VerifyStatus()
|
||||||
|
{
|
||||||
|
return STATUS_NORMAL;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef DATAFETCHER_H
|
||||||
|
#define DATAFETCHER_H
|
||||||
|
|
||||||
|
#include "globalparameters.h"
|
||||||
|
|
||||||
|
class DataFetcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DataFetcher();
|
||||||
|
virtual ~DataFetcher();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool Fetch(TableData& tbl_data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int VerifyStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DATAFETCHER_H
|
|
@ -0,0 +1,202 @@
|
||||||
|
#include "devicepropertypage.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
#include "globalparameters.h"
|
||||||
|
#include "mytablemodel.h"
|
||||||
|
|
||||||
|
DevicePropertyPage::DevicePropertyPage(QWidget *parent) :
|
||||||
|
QWidget(parent),m_pTableView(nullptr),m_pButton(nullptr)
|
||||||
|
{
|
||||||
|
InitializeTable();
|
||||||
|
|
||||||
|
m_pTimer = new QTimer(this);
|
||||||
|
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(handleTimeout()));
|
||||||
|
//m_pTimer->start(AppData::getInstance()->nTimeOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePropertyPage::~DevicePropertyPage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::handleTimeout()
|
||||||
|
{
|
||||||
|
if(m_pTimer->isActive())
|
||||||
|
{
|
||||||
|
m_pTimer->stop();
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
|
||||||
|
int nInterval = 5000;
|
||||||
|
m_pTimer->start(nInterval*1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::InitializeTableView(MyTableModel *model, QTableView *tableView)
|
||||||
|
{
|
||||||
|
//设置tableview的model
|
||||||
|
model->setHeadData(AppData::getInstance()->lstDataTableHeaderText);
|
||||||
|
tableView->setModel(model);
|
||||||
|
|
||||||
|
QHeaderView* pHeaderView = tableView->horizontalHeader();
|
||||||
|
//pHeaderView->setStyleSheet("QHeaderView::section {color: black;padding-left: 4px;border: 1px solid #6c6c6c;}");
|
||||||
|
pHeaderView->setStyleSheet("QHeaderView::section{background:lightgray;}");
|
||||||
|
|
||||||
|
// pHeaderView->setSectionResizeMode(QHeaderView::Stretch); //Stretch
|
||||||
|
|
||||||
|
pHeaderView->setHidden(false); //false 显示行号列 true Hide
|
||||||
|
|
||||||
|
//pHeaderView->setVisible(true);
|
||||||
|
//pHeaderView->setFixedHeight(40);
|
||||||
|
|
||||||
|
//点击表时不对表头行光亮(获取焦点)
|
||||||
|
pHeaderView->setHighlightSections(false);
|
||||||
|
// pHeaderView->setDefaultSectionSize(200);
|
||||||
|
|
||||||
|
// //设置表头字体加粗
|
||||||
|
// QFont font = pHeaderView->font();
|
||||||
|
// font.setBold(true);
|
||||||
|
// pHeaderView->setFont(font);
|
||||||
|
|
||||||
|
//设置表头字体
|
||||||
|
pHeaderView->setFont(QFont("Arial", 12));
|
||||||
|
|
||||||
|
// 设置表头列宽自动调整
|
||||||
|
for (int i = 0; i < model->columnCount(); ++i)
|
||||||
|
{
|
||||||
|
pHeaderView->setSectionResizeMode(i, QHeaderView::Interactive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 允许用户通过拖动表头边缘调整列宽
|
||||||
|
//pHeaderView->setSectionResizeMode(QHeaderView::Interactive);
|
||||||
|
|
||||||
|
tableView->verticalHeader()->setDefaultSectionSize(30); //行高
|
||||||
|
|
||||||
|
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
|
tableView->setAlternatingRowColors(true);
|
||||||
|
tableView->setTextElideMode(Qt::ElideMiddle);
|
||||||
|
|
||||||
|
|
||||||
|
//所有单元格的字体 设置成一样
|
||||||
|
tableView->setFont(QFont("Arial", 9));
|
||||||
|
|
||||||
|
//设置表格数据区内的所有单元格都不允许编辑
|
||||||
|
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
//设置列宽
|
||||||
|
int base = 120; //w / (model->columnCount()-1);
|
||||||
|
tableView->setColumnWidth(0,base-30);
|
||||||
|
tableView->setColumnWidth(1,base*3+40);
|
||||||
|
tableView->setColumnWidth(2,base);
|
||||||
|
tableView->setColumnWidth(3,base-40);
|
||||||
|
tableView->setColumnWidth(4,base+50);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tableView->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::InitializeTable()
|
||||||
|
{
|
||||||
|
m_myModel = new MyTableModel(this);
|
||||||
|
m_myModel->setHeadData(AppData::getInstance()->lstDataTableHeaderText);
|
||||||
|
|
||||||
|
m_pTableView = new QTableView(this);
|
||||||
|
m_pButton = new QPushButton(tr("Refresh"), this);
|
||||||
|
|
||||||
|
// 创建主布局
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
InitializeTableView(m_myModel,m_pTableView);
|
||||||
|
|
||||||
|
mainLayout->addWidget(m_pTableView);
|
||||||
|
|
||||||
|
// 创建一个水平布局来包含按钮
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->addStretch(); // 让按钮保持在右侧
|
||||||
|
buttonLayout->addWidget(m_pButton);
|
||||||
|
buttonLayout->setContentsMargins(0, 0, 0, 0); // 取消按钮的边距
|
||||||
|
|
||||||
|
// 将表格视图和按钮布局添加到主布局
|
||||||
|
mainLayout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0); // 取消主布局的边距
|
||||||
|
mainLayout->setSpacing(10); // 取消布局间的间距
|
||||||
|
|
||||||
|
// 设置固定大小和位置的按钮
|
||||||
|
m_pButton->setFixedSize(100, 30); // 设置按钮的固定大小
|
||||||
|
|
||||||
|
// 连接信号和槽
|
||||||
|
connect(m_pTableView, &QTableView::doubleClicked, this, &DevicePropertyPage::onTableViewDoubleClicked);
|
||||||
|
connect(m_pButton, &QPushButton::clicked, this, &DevicePropertyPage::onButtonClicked);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::Refresh()
|
||||||
|
{
|
||||||
|
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||||
|
TableData tbl_data;
|
||||||
|
if (Fetch(tbl_data))
|
||||||
|
{
|
||||||
|
m_myModel->setModelData(tbl_data);
|
||||||
|
}
|
||||||
|
QGuiApplication::restoreOverrideCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::setBaseType(unsigned int base, unsigned int mask)
|
||||||
|
{
|
||||||
|
filterBaseType = base;
|
||||||
|
mask_code = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DevicePropertyPage::onButtonClicked()
|
||||||
|
{
|
||||||
|
m_pTimer->stop();
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DevicePropertyPage::onTableViewDoubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
//QAbstractItemModel *model=ui->tableView->model();
|
||||||
|
MyTableModel *model = (MyTableModel *)m_pTableView->model();
|
||||||
|
QModelIndex mindex = model->index(index.row(),7); //index.row()为算选择的行号。7为所选中行的第8列。。
|
||||||
|
QVariant datatemp=model->data(mindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePropertyPage::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
#if 0
|
||||||
|
// 获取当前QTableView的总宽度
|
||||||
|
int currentTotalWidth = m_pTableView->viewport()->width();
|
||||||
|
|
||||||
|
// 计算总的初始宽度
|
||||||
|
int initialTotalWidth = 0;
|
||||||
|
for (int width : columnWidths) {
|
||||||
|
initialTotalWidth += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算比例因子
|
||||||
|
double scaleFactor = static_cast<double>(currentTotalWidth) / initialTotalWidth;
|
||||||
|
|
||||||
|
// 重新设置列宽,按比例调整
|
||||||
|
for (int i = 0; i < columnWidths.size(); ++i) {
|
||||||
|
int newWidth = static_cast<int>(columnWidths[i] * scaleFactor);
|
||||||
|
m_pTableView->setColumnWidth(i, newWidth);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef DEVICEPROPERTYPAGE_H
|
||||||
|
#define DEVICEPROPERTYPAGE_H
|
||||||
|
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "datafetcher.h"
|
||||||
|
|
||||||
|
class MyTableModel;
|
||||||
|
class QTimer;
|
||||||
|
class QTableView;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
|
class DevicePropertyPage : public QWidget,public DataFetcher
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DevicePropertyPage(QWidget *parent = nullptr);
|
||||||
|
~DevicePropertyPage();
|
||||||
|
void setBaseType(unsigned int base,unsigned int mask);
|
||||||
|
void InitializeTable();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void handleTimeout(); //超时处理函数
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer *m_pTimer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MyTableModel* m_myModel;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Refresh();
|
||||||
|
void InitializeTableView(MyTableModel *model, QTableView *tableView);
|
||||||
|
|
||||||
|
// 重写resizeEvent,当QTableView窗口大小变化时按比例调整列宽
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onButtonClicked();
|
||||||
|
|
||||||
|
void onTableViewDoubleClicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int filterBaseType;
|
||||||
|
unsigned int mask_code;
|
||||||
|
QTableView* m_pTableView;
|
||||||
|
QPushButton* m_pButton;
|
||||||
|
QVector<int> columnWidths; // 存储初始列宽
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEVICEPROPERTYPAGE_H
|
|
@ -0,0 +1,69 @@
|
||||||
|
QT += core gui
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
CONFIG += c++17
|
||||||
|
|
||||||
|
QMAKE_LFLAGS += /ignore:4099
|
||||||
|
QMAKE_CXXFLAGS_WARN_ON += -wd4100
|
||||||
|
|
||||||
|
include("$$PWD/QtSingleApplication/qtsingleapplication.pri")
|
||||||
|
|
||||||
|
DEFINES += HAVE_CONFIG_H
|
||||||
|
DEFINES += _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../../SDK/include
|
||||||
|
|
||||||
|
CONFIG(debug, debug|debug) {
|
||||||
|
INCLUDEPATH += "D:/Visual Leak Detector/include"
|
||||||
|
win32:LIBS += "D:/Visual Leak Detector/lib/Win64/vld.lib"
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG(debug, debug|release) {
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\libdesd.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\OpenSSL_VC\libcrypto64MDd.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\OpenSSL_VC\libssl64MDd.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\hv.lib
|
||||||
|
win32:LIBS += Ws2_32.lib
|
||||||
|
}else{
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\libdes.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\OpenSSL_VC\libcrypto64MD.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\OpenSSL_VC\libssl64MD.lib
|
||||||
|
win32:LIBS += $$PWD/..\..\SDK\lib\hvd.lib
|
||||||
|
win32:LIBS += Ws2_32.lib
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# You can make your code fail to compile if it uses deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
datafetcher.cpp \
|
||||||
|
devicepropertypage.cpp \
|
||||||
|
globalparameters.cpp \
|
||||||
|
main.cpp \
|
||||||
|
maindialog.cpp \
|
||||||
|
mainwindow.cpp \
|
||||||
|
mytablemodel.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
datafetcher.h \
|
||||||
|
devicepropertypage.h \
|
||||||
|
globalparameters.h \
|
||||||
|
maindialog.h \
|
||||||
|
mainwindow.h \
|
||||||
|
mytablemodel.h \
|
||||||
|
singleton.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
maindialog.ui \
|
||||||
|
mainwindow.ui
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
emscfgres.qrc
|
|
@ -0,0 +1,16 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>images/emscfg-main.ico</file>
|
||||||
|
<file>images/hj-net.png</file>
|
||||||
|
<file>images/icon.png</file>
|
||||||
|
<file>images/PageAir.png</file>
|
||||||
|
<file>images/PageBattery.png</file>
|
||||||
|
<file>images/PageFan.png</file>
|
||||||
|
<file>images/PagePower.png</file>
|
||||||
|
<file>images/PagePV.png</file>
|
||||||
|
<file>images/PageSensor.png</file>
|
||||||
|
<file>images/PageSetting.png</file>
|
||||||
|
<file>images/PageSwitch.png</file>
|
||||||
|
<file>images/PageUps.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QString>
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCursor>
|
||||||
|
|
||||||
|
#include "globalparameters.h"
|
||||||
|
#include "mytablemodel.h"
|
||||||
|
|
||||||
|
AppData::~AppData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AppData::AppData(token)
|
||||||
|
{
|
||||||
|
lstDataTableHeaderText << ("Status")
|
||||||
|
<< ("Parameter")
|
||||||
|
<< ("Value")
|
||||||
|
<< ("Unit")
|
||||||
|
<< ("Time");
|
||||||
|
|
||||||
|
nTimeOut = 5000;
|
||||||
|
qsDestinationIp = "127.0.0.1";
|
||||||
|
|
||||||
|
qsLastErrorString = "OK";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AppCommon::AppCommon(token)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AppCommon::~AppCommon()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppCommon::InitializeTableView(MyTableModel *model, QTableView *tableView)
|
||||||
|
{
|
||||||
|
//设置tableview的model
|
||||||
|
model->setHeadData(AppData::getInstance()->lstDataTableHeaderText);
|
||||||
|
tableView->setModel(model);
|
||||||
|
|
||||||
|
QHeaderView* pHeaderView = tableView->horizontalHeader();
|
||||||
|
//pHeaderView->setStyleSheet("QHeaderView::section {color: black;padding-left: 4px;border: 1px solid #6c6c6c;}");
|
||||||
|
pHeaderView->setStyleSheet("QHeaderView::section{background:lightgray;}");
|
||||||
|
|
||||||
|
// pHeaderView->setSectionResizeMode(QHeaderView::Stretch); //Stretch
|
||||||
|
|
||||||
|
pHeaderView->setHidden(false); //false 显示行号列 true Hide
|
||||||
|
//pHeaderView->setVisible(true);
|
||||||
|
//pHeaderView->setFixedHeight(40);
|
||||||
|
|
||||||
|
//点击表时不对表头行光亮(获取焦点)
|
||||||
|
pHeaderView->setHighlightSections(false);
|
||||||
|
//pHeaderView->setDefaultSectionSize(35);
|
||||||
|
|
||||||
|
// //设置表头字体加粗
|
||||||
|
// QFont font = pHeaderView->font();
|
||||||
|
// font.setBold(true);
|
||||||
|
// pHeaderView->setFont(font);
|
||||||
|
|
||||||
|
//设置表头字体
|
||||||
|
pHeaderView->setFont(QFont("Arial", 12));
|
||||||
|
|
||||||
|
// 设置表头列宽自动调整
|
||||||
|
for (int i = 0; i < model->columnCount(); ++i) {
|
||||||
|
pHeaderView->setSectionResizeMode(i, QHeaderView::Stretch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 允许用户通过拖动表头边缘调整列宽
|
||||||
|
pHeaderView->setSectionResizeMode(QHeaderView::Interactive);
|
||||||
|
|
||||||
|
tableView->verticalHeader()->setDefaultSectionSize(30); //行高
|
||||||
|
|
||||||
|
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
|
tableView->setAlternatingRowColors(true);
|
||||||
|
tableView->setTextElideMode(Qt::ElideMiddle);
|
||||||
|
|
||||||
|
|
||||||
|
//所有单元格的字体 设置成一样
|
||||||
|
tableView->setFont(QFont("Arial", 9));
|
||||||
|
|
||||||
|
//设置表格数据区内的所有单元格都不允许编辑
|
||||||
|
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//设置列宽
|
||||||
|
int w = tableView->width();
|
||||||
|
int base = w /(AppData::getInstance()->lstDataTableHeaderText.count()-1);
|
||||||
|
tableView->setColumnWidth(0,base-45);
|
||||||
|
tableView->setColumnWidth(1,base-20);
|
||||||
|
tableView->setColumnWidth(2,base+30);
|
||||||
|
tableView->setColumnWidth(3,base+10);
|
||||||
|
tableView->setColumnWidth(4,base);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tableView->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaitorCursor::CWaitorCursor()
|
||||||
|
{
|
||||||
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaitorCursor::~CWaitorCursor()
|
||||||
|
{
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef GLOBALPARAMETERS_H
|
||||||
|
#define GLOBALPARAMETERS_H
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
class QAbstractTableModel;
|
||||||
|
class QTableView;
|
||||||
|
class MyTableModel;
|
||||||
|
|
||||||
|
//采集设备参数所处的状态
|
||||||
|
typedef enum _tagSignalStatus
|
||||||
|
{
|
||||||
|
STATUS_NORMAL = 0,
|
||||||
|
STATUS_WARN = 1,
|
||||||
|
STATUS_ERROR = 2,
|
||||||
|
STATUS_INFO = 3,
|
||||||
|
}SignalStatus;
|
||||||
|
|
||||||
|
typedef struct _ModelItem
|
||||||
|
{
|
||||||
|
SignalStatus status;
|
||||||
|
std::string ParameterName;
|
||||||
|
std::string value;
|
||||||
|
std::string unit;
|
||||||
|
std::string sampleTime;
|
||||||
|
}ModelItem;
|
||||||
|
|
||||||
|
typedef QList<ModelItem> TableData;
|
||||||
|
|
||||||
|
class CWaitorCursor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWaitorCursor();
|
||||||
|
~CWaitorCursor();
|
||||||
|
};
|
||||||
|
|
||||||
|
//全局变量
|
||||||
|
class AppData:public Singleton<AppData>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AppData(token);
|
||||||
|
~AppData();
|
||||||
|
AppData(const AppData &other) = delete;
|
||||||
|
AppData& operator=(const AppData &other) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//数据表格的表头
|
||||||
|
QStringList lstDataTableHeaderText;
|
||||||
|
|
||||||
|
//定时刷新间隔
|
||||||
|
int nTimeOut;
|
||||||
|
|
||||||
|
//目标机器IP
|
||||||
|
QString qsDestinationIp;
|
||||||
|
|
||||||
|
//最后的错误信息
|
||||||
|
QString qsLastErrorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//全局通用类
|
||||||
|
class AppCommon:public Singleton<AppCommon>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AppCommon(token);
|
||||||
|
~AppCommon();
|
||||||
|
|
||||||
|
AppCommon(const AppCommon&)=delete;
|
||||||
|
AppCommon& operator =(const AppCommon&)= delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void InitializeTableView(MyTableModel* model,QTableView* tableView);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLOBALPARAMETERS_H
|
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 8.7 KiB |
|
@ -0,0 +1,73 @@
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#include <vld.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include "qtsingleapplication.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QTranslator>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
#include <hv/hv.h>
|
||||||
|
#include <hv/hmain.h>
|
||||||
|
#include <hv/iniparser.h>
|
||||||
|
#include <hv/hloop.h>
|
||||||
|
#include <hv/hsocket.h>
|
||||||
|
#include <hv/hssl.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QString app_unique_name("emsConfigurer_application_name");
|
||||||
|
QtSingleApplication app(app_unique_name,argc, argv);
|
||||||
|
if(app.isRunning())
|
||||||
|
{
|
||||||
|
QMessageBox::information(nullptr, "EMS Configurer", "Another instance is already running.");
|
||||||
|
app.sendMessage("raise_window_noop", 1000); //1s后激活前个实例
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_ctx_init(argc, argv);
|
||||||
|
QString appDir = QCoreApplication::applicationDirPath();
|
||||||
|
std::string logFilePath = (appDir + QString::fromStdString("/emsConfigurer.log")).toStdString();
|
||||||
|
|
||||||
|
hlog_set_file(logFilePath.c_str());
|
||||||
|
hlogi("=========--- Welcome to the Earth ---=========");
|
||||||
|
hlogi("%s version: %s", argv[0], "1.1.0");
|
||||||
|
hlog_fsync();
|
||||||
|
|
||||||
|
QTranslator translator;
|
||||||
|
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||||
|
for (const QString &locale : uiLanguages)
|
||||||
|
{
|
||||||
|
const QString baseName = "emsConfigurer_" + QLocale(locale).name();
|
||||||
|
if (translator.load(":/i18n/" + baseName))
|
||||||
|
{
|
||||||
|
app.installTranslator(&translator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow w;
|
||||||
|
//隐藏(不显示)最大化最小化按钮
|
||||||
|
w.setWindowFlags(w.windowFlags()&~Qt::WindowMinMaxButtonsHint);
|
||||||
|
//w.setWindowFlags(w.windowFlags() | Qt::WindowStaysOnTopHint);
|
||||||
|
|
||||||
|
w.setStyleSheet("{border-radius: 4px;}"); // 定制圆角
|
||||||
|
// ".QLabel{background: gray;}.QTextEdit{background: white;}");
|
||||||
|
|
||||||
|
//获取窗口尺寸并居中
|
||||||
|
QScreen *scr = app.primaryScreen();
|
||||||
|
int scr_w = scr->size().width();
|
||||||
|
int scr_h = scr->size().height();
|
||||||
|
w.move((scr_w - w.width()) / 2, (scr_h - w.height()) / 2);
|
||||||
|
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
int ret = app.exec();
|
||||||
|
hlogi("=========--- I'll be back! ---=========");
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
#include "maindialog.h"
|
||||||
|
#include "ui_maindialog.h"
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
|
#include "devicepropertypage.h"
|
||||||
|
|
||||||
|
MainDialog::MainDialog(QWidget *parent) :
|
||||||
|
QMainWindow (parent),
|
||||||
|
ui(new Ui::MainDialog)
|
||||||
|
{
|
||||||
|
//ui->setupUi(this);
|
||||||
|
|
||||||
|
this->setWindowIcon(QIcon(":/images/icon.png"));
|
||||||
|
|
||||||
|
InitializeUI();
|
||||||
|
|
||||||
|
// Load the window state
|
||||||
|
loadWindowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainDialog::~MainDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::InitializeUI()
|
||||||
|
{
|
||||||
|
// Create central widget and layout
|
||||||
|
this->takeCentralWidget();
|
||||||
|
QWidget *centralWidget = new QWidget(this);
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
|
||||||
|
|
||||||
|
//Create toolbar
|
||||||
|
CreateToolbar();
|
||||||
|
|
||||||
|
// Set up the QListWidget
|
||||||
|
m_pDeviceListWidget = new QListWidget(this);
|
||||||
|
|
||||||
|
m_pDeviceListWidget->setStyleSheet("background-color:transparent");
|
||||||
|
m_pDeviceListWidget->setViewMode(QListView::IconMode);
|
||||||
|
m_pDeviceListWidget->setIconSize(QSize(70, 70));
|
||||||
|
m_pDeviceListWidget->setGridSize(QSize(145, 100)); // item 的大小
|
||||||
|
m_pDeviceListWidget->setMovement(QListView::Static);
|
||||||
|
|
||||||
|
m_pDeviceListWidget->setMaximumWidth(170);
|
||||||
|
m_pDeviceListWidget->setMinimumWidth(170); // Set minimum width
|
||||||
|
|
||||||
|
m_pDeviceListWidget->setResizeMode(QListView::Fixed);
|
||||||
|
|
||||||
|
m_pDeviceListWidget->setSpacing(25);
|
||||||
|
//m_pDeviceListWidget->setUniformItemSizes(true); // 所有的 item 一样大
|
||||||
|
m_pDeviceListWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
|
||||||
|
|
||||||
|
CreateIcon(QIcon(":/images/PagePower.png"),tr("Power"));
|
||||||
|
CreateIcon(QIcon(":/images/PageBattery.png"),tr("Battery"));
|
||||||
|
CreateIcon(QIcon(":/images/PageSwitch.png"),tr("Switch"));
|
||||||
|
CreateIcon(QIcon(":/images/PageAir.png"),tr("Air"));
|
||||||
|
CreateIcon(QIcon(":/images/PageFan.png"),tr("Fan"));
|
||||||
|
CreateIcon(QIcon(":/images/PageSensor.png"),tr("Sensor"));
|
||||||
|
|
||||||
|
// Set up the QStackedWidget
|
||||||
|
CreateTablePage();
|
||||||
|
|
||||||
|
// Set up the QSplitter to manage the resizing of QListWidget and QStackedWidget
|
||||||
|
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
|
||||||
|
splitter->addWidget(m_pDeviceListWidget);
|
||||||
|
splitter->addWidget(m_pDevicestackedWidget);
|
||||||
|
splitter->setSizes(QList<int>({200, 600})); // Set initial sizes (200 for QListWidget, 600 for QStackedWidget)
|
||||||
|
|
||||||
|
// Disable splitter dragging
|
||||||
|
splitter->setChildrenCollapsible(false);
|
||||||
|
|
||||||
|
// 将工具栏添加到主窗口的顶部
|
||||||
|
//addToolBar(Qt::TopToolBarArea, m_pMainToolBar);
|
||||||
|
|
||||||
|
// Set up layout
|
||||||
|
mainLayout->addWidget(m_pMainToolBar);
|
||||||
|
mainLayout->addWidget(splitter);
|
||||||
|
centralWidget->setLayout(mainLayout);
|
||||||
|
|
||||||
|
// Set central widget
|
||||||
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
|
// Set initial size of the dialog
|
||||||
|
setWindowTitle(tr("EMS Configurer "));
|
||||||
|
|
||||||
|
//resize(800, 600);
|
||||||
|
|
||||||
|
setMinimumSize(1024, 768);
|
||||||
|
|
||||||
|
connect(m_pDeviceListWidget, &QListWidget::currentItemChanged, this, &MainDialog::changePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainDialog::CreateToolbar()
|
||||||
|
{
|
||||||
|
m_pMainToolBar = new QToolBar(this);
|
||||||
|
m_pMainToolBar->setIconSize(QSize(48, 48));
|
||||||
|
|
||||||
|
// 创建一个水平布局以容纳图标和占位符
|
||||||
|
QWidget *toolBarWidget = new QWidget(this);
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout(toolBarWidget);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0); // 去除内边距
|
||||||
|
|
||||||
|
// 添加一个弹性空间以推送图标到右侧
|
||||||
|
QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
|
layout->addItem(spacer);
|
||||||
|
|
||||||
|
// Create actions for the toolbar
|
||||||
|
QAction *action1 = new QAction(QIcon(":/images/icon.png"), "Button 1", this);
|
||||||
|
QAction *action2 = new QAction(QIcon(":/images/icon.png"), "Button 2", this);
|
||||||
|
QAction *action3 = new QAction(QIcon(":/images/icon.png"), "About...", this);
|
||||||
|
|
||||||
|
// Add actions to the toolbar
|
||||||
|
m_pMainToolBar->addAction(action1);
|
||||||
|
m_pMainToolBar->addAction(action2);
|
||||||
|
m_pMainToolBar->addAction(action3);
|
||||||
|
|
||||||
|
// 将工具栏的 widget 设置为包含图标和占位符的 widget
|
||||||
|
m_pMainToolBar->addWidget(toolBarWidget);
|
||||||
|
|
||||||
|
// Connect actions to slots
|
||||||
|
connect(action1, &QAction::triggered, this, &MainDialog::onToolButton1Clicked);
|
||||||
|
connect(action2, &QAction::triggered, this, &MainDialog::onToolButton1Clicked);
|
||||||
|
connect(action3, &QAction::triggered, this, &MainDialog::onAboutButtonClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::CreateTablePage()
|
||||||
|
{
|
||||||
|
m_pDevicestackedWidget = new QStackedWidget(this);
|
||||||
|
|
||||||
|
QVBoxLayout *stackedWidgetLayout = new QVBoxLayout(m_pDevicestackedWidget);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
//m_pDevicestackedWidget->setLayout(stackedWidgetLayout);
|
||||||
|
stackedWidgetLayout->addWidget(m_pDevicestackedWidget);
|
||||||
|
|
||||||
|
DevicePropertyPage *page1 = new DevicePropertyPage(m_pDevicestackedWidget);
|
||||||
|
DevicePropertyPage *page2 = new DevicePropertyPage(m_pDevicestackedWidget);
|
||||||
|
|
||||||
|
m_pDevicestackedWidget->addWidget(page1); // Add QTableView as a page
|
||||||
|
m_pDevicestackedWidget->addWidget(page2);
|
||||||
|
|
||||||
|
m_pDevicestackedWidget->addWidget(new QPushButton("Page 3"));
|
||||||
|
m_pDevicestackedWidget->addWidget(new QPushButton("Page 4"));
|
||||||
|
m_pDevicestackedWidget->addWidget(new QPushButton("Page 5"));
|
||||||
|
m_pDevicestackedWidget->addWidget(new QPushButton("Page 6"));
|
||||||
|
#endif
|
||||||
|
// setLayout(stackedWidgetLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::CreateIcon(const QIcon& icon,QString text)
|
||||||
|
{
|
||||||
|
QListWidgetItem *itemButton = new QListWidgetItem(m_pDeviceListWidget);
|
||||||
|
itemButton->setIcon(icon);
|
||||||
|
itemButton->setText(text);
|
||||||
|
itemButton->setTextAlignment(Qt::AlignHCenter);
|
||||||
|
itemButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
|
||||||
|
{
|
||||||
|
if (!current)
|
||||||
|
current = previous;
|
||||||
|
|
||||||
|
m_pDevicestackedWidget->setCurrentIndex(m_pDeviceListWidget->row(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
// Save the window state
|
||||||
|
saveWindowState();
|
||||||
|
QMainWindow::closeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::saveWindowState()
|
||||||
|
{
|
||||||
|
QSettings settings("HJ-NET", "EMSCFG");
|
||||||
|
settings.setValue("geometry", saveGeometry());
|
||||||
|
settings.setValue("windowState", saveState());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::loadWindowState()
|
||||||
|
{
|
||||||
|
QSettings settings("HJ-NET", "EMSCFG");
|
||||||
|
restoreGeometry(settings.value("geometry").toByteArray());
|
||||||
|
restoreState(settings.value("windowState").toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::onToolButton1Clicked()
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, "Button Clicked", "Button 1 was clicked!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::onToolButton2Clicked()
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, "Button Clicked", "Button 2 was clicked!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainDialog::onAboutButtonClicked()
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, "Button Clicked", "About");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef MAINDIALOG_H
|
||||||
|
#define MAINDIALOG_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MainDialog : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainDialog(QWidget *parent = nullptr);
|
||||||
|
~MainDialog();
|
||||||
|
|
||||||
|
void InitializeUI();
|
||||||
|
void loadWindowState();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onToolButton1Clicked();
|
||||||
|
void onToolButton2Clicked();
|
||||||
|
void onAboutButtonClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainDialog *ui;
|
||||||
|
QListWidget *m_pDeviceListWidget;
|
||||||
|
QStackedWidget *m_pDevicestackedWidget;
|
||||||
|
QToolBar *m_pMainToolBar;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void CreateToolbar();
|
||||||
|
void CreateIcon(const QIcon& icon,QString text);
|
||||||
|
void CreateTablePage();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
void saveWindowState();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINDIALOG_H
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainDialog</class>
|
||||||
|
<widget class="QDialog" name="MainDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>867</width>
|
||||||
|
<height>665</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::NoContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionValidator>
|
||||||
|
|
||||||
|
#include "MainDialog.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
, ui(new Ui::MainWindow)
|
||||||
|
, m_pMainDialog(nullptr)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->setWindowIcon(QIcon(":/images/icon.png"));
|
||||||
|
|
||||||
|
QPixmap pixmap(":/images/hj-net.png");
|
||||||
|
pixmap = pixmap.scaled(250, 75, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放
|
||||||
|
ui->label_logo->setPixmap(pixmap);
|
||||||
|
|
||||||
|
QString qsLineEditStyle("QLineEdit { min-height: 20px; min-width: 120px; }");
|
||||||
|
ui->userToken->setStyleSheet(qsLineEditStyle);
|
||||||
|
ui->serverIp->setStyleSheet(qsLineEditStyle);
|
||||||
|
|
||||||
|
QRegularExpression rx("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
|
||||||
|
QRegularExpressionValidator* ipValidator = new QRegularExpressionValidator(rx, this);
|
||||||
|
ui->serverIp->setValidator(ipValidator);
|
||||||
|
setIp("127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
if (m_pMainDialog)
|
||||||
|
{
|
||||||
|
delete m_pMainDialog;
|
||||||
|
m_pMainDialog = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setIp(const QString &ip)
|
||||||
|
{
|
||||||
|
ui->serverIp->setText(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_pb_Logon_clicked()
|
||||||
|
{
|
||||||
|
m_pMainDialog = new MainDialog();
|
||||||
|
m_pMainDialog->show();
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
class MainDialog;
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui { class MainWindow; }
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget *parent = nullptr);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setIp(const QString &ip);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pb_Logon_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
MainDialog* m_pMainDialog;
|
||||||
|
};
|
||||||
|
#endif // MAINWINDOW_H
|
|
@ -0,0 +1,219 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>551</width>
|
||||||
|
<height>352</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::NoContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>EMS Configurer</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>130</x>
|
||||||
|
<y>176</y>
|
||||||
|
<width>61</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Host IP</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>140</x>
|
||||||
|
<y>60</y>
|
||||||
|
<width>231</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>26</pointsize>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configurer</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="serverIp">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>173</y>
|
||||||
|
<width>124</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>370</x>
|
||||||
|
<y>88</y>
|
||||||
|
<width>161</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>for EMU Host</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pb_Test">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>350</x>
|
||||||
|
<y>173</y>
|
||||||
|
<width>51</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Test</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_logo">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>7</x>
|
||||||
|
<y>7</y>
|
||||||
|
<width>261</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>WWW.HJ-NET.COM</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>140</x>
|
||||||
|
<y>280</y>
|
||||||
|
<width>251</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pb_Logon">
|
||||||
|
<property name="text">
|
||||||
|
<string>Logon</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pb_Close">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="userToken">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>233</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::NoContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="inputMethodHints">
|
||||||
|
<set>Qt::ImhHiddenText|Qt::ImhNoAutoUppercase|Qt::ImhNoEditMenu|Qt::ImhNoPredictiveText|Qt::ImhSensitiveData</set>
|
||||||
|
</property>
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>130</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>68</width>
|
||||||
|
<height>30</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Login name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>130</x>
|
||||||
|
<y>233</y>
|
||||||
|
<width>56</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Password</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="userName">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>203</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,151 @@
|
||||||
|
#include <QColor>
|
||||||
|
#include "mytablemodel.h"
|
||||||
|
|
||||||
|
|
||||||
|
MyTableModel::MyTableModel(QObject* parent)
|
||||||
|
:QAbstractTableModel(parent)
|
||||||
|
{
|
||||||
|
for(int i=0;i<100;i++)
|
||||||
|
{
|
||||||
|
ModelItem item;
|
||||||
|
item.status = STATUS_WARN;
|
||||||
|
item.ParameterName= "Visual Leak Detector detected 1 memory leak (84 bytes)";
|
||||||
|
item.sampleTime = "2024-9-10 11:22:33.444";
|
||||||
|
item.unit = "C";
|
||||||
|
item.value = "100";
|
||||||
|
m_modelData.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MyTableModel::rowCount(const QModelIndex & /*parent*/) const
|
||||||
|
{
|
||||||
|
return m_modelData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int MyTableModel::columnCount(const QModelIndex & /*parent*/) const
|
||||||
|
{
|
||||||
|
return AppData::getInstance()->lstDataTableHeaderText.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MyTableModel::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||||
|
{
|
||||||
|
const int row = index.row();
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if (m_modelData.at(row).status == STATUS_NORMAL) return tr("Normal");
|
||||||
|
if (m_modelData.at(row).status == STATUS_INFO) return tr("INFO");
|
||||||
|
if (m_modelData.at(row).status == STATUS_WARN) return tr("WARN");
|
||||||
|
if (m_modelData.at(row).status == STATUS_ERROR) return tr("ERROR");
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
return m_modelData.at(row).ParameterName.c_str();
|
||||||
|
}
|
||||||
|
case 2: return m_modelData.at(row).value.c_str();
|
||||||
|
case 3: return m_modelData.at(row).unit.c_str();
|
||||||
|
case 4: return m_modelData.at(row).sampleTime.c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//对齐处理
|
||||||
|
if (role == Qt::TextAlignmentRole)
|
||||||
|
{
|
||||||
|
//const int row = index.row();
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
return QVariant(Qt::AlignLeft|Qt::AlignVCenter);
|
||||||
|
break;
|
||||||
|
//case 4:
|
||||||
|
// return QVariant(Qt::AlignRight|Qt::AlignVCenter);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
return Qt::AlignCenter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::BackgroundRole)
|
||||||
|
{
|
||||||
|
const int row = index.row();
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 0: //状态
|
||||||
|
case 2: //数值
|
||||||
|
{
|
||||||
|
if (m_modelData.at(row).status == STATUS_WARN)
|
||||||
|
return QVariant(QColor(Qt::yellow));
|
||||||
|
else if (m_modelData.at(row).status == STATUS_ERROR)
|
||||||
|
return QVariant(QColor(Qt::red));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
||||||
|
{
|
||||||
|
if (section < m_headeList.size())
|
||||||
|
{
|
||||||
|
return m_headeList[section];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QAbstractItemModel::headerData(section, orientation, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TableData *MyTableModel::getModelData() const
|
||||||
|
{
|
||||||
|
return &m_modelData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
|
{
|
||||||
|
//beginResetModel();
|
||||||
|
if (!index.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//endResetModel(); //在结束前添加此函数
|
||||||
|
return QAbstractTableModel::setData(index, value, role);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyTableModel::setModelData(TableData data)
|
||||||
|
{
|
||||||
|
//修改数据前后,用beginResetModel()和endResetModel()
|
||||||
|
beginResetModel(); //通过这个告诉我要开始修改model了
|
||||||
|
m_modelData.clear();
|
||||||
|
|
||||||
|
for (int i = 0;i < data.count();++i)
|
||||||
|
{
|
||||||
|
m_modelData.append(data[i]);
|
||||||
|
}
|
||||||
|
endResetModel(); //通过这个告诉我修改model结束了
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyTableModel::clearModelData()
|
||||||
|
{
|
||||||
|
m_modelData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyTableModel::setHeadData(QStringList i_list)
|
||||||
|
{
|
||||||
|
m_headeList=i_list;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#ifndef MYTABLEMODEL_H
|
||||||
|
#define MYTABLEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QString>
|
||||||
|
#include "globalparameters.h"
|
||||||
|
|
||||||
|
class MyTableModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyTableModel(QObject* parent);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||||
|
int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||||
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||||
|
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& index) const Q_DECL_OVERRIDE;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
const TableData *getModelData() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TableData m_modelData;
|
||||||
|
QStringList m_headeList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setHeadData(QStringList i_list);
|
||||||
|
void setModelData(TableData data);
|
||||||
|
void clearModelData();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MYTABLEMODEL_H
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef SINGLETON_H
|
||||||
|
#define SINGLETON_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static T* getInstance() noexcept(std::is_nothrow_constructible<T>::value)
|
||||||
|
{
|
||||||
|
static T instance{token()};
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
virtual ~Singleton() =default;
|
||||||
|
Singleton(const Singleton&)=delete;
|
||||||
|
Singleton& operator =(const Singleton&)=delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct token{}; // helper class
|
||||||
|
Singleton() noexcept=default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SINGLETON_H
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.35130.168
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinDataHubs", "WinDataHubs.vcxproj", "{2192CF4F-DE56-4896-9EA1-4C61B40590A5}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{2192CF4F-DE56-4896-9EA1-4C61B40590A5}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {81B0EBA0-C45B-4F9A-B3E8-4780447CB231}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,167 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{2192cf4f-de56-4896-9ea1-4c61b40590a5}</ProjectGuid>
|
||||||
|
<RootNamespace>WinDataHubs</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(SolutionDir)\..\..\sdk\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>$(SolutionDir)\..\..\sdk\lib;$(LibraryPath)</LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(SolutionDir)\..\..\sdk\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>$(SolutionDir)\..\..\sdk\Lib;$(LibraryPath)</LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>hv.lib;zlibd.lib;mysqlcppconn.lib;libiconvD.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="eventhandler.cpp" />
|
||||||
|
<ClCompile Include="iconv-utils.cpp" />
|
||||||
|
<ClCompile Include="kutilities.cpp" />
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="openjson.cpp" />
|
||||||
|
<ClCompile Include="opmysql.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="eventhandler.h" />
|
||||||
|
<ClInclude Include="frame_define.h" />
|
||||||
|
<ClInclude Include="iconv-utils.h" />
|
||||||
|
<ClInclude Include="kdefine.h" />
|
||||||
|
<ClInclude Include="kutilities.h" />
|
||||||
|
<ClInclude Include="mqtt_msg.h" />
|
||||||
|
<ClInclude Include="openjson.h" />
|
||||||
|
<ClInclude Include="opmysql.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -8,7 +8,8 @@ log_filesize = 16M
|
||||||
# worker_processes = auto # auto = ncpu
|
# worker_processes = auto # auto = ncpu
|
||||||
# worker_processes = auto
|
# worker_processes = auto
|
||||||
worker_processed = 0
|
worker_processed = 0
|
||||||
worker_threads = auto
|
# worker_threads = auto
|
||||||
|
worker_threads = 1
|
||||||
|
|
||||||
host = 0.0.0.0
|
host = 0.0.0.0
|
||||||
port = 44242
|
port = 44242
|
||||||
|
|
|
@ -76,20 +76,27 @@
|
||||||
<ImportGroup Label="PropertySheets" />
|
<ImportGroup Label="PropertySheets" />
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<IncludePath>D:\My Documents\汇珏网络\15. EMS\projects\sdk\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)\..\..\sdk\include;$(IncludePath)</IncludePath>
|
||||||
<ProjectPublicIncludePath>-I/usr/local/include</ProjectPublicIncludePath>
|
<ProjectPublicIncludePath>-I/usr/local/include</ProjectPublicIncludePath>
|
||||||
|
<LibraryPath>$(SolutionDir)\..\..\sdk\lib;</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||||
<IncludePath>D:\My Documents\汇珏网络\15. EMS\projects\emsApplication\sdk\include;$(IncludePath)</IncludePath>
|
<IncludePath>..\..\..\emsApplication\sdk\include;$(IncludePath)</IncludePath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="eventhandler.cpp" />
|
||||||
<ClCompile Include="iconv-utils.cpp" />
|
<ClCompile Include="iconv-utils.cpp" />
|
||||||
|
<ClCompile Include="kutilities.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="openjson.cpp" />
|
<ClCompile Include="openjson.cpp" />
|
||||||
<ClCompile Include="opmysql.cpp" />
|
<ClCompile Include="opmysql.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="eventhandler.h" />
|
||||||
|
<ClInclude Include="frame_define.h" />
|
||||||
<ClInclude Include="iconv-utils.h" />
|
<ClInclude Include="iconv-utils.h" />
|
||||||
|
<ClInclude Include="kdefine.h" />
|
||||||
|
<ClInclude Include="kutilities.h" />
|
||||||
<ClInclude Include="mqtt_msg.h" />
|
<ClInclude Include="mqtt_msg.h" />
|
||||||
<ClInclude Include="openjson.h" />
|
<ClInclude Include="openjson.h" />
|
||||||
<ClInclude Include="opmysql.h" />
|
<ClInclude Include="opmysql.h" />
|
||||||
|
@ -103,6 +110,7 @@
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalOptions>-L/usr/local/lib</AdditionalOptions>
|
<AdditionalOptions>-L/usr/local/lib</AdditionalOptions>
|
||||||
<LibraryDependencies>hv;sqlite3;dl</LibraryDependencies>
|
<LibraryDependencies>hv;sqlite3;dl</LibraryDependencies>
|
||||||
|
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||||
|
|
|
@ -0,0 +1,249 @@
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
|
#include <hv/hv.h>
|
||||||
|
#include <hv/hmain.h>
|
||||||
|
#include <hv/iniparser.h>
|
||||||
|
#include <hv/hloop.h>
|
||||||
|
#include <hv/hsocket.h>
|
||||||
|
#include <hv/hssl.h>
|
||||||
|
|
||||||
|
#include "kdefine.h"
|
||||||
|
#include "frame_define.h"
|
||||||
|
#include "openjson.h"
|
||||||
|
#include "iconv-utils.h"
|
||||||
|
#include "kutilities.h"
|
||||||
|
#include "opmysql.h"
|
||||||
|
#include "mqtt_msg.h"
|
||||||
|
|
||||||
|
EventHandler::EventHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler::~EventHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EventHandler::onRecvHandler(hio_t* io, void* buf, int readbytes)
|
||||||
|
{
|
||||||
|
__USING_NAMESPACE_HJ__;
|
||||||
|
|
||||||
|
char localaddrstr[SOCKADDR_STRLEN] = { 0 };
|
||||||
|
char peeraddrstr[SOCKADDR_STRLEN] = { 0 };
|
||||||
|
hlogi("### 1 ### on_recv fd=%d readbytes=%d [%s] <==== [%s]", hio_fd(io), readbytes,
|
||||||
|
SOCKADDR_STR(hio_localaddr(io), localaddrstr),
|
||||||
|
SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
|
||||||
|
|
||||||
|
MessageFrame respFrame;
|
||||||
|
if( readbytes > 0xFFFF - 1 )
|
||||||
|
{
|
||||||
|
hloge("too large data buffer to process: %d", readbytes);
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_BUF_LEN);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(buf, readbytes).c_str());
|
||||||
|
|
||||||
|
MessageFrame* pReadFrame = (MessageFrame*)buf;
|
||||||
|
hlogi("on_recv fd=%d frame_len=%d [0x%x] ", hio_fd(io), pReadFrame->frame_len, pReadFrame->frame_len);
|
||||||
|
|
||||||
|
if( pReadFrame->frame_len > 0xFFFF - 1 )
|
||||||
|
{
|
||||||
|
hloge("too big string buffer to process: %d, it should be less than %d", pReadFrame->frame_len, 0xFFFF);
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_LEN);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Frame_DeviceData_Request == pReadFrame->frame_type )
|
||||||
|
{
|
||||||
|
handleGatherData(io, buf, readbytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EventHandler::handleGatherData(hio_t* io, void* buf, int readbytes)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
|
||||||
|
__USING_NAMESPACE_HJ__;
|
||||||
|
|
||||||
|
MessageFrame respFrame;
|
||||||
|
MessageFrame* pReadFrame = (MessageFrame*)buf;
|
||||||
|
hlogi("<=== reveive device data request");
|
||||||
|
|
||||||
|
OpenJson json;
|
||||||
|
|
||||||
|
CODING buf_code = GetCoding((unsigned char*)pReadFrame->frame_content, pReadFrame->frame_len); //判断是否是utf-8
|
||||||
|
|
||||||
|
hlogi("<=== recieve buffer coding is [%s]", buf_code == GBK ? "GBK" : (buf_code == UTF8 ? "UTF8" : "UNKNOWN CODING"));
|
||||||
|
|
||||||
|
MessageData* pData = (MessageData*)pReadFrame->frame_content;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
hlogd("<=== MessageData structure [\n%s\n]", printHex(pData, pReadFrame->frame_len).c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//这里将帧内帧的内容转换为字符串,符合json格式的字符串,详见mqtt_msg.h的MessageData结构定义
|
||||||
|
std::string msg((char*)pReadFrame->frame_content + MSG_HEADER_LENGTH, pReadFrame->frame_len - MSG_HEADER_LENGTH);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
hlogd("<=== json content [\n%s\n]", msg.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( buf_code == CODING::GBK
|
||||||
|
|| buf_code == CODING::UNKOWN )
|
||||||
|
{
|
||||||
|
std::string str_result;
|
||||||
|
//转换为UTF8
|
||||||
|
if( !GBKToUTF8(msg, str_result) )
|
||||||
|
{
|
||||||
|
hloge("Failed to transfer code from GBK to UTF-8");
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_UTF8);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogi("Successfuly transfer code from GBK to UTF-8!");
|
||||||
|
msg = str_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
hlogd("<=== recieve !!VALID!! mqtt pack len =[%d] data=[%s]", msg.length(), msg.c_str()); //这里还是好的
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int len = msg.length();
|
||||||
|
char* pTmp = new char[len];
|
||||||
|
memcpy(pTmp, msg.c_str(), len);
|
||||||
|
|
||||||
|
std::shared_ptr<char> ptr; //放个智能指针省得忘记删除
|
||||||
|
ptr.reset(pTmp);
|
||||||
|
|
||||||
|
//hlogi("<=== decode OK, msg=[%s]", msg.c_str());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 17).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 18).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 19).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 20).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 21).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 22).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 23).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 24).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 25).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 26).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 27).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 28).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 29).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 30).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 31).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 32).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 33).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 34).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 61).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 62).c_str());
|
||||||
|
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 63).c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//hlogd("<=== decode OK [\n%s\n]", printHex(pTmp, len).c_str());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( !json.decode(msg) )
|
||||||
|
{
|
||||||
|
hloge("Failed to decode json string pack , length=%d", readbytes);
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_JSON_FMT);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fsucode = json["FsuCode"].s();
|
||||||
|
std::string msg_type = json["type"].s();
|
||||||
|
std::string timestamp = get_current_timestamp(); // json["TimeStamp"].s();
|
||||||
|
|
||||||
|
if( fsucode.length() == 0 )
|
||||||
|
{
|
||||||
|
//delete[] pTmp;
|
||||||
|
hlogw("!!empty fsucode recieved!");
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_FSUCODE);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogi("<=== decode OK, recieve fsucode=[%s] type=[%s] ts=[%s]", fsucode.c_str(), msg_type.c_str(), timestamp.c_str());
|
||||||
|
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
hlogd("<<<<Check Mem after decode here>>>> \n[\n%s\n]\n", printHex(pTmp, len).c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string out_compress;
|
||||||
|
|
||||||
|
int zip_ret = 0;
|
||||||
|
if( (zip_ret = CompressString(pTmp, len, out_compress, Z_DEFAULT_COMPRESSION)) != Z_OK )
|
||||||
|
{
|
||||||
|
hloge("Failed to compress source data, zip return value %d", zip_ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogd("<<<<Compress result: string size from original [%d] to [%d]", len, out_compress.size());
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
hlogd("<<<<Compressed string here>>>> \n[\n%s\n]\n", printHex(out_compress.c_str(), out_compress.size()).c_str());
|
||||||
|
#endif
|
||||||
|
//std::string msg2(pTmp, len);
|
||||||
|
|
||||||
|
if( msg_type == "gateway-data"
|
||||||
|
|| msg_type == "gateway-alarmdata"
|
||||||
|
|| msg_type == "gateway-writedata"
|
||||||
|
|| msg_type == "gateway-readdata"
|
||||||
|
|| msg_type == "web-write"
|
||||||
|
|| msg_type == "web-alarm" )
|
||||||
|
{
|
||||||
|
auto& IdCodeContent = json["IdCodeContent"];
|
||||||
|
if( IdCodeContent.size() <= 0 )
|
||||||
|
{
|
||||||
|
//delete[] pTmp;
|
||||||
|
hloge("invalid IdCodeContent's size: %d", IdCodeContent.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& pNode = IdCodeContent[0]; //这是只解析第一个节点
|
||||||
|
std::string oid = pNode["OID"].s();
|
||||||
|
|
||||||
|
OpDatabase::getInstance()->InsertMessage(timestamp, msg_type, fsucode, out_compress, (int)pData->mqtt_topic, (int)pData->device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msg_type == "web-read" )
|
||||||
|
{
|
||||||
|
auto& IdCodeContent = json["IdCodes"];
|
||||||
|
if( IdCodeContent.size() <= 0 )
|
||||||
|
{
|
||||||
|
hloge("invalid IdCodes's size: %d", IdCodeContent.size());
|
||||||
|
//delete[] pTmp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& pNode = IdCodeContent[0]; //这是只解析第一个节点
|
||||||
|
std::string oid = pNode.s();
|
||||||
|
|
||||||
|
OpDatabase::getInstance()->InsertMessage(timestamp, msg_type, fsucode, out_compress, (int)pData->mqtt_topic, (int)pData->device_id);
|
||||||
|
}
|
||||||
|
//delete[] pTmp;
|
||||||
|
}
|
||||||
|
catch( const char* errMsg )
|
||||||
|
{
|
||||||
|
hloge("Failed to decode json string pack , catch error:%s", errMsg);
|
||||||
|
respFrame.setErrorFrame(ERR_INVALID_JSON_FMT);
|
||||||
|
hio_write(io, (void*)&respFrame, sizeof respFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hv/hloop.h>
|
||||||
|
|
||||||
|
class EventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EventHandler();
|
||||||
|
virtual ~EventHandler();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void onRecvHandler(hio_t* io, void* buf, int readbytes);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//处理采集程序上传的数据,以JSON数据上报
|
||||||
|
static void handleGatherData(hio_t* io, void* buf, int readbytes);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
#include "kdefine.h"
|
||||||
|
|
||||||
|
__NAMESPACE_BEGIN__(HJ)
|
||||||
|
|
||||||
|
#define FRAME_HEADER_LENGTH (5)
|
||||||
|
#define FRAME_TAILE_LENGTH (4)
|
||||||
|
|
||||||
|
typedef enum tagErrorCode : unsigned char
|
||||||
|
{
|
||||||
|
ERR_OK = 0X00,
|
||||||
|
ERR_INVALID_LEN = 0X01,
|
||||||
|
ERR_INVALID_UTF8 = 0X02,
|
||||||
|
ERR_INVALID_BUF_LEN = 0X03,
|
||||||
|
ERR_INVALID_JSON_FMT = 0X04,
|
||||||
|
ERR_INVALID_FSUCODE = 0X05,
|
||||||
|
ERR_UNKOWN = 0XFF
|
||||||
|
}ErrorCode;
|
||||||
|
|
||||||
|
typedef enum tagFrameType : unsigned char
|
||||||
|
{
|
||||||
|
Frame_Response = 0x00, //返回帧
|
||||||
|
Frame_Request = 0x01, //请求帧
|
||||||
|
Frame_DeviceData_Request = 0x02, //来自采集程序的数据请求包,将数据保存到数据库中
|
||||||
|
}FrameType;
|
||||||
|
|
||||||
|
typedef struct tagFrameTail
|
||||||
|
{
|
||||||
|
unsigned char frame_delimiter[4] = { 0xEE,0xFF,0xEE,0xFF };
|
||||||
|
}FrameTail;
|
||||||
|
|
||||||
|
typedef struct tagFrame
|
||||||
|
{
|
||||||
|
FrameType frame_type; //帧类型
|
||||||
|
unsigned int frame_len; //帧数据长度
|
||||||
|
unsigned char frame_content[1]; //帧的内容,实际应为json字符串,由json内容自解释
|
||||||
|
tagFrame()
|
||||||
|
{
|
||||||
|
frame_type = Frame_Response;
|
||||||
|
frame_len = 1;
|
||||||
|
frame_content[0] = ERR_OK;
|
||||||
|
}
|
||||||
|
void setErrorFrame(ErrorCode err = ERR_OK)
|
||||||
|
{
|
||||||
|
frame_len = 1;
|
||||||
|
frame_content[0] = err;
|
||||||
|
}
|
||||||
|
}MessageFrame;
|
||||||
|
|
||||||
|
__NAMESPACE_END__(HJ)
|
||||||
|
|
||||||
|
#pragma pack()
|
|
@ -135,8 +135,11 @@ int code_convert(const char* from_charset, const char* to_charset, char* inbuf,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
iconv_close(cd);
|
iconv_close(cd);
|
||||||
*pout = '\0';
|
#ifndef _WIN32
|
||||||
|
* pout = '\0';
|
||||||
|
#else
|
||||||
|
*pout = (char*)'\0';
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef __KDEFINE_INCLUDE__
|
||||||
|
#define __KDEFINE_INCLUDE__
|
||||||
|
|
||||||
|
#define K22_STR_EXP(__A) #__A
|
||||||
|
#define K22_STR(__A) K22_STR_EXP(__A)
|
||||||
|
#define K22_STRW_EXP(__A) L ## #__A
|
||||||
|
#define K22_STRW(__A) K22_STRW_EXP(__A)
|
||||||
|
|
||||||
|
#define K22_CMS_VERSION_MAJOR 1
|
||||||
|
#define K22_CMS_VERSION_MINOR 215
|
||||||
|
#define K22_CMS_VERSION_REVISION 0
|
||||||
|
#define K22_VERSION K22_STR(K22_CMS_VERSION_MAJOR) "." K22_STR(K22_CMS_VERSION_MINOR) "." K22_STR(K22_CMS_VERSION_REVISION) ""
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
# ifndef EXTERN_C
|
||||||
|
# define EXTERN_C extern "C"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef BEGIN_EXTERN_C
|
||||||
|
# define BEGIN_EXTERN_C extern "C" {
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef END_EXTERN_C
|
||||||
|
# define END_EXTERN_C } // extern "C"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define EXTERN_C extern
|
||||||
|
# define BEGIN_EXTERN_C
|
||||||
|
# define END_EXTERN_C
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define __NAMESPACE_BEGIN__(X) namespace X {
|
||||||
|
#define __NAMESPACE_END__(X) }
|
||||||
|
#define __USING_NAMESPACE__(X) using namespace X
|
||||||
|
#define __USING_NAMESPACE_HJ__ using namespace HJ
|
||||||
|
|
||||||
|
#endif //__KDEFINE_INCLUDE__
|
|
@ -0,0 +1,269 @@
|
||||||
|
#include "kutilities.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#define CHUNK 16384
|
||||||
|
|
||||||
|
/* Compress from file source to file dest until EOF on source.
|
||||||
|
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
|
||||||
|
allocated for processing, Z_STREAM_ERROR if an invalid compression
|
||||||
|
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
|
||||||
|
version of the library linked do not match, or Z_ERRNO if there is
|
||||||
|
an error reading or writing the files. */
|
||||||
|
int CompressString(const char* in_str, size_t in_len, std::string& out_str, int level)
|
||||||
|
{
|
||||||
|
if( !in_str )
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
|
||||||
|
int ret, flush;
|
||||||
|
unsigned have;
|
||||||
|
z_stream strm;
|
||||||
|
|
||||||
|
unsigned char out[CHUNK];
|
||||||
|
|
||||||
|
/* allocate deflate state */
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
ret = deflateInit(&strm, level);
|
||||||
|
if( ret != Z_OK )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
std::shared_ptr<z_stream> sp_strm(&strm, [](z_stream* strm)
|
||||||
|
{
|
||||||
|
(void)deflateEnd(strm);
|
||||||
|
});
|
||||||
|
|
||||||
|
const char* end = in_str + in_len;
|
||||||
|
|
||||||
|
//size_t pos_index = 0;
|
||||||
|
size_t distance = 0;
|
||||||
|
/* compress until end of file */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
distance = end - in_str;
|
||||||
|
strm.avail_in = (distance >= CHUNK) ? CHUNK : distance;
|
||||||
|
strm.next_in = (Bytef*)in_str;
|
||||||
|
|
||||||
|
// next pos
|
||||||
|
in_str += strm.avail_in;
|
||||||
|
flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;
|
||||||
|
|
||||||
|
/* run deflate() on input until output buffer not full, finish
|
||||||
|
compression if all of source has been read in */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
ret = deflate(&strm, flush); /* no bad return value */
|
||||||
|
if( ret == Z_STREAM_ERROR )
|
||||||
|
break;
|
||||||
|
have = CHUNK - strm.avail_out;
|
||||||
|
out_str.append((const char*)out, have);
|
||||||
|
}
|
||||||
|
while( strm.avail_out == 0 );
|
||||||
|
|
||||||
|
if( strm.avail_in != 0 ); /* all input will be used */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* done when last data in file processed */
|
||||||
|
}
|
||||||
|
while( flush != Z_FINISH );
|
||||||
|
|
||||||
|
if( ret != Z_STREAM_END ) /* stream will be complete */
|
||||||
|
return Z_STREAM_ERROR;
|
||||||
|
|
||||||
|
/* clean up and return */
|
||||||
|
return Z_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decompress from file source to file dest until stream ends or EOF.
|
||||||
|
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
|
||||||
|
allocated for processing, Z_DATA_ERROR if the deflate data is
|
||||||
|
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
|
||||||
|
the version of the library linked do not match, or Z_ERRNO if there
|
||||||
|
is an error reading or writing the files. */
|
||||||
|
int DecompressString(const char* in_str, size_t in_len, std::string& out_str)
|
||||||
|
{
|
||||||
|
if( !in_str )
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
unsigned have;
|
||||||
|
z_stream strm;
|
||||||
|
unsigned char out[CHUNK];
|
||||||
|
|
||||||
|
/* allocate inflate state */
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
ret = inflateInit(&strm);
|
||||||
|
if( ret != Z_OK )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
std::shared_ptr<z_stream> sp_strm(&strm, [](z_stream* strm)
|
||||||
|
{
|
||||||
|
(void)inflateEnd(strm);
|
||||||
|
});
|
||||||
|
|
||||||
|
const char* end = in_str + in_len;
|
||||||
|
|
||||||
|
//size_t pos_index = 0;
|
||||||
|
size_t distance = 0;
|
||||||
|
|
||||||
|
int flush = 0;
|
||||||
|
/* decompress until deflate stream ends or end of file */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
distance = end - in_str;
|
||||||
|
strm.avail_in = (distance >= CHUNK) ? CHUNK : distance;
|
||||||
|
strm.next_in = (Bytef*)in_str;
|
||||||
|
|
||||||
|
// next pos
|
||||||
|
in_str += strm.avail_in;
|
||||||
|
flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;
|
||||||
|
|
||||||
|
/* run inflate() on input until output buffer not full */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
if( ret == Z_STREAM_ERROR ) /* state not clobbered */
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch( ret )
|
||||||
|
{
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
ret = Z_DATA_ERROR; /* and fall through */
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
have = CHUNK - strm.avail_out;
|
||||||
|
out_str.append((const char*)out, have);
|
||||||
|
}
|
||||||
|
while( strm.avail_out == 0 );
|
||||||
|
|
||||||
|
/* done when inflate() says it's done */
|
||||||
|
}
|
||||||
|
while( flush != Z_FINISH );
|
||||||
|
|
||||||
|
/* clean up and return */
|
||||||
|
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 函数用于将内存块转换为十六进制字符串
|
||||||
|
std::string printHex(const void* data, size_t size)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
std::ostringstream ossrow;
|
||||||
|
|
||||||
|
const size_t lineSize = 16; // 每行输出的字节数
|
||||||
|
const unsigned char* p = static_cast<const unsigned char*>(data);
|
||||||
|
|
||||||
|
int ic = 0;
|
||||||
|
int row = 0;
|
||||||
|
|
||||||
|
ossrow << std::setw(8) << std::setfill('0') << std::hex << row++ << "h : ";
|
||||||
|
oss << ossrow.str().c_str();
|
||||||
|
|
||||||
|
for( size_t i = 0; i < size; ++i )
|
||||||
|
{
|
||||||
|
ic++;
|
||||||
|
|
||||||
|
// 每个字节之间用空格分隔
|
||||||
|
oss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast<int>(p[i]);
|
||||||
|
|
||||||
|
char ch = (isprint(p[i]) != 0) ? p[i] : '.';
|
||||||
|
|
||||||
|
oss2 << ch;
|
||||||
|
|
||||||
|
// 每lineSize个字节换行
|
||||||
|
if( (i + 1) % lineSize == 0 )
|
||||||
|
{
|
||||||
|
ossrow.clear();
|
||||||
|
ossrow.str("");
|
||||||
|
|
||||||
|
oss << " [" << oss2.str().c_str() << "]" << std::endl;
|
||||||
|
oss2.clear();
|
||||||
|
oss2.str("");
|
||||||
|
|
||||||
|
ossrow << std::setw(8) << std::setfill('0') << std::hex << row++ << "h : ";
|
||||||
|
oss << ossrow.str().c_str();
|
||||||
|
|
||||||
|
ic = 0;
|
||||||
|
}
|
||||||
|
else if( i == size - 1 )
|
||||||
|
{
|
||||||
|
if( (i + 1) % lineSize != 0 )
|
||||||
|
{
|
||||||
|
if( i % 2 != 0 )
|
||||||
|
{
|
||||||
|
for( size_t j = 0; j < (lineSize - ic); j++ )
|
||||||
|
{
|
||||||
|
oss << " --";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( size_t j = 0; j < (lineSize - ic); j++ )
|
||||||
|
{
|
||||||
|
oss << " --";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oss << " [" << oss2.str().c_str();
|
||||||
|
|
||||||
|
if( (i + 1) % lineSize != 0 )
|
||||||
|
{
|
||||||
|
for( size_t j = 0; j < (lineSize - ic); j++ )
|
||||||
|
{
|
||||||
|
oss << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << "]" << std::endl;
|
||||||
|
oss2.clear();
|
||||||
|
oss2.str("");
|
||||||
|
|
||||||
|
ic = 0;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if( (i + 1) % 8 == 0 )
|
||||||
|
{
|
||||||
|
oss << " ";
|
||||||
|
oss2 << " ";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oss << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string get_current_timestamp()
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
//通过不同精度获取相差的毫秒数
|
||||||
|
uint64_t dis_millseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count()
|
||||||
|
- std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count() * 1000;
|
||||||
|
time_t tt = std::chrono::system_clock::to_time_t(now);
|
||||||
|
auto time_tm = localtime(&tt);
|
||||||
|
char strTime[25] = { 0 };
|
||||||
|
sprintf(strTime, "%d-%02d-%02d %02d:%02d:%02d.%03d", time_tm->tm_year + 1900,
|
||||||
|
time_tm->tm_mon + 1, time_tm->tm_mday, time_tm->tm_hour,
|
||||||
|
time_tm->tm_min, time_tm->tm_sec, (int)dis_millseconds);
|
||||||
|
return std::string(strTime);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <zlib/zlib.h>
|
||||||
|
|
||||||
|
int CompressString(const char* in_str, size_t in_len, std::string& out_str, int level);
|
||||||
|
int DecompressString(const char* in_str, size_t in_len, std::string& out_str);
|
||||||
|
std::string printHex(const void* data, size_t size);
|
||||||
|
std::string get_current_timestamp();
|
|
@ -1,11 +1,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <hv/hv.h>
|
#include <hv/hv.h>
|
||||||
#include <hv/hmain.h>
|
#include <hv/hmain.h>
|
||||||
|
@ -13,180 +12,28 @@
|
||||||
#include <hv/hloop.h>
|
#include <hv/hloop.h>
|
||||||
#include <hv/hsocket.h>
|
#include <hv/hsocket.h>
|
||||||
#include <hv/hssl.h>
|
#include <hv/hssl.h>
|
||||||
#include <zlib/zlib.h>
|
|
||||||
|
|
||||||
#include "mqtt_msg.h"
|
#include "kdefine.h"
|
||||||
#include "openjson.h"
|
|
||||||
#include "opmysql.h"
|
#include "opmysql.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
#include "iconv-utils.h"
|
#ifndef TEST_UNPACK
|
||||||
|
|
||||||
#define TEST_UNPACK 1
|
#define TEST_UNPACK 1
|
||||||
|
#endif
|
||||||
#define K22_STR_EXP(__A) #__A
|
|
||||||
#define K22_STR(__A) K22_STR_EXP(__A)
|
|
||||||
#define K22_CMS_VERSION_MAJOR 1
|
|
||||||
#define K22_CMS_VERSION_MINOR 215
|
|
||||||
#define K22_CMS_VERSION_REVISION 0
|
|
||||||
#define K22_VERSION K22_STR(K22_CMS_VERSION_MAJOR) "." K22_STR(K22_CMS_VERSION_MINOR) "." K22_STR(K22_CMS_VERSION_REVISION) ""
|
|
||||||
|
|
||||||
#define CHUNK 16384
|
|
||||||
|
|
||||||
/* Compress from file source to file dest until EOF on source.
|
|
||||||
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
|
|
||||||
allocated for processing, Z_STREAM_ERROR if an invalid compression
|
|
||||||
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
|
|
||||||
version of the library linked do not match, or Z_ERRNO if there is
|
|
||||||
an error reading or writing the files. */
|
|
||||||
int CompressString(const char* in_str, size_t in_len, std::string& out_str, int level)
|
|
||||||
{
|
|
||||||
if (!in_str)
|
|
||||||
return Z_DATA_ERROR;
|
|
||||||
|
|
||||||
int ret, flush;
|
|
||||||
unsigned have;
|
|
||||||
z_stream strm;
|
|
||||||
|
|
||||||
unsigned char out[CHUNK];
|
|
||||||
|
|
||||||
/* allocate deflate state */
|
|
||||||
strm.zalloc = Z_NULL;
|
|
||||||
strm.zfree = Z_NULL;
|
|
||||||
strm.opaque = Z_NULL;
|
|
||||||
ret = deflateInit(&strm, level);
|
|
||||||
if (ret != Z_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
std::shared_ptr<z_stream> sp_strm(&strm, [](z_stream* strm)
|
|
||||||
{
|
|
||||||
(void)deflateEnd(strm);
|
|
||||||
});
|
|
||||||
|
|
||||||
const char* end = in_str + in_len;
|
|
||||||
|
|
||||||
//size_t pos_index = 0;
|
|
||||||
size_t distance = 0;
|
|
||||||
/* compress until end of file */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
distance = end - in_str;
|
|
||||||
strm.avail_in = (distance >= CHUNK) ? CHUNK : distance;
|
|
||||||
strm.next_in = (Bytef*)in_str;
|
|
||||||
|
|
||||||
// next pos
|
|
||||||
in_str += strm.avail_in;
|
|
||||||
flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;
|
|
||||||
|
|
||||||
/* run deflate() on input until output buffer not full, finish
|
|
||||||
compression if all of source has been read in */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
strm.avail_out = CHUNK;
|
|
||||||
strm.next_out = out;
|
|
||||||
ret = deflate(&strm, flush); /* no bad return value */
|
|
||||||
if (ret == Z_STREAM_ERROR)
|
|
||||||
break;
|
|
||||||
have = CHUNK - strm.avail_out;
|
|
||||||
out_str.append((const char*)out, have);
|
|
||||||
} while (strm.avail_out == 0);
|
|
||||||
|
|
||||||
if (strm.avail_in != 0); /* all input will be used */
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* done when last data in file processed */
|
|
||||||
} while (flush != Z_FINISH);
|
|
||||||
|
|
||||||
if (ret != Z_STREAM_END) /* stream will be complete */
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* clean up and return */
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress from file source to file dest until stream ends or EOF.
|
|
||||||
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
|
|
||||||
allocated for processing, Z_DATA_ERROR if the deflate data is
|
|
||||||
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
|
|
||||||
the version of the library linked do not match, or Z_ERRNO if there
|
|
||||||
is an error reading or writing the files. */
|
|
||||||
int DecompressString(const char* in_str, size_t in_len, std::string& out_str)
|
|
||||||
{
|
|
||||||
if (!in_str)
|
|
||||||
return Z_DATA_ERROR;
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
unsigned have;
|
|
||||||
z_stream strm;
|
|
||||||
unsigned char out[CHUNK];
|
|
||||||
|
|
||||||
/* allocate inflate state */
|
|
||||||
strm.zalloc = Z_NULL;
|
|
||||||
strm.zfree = Z_NULL;
|
|
||||||
strm.opaque = Z_NULL;
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit(&strm);
|
|
||||||
if (ret != Z_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
std::shared_ptr<z_stream> sp_strm(&strm, [](z_stream* strm)
|
|
||||||
{
|
|
||||||
(void)inflateEnd(strm);
|
|
||||||
});
|
|
||||||
|
|
||||||
const char* end = in_str + in_len;
|
|
||||||
|
|
||||||
//size_t pos_index = 0;
|
|
||||||
size_t distance = 0;
|
|
||||||
|
|
||||||
int flush = 0;
|
|
||||||
/* decompress until deflate stream ends or end of file */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
distance = end - in_str;
|
|
||||||
strm.avail_in = (distance >= CHUNK) ? CHUNK : distance;
|
|
||||||
strm.next_in = (Bytef*)in_str;
|
|
||||||
|
|
||||||
// next pos
|
|
||||||
in_str += strm.avail_in;
|
|
||||||
flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;
|
|
||||||
|
|
||||||
/* run inflate() on input until output buffer not full */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
strm.avail_out = CHUNK;
|
|
||||||
strm.next_out = out;
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
|
||||||
|
|
||||||
if (ret == Z_STREAM_ERROR) /* state not clobbered */
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (ret)
|
|
||||||
{
|
|
||||||
case Z_NEED_DICT:
|
|
||||||
ret = Z_DATA_ERROR; /* and fall through */
|
|
||||||
case Z_DATA_ERROR:
|
|
||||||
case Z_MEM_ERROR:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
have = CHUNK - strm.avail_out;
|
|
||||||
out_str.append((const char*)out, have);
|
|
||||||
} while (strm.avail_out == 0);
|
|
||||||
|
|
||||||
/* done when inflate() says it's done */
|
|
||||||
} while (flush != Z_FINISH);
|
|
||||||
|
|
||||||
/* clean up and return */
|
|
||||||
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//static OpDatabase gOpDatabase;
|
|
||||||
|
|
||||||
#if TEST_UNPACK
|
#if TEST_UNPACK
|
||||||
static unpack_setting_t unpack_setting;
|
static unpack_setting_t unpack_setting;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//连接关闭回调
|
||||||
|
static void on_close(hio_t* io);
|
||||||
|
//接入回调
|
||||||
|
static void on_accept(hio_t* io);
|
||||||
|
//接收到数据
|
||||||
|
static void on_recv(hio_t* io, void* buf, int readbytes);
|
||||||
|
//重载参数回调
|
||||||
|
static void on_reload(void* userdata);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @build: make
|
* @build: make
|
||||||
* @usage: datahubs -h
|
* @usage: datahubs -h
|
||||||
|
@ -212,6 +59,7 @@ typedef struct conf_ctx_s
|
||||||
std::string dbuser;
|
std::string dbuser;
|
||||||
std::string dbname;
|
std::string dbname;
|
||||||
} conf_ctx_t;
|
} conf_ctx_t;
|
||||||
|
|
||||||
conf_ctx_t g_conf_ctx;
|
conf_ctx_t g_conf_ctx;
|
||||||
|
|
||||||
inline void conf_ctx_init(conf_ctx_t* ctx)
|
inline void conf_ctx_init(conf_ctx_t* ctx)
|
||||||
|
@ -284,6 +132,7 @@ int parse_confile(const char* confile)
|
||||||
strncpy(g_main_ctx.logfile, str.c_str(), sizeof(g_main_ctx.logfile));
|
strncpy(g_main_ctx.logfile, str.c_str(), sizeof(g_main_ctx.logfile));
|
||||||
}
|
}
|
||||||
hlog_set_file(g_main_ctx.logfile);
|
hlog_set_file(g_main_ctx.logfile);
|
||||||
|
#if 1
|
||||||
// loglevel
|
// loglevel
|
||||||
str = g_conf_ctx.parser->GetValue("loglevel");
|
str = g_conf_ctx.parser->GetValue("loglevel");
|
||||||
if (!str.empty())
|
if (!str.empty())
|
||||||
|
@ -308,14 +157,26 @@ int parse_confile(const char* confile)
|
||||||
{
|
{
|
||||||
logger_enable_fsync(hlog, hv_getboolean(str.c_str()));
|
logger_enable_fsync(hlog, hv_getboolean(str.c_str()));
|
||||||
}
|
}
|
||||||
// first log here
|
#endif
|
||||||
|
|
||||||
// first log here
|
// first log here
|
||||||
hlogi("=========--- Welcome to the Earth ---=========");
|
hlogi("=========--- Welcome to the Earth ---=========");
|
||||||
hlogi("%s version: %s", g_main_ctx.program_name, K22_VERSION);
|
hlogi("%s version: %s", g_main_ctx.program_name, K22_VERSION);
|
||||||
hlog_fsync();
|
hlog_fsync();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_conf_ctx.worker_processes = 1;
|
||||||
|
g_conf_ctx.worker_threads = 1;
|
||||||
|
g_conf_ctx.host = "0.0.0.0";
|
||||||
|
g_conf_ctx.port = 44242;
|
||||||
|
g_conf_ctx.dbname = "hjems";
|
||||||
|
g_conf_ctx.dbuser = "root";
|
||||||
|
g_conf_ctx.dbserver = "tcp://127.0.0.1:3306";
|
||||||
|
#endif
|
||||||
// worker_processes
|
// worker_processes
|
||||||
int worker_processes = 0;
|
int worker_processes = 0;
|
||||||
|
|
||||||
|
#if 1
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Disable multi-processes mode for debugging
|
// Disable multi-processes mode for debugging
|
||||||
worker_processes = 0;
|
worker_processes = 0;
|
||||||
|
@ -351,6 +212,7 @@ int parse_confile(const char* confile)
|
||||||
worker_threads = atoi(str.c_str());
|
worker_threads = atoi(str.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_conf_ctx.worker_threads = LIMIT(0, worker_threads, 64);
|
g_conf_ctx.worker_threads = LIMIT(0, worker_threads, 64);
|
||||||
|
|
||||||
//host
|
//host
|
||||||
|
@ -422,15 +284,10 @@ int parse_confile(const char* confile)
|
||||||
hlogi("dbserver = ('%s')", g_conf_ctx.dbserver.c_str());
|
hlogi("dbserver = ('%s')", g_conf_ctx.dbserver.c_str());
|
||||||
|
|
||||||
hlogi("parse_confile('%s') OK", confile);
|
hlogi("parse_confile('%s') OK", confile);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_reload(void* userdata)
|
|
||||||
{
|
|
||||||
hlogi("reload confile [%s]", g_main_ctx.confile);
|
|
||||||
parse_confile(g_main_ctx.confile);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////1///////////////////////////////
|
//////1///////////////////////////////
|
||||||
#if 0
|
#if 0
|
||||||
#define LOCKFILE "/var/lock/datahub.lock"
|
#define LOCKFILE "/var/lock/datahub.lock"
|
||||||
|
@ -537,6 +394,14 @@ int main(int argc, char** argv)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// signal
|
||||||
|
signal_init(on_reload);
|
||||||
|
const char* signal = get_arg("s");
|
||||||
|
if( signal )
|
||||||
|
{
|
||||||
|
signal_handle(signal);
|
||||||
|
}
|
||||||
|
|
||||||
// g_conf_ctx
|
// g_conf_ctx
|
||||||
conf_ctx_init(&g_conf_ctx);
|
conf_ctx_init(&g_conf_ctx);
|
||||||
const char* confile = get_arg("c");
|
const char* confile = get_arg("c");
|
||||||
|
@ -553,13 +418,6 @@ int main(int argc, char** argv)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal
|
|
||||||
signal_init(on_reload);
|
|
||||||
const char* signal = get_arg("s");
|
|
||||||
if (signal)
|
|
||||||
{
|
|
||||||
signal_handle(signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OS_UNIX
|
#ifdef OS_UNIX
|
||||||
// daemon
|
// daemon
|
||||||
|
@ -596,294 +454,55 @@ int main(int argc, char** argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void worker_fn(void* userdata)
|
||||||
|
{
|
||||||
|
conf_ctx_t* ptrCtx = (conf_ctx_t*)(intptr_t)(userdata);
|
||||||
|
long port = ptrCtx->port;
|
||||||
|
|
||||||
|
//initialize database connection
|
||||||
|
bool dbok = OpDatabase::getInstance()->OpenDatabase(ptrCtx->dbserver,ptrCtx->dbuser,ptrCtx->dbname);
|
||||||
|
if (!dbok)
|
||||||
|
{
|
||||||
|
hloge("failed to open database, exit now...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogi("database connection created!");
|
||||||
|
|
||||||
|
hloop_t* loop = hloop_new(0);
|
||||||
|
const char* host = ptrCtx->host.c_str();
|
||||||
|
hio_t* listenio = hloop_create_tcp_server(loop, host, port, on_accept);
|
||||||
|
|
||||||
|
if (listenio == NULL)
|
||||||
|
{
|
||||||
|
hloge("worker process finished");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogi("port=%ld pid=%ld tid=%ld listenfd=%d", port, hv_getpid(), hv_gettid(), hio_fd(listenio));
|
||||||
|
|
||||||
|
hloop_run(loop);
|
||||||
|
|
||||||
|
hlogi("database connection close!");
|
||||||
|
OpDatabase::getInstance()->CloseDatabase();
|
||||||
|
|
||||||
|
hloop_free(&loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 各回调函数定义
|
||||||
|
|
||||||
|
static void on_reload(void* userdata)
|
||||||
|
{
|
||||||
|
hlogi("reload confile [%s]", g_main_ctx.confile);
|
||||||
|
parse_confile(g_main_ctx.confile);
|
||||||
|
}
|
||||||
|
|
||||||
static void on_close(hio_t* io)
|
static void on_close(hio_t* io)
|
||||||
{
|
{
|
||||||
hlogi("on_close fd=%d error=%d", hio_fd(io), hio_error(io));
|
hlogi("on_close fd=%d error=%d", hio_fd(io), hio_error(io));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_current_timestamp()
|
|
||||||
{
|
|
||||||
auto now = std::chrono::system_clock::now();
|
|
||||||
//通过不同精度获取相差的毫秒数
|
|
||||||
uint64_t dis_millseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count()
|
|
||||||
- std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count() * 1000;
|
|
||||||
time_t tt = std::chrono::system_clock::to_time_t(now);
|
|
||||||
auto time_tm = localtime(&tt);
|
|
||||||
char strTime[25] = { 0 };
|
|
||||||
sprintf(strTime, "%d-%02d-%02d %02d:%02d:%02d.%03d", time_tm->tm_year + 1900,
|
|
||||||
time_tm->tm_mon + 1, time_tm->tm_mday, time_tm->tm_hour,
|
|
||||||
time_tm->tm_min, time_tm->tm_sec, (int)dis_millseconds);
|
|
||||||
return std::string(strTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 函数用于将内存块转换为十六进制字符串
|
|
||||||
std::string printHex(const void* data, size_t size)
|
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
|
||||||
std::ostringstream oss2;
|
|
||||||
std::ostringstream ossrow;
|
|
||||||
|
|
||||||
const size_t lineSize = 16; // 每行输出的字节数
|
|
||||||
const unsigned char* p = static_cast<const unsigned char*>(data);
|
|
||||||
|
|
||||||
int ic = 0;
|
|
||||||
int row = 0;
|
|
||||||
|
|
||||||
ossrow << std::setw(8) << std::setfill('0') << std::hex << row++ << "h : ";
|
|
||||||
oss << ossrow.str().c_str();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
ic++;
|
|
||||||
|
|
||||||
// 每个字节之间用空格分隔
|
|
||||||
oss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast<int>(p[i]);
|
|
||||||
|
|
||||||
char ch = (isprint(p[i]) != 0) ? p[i] : '.';
|
|
||||||
|
|
||||||
oss2 << ch;
|
|
||||||
|
|
||||||
// 每lineSize个字节换行
|
|
||||||
if ((i + 1) % lineSize == 0)
|
|
||||||
{
|
|
||||||
ossrow.clear();
|
|
||||||
ossrow.str("");
|
|
||||||
|
|
||||||
oss << " [" << oss2.str().c_str() << "]" << std::endl;
|
|
||||||
oss2.clear();
|
|
||||||
oss2.str("");
|
|
||||||
|
|
||||||
ossrow << std::setw(8) << std::setfill('0') << std::hex << row++ << "h : ";
|
|
||||||
oss << ossrow.str().c_str();
|
|
||||||
|
|
||||||
ic = 0;
|
|
||||||
}
|
|
||||||
else if (i == size - 1)
|
|
||||||
{
|
|
||||||
if ((i + 1) % lineSize != 0)
|
|
||||||
{
|
|
||||||
if (i % 2 != 0)
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < (lineSize - ic); j++)
|
|
||||||
{
|
|
||||||
oss << " --";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < (lineSize - ic); j++)
|
|
||||||
{
|
|
||||||
oss << " --";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oss << " [" << oss2.str().c_str();
|
|
||||||
|
|
||||||
if ((i + 1) % lineSize != 0)
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < (lineSize - ic); j++)
|
|
||||||
{
|
|
||||||
oss << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
oss << "]" << std::endl;
|
|
||||||
oss2.clear();
|
|
||||||
oss2.str("");
|
|
||||||
|
|
||||||
ic = 0;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if ((i + 1) % 8 == 0)
|
|
||||||
{
|
|
||||||
oss << " ";
|
|
||||||
oss2 << " ";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oss << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//接收到数据
|
|
||||||
static void on_recv(hio_t* io, void* buf, int readbytes)
|
|
||||||
{
|
|
||||||
char localaddrstr[SOCKADDR_STRLEN] = { 0 };
|
|
||||||
char peeraddrstr[SOCKADDR_STRLEN] = { 0 };
|
|
||||||
hlogi("### 1 ### on_recv fd=%d readbytes=%d [%s] <==== [%s]", hio_fd(io), readbytes,
|
|
||||||
SOCKADDR_STR(hio_localaddr(io), localaddrstr),
|
|
||||||
SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
|
|
||||||
|
|
||||||
char ret[1] = { 0 };
|
|
||||||
if (readbytes > 0xFFFF - 1)
|
|
||||||
{
|
|
||||||
hloge("too large data buffer to process: %d", readbytes);
|
|
||||||
ret[0] = 1;
|
|
||||||
hio_write(io, (void*)ret, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageData* pData = (MessageData*)buf;
|
|
||||||
|
|
||||||
OpenJson json;
|
|
||||||
|
|
||||||
if (pData->content_len > 0xFFFF - 1)
|
|
||||||
{
|
|
||||||
hloge("too big string buffer to process: %d, it should be less than %d", pData->content_len, 0xFFFF);
|
|
||||||
ret[0] = 1;
|
|
||||||
hio_write(io, (void*)ret, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CODING buf_code = GetCoding((unsigned char*)pData->content_data, pData->content_len); //判断是否是utf-8
|
|
||||||
|
|
||||||
hlogi("<=== recieve buffer code is [%d]", buf_code);
|
|
||||||
|
|
||||||
std::string msg(pData->content_data, pData->content_len);
|
|
||||||
|
|
||||||
if (buf_code == CODING::GBK
|
|
||||||
|| buf_code == CODING::UNKOWN)
|
|
||||||
{
|
|
||||||
std::string str_result;
|
|
||||||
//转换为UTF8
|
|
||||||
if (!GBKToUTF8(msg, str_result))
|
|
||||||
{
|
|
||||||
hloge("Failed to transfer code from GBK to UTF-8");
|
|
||||||
ret[0] = 1;
|
|
||||||
hio_write(io, (void*)ret, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hlogi("Successfuly transfer code from GBK to UTF-8!");
|
|
||||||
msg = str_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
hlogd("<=== recieve !!VALID!! mqtt pack len =[%d] data=[%s]", msg.length(), msg.c_str()); //这里还是好的
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int len = msg.length();
|
|
||||||
char* pTmp = new char[len];
|
|
||||||
memcpy(pTmp, msg.c_str(), len);
|
|
||||||
|
|
||||||
std::shared_ptr<char> ptr; //放个智能指针省得忘记删除
|
|
||||||
ptr.reset(pTmp);
|
|
||||||
|
|
||||||
//hlogi("<=== decode OK, msg=[%s]", msg.c_str());
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 17).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 18).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 19).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 20).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 21).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 22).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 23).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 24).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 25).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 26).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 27).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 28).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 29).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 30).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 31).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 32).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 33).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 34).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 61).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 62).c_str());
|
|
||||||
hlogi("<=== decode OK [\n%s\n]", printHex(pTmp, 63).c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//hlogd("<=== decode OK [\n%s\n]", printHex(pTmp, len).c_str());
|
|
||||||
|
|
||||||
if (!json.decode(msg))
|
|
||||||
{
|
|
||||||
//delete[] pTmp;
|
|
||||||
hloge("Failed to decode json string pack , length=%d", readbytes);
|
|
||||||
ret[0] = 1;
|
|
||||||
hio_write(io, (void*)ret, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hio_write(io, (void*)ret, 1);
|
|
||||||
|
|
||||||
std::string fsucode = json["FsuCode"].s();
|
|
||||||
std::string msg_type = json["type"].s();
|
|
||||||
std::string timestamp = get_current_timestamp(); // json["TimeStamp"].s();
|
|
||||||
|
|
||||||
if (fsucode.length() == 0)
|
|
||||||
{
|
|
||||||
//delete[] pTmp;
|
|
||||||
hlogw("!!empty fsucode recieved!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hlogi("<=== decode OK, recieve fsucode=[%s] type=[%s] ts=[%s]", fsucode.c_str(), msg_type.c_str(), timestamp.c_str());
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
hlogd("<<<<Check Mem after decode here>>>> \n[\n%s\n]\n", printHex(pTmp, len).c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string out_compress;
|
|
||||||
|
|
||||||
int zip_ret = 0;
|
|
||||||
if ((zip_ret = CompressString(pTmp, len, out_compress, Z_DEFAULT_COMPRESSION)) != Z_OK)
|
|
||||||
{
|
|
||||||
hloge("Failed to compress source data, zip return value %d", zip_ret);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hlogd("<<<<Compress result: string size from original [%d] to [%d]", len, out_compress.size());
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
hlogd("<<<<Compress string here>>>> \n[\n%s\n]\n", printHex(out_compress.c_str(), out_compress.size()).c_str());
|
|
||||||
#endif
|
|
||||||
//std::string msg2(pTmp, len);
|
|
||||||
|
|
||||||
if (msg_type == "gateway-data"
|
|
||||||
|| msg_type == "gateway-alarmdata"
|
|
||||||
|| msg_type == "gateway-writedata"
|
|
||||||
|| msg_type == "gateway-readdata"
|
|
||||||
|| msg_type == "web-write"
|
|
||||||
|| msg_type == "web-alarm")
|
|
||||||
{
|
|
||||||
auto& IdCodeContent = json["IdCodeContent"];
|
|
||||||
if (IdCodeContent.size() <= 0)
|
|
||||||
{
|
|
||||||
//delete[] pTmp;
|
|
||||||
hloge("invalid IdCodeContent's size: %d", IdCodeContent.size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& pNode = IdCodeContent[0]; //这是只解析第一个节点
|
|
||||||
std::string oid = pNode["OID"].s();
|
|
||||||
|
|
||||||
OpDatabase::getInstance()->InsertMessage(timestamp, msg_type, fsucode, out_compress, (int)pData->mqtt_topic, (int)pData->device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg_type == "web-read")
|
|
||||||
{
|
|
||||||
auto& IdCodeContent = json["IdCodes"];
|
|
||||||
if (IdCodeContent.size() <= 0)
|
|
||||||
{
|
|
||||||
hloge("invalid IdCodes's size: %d", IdCodeContent.size());
|
|
||||||
//delete[] pTmp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& pNode = IdCodeContent[0]; //这是只解析第一个节点
|
|
||||||
std::string oid = pNode.s();
|
|
||||||
|
|
||||||
OpDatabase::getInstance()->InsertMessage(timestamp, msg_type, fsucode, out_compress, (int)pData->mqtt_topic, (int)pData->device_id);
|
|
||||||
}
|
|
||||||
//delete[] pTmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//接入回调
|
//接入回调
|
||||||
static void on_accept(hio_t* io)
|
static void on_accept(hio_t* io)
|
||||||
{
|
{
|
||||||
|
@ -905,37 +524,9 @@ static void on_accept(hio_t* io)
|
||||||
hio_read_start(io);
|
hio_read_start(io);
|
||||||
}
|
}
|
||||||
|
|
||||||
void worker_fn(void* userdata)
|
//接收到数据
|
||||||
|
static void on_recv(hio_t* io, void* buf, int readbytes)
|
||||||
{
|
{
|
||||||
conf_ctx_t* ptrCtx = (conf_ctx_t*)(intptr_t)(userdata);
|
EventHandler::onRecvHandler(io, buf, readbytes);
|
||||||
long port = ptrCtx->port;
|
|
||||||
|
|
||||||
//initialize database connection
|
|
||||||
bool dbok = OpDatabase::getInstance()->OpenDatabase(ptrCtx->dbserver,ptrCtx->dbuser,ptrCtx->dbname);
|
|
||||||
if (!dbok)
|
|
||||||
{
|
|
||||||
hloge("failed to open database, exit now...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hlogi("database connection created!");
|
|
||||||
|
|
||||||
hloop_t* loop = hloop_new(0);
|
|
||||||
const char* host = ptrCtx->host.c_str();
|
|
||||||
hio_t* listenio = hloop_create_tcp_server(loop, host, port, on_accept);
|
|
||||||
|
|
||||||
if (listenio == NULL)
|
|
||||||
{
|
|
||||||
hlogw("worker process finished");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hlogi("port=%ld pid=%ld tid=%ld listenfd=%d", port, hv_getpid(), hv_gettid(), hio_fd(listenio));
|
|
||||||
|
|
||||||
hloop_run(loop);
|
|
||||||
|
|
||||||
hlogi("database connection close!");
|
|
||||||
OpDatabase::getInstance()->CloseDatabase();
|
|
||||||
|
|
||||||
hloop_free(&loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "kdefine.h"
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
__NAMESPACE_BEGIN__(HJ)
|
||||||
|
|
||||||
|
#define MSG_HEADER_LENGTH (8)
|
||||||
|
|
||||||
typedef enum tagTopic : char
|
typedef enum tagTopic : char
|
||||||
{
|
{
|
||||||
GateWayPublicTopic_Server = 0,
|
GateWayPublicTopic_Server = 0,
|
||||||
ServerPublicTopic_GateWay = 1,
|
ServerPublicTopic_GateWay = 1,
|
||||||
}MQTT_Topic;
|
} MQTT_Topic;
|
||||||
|
|
||||||
typedef enum tagDataType : char
|
typedef enum tagDataType : char
|
||||||
{
|
{
|
||||||
|
@ -15,7 +22,9 @@ typedef enum tagDataType : char
|
||||||
DT_GATEWAY_CTRLDATA = 4,
|
DT_GATEWAY_CTRLDATA = 4,
|
||||||
DT_WEB_CTRL = 5,
|
DT_WEB_CTRL = 5,
|
||||||
DT_WEB_WRITE = 6,
|
DT_WEB_WRITE = 6,
|
||||||
DT_GATEWAY_WRITE = 7
|
DT_GATEWAY_WRITE = 7,
|
||||||
|
FRAME_REQUEST = 8,
|
||||||
|
FRAME_RESPONSE = 9,
|
||||||
}MQTT_DataType;
|
}MQTT_DataType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,4 +56,6 @@ typedef struct tagMsgData
|
||||||
char content_data[1]; //MQTT包字符串的内容
|
char content_data[1]; //MQTT包字符串的内容
|
||||||
}MessageData;
|
}MessageData;
|
||||||
|
|
||||||
|
__NAMESPACE_END__(HJ)
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
|
@ -20,10 +20,13 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <hv/hlog.h>
|
||||||
|
|
||||||
#include "openjson.h"
|
#include "openjson.h"
|
||||||
|
|
||||||
|
//#define PRINTF printf
|
||||||
|
#define PRINTF hloge
|
||||||
|
|
||||||
#define PRINTF printf
|
|
||||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1400 ))
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1400 ))
|
||||||
inline int SNPRINTF(char* buffer, size_t size, const char* format, ...)
|
inline int SNPRINTF(char* buffer, size_t size, const char* format, ...)
|
||||||
{
|
{
|
||||||
|
@ -188,10 +191,10 @@ bool OpenJson::Box::remove(OpenJson* node)
|
||||||
//JsonContext
|
//JsonContext
|
||||||
OpenJson::Context::Context()
|
OpenJson::Context::Context()
|
||||||
:
|
:
|
||||||
offset_(0),
|
|
||||||
data_(0),
|
data_(0),
|
||||||
root_(0),
|
size_(0),
|
||||||
size_(0)
|
offset_(0),
|
||||||
|
root_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,10 +281,10 @@ OpenJson::OpenJson(JsonType type)
|
||||||
:type_(type),
|
:type_(type),
|
||||||
context_(0),
|
context_(0),
|
||||||
wcontext_(0),
|
wcontext_(0),
|
||||||
box_(0),
|
|
||||||
idx_(0),
|
idx_(0),
|
||||||
key_(0),
|
|
||||||
len_(0),
|
len_(0),
|
||||||
|
box_(0),
|
||||||
|
key_(0),
|
||||||
segment_(0)
|
segment_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -783,12 +786,16 @@ OpenJson& OpenJson::object(const char* key)
|
||||||
{
|
{
|
||||||
if (type_ == ARRAY)
|
if (type_ == ARRAY)
|
||||||
{
|
{
|
||||||
Log("JsonNode must be OBJECT, not ARRAY");
|
PRINTF("JsonNode must be OBJECT, not ARRAY");
|
||||||
}
|
}
|
||||||
type_ = OBJECT;
|
type_ = OBJECT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if( !box_ )
|
||||||
|
{
|
||||||
|
PRINTF("JsonNode must be OBJECT, not NOTHING! key:[%s]", key);
|
||||||
|
}
|
||||||
assert(box_);
|
assert(box_);
|
||||||
}
|
}
|
||||||
if (!box_) box_ = new Box;
|
if (!box_) box_ = new Box;
|
||||||
|
@ -828,7 +835,7 @@ void OpenJson::addNode(OpenJson* node)
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
if (type_ != OBJECT && type_ != ARRAY)
|
if (type_ != OBJECT && type_ != ARRAY)
|
||||||
{
|
{
|
||||||
Log("JsonNode must be OBJECT or ARRAY");
|
PRINTF("JsonNode must be OBJECT or ARRAY");
|
||||||
type_ = node->key_ ? OBJECT : ARRAY;
|
type_ = node->key_ ? OBJECT : ARRAY;
|
||||||
}
|
}
|
||||||
if (box_ == 0) box_ = new Box;
|
if (box_ == 0) box_ = new Box;
|
||||||
|
|
|
@ -34,7 +34,8 @@ bool OpDatabase::OpenDatabase(const std::string& server, const std::string& dbus
|
||||||
// 数据库连接配置
|
// 数据库连接配置
|
||||||
//std::string server = "tcp://127.0.0.1:3306";
|
//std::string server = "tcp://127.0.0.1:3306";
|
||||||
//std::string dbuser = "root";
|
//std::string dbuser = "root";
|
||||||
std::string password = "Hj57471000";
|
//std::string password = "Hj57471000";
|
||||||
|
std::string password = "L2ysc1s1kr";
|
||||||
//std::string database = "hjems";
|
//std::string database = "hjems";
|
||||||
|
|
||||||
// 创建连接
|
// 创建连接
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_BUILD_CONFIG_H_
|
#ifndef _SQL_BUILD_CONFIG_H_
|
||||||
#define _SQL_BUILD_CONFIG_H_
|
#define _SQL_BUILD_CONFIG_H_
|
||||||
|
|
|
@ -1,13 +1,32 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPL
|
* This program is free software; you can redistribute it and/or modify
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
* published by the Free Software Foundation.
|
||||||
conditions of the GPL as it is applied to this software, see the
|
*
|
||||||
FLOSS License Exception
|
* This program is also distributed with certain software (including
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
*/
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
// libmysql defines HAVE_STRTOUL (on win), so we have to follow different pattern in definitions names
|
// libmysql defines HAVE_STRTOUL (on win), so we have to follow different pattern in definitions names
|
||||||
// to avoid annoying warnings.
|
// to avoid annoying warnings.
|
||||||
|
@ -35,27 +54,34 @@
|
||||||
#define HAVE_UINT32_T 1
|
#define HAVE_UINT32_T 1
|
||||||
#define HAVE_INT64_T 1
|
#define HAVE_INT64_T 1
|
||||||
#define HAVE_UINT64_T 1
|
#define HAVE_UINT64_T 1
|
||||||
/* #undef HAVE_MS_INT8 */
|
#define HAVE_MS_INT8 1
|
||||||
/* #undef HAVE_MS_UINT8 */
|
#define HAVE_MS_UINT8 1
|
||||||
/* #undef HAVE_MS_INT16 */
|
#define HAVE_MS_INT16 1
|
||||||
/* #undef HAVE_MS_UINT16 */
|
#define HAVE_MS_UINT16 1
|
||||||
/* #undef HAVE_MS_INT32 */
|
#define HAVE_MS_INT32 1
|
||||||
/* #undef HAVE_MS_UINT32 */
|
#define HAVE_MS_UINT32 1
|
||||||
/* #undef HAVE_MS_INT64 */
|
#define HAVE_MS_INT64 1
|
||||||
/* #undef HAVE_MS_UINT64 */
|
#define HAVE_MS_UINT64 1
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_STDINT_H
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
|
#if defined(HAVE_INTTYPES_H) && !defined(_WIN32)
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#ifndef CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES
|
#ifndef CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1600
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#if !defined(HAVE_INT8_T) && defined(HAVE_MS_INT8)
|
#if !defined(HAVE_INT8_T) && defined(HAVE_MS_INT8)
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,5 +112,6 @@ typedef __int64 int64_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // _MSC_VER >= 1600
|
||||||
#endif // CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES
|
#endif // CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
|
@ -1,42 +1,49 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_CONNECTION_H_
|
#ifndef _SQL_CONNECTION_H_
|
||||||
#define _SQL_CONNECTION_H_
|
#define _SQL_CONNECTION_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/variant.hpp>
|
|
||||||
|
|
||||||
#include "build_config.h"
|
#include "build_config.h"
|
||||||
#include "warning.h"
|
#include "warning.h"
|
||||||
#include "sqlstring.h"
|
#include "sqlstring.h"
|
||||||
|
#include "variant.h"
|
||||||
|
|
||||||
namespace sql
|
namespace sql
|
||||||
{
|
{
|
||||||
|
|
||||||
|
typedef sql::Variant ConnectPropertyVal;
|
||||||
typedef boost::variant<int, double, bool, sql::SQLString > ConnectPropertyVal;
|
|
||||||
|
|
||||||
typedef std::map< sql::SQLString, ConnectPropertyVal > ConnectOptionsMap;
|
typedef std::map< sql::SQLString, ConnectPropertyVal > ConnectOptionsMap;
|
||||||
|
|
||||||
|
@ -54,6 +61,12 @@ typedef enum transaction_isolation
|
||||||
TRANSACTION_SERIALIZABLE
|
TRANSACTION_SERIALIZABLE
|
||||||
} enum_transaction_isolation;
|
} enum_transaction_isolation;
|
||||||
|
|
||||||
|
enum ssl_mode
|
||||||
|
{
|
||||||
|
SSL_MODE_DISABLED= 1, SSL_MODE_PREFERRED, SSL_MODE_REQUIRED,
|
||||||
|
SSL_MODE_VERIFY_CA, SSL_MODE_VERIFY_IDENTITY
|
||||||
|
};
|
||||||
|
|
||||||
class Savepoint
|
class Savepoint
|
||||||
{
|
{
|
||||||
/* Prevent use of these */
|
/* Prevent use of these */
|
||||||
|
@ -99,6 +112,8 @@ public:
|
||||||
|
|
||||||
virtual void getClientOption(const sql::SQLString & optionName, void * optionValue) = 0;
|
virtual void getClientOption(const sql::SQLString & optionName, void * optionValue) = 0;
|
||||||
|
|
||||||
|
virtual sql::SQLString getClientOption(const sql::SQLString & optionName) = 0;
|
||||||
|
|
||||||
virtual DatabaseMetaData * getMetaData() = 0;
|
virtual DatabaseMetaData * getMetaData() = 0;
|
||||||
|
|
||||||
virtual enum_transaction_isolation getTransactionIsolation() = 0;
|
virtual enum_transaction_isolation getTransactionIsolation() = 0;
|
||||||
|
@ -109,6 +124,10 @@ public:
|
||||||
|
|
||||||
virtual bool isReadOnly() = 0;
|
virtual bool isReadOnly() = 0;
|
||||||
|
|
||||||
|
virtual bool isValid() = 0;
|
||||||
|
|
||||||
|
virtual bool reconnect() = 0;
|
||||||
|
|
||||||
virtual sql::SQLString nativeSQL(const sql::SQLString& sql) = 0;
|
virtual sql::SQLString nativeSQL(const sql::SQLString& sql) = 0;
|
||||||
|
|
||||||
virtual PreparedStatement * prepareStatement(const sql::SQLString& sql) = 0;
|
virtual PreparedStatement * prepareStatement(const sql::SQLString& sql) = 0;
|
||||||
|
@ -137,6 +156,8 @@ public:
|
||||||
|
|
||||||
virtual sql::Connection * setClientOption(const sql::SQLString & optionName, const void * optionValue) = 0;
|
virtual sql::Connection * setClientOption(const sql::SQLString & optionName, const void * optionValue) = 0;
|
||||||
|
|
||||||
|
virtual sql::Connection * setClientOption(const sql::SQLString & optionName, const sql::SQLString & optionValue) = 0;
|
||||||
|
|
||||||
virtual void setHoldability(int holdability) = 0;
|
virtual void setHoldability(int holdability) = 0;
|
||||||
|
|
||||||
virtual void setReadOnly(bool readOnly) = 0;
|
virtual void setReadOnly(bool readOnly) = 0;
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_DATATYPE_H_
|
#ifndef _SQL_DATATYPE_H_
|
||||||
#define _SQL_DATATYPE_H_
|
#define _SQL_DATATYPE_H_
|
||||||
|
@ -57,7 +65,8 @@ public:
|
||||||
GEOMETRY,
|
GEOMETRY,
|
||||||
ENUM,
|
ENUM,
|
||||||
SET,
|
SET,
|
||||||
SQLNULL
|
SQLNULL,
|
||||||
|
JSON
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_DRIVER_H_
|
#ifndef _SQL_DRIVER_H_
|
||||||
#define _SQL_DRIVER_H_
|
#define _SQL_DRIVER_H_
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_EXCEPTION_H_
|
#ifndef _SQL_EXCEPTION_H_
|
||||||
#define _SQL_EXCEPTION_H_
|
#define _SQL_EXCEPTION_H_
|
||||||
|
@ -33,6 +41,7 @@
|
||||||
namespace sql
|
namespace sql
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if (__cplusplus < 201103L)
|
||||||
#define MEMORY_ALLOC_OPERATORS(Class) \
|
#define MEMORY_ALLOC_OPERATORS(Class) \
|
||||||
void* operator new(size_t size) throw (std::bad_alloc) { return ::operator new(size); } \
|
void* operator new(size_t size) throw (std::bad_alloc) { return ::operator new(size); } \
|
||||||
void* operator new(size_t, void*) throw(); \
|
void* operator new(size_t, void*) throw(); \
|
||||||
|
@ -41,7 +50,17 @@ namespace sql
|
||||||
void* operator new[](size_t, void*) throw(); \
|
void* operator new[](size_t, void*) throw(); \
|
||||||
void* operator new[](size_t, const std::nothrow_t&) throw(); \
|
void* operator new[](size_t, const std::nothrow_t&) throw(); \
|
||||||
void* operator new(size_t N, std::allocator<Class>&);
|
void* operator new(size_t N, std::allocator<Class>&);
|
||||||
|
#else
|
||||||
|
#define MEMORY_ALLOC_OPERATORS(Class) \
|
||||||
|
void* operator new(size_t size){ return ::operator new(size); } \
|
||||||
|
void* operator new(size_t, void*) noexcept; \
|
||||||
|
void* operator new(size_t, const std::nothrow_t&) noexcept; \
|
||||||
|
void* operator new[](size_t); \
|
||||||
|
void* operator new[](size_t, void*) noexcept; \
|
||||||
|
void* operator new[](size_t, const std::nothrow_t&) noexcept; \
|
||||||
|
void* operator new(size_t N, std::allocator<Class>&);
|
||||||
|
|
||||||
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma warning (disable : 4290)
|
#pragma warning (disable : 4290)
|
||||||
//warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
//warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||||
|
@ -121,6 +140,29 @@ struct CPPCONN_PUBLIC_FUNC NonScrollableException : public SQLException
|
||||||
NonScrollableException(const std::string& reason) : SQLException(reason, "", 0) {}
|
NonScrollableException(const std::string& reason) : SQLException(reason, "", 0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CPPCONN_PUBLIC_FUNC SQLUnsupportedOptionException : public SQLException
|
||||||
|
{
|
||||||
|
SQLUnsupportedOptionException(const SQLUnsupportedOptionException& e, const std::string conn_option) :
|
||||||
|
SQLException(e.what(), e.sql_state, e.errNo),
|
||||||
|
option(conn_option )
|
||||||
|
{}
|
||||||
|
|
||||||
|
SQLUnsupportedOptionException(const std::string& reason, const std::string conn_option) :
|
||||||
|
SQLException(reason, "", 0),
|
||||||
|
option(conn_option )
|
||||||
|
{}
|
||||||
|
|
||||||
|
const char *getConnectionOption() const
|
||||||
|
{
|
||||||
|
return option.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SQLUnsupportedOptionException() throw () {};
|
||||||
|
protected:
|
||||||
|
const std::string option;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace sql */
|
} /* namespace sql */
|
||||||
|
|
||||||
#endif /* _SQL_EXCEPTION_H_ */
|
#endif /* _SQL_EXCEPTION_H_ */
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_METADATA_H_
|
#ifndef _SQL_METADATA_H_
|
||||||
#define _SQL_METADATA_H_
|
#define _SQL_METADATA_H_
|
||||||
|
@ -245,6 +253,10 @@ public:
|
||||||
|
|
||||||
virtual const sql::SQLString& getSchemaTerm() = 0;
|
virtual const sql::SQLString& getSchemaTerm() = 0;
|
||||||
|
|
||||||
|
virtual ResultSet * getSchemaCollation(const sql::SQLString& catalog, const sql::SQLString& schemaPattern) = 0;
|
||||||
|
|
||||||
|
virtual ResultSet * getSchemaCharset(const sql::SQLString& catalog, const sql::SQLString& schemaPattern) = 0;
|
||||||
|
|
||||||
virtual const sql::SQLString& getSearchStringEscape() = 0;
|
virtual const sql::SQLString& getSearchStringEscape() = 0;
|
||||||
|
|
||||||
virtual const sql::SQLString& getSQLKeywords() = 0;
|
virtual const sql::SQLString& getSQLKeywords() = 0;
|
||||||
|
@ -265,6 +277,10 @@ public:
|
||||||
|
|
||||||
virtual ResultSet * getTableTypes() = 0;
|
virtual ResultSet * getTableTypes() = 0;
|
||||||
|
|
||||||
|
virtual ResultSet * getTableCollation(const sql::SQLString& catalog, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern) = 0;
|
||||||
|
|
||||||
|
virtual ResultSet * getTableCharset(const sql::SQLString& catalog, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern) = 0;
|
||||||
|
|
||||||
virtual const sql::SQLString& getTimeDateFunctions() = 0;
|
virtual const sql::SQLString& getTimeDateFunctions() = 0;
|
||||||
|
|
||||||
virtual ResultSet * getTypeInfo() = 0;
|
virtual ResultSet * getTypeInfo() = 0;
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_PARAMETER_METADATA_H_
|
#ifndef _SQL_PARAMETER_METADATA_H_
|
||||||
#define _SQL_PARAMETER_METADATA_H_
|
#define _SQL_PARAMETER_METADATA_H_
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _SQL_PREPARED_STATEMENT_H_
|
#ifndef _SQL_PREPARED_STATEMENT_H_
|
||||||
|
@ -58,6 +66,8 @@ public:
|
||||||
|
|
||||||
virtual ParameterMetaData * getParameterMetaData() = 0;
|
virtual ParameterMetaData * getParameterMetaData() = 0;
|
||||||
|
|
||||||
|
virtual bool getMoreResults() = 0;
|
||||||
|
|
||||||
virtual void setBigInt(unsigned int parameterIndex, const sql::SQLString& value) = 0;
|
virtual void setBigInt(unsigned int parameterIndex, const sql::SQLString& value) = 0;
|
||||||
|
|
||||||
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
|
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_RESULTSET_H_
|
#ifndef _SQL_RESULTSET_H_
|
||||||
#define _SQL_RESULTSET_H_
|
#define _SQL_RESULTSET_H_
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_RESULTSET_METADATA_H_
|
#ifndef _SQL_RESULTSET_METADATA_H_
|
||||||
#define _SQL_RESULTSET_METADATA_H_
|
#define _SQL_RESULTSET_METADATA_H_
|
||||||
|
@ -55,6 +63,10 @@ public:
|
||||||
|
|
||||||
virtual SQLString getColumnTypeName(unsigned int column) = 0;
|
virtual SQLString getColumnTypeName(unsigned int column) = 0;
|
||||||
|
|
||||||
|
virtual SQLString getColumnCharset(unsigned int columnIndex) = 0;
|
||||||
|
|
||||||
|
virtual SQLString getColumnCollation(unsigned int columnIndex) = 0;
|
||||||
|
|
||||||
virtual unsigned int getPrecision(unsigned int column) = 0;
|
virtual unsigned int getPrecision(unsigned int column) = 0;
|
||||||
|
|
||||||
virtual unsigned int getScale(unsigned int column) = 0;
|
virtual unsigned int getScale(unsigned int column) = 0;
|
||||||
|
@ -73,6 +85,8 @@ public:
|
||||||
|
|
||||||
virtual int isNullable(unsigned int column) = 0;
|
virtual int isNullable(unsigned int column) = 0;
|
||||||
|
|
||||||
|
virtual bool isNumeric(unsigned int column) = 0;
|
||||||
|
|
||||||
virtual bool isReadOnly(unsigned int column) = 0;
|
virtual bool isReadOnly(unsigned int column) = 0;
|
||||||
|
|
||||||
virtual bool isSearchable(unsigned int column) = 0;
|
virtual bool isSearchable(unsigned int column) = 0;
|
||||||
|
|
|
@ -1,31 +1,40 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_STRING_H_
|
#ifndef _SQL_STRING_H_
|
||||||
#define _SQL_STRING_H_
|
#define _SQL_STRING_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
#include "build_config.h"
|
#include "build_config.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -102,6 +111,30 @@ namespace sql
|
||||||
return realStr.compare(pos1, n1, s);
|
return realStr.compare(pos1, n1, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int caseCompare(const SQLString &s) const
|
||||||
|
{
|
||||||
|
std::string tmp(realStr), str(s);
|
||||||
|
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
return tmp.compare(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int caseCompare(const char * s) const
|
||||||
|
{
|
||||||
|
std::string tmp(realStr), str(s);
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
|
||||||
|
return tmp.compare(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int caseCompare(size_t pos1, size_t n1, const char * s) const
|
||||||
|
{
|
||||||
|
std::string tmp(realStr.c_str() + pos1, n1), str(s);
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
|
||||||
|
return tmp.compare(str);
|
||||||
|
}
|
||||||
|
|
||||||
const std::string & asStdString() const
|
const std::string & asStdString() const
|
||||||
{
|
{
|
||||||
return realStr;
|
return realStr;
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_STATEMENT_H_
|
#ifndef _SQL_STATEMENT_H_
|
||||||
#define _SQL_STATEMENT_H_
|
#define _SQL_STATEMENT_H_
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is also distributed with certain software (including
|
||||||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||||||
|
* as designated in a particular file or component or in included license
|
||||||
|
* documentation. The authors of MySQL hereby grant you an
|
||||||
|
* additional permission to link the program and your derivative works
|
||||||
|
* with the separately licensed software that they have included with
|
||||||
|
* MySQL.
|
||||||
|
*
|
||||||
|
* Without limiting anything contained in the foregoing, this file,
|
||||||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||||||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||||||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License, version 2.0, for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
|
||||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
||||||
MySQL Connectors. There are special exceptions to the terms and
|
|
||||||
conditions of the GPLv2 as it is applied to this software, see the
|
|
||||||
FLOSS License Exception
|
|
||||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published
|
|
||||||
by the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SQL_WARNING_H_
|
#ifndef _SQL_WARNING_H_
|
||||||
#define _SQL_WARNING_H_
|
#define _SQL_WARNING_H_
|
||||||
|
@ -59,7 +67,7 @@ protected:
|
||||||
|
|
||||||
virtual ~SQLWarning(){};
|
virtual ~SQLWarning(){};
|
||||||
|
|
||||||
SQLWarning(const SQLWarning& e){};
|
SQLWarning(const SQLWarning&){};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SQLWarning & operator = (const SQLWarning & rhs);
|
const SQLWarning & operator = (const SQLWarning & rhs);
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
#ifndef HV_ASYNC_HTTP_CLIENT_H_
|
||||||
|
#define HV_ASYNC_HTTP_CLIENT_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "EventLoopThread.h"
|
||||||
|
#include "Channel.h"
|
||||||
|
|
||||||
|
#include "HttpMessage.h"
|
||||||
|
#include "HttpParser.h"
|
||||||
|
|
||||||
|
namespace hv {
|
||||||
|
|
||||||
|
template<typename Conn>
|
||||||
|
class ConnPool {
|
||||||
|
public:
|
||||||
|
int size() {
|
||||||
|
return conns_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(Conn& conn) {
|
||||||
|
if (conns_.empty()) return false;
|
||||||
|
conn = conns_.front();
|
||||||
|
conns_.pop_front();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add(const Conn& conn) {
|
||||||
|
conns_.push_back(conn);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(const Conn& conn) {
|
||||||
|
auto iter = conns_.begin();
|
||||||
|
while (iter != conns_.end()) {
|
||||||
|
if (*iter == conn) {
|
||||||
|
iter = conns_.erase(iter);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<Conn> conns_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HttpClientTask {
|
||||||
|
HttpRequestPtr req;
|
||||||
|
HttpResponseCallback cb;
|
||||||
|
uint64_t start_time;
|
||||||
|
};
|
||||||
|
typedef std::shared_ptr<HttpClientTask> HttpClientTaskPtr;
|
||||||
|
|
||||||
|
struct HttpClientContext {
|
||||||
|
HttpClientTaskPtr task;
|
||||||
|
|
||||||
|
HttpResponsePtr resp;
|
||||||
|
HttpParserPtr parser;
|
||||||
|
TimerID timerID;
|
||||||
|
|
||||||
|
HttpClientContext() {
|
||||||
|
timerID = INVALID_TIMER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
~HttpClientContext() {
|
||||||
|
cancelTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelTimer() {
|
||||||
|
if (timerID != INVALID_TIMER_ID) {
|
||||||
|
killTimer(timerID);
|
||||||
|
timerID = INVALID_TIMER_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelTask() {
|
||||||
|
cancelTimer();
|
||||||
|
task = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback() {
|
||||||
|
cancelTimer();
|
||||||
|
if (task && task->cb) {
|
||||||
|
task->cb(resp);
|
||||||
|
}
|
||||||
|
// NOTE: task done
|
||||||
|
task = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void successCallback() {
|
||||||
|
callback();
|
||||||
|
resp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void errorCallback() {
|
||||||
|
resp = NULL;
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HV_EXPORT AsyncHttpClient : private EventLoopThread {
|
||||||
|
public:
|
||||||
|
AsyncHttpClient(EventLoopPtr loop = NULL) : EventLoopThread(loop) {
|
||||||
|
if (loop == NULL) {
|
||||||
|
EventLoopThread::start(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~AsyncHttpClient() {
|
||||||
|
EventLoopThread::stop(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// thread-safe
|
||||||
|
int send(const HttpRequestPtr& req, HttpResponseCallback resp_cb);
|
||||||
|
int send(const HttpClientTaskPtr& task) {
|
||||||
|
EventLoopThread::loop()->queueInLoop(std::bind(&AsyncHttpClient::sendInLoop, this, task));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void sendInLoop(HttpClientTaskPtr task) {
|
||||||
|
int err = doTask(task);
|
||||||
|
if (err != 0 && task->cb) {
|
||||||
|
task->cb(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int doTask(const HttpClientTaskPtr& task);
|
||||||
|
|
||||||
|
static int sendRequest(const SocketChannelPtr& channel);
|
||||||
|
|
||||||
|
// channel
|
||||||
|
const SocketChannelPtr& getChannel(int fd) {
|
||||||
|
return channels[fd];
|
||||||
|
// return fd < channels.capacity() ? channels[fd] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SocketChannelPtr& addChannel(hio_t* io) {
|
||||||
|
auto channel = std::make_shared<SocketChannel>(io);
|
||||||
|
channel->newContext<HttpClientContext>();
|
||||||
|
int fd = channel->fd();
|
||||||
|
channels[fd] = channel;
|
||||||
|
return channels[fd];
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeChannel(const SocketChannelPtr& channel) {
|
||||||
|
channel->deleteContext<HttpClientContext>();
|
||||||
|
int fd = channel->fd();
|
||||||
|
channels.erase(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// NOTE: just one loop thread, no need mutex.
|
||||||
|
// fd => SocketChannelPtr
|
||||||
|
std::map<int, SocketChannelPtr> channels;
|
||||||
|
// peeraddr => ConnPool
|
||||||
|
std::map<std::string, ConnPool<int>> conn_pools;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HV_ASYNC_HTTP_CLIENT_H_
|
|
@ -241,7 +241,7 @@ typedef std::shared_ptr<EventLoop> EventLoopPtr;
|
||||||
static inline EventLoop* tlsEventLoop() {
|
static inline EventLoop* tlsEventLoop() {
|
||||||
return (EventLoop*)ThreadLocalStorage::get(ThreadLocalStorage::EVENT_LOOP);
|
return (EventLoop*)ThreadLocalStorage::get(ThreadLocalStorage::EVENT_LOOP);
|
||||||
}
|
}
|
||||||
#define currentThreadEventLoop tlsEventLoop()
|
#define currentThreadEventLoop ::hv::tlsEventLoop()
|
||||||
|
|
||||||
static inline TimerID setTimer(int timeout_ms, TimerCallback cb, uint32_t repeat = INFINITE) {
|
static inline TimerID setTimer(int timeout_ms, TimerCallback cb, uint32_t repeat = INFINITE) {
|
||||||
EventLoop* loop = tlsEventLoop();
|
EventLoop* loop = tlsEventLoop();
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
Functor pre = Functor(),
|
Functor pre = Functor(),
|
||||||
Functor post = Functor()) {
|
Functor post = Functor()) {
|
||||||
if (status() >= kStarting && status() < kStopped) return;
|
if (status() >= kStarting && status() < kStopped) return;
|
||||||
|
if (isRunning()) return;
|
||||||
setStatus(kStarting);
|
setStatus(kStarting);
|
||||||
|
|
||||||
thread_ = std::make_shared<std::thread>(&EventLoopThread::loop_thread, this, pre, post);
|
thread_ = std::make_shared<std::thread>(&EventLoopThread::loop_thread, this, pre, post);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
/*
|
/*
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "http_client.h"
|
#include "HttpClient.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
HttpRequest req;
|
HttpRequest req;
|
||||||
|
@ -30,7 +30,6 @@ int main(int argc, char* argv[]) {
|
||||||
typedef struct http_client_s http_client_t;
|
typedef struct http_client_s http_client_t;
|
||||||
|
|
||||||
HV_EXPORT http_client_t* http_client_new(const char* host = NULL, int port = DEFAULT_HTTP_PORT, int https = 0);
|
HV_EXPORT http_client_t* http_client_new(const char* host = NULL, int port = DEFAULT_HTTP_PORT, int https = 0);
|
||||||
HV_EXPORT int http_client_close(http_client_t* cli);
|
|
||||||
HV_EXPORT int http_client_del(http_client_t* cli);
|
HV_EXPORT int http_client_del(http_client_t* cli);
|
||||||
HV_EXPORT const char* http_client_strerror(int errcode);
|
HV_EXPORT const char* http_client_strerror(int errcode);
|
||||||
|
|
||||||
|
@ -69,6 +68,15 @@ HV_EXPORT int http_client_send(HttpRequest* req, HttpResponse* resp);
|
||||||
// http_client_send_async(&default_async_client, ...)
|
// http_client_send_async(&default_async_client, ...)
|
||||||
HV_EXPORT int http_client_send_async(HttpRequestPtr req, HttpResponseCallback resp_cb = NULL);
|
HV_EXPORT int http_client_send_async(HttpRequestPtr req, HttpResponseCallback resp_cb = NULL);
|
||||||
|
|
||||||
|
// low-level api
|
||||||
|
// @retval >=0 connfd, <0 error
|
||||||
|
HV_EXPORT int http_client_connect(http_client_t* cli, const char* host, int port, int https, int timeout);
|
||||||
|
HV_EXPORT int http_client_send_header(http_client_t* cli, HttpRequest* req);
|
||||||
|
HV_EXPORT int http_client_send_data(http_client_t* cli, const char* data, int size);
|
||||||
|
HV_EXPORT int http_client_recv_data(http_client_t* cli, char* data, int size);
|
||||||
|
HV_EXPORT int http_client_recv_response(http_client_t* cli, HttpResponse* resp);
|
||||||
|
HV_EXPORT int http_client_close(http_client_t* cli);
|
||||||
|
|
||||||
namespace hv {
|
namespace hv {
|
||||||
|
|
||||||
class HttpClient {
|
class HttpClient {
|
||||||
|
@ -134,7 +142,22 @@ public:
|
||||||
return http_client_send_async(_client, req, std::move(resp_cb));
|
return http_client_send_async(_client, req, std::move(resp_cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
// close
|
// low-level api
|
||||||
|
int connect(const char* host, int port = DEFAULT_HTTP_PORT, int https = 0, int timeout = DEFAULT_HTTP_CONNECT_TIMEOUT) {
|
||||||
|
return http_client_connect(_client, host, port, https, timeout);
|
||||||
|
}
|
||||||
|
int sendHeader(HttpRequest* req) {
|
||||||
|
return http_client_send_header(_client, req);
|
||||||
|
}
|
||||||
|
int sendData(const char* data, int size) {
|
||||||
|
return http_client_send_data(_client, data, size);
|
||||||
|
}
|
||||||
|
int recvData(char* data, int size) {
|
||||||
|
return http_client_recv_data(_client, data, size);
|
||||||
|
}
|
||||||
|
int recvResponse(HttpResponse* resp) {
|
||||||
|
return http_client_recv_response(_client, resp);
|
||||||
|
}
|
||||||
int close() {
|
int close() {
|
||||||
return http_client_close(_client);
|
return http_client_close(_client);
|
||||||
}
|
}
|
|
@ -46,19 +46,6 @@
|
||||||
#include "httpdef.h"
|
#include "httpdef.h"
|
||||||
#include "http_content.h"
|
#include "http_content.h"
|
||||||
|
|
||||||
namespace hv {
|
|
||||||
|
|
||||||
struct NetAddr {
|
|
||||||
std::string ip;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
std::string ipport() {
|
|
||||||
return hv::asprintf("%s:%d", ip.c_str(), port);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||||
// Cookie: sessionid=1; domain=.example.com; path=/; max-age=86400; secure; httponly
|
// Cookie: sessionid=1; domain=.example.com; path=/; max-age=86400; secure; httponly
|
||||||
struct HV_EXPORT HttpCookie {
|
struct HV_EXPORT HttpCookie {
|
||||||
|
@ -297,6 +284,7 @@ public:
|
||||||
void* Content() {
|
void* Content() {
|
||||||
if (content == NULL && body.size() != 0) {
|
if (content == NULL && body.size() != 0) {
|
||||||
content = (void*)body.data();
|
content = (void*)body.data();
|
||||||
|
content_length = body.size();
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
|
|
||||||
#include "hexport.h"
|
#include "hexport.h"
|
||||||
#include "hssl.h"
|
#include "hssl.h"
|
||||||
|
// #include "EventLoop.h"
|
||||||
#include "HttpService.h"
|
#include "HttpService.h"
|
||||||
// #include "WebSocketServer.h"
|
// #include "WebSocketServer.h"
|
||||||
namespace hv {
|
namespace hv {
|
||||||
|
class EventLoop;
|
||||||
struct WebSocketService;
|
struct WebSocketService;
|
||||||
}
|
}
|
||||||
using hv::HttpService;
|
using hv::HttpService;
|
||||||
|
@ -72,18 +74,16 @@ int main() {
|
||||||
return 200;
|
return 200;
|
||||||
});
|
});
|
||||||
|
|
||||||
HttpServer server;
|
HttpServer server(&service);
|
||||||
server.registerHttpService(&service);
|
|
||||||
server.setPort(8080);
|
|
||||||
server.setThreadNum(4);
|
server.setThreadNum(4);
|
||||||
server.run();
|
server.run(":8080");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace hv {
|
namespace hv {
|
||||||
|
|
||||||
class HttpServer : public http_server_t {
|
class HV_EXPORT HttpServer : public http_server_t {
|
||||||
public:
|
public:
|
||||||
HttpServer(HttpService* service = NULL)
|
HttpServer(HttpService* service = NULL)
|
||||||
: http_server_t()
|
: http_server_t()
|
||||||
|
@ -96,6 +96,8 @@ public:
|
||||||
this->service = service;
|
this->service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<hv::EventLoop> loop(int idx = -1);
|
||||||
|
|
||||||
void setHost(const char* host = "0.0.0.0") {
|
void setHost(const char* host = "0.0.0.0") {
|
||||||
if (host) strcpy(this->host, host);
|
if (host) strcpy(this->host, host);
|
||||||
}
|
}
|
||||||
|
@ -117,6 +119,11 @@ public:
|
||||||
this->worker_threads = num;
|
this->worker_threads = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMaxWorkerConnectionNum(uint32_t num) {
|
||||||
|
this->worker_connections = num;
|
||||||
|
}
|
||||||
|
size_t connectionNum();
|
||||||
|
|
||||||
// SSL/TLS
|
// SSL/TLS
|
||||||
int setSslCtx(hssl_ctx_t ssl_ctx) {
|
int setSslCtx(hssl_ctx_t ssl_ctx) {
|
||||||
this->ssl_ctx = ssl_ctx;
|
this->ssl_ctx = ssl_ctx;
|
||||||
|
@ -130,12 +137,20 @@ public:
|
||||||
return setSslCtx(ssl_ctx);
|
return setSslCtx(ssl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int run(bool wait = true) {
|
// run(":8080")
|
||||||
|
// run("0.0.0.0:8080")
|
||||||
|
// run("[::]:8080")
|
||||||
|
int run(const char* ip_port = NULL, bool wait = true) {
|
||||||
|
if (ip_port) {
|
||||||
|
hv::NetAddr listen_addr(ip_port);
|
||||||
|
if (listen_addr.ip.size() != 0) setHost(listen_addr.ip.c_str());
|
||||||
|
if (listen_addr.port != 0) setPort(listen_addr.port);
|
||||||
|
}
|
||||||
return http_server_run(this, wait);
|
return http_server_run(this, wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
int start() {
|
int start(const char* ip_port = NULL) {
|
||||||
return run(false);
|
return run(ip_port, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int stop() {
|
int stop() {
|
||||||
|
|
|
@ -32,7 +32,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
EventLoopPtr loop(int idx = -1) {
|
EventLoopPtr loop(int idx = -1) {
|
||||||
return worker_threads.loop(idx);
|
EventLoopPtr worker_loop = worker_threads.loop(idx);
|
||||||
|
if (worker_loop == NULL) {
|
||||||
|
worker_loop = acceptor_loop;
|
||||||
|
}
|
||||||
|
return worker_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@retval >=0 listenfd, <0 error
|
//@retval >=0 listenfd, <0 error
|
||||||
|
@ -294,8 +298,10 @@ public:
|
||||||
// start thread-safe
|
// start thread-safe
|
||||||
void start(bool wait_threads_started = true) {
|
void start(bool wait_threads_started = true) {
|
||||||
TcpServerEventLoopTmpl<TSocketChannel>::start(wait_threads_started);
|
TcpServerEventLoopTmpl<TSocketChannel>::start(wait_threads_started);
|
||||||
|
if (!isRunning()) {
|
||||||
EventLoopThread::start(wait_threads_started);
|
EventLoopThread::start(wait_threads_started);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// stop thread-safe
|
// stop thread-safe
|
||||||
void stop(bool wait_threads_stopped = true) {
|
void stop(bool wait_threads_stopped = true) {
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
perror("bind");
|
perror("bind");
|
||||||
}
|
}
|
||||||
|
hio_set_localaddr(channel->io(), &local_addr.sa, SOCKADDR_LEN(&local_addr));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,11 @@ HV_INLINE std::string Base64Decode(const char* str, unsigned int len = 0) {
|
||||||
int decoded_size = BASE64_DECODE_OUT_SIZE(len);
|
int decoded_size = BASE64_DECODE_OUT_SIZE(len);
|
||||||
std::string decoded_buf(decoded_size + 1, 0);
|
std::string decoded_buf(decoded_size + 1, 0);
|
||||||
decoded_size = hv_base64_decode(str, len, (unsigned char*)decoded_buf.data());
|
decoded_size = hv_base64_decode(str, len, (unsigned char*)decoded_buf.data());
|
||||||
|
if (decoded_size > 0) {
|
||||||
decoded_buf.resize(decoded_size);
|
decoded_buf.resize(decoded_size);
|
||||||
|
} else {
|
||||||
|
decoded_buf.clear();
|
||||||
|
}
|
||||||
return decoded_buf;
|
return decoded_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
#ifndef HV_DNS_H_
|
|
||||||
#define HV_DNS_H_
|
|
||||||
|
|
||||||
#include "hexport.h"
|
|
||||||
#include "hplatform.h"
|
|
||||||
|
|
||||||
#define DNS_PORT 53
|
|
||||||
|
|
||||||
#define DNS_QUERY 0
|
|
||||||
#define DNS_RESPONSE 1
|
|
||||||
|
|
||||||
#define DNS_TYPE_A 1 // ipv4
|
|
||||||
#define DNS_TYPE_NS 2
|
|
||||||
#define DNS_TYPE_CNAME 5
|
|
||||||
#define DNS_TYPE_SOA 6
|
|
||||||
#define DNS_TYPE_WKS 11
|
|
||||||
#define DNS_TYPE_PTR 12
|
|
||||||
#define DNS_TYPE_HINFO 13
|
|
||||||
#define DNS_TYPE_MX 15
|
|
||||||
#define DNS_TYPE_AAAA 28 // ipv6
|
|
||||||
#define DNS_TYPE_AXFR 252
|
|
||||||
#define DNS_TYPE_ANY 255
|
|
||||||
|
|
||||||
#define DNS_CLASS_IN 1
|
|
||||||
|
|
||||||
#define DNS_NAME_MAXLEN 256
|
|
||||||
|
|
||||||
// sizeof(dnshdr_t) = 12
|
|
||||||
typedef struct dnshdr_s {
|
|
||||||
uint16_t transaction_id;
|
|
||||||
// flags
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
uint8_t rd:1;
|
|
||||||
uint8_t tc:1;
|
|
||||||
uint8_t aa:1;
|
|
||||||
uint8_t opcode:4;
|
|
||||||
uint8_t qr:1;
|
|
||||||
|
|
||||||
uint8_t rcode:4;
|
|
||||||
uint8_t cd:1;
|
|
||||||
uint8_t ad:1;
|
|
||||||
uint8_t res:1;
|
|
||||||
uint8_t ra:1;
|
|
||||||
#elif BYTE_ORDER == BIG_ENDIAN
|
|
||||||
uint8_t qr:1; // DNS_QUERY or DNS_RESPONSE
|
|
||||||
uint8_t opcode:4;
|
|
||||||
uint8_t aa:1; // authoritative
|
|
||||||
uint8_t tc:1; // truncated
|
|
||||||
uint8_t rd:1; // recursion desired
|
|
||||||
|
|
||||||
uint8_t ra:1; // recursion available
|
|
||||||
uint8_t res:1; // reserved
|
|
||||||
uint8_t ad:1; // authenticated data
|
|
||||||
uint8_t cd:1; // checking disable
|
|
||||||
uint8_t rcode:4;
|
|
||||||
#else
|
|
||||||
#error "BYTE_ORDER undefined!"
|
|
||||||
#endif
|
|
||||||
uint16_t nquestion;
|
|
||||||
uint16_t nanswer;
|
|
||||||
uint16_t nauthority;
|
|
||||||
uint16_t naddtional;
|
|
||||||
} dnshdr_t;
|
|
||||||
|
|
||||||
typedef struct dns_rr_s {
|
|
||||||
char name[DNS_NAME_MAXLEN]; // original domain, such as www.example.com
|
|
||||||
uint16_t rtype;
|
|
||||||
uint16_t rclass;
|
|
||||||
uint32_t ttl;
|
|
||||||
uint16_t datalen;
|
|
||||||
char* data;
|
|
||||||
} dns_rr_t;
|
|
||||||
|
|
||||||
typedef struct dns_s {
|
|
||||||
dnshdr_t hdr;
|
|
||||||
dns_rr_t* questions;
|
|
||||||
dns_rr_t* answers;
|
|
||||||
dns_rr_t* authorities;
|
|
||||||
dns_rr_t* addtionals;
|
|
||||||
} dns_t;
|
|
||||||
|
|
||||||
BEGIN_EXTERN_C
|
|
||||||
|
|
||||||
// www.example.com => 3www7example3com
|
|
||||||
HV_EXPORT int dns_name_encode(const char* domain, char* buf);
|
|
||||||
// 3www7example3com => www.example.com
|
|
||||||
HV_EXPORT int dns_name_decode(const char* buf, char* domain);
|
|
||||||
|
|
||||||
HV_EXPORT int dns_rr_pack(dns_rr_t* rr, char* buf, int len);
|
|
||||||
HV_EXPORT int dns_rr_unpack(char* buf, int len, dns_rr_t* rr, int is_question);
|
|
||||||
|
|
||||||
HV_EXPORT int dns_pack(dns_t* dns, char* buf, int len);
|
|
||||||
HV_EXPORT int dns_unpack(char* buf, int len, dns_t* dns);
|
|
||||||
// NOTE: free dns->rrs
|
|
||||||
HV_EXPORT void dns_free(dns_t* dns);
|
|
||||||
|
|
||||||
// dns_pack -> sendto -> recvfrom -> dns_unpack
|
|
||||||
HV_EXPORT int dns_query(dns_t* query, dns_t* response, const char* nameserver DEFAULT("127.0.1.1"));
|
|
||||||
|
|
||||||
// domain -> dns_t query; -> dns_query -> dns_t response; -> addrs
|
|
||||||
HV_EXPORT int nslookup(const char* domain, uint32_t* addrs, int naddr, const char* nameserver DEFAULT("127.0.1.1"));
|
|
||||||
|
|
||||||
END_EXTERN_C
|
|
||||||
|
|
||||||
#endif // HV_DNS_H_
|
|
|
@ -1,96 +0,0 @@
|
||||||
#ifndef HV_FTP_H_
|
|
||||||
#define HV_FTP_H_
|
|
||||||
|
|
||||||
#include "hexport.h"
|
|
||||||
|
|
||||||
#define FTP_COMMAND_PORT 21
|
|
||||||
#define FTP_DATA_PORT 20
|
|
||||||
|
|
||||||
// ftp_command
|
|
||||||
// X(name)
|
|
||||||
#define FTP_COMMAND_MAP(X) \
|
|
||||||
X(HELP) \
|
|
||||||
X(USER) \
|
|
||||||
X(PASS) \
|
|
||||||
X(PWD) \
|
|
||||||
X(CWD) \
|
|
||||||
X(CDUP) \
|
|
||||||
X(MKD) \
|
|
||||||
X(RMD) \
|
|
||||||
X(STAT) \
|
|
||||||
X(SIZE) \
|
|
||||||
X(DELE) \
|
|
||||||
X(RNFR) \
|
|
||||||
X(RNTO) \
|
|
||||||
X(PORT) \
|
|
||||||
X(PASV) \
|
|
||||||
X(LIST) \
|
|
||||||
X(NLST) \
|
|
||||||
X(APPE) \
|
|
||||||
X(RETR) \
|
|
||||||
X(STOR) \
|
|
||||||
X(QUIT) \
|
|
||||||
|
|
||||||
enum ftp_command {
|
|
||||||
#define X(name) FTP_##name,
|
|
||||||
FTP_COMMAND_MAP(X)
|
|
||||||
#undef X
|
|
||||||
};
|
|
||||||
|
|
||||||
// ftp_status
|
|
||||||
// XXX(code, name, string)
|
|
||||||
#define FTP_STATUS_MAP(XXX) \
|
|
||||||
XXX(220, READY, Ready) \
|
|
||||||
XXX(221, BYE, Bye) \
|
|
||||||
XXX(226, TRANSFER_COMPLETE, Transfer complete) \
|
|
||||||
XXX(227, PASV, Entering Passive Mode) \
|
|
||||||
XXX(331, PASS, Password required) \
|
|
||||||
XXX(230, LOGIN_OK, Login OK) \
|
|
||||||
XXX(250, OK, OK) \
|
|
||||||
XXX(500, BAD_SYNTAX, Bad syntax) \
|
|
||||||
XXX(530, NOT_LOGIN, Not login) \
|
|
||||||
|
|
||||||
enum ftp_status {
|
|
||||||
#define XXX(code, name, string) FTP_STATUS_##name = code,
|
|
||||||
FTP_STATUS_MAP(XXX)
|
|
||||||
#undef XXX
|
|
||||||
};
|
|
||||||
|
|
||||||
// more friendly macros
|
|
||||||
#define FTP_MKDIR FTP_MKD
|
|
||||||
#define FTP_RMDIR FTP_RMD
|
|
||||||
#define FTP_APPEND FTP_APPE
|
|
||||||
#define FTP_REMOVE FTP_DELE
|
|
||||||
#define FTP_DOWNLOAD FTP_RETR
|
|
||||||
#define FTP_UPLOAD FTP_STOR
|
|
||||||
|
|
||||||
#define FTP_RECV_BUFSIZE 8192
|
|
||||||
|
|
||||||
typedef struct ftp_handle_s {
|
|
||||||
int sockfd;
|
|
||||||
char recvbuf[FTP_RECV_BUFSIZE];
|
|
||||||
void* userdata;
|
|
||||||
} ftp_handle_t;
|
|
||||||
|
|
||||||
BEGIN_EXTERN_C
|
|
||||||
|
|
||||||
HV_EXPORT const char* ftp_command_str(enum ftp_command cmd);
|
|
||||||
HV_EXPORT const char* ftp_status_str(enum ftp_status status);
|
|
||||||
|
|
||||||
HV_EXPORT int ftp_connect(ftp_handle_t* hftp, const char* host, int port);
|
|
||||||
HV_EXPORT int ftp_login(ftp_handle_t* hftp, const char* username, const char* password);
|
|
||||||
HV_EXPORT int ftp_quit(ftp_handle_t* hftp);
|
|
||||||
|
|
||||||
HV_EXPORT int ftp_exec(ftp_handle_t* hftp, const char* cmd, const char* param);
|
|
||||||
|
|
||||||
// local => remote
|
|
||||||
HV_EXPORT int ftp_upload(ftp_handle_t* hftp, const char* local_filepath, const char* remote_filepath);
|
|
||||||
// remote => local
|
|
||||||
HV_EXPORT int ftp_download(ftp_handle_t* hftp, const char* remote_filepath, const char* local_filepath);
|
|
||||||
|
|
||||||
typedef int (*ftp_download_cb)(ftp_handle_t* hftp, char* buf, int len);
|
|
||||||
HV_EXPORT int ftp_download_with_cb(ftp_handle_t* hftp, const char* filepath, ftp_download_cb cb);
|
|
||||||
|
|
||||||
END_EXTERN_C
|
|
||||||
|
|
||||||
#endif // HV_FTP_H_
|
|
|
@ -82,6 +82,7 @@ HV_EXPORT char* hv_strncat(char* dest, const char* src, size_t n);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HV_EXPORT char* hv_strnchr(const char* s, char c, size_t n);
|
HV_EXPORT char* hv_strnchr(const char* s, char c, size_t n);
|
||||||
|
HV_EXPORT char* hv_strnrchr(const char* s, char c, size_t n);
|
||||||
|
|
||||||
#define hv_strrchr_dot(str) strrchr(str, '.')
|
#define hv_strrchr_dot(str) strrchr(str, '.')
|
||||||
HV_EXPORT char* hv_strrchr_dir(const char* filepath);
|
HV_EXPORT char* hv_strrchr_dir(const char* filepath);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STDATOMIC_H
|
#ifndef HAVE_STDATOMIC_H
|
||||||
#define HAVE_STDATOMIC_H 1
|
#define HAVE_STDATOMIC_H 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SYS_TYPES_H
|
#ifndef HAVE_SYS_TYPES_H
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SYS_TIME_H
|
#ifndef HAVE_SYS_TIME_H
|
||||||
#define HAVE_SYS_TIME_H 1
|
#define HAVE_SYS_TIME_H 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_FCNTL_H
|
#ifndef HAVE_FCNTL_H
|
||||||
|
@ -30,11 +30,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_PTHREAD_H
|
#ifndef HAVE_PTHREAD_H
|
||||||
#define HAVE_PTHREAD_H 1
|
#define HAVE_PTHREAD_H 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_ENDIAN_H
|
#ifndef HAVE_ENDIAN_H
|
||||||
#define HAVE_ENDIAN_H 1
|
#define HAVE_ENDIAN_H 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SYS_ENDIAN_H
|
#ifndef HAVE_SYS_ENDIAN_H
|
||||||
|
@ -54,46 +54,49 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_CLOCK_GETTIME
|
#ifndef HAVE_CLOCK_GETTIME
|
||||||
#define HAVE_CLOCK_GETTIME 1
|
#define HAVE_CLOCK_GETTIME 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GETTIMEOFDAY
|
#ifndef HAVE_GETTIMEOFDAY
|
||||||
#define HAVE_GETTIMEOFDAY 1
|
#define HAVE_GETTIMEOFDAY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_PTHREAD_SPIN_LOCK
|
#ifndef HAVE_PTHREAD_SPIN_LOCK
|
||||||
#define HAVE_PTHREAD_SPIN_LOCK 1
|
#define HAVE_PTHREAD_SPIN_LOCK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||||
#define HAVE_PTHREAD_MUTEX_TIMEDLOCK 1
|
#define HAVE_PTHREAD_MUTEX_TIMEDLOCK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SEM_TIMEDWAIT
|
#ifndef HAVE_SEM_TIMEDWAIT
|
||||||
#define HAVE_SEM_TIMEDWAIT 1
|
#define HAVE_SEM_TIMEDWAIT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_PIPE
|
#ifndef HAVE_PIPE
|
||||||
#define HAVE_PIPE 1
|
#define HAVE_PIPE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SOCKETPAIR
|
#ifndef HAVE_SOCKETPAIR
|
||||||
#define HAVE_SOCKETPAIR 1
|
#define HAVE_SOCKETPAIR 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_EVENTFD
|
#ifndef HAVE_EVENTFD
|
||||||
#define HAVE_EVENTFD 1
|
#define HAVE_EVENTFD 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SETPROCTITLE
|
#ifndef HAVE_SETPROCTITLE
|
||||||
#define HAVE_SETPROCTITLE 0
|
#define HAVE_SETPROCTITLE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* #undef WITH_OPENSSL */
|
#define WITH_OPENSSL 1
|
||||||
/* #undef WITH_GNUTLS */
|
/* #undef WITH_GNUTLS */
|
||||||
/* #undef WITH_MBEDTLS */
|
/* #undef WITH_MBEDTLS */
|
||||||
|
|
||||||
/* #undef ENABLE_UDS */
|
/* #undef ENABLE_UDS */
|
||||||
/* #undef USE_MULTIMAP */
|
/* #undef USE_MULTIMAP */
|
||||||
|
|
||||||
|
#define WITH_WEPOLL 1
|
||||||
/* #undef WITH_KCP */
|
/* #undef WITH_KCP */
|
||||||
|
|
||||||
#endif // HV_CONFIG_H_
|
#endif // HV_CONFIG_H_
|
||||||
|
|
|
@ -37,32 +37,6 @@
|
||||||
#define HV_UNUSED
|
#define HV_UNUSED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// @param[IN | OUT | INOUT]
|
|
||||||
#ifndef IN
|
|
||||||
#define IN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OUT
|
|
||||||
#define OUT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef INOUT
|
|
||||||
#define INOUT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// @field[OPTIONAL | REQUIRED | REPEATED]
|
|
||||||
#ifndef OPTIONAL
|
|
||||||
#define OPTIONAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef REQUIRED
|
|
||||||
#define REQUIRED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef REPEATED
|
|
||||||
#define REPEATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#ifndef EXTERN_C
|
#ifndef EXTERN_C
|
||||||
|
|
|
@ -11,16 +11,18 @@ typedef struct hevent_s hevent_t;
|
||||||
|
|
||||||
// NOTE: The following structures are subclasses of hevent_t,
|
// NOTE: The following structures are subclasses of hevent_t,
|
||||||
// inheriting hevent_t data members and function members.
|
// inheriting hevent_t data members and function members.
|
||||||
|
typedef struct hio_s hio_t;
|
||||||
typedef struct hidle_s hidle_t;
|
typedef struct hidle_s hidle_t;
|
||||||
typedef struct htimer_s htimer_t;
|
typedef struct htimer_s htimer_t;
|
||||||
typedef struct htimeout_s htimeout_t;
|
typedef struct htimeout_s htimeout_t;
|
||||||
typedef struct hperiod_s hperiod_t;
|
typedef struct hperiod_s hperiod_t;
|
||||||
typedef struct hio_s hio_t;
|
typedef struct hevent_s hsignal_t;
|
||||||
|
|
||||||
typedef void (*hevent_cb) (hevent_t* ev);
|
typedef void (*hevent_cb) (hevent_t* ev);
|
||||||
|
typedef void (*hio_cb) (hio_t* io);
|
||||||
typedef void (*hidle_cb) (hidle_t* idle);
|
typedef void (*hidle_cb) (hidle_t* idle);
|
||||||
typedef void (*htimer_cb) (htimer_t* timer);
|
typedef void (*htimer_cb) (htimer_t* timer);
|
||||||
typedef void (*hio_cb) (hio_t* io);
|
typedef void (*hsignal_cb) (hsignal_t* sig);
|
||||||
|
|
||||||
typedef void (*haccept_cb) (hio_t* io);
|
typedef void (*haccept_cb) (hio_t* io);
|
||||||
typedef void (*hconnect_cb) (hio_t* io);
|
typedef void (*hconnect_cb) (hio_t* io);
|
||||||
|
@ -31,7 +33,8 @@ typedef void (*hclose_cb) (hio_t* io);
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HLOOP_STATUS_STOP,
|
HLOOP_STATUS_STOP,
|
||||||
HLOOP_STATUS_RUNNING,
|
HLOOP_STATUS_RUNNING,
|
||||||
HLOOP_STATUS_PAUSE
|
HLOOP_STATUS_PAUSE,
|
||||||
|
HLOOP_STATUS_DESTROY
|
||||||
} hloop_status_e;
|
} hloop_status_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -41,6 +44,7 @@ typedef enum {
|
||||||
HEVENT_TYPE_PERIOD = 0x00000020,
|
HEVENT_TYPE_PERIOD = 0x00000020,
|
||||||
HEVENT_TYPE_TIMER = HEVENT_TYPE_TIMEOUT|HEVENT_TYPE_PERIOD,
|
HEVENT_TYPE_TIMER = HEVENT_TYPE_TIMEOUT|HEVENT_TYPE_PERIOD,
|
||||||
HEVENT_TYPE_IDLE = 0x00000100,
|
HEVENT_TYPE_IDLE = 0x00000100,
|
||||||
|
HEVENT_TYPE_SIGNAL = 0x00000200,
|
||||||
HEVENT_TYPE_CUSTOM = 0x00000400, // 1024
|
HEVENT_TYPE_CUSTOM = 0x00000400, // 1024
|
||||||
} hevent_type_e;
|
} hevent_type_e;
|
||||||
|
|
||||||
|
@ -93,6 +97,7 @@ typedef enum {
|
||||||
HIO_TYPE_STDIO = 0x0000000F,
|
HIO_TYPE_STDIO = 0x0000000F,
|
||||||
|
|
||||||
HIO_TYPE_FILE = 0x00000010,
|
HIO_TYPE_FILE = 0x00000010,
|
||||||
|
HIO_TYPE_PIPE = 0x00000020,
|
||||||
|
|
||||||
HIO_TYPE_IP = 0x00000100,
|
HIO_TYPE_IP = 0x00000100,
|
||||||
HIO_TYPE_SOCK_RAW = 0x00000F00,
|
HIO_TYPE_SOCK_RAW = 0x00000F00,
|
||||||
|
@ -182,6 +187,10 @@ HV_EXPORT void* hloop_userdata(hloop_t* loop);
|
||||||
// NOTE: hloop_post_event is thread-safe, used to post event from other thread to loop thread.
|
// NOTE: hloop_post_event is thread-safe, used to post event from other thread to loop thread.
|
||||||
HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);
|
HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);
|
||||||
|
|
||||||
|
// signal
|
||||||
|
HV_EXPORT hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);
|
||||||
|
HV_EXPORT void hsignal_del(hsignal_t* sig);
|
||||||
|
|
||||||
// idle
|
// idle
|
||||||
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
|
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
|
||||||
HV_EXPORT void hidle_del(hidle_t* idle);
|
HV_EXPORT void hidle_del(hidle_t* idle);
|
||||||
|
@ -435,6 +444,10 @@ HV_EXPORT hio_t* hloop_create_udp_server (hloop_t* loop, const char* host, int p
|
||||||
// @see examples/nc.c
|
// @see examples/nc.c
|
||||||
HV_EXPORT hio_t* hloop_create_udp_client (hloop_t* loop, const char* host, int port);
|
HV_EXPORT hio_t* hloop_create_udp_client (hloop_t* loop, const char* host, int port);
|
||||||
|
|
||||||
|
//-----------------pipe---------------------------------------------
|
||||||
|
// @see examples/pipe_test.c
|
||||||
|
HV_EXPORT int hio_create_pipe(hloop_t* loop, hio_t* pipeio[2]);
|
||||||
|
|
||||||
//-----------------upstream---------------------------------------------
|
//-----------------upstream---------------------------------------------
|
||||||
// hio_read(io)
|
// hio_read(io)
|
||||||
// hio_read(io->upstream_io)
|
// hio_read(io->upstream_io)
|
||||||
|
|
|
@ -65,6 +65,7 @@ typedef struct option_s {
|
||||||
char short_opt;
|
char short_opt;
|
||||||
const char* long_opt;
|
const char* long_opt;
|
||||||
int arg_type;
|
int arg_type;
|
||||||
|
const char* description;
|
||||||
} option_t;
|
} option_t;
|
||||||
|
|
||||||
HV_EXPORT int main_ctx_init(int argc, char** argv);
|
HV_EXPORT int main_ctx_init(int argc, char** argv);
|
||||||
|
@ -76,7 +77,8 @@ HV_EXPORT void main_ctx_free(void);
|
||||||
// watch -n10 ls
|
// watch -n10 ls
|
||||||
HV_EXPORT int parse_opt(int argc, char** argv, const char* opt);
|
HV_EXPORT int parse_opt(int argc, char** argv, const char* opt);
|
||||||
// gcc -g -Wall -O3 -std=cpp main.c
|
// gcc -g -Wall -O3 -std=cpp main.c
|
||||||
HV_EXPORT int parse_opt_long(int argc, char** argv, const option_t* long_options, int size);
|
HV_EXPORT int parse_opt_long(int argc, char** argv, const option_t* long_options, int opt_size);
|
||||||
|
HV_EXPORT int dump_opt_long(const option_t* long_options, int opt_size, char* out_str, int out_size);
|
||||||
HV_EXPORT const char* get_arg(const char* key);
|
HV_EXPORT const char* get_arg(const char* key);
|
||||||
HV_EXPORT const char* get_env(const char* key);
|
HV_EXPORT const char* get_env(const char* key);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#undef OS_UNIX
|
#undef OS_UNIX
|
||||||
#define OS_WIN
|
#define OS_WIN
|
||||||
#else
|
#else
|
||||||
|
#undef OS_WIN
|
||||||
#define OS_UNIX
|
#define OS_UNIX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -142,6 +143,12 @@
|
||||||
|
|
||||||
// headers
|
// headers
|
||||||
#ifdef OS_WIN
|
#ifdef OS_WIN
|
||||||
|
#ifndef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
#elif _WIN32_WINNT < 0x0600
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
#endif
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -82,9 +82,11 @@ HV_INLINE int nonblocking(int s) {
|
||||||
return fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
|
return fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef closesocket
|
||||||
HV_INLINE int closesocket(int sockfd) {
|
HV_INLINE int closesocket(int sockfd) {
|
||||||
return close(sockfd);
|
return close(sockfd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,18 @@ HV_EXPORT std::string trim_pairs(const std::string& str, const char* pairs = PAI
|
||||||
HV_EXPORT std::string replace(const std::string& str, const std::string& find, const std::string& rep);
|
HV_EXPORT std::string replace(const std::string& str, const std::string& find, const std::string& rep);
|
||||||
HV_EXPORT std::string replaceAll(const std::string& str, const std::string& find, const std::string& rep);
|
HV_EXPORT std::string replaceAll(const std::string& str, const std::string& find, const std::string& rep);
|
||||||
|
|
||||||
|
struct HV_EXPORT NetAddr {
|
||||||
|
std::string ip;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
NetAddr() : port(0) {}
|
||||||
|
NetAddr(const std::string& _ip, int _port) : ip(_ip), port(_port) {}
|
||||||
|
NetAddr(const std::string& ipport) { from_string(ipport); }
|
||||||
|
|
||||||
|
void from_string(const std::string& ipport);
|
||||||
|
std::string to_string();
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace hv
|
} // end namespace hv
|
||||||
|
|
||||||
#endif // HV_STRING_H_
|
#endif // HV_STRING_H_
|
||||||
|
|
|
@ -8,7 +8,7 @@ BEGIN_EXTERN_C
|
||||||
|
|
||||||
#define HV_VERSION_MAJOR 1
|
#define HV_VERSION_MAJOR 1
|
||||||
#define HV_VERSION_MINOR 3
|
#define HV_VERSION_MINOR 3
|
||||||
#define HV_VERSION_PATCH 2
|
#define HV_VERSION_PATCH 3
|
||||||
|
|
||||||
#define HV_VERSION_STRING STRINGIFY(HV_VERSION_MAJOR) "." \
|
#define HV_VERSION_STRING STRINGIFY(HV_VERSION_MAJOR) "." \
|
||||||
STRINGIFY(HV_VERSION_MINOR) "." \
|
STRINGIFY(HV_VERSION_MINOR) "." \
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
#ifndef HV_ICMP_H_
|
|
||||||
#define HV_ICMP_H_
|
|
||||||
|
|
||||||
#include "hexport.h"
|
|
||||||
|
|
||||||
BEGIN_EXTERN_C
|
|
||||||
|
|
||||||
// @param cnt: ping count
|
|
||||||
// @return: ok count
|
|
||||||
// @note: printd $CC -DPRINT_DEBUG
|
|
||||||
HV_EXPORT int ping(const char* host, int cnt DEFAULT(4));
|
|
||||||
|
|
||||||
END_EXTERN_C
|
|
||||||
|
|
||||||
#endif // HV_ICMP_H_
|
|
|
@ -29,6 +29,7 @@ struct mqtt_client_s {
|
||||||
unsigned char alloced_ssl_ctx: 1; // intern
|
unsigned char alloced_ssl_ctx: 1; // intern
|
||||||
unsigned char connected : 1;
|
unsigned char connected : 1;
|
||||||
unsigned short keepalive;
|
unsigned short keepalive;
|
||||||
|
int ping_cnt;
|
||||||
char client_id[64];
|
char client_id[64];
|
||||||
// will
|
// will
|
||||||
mqtt_message_t* will;
|
mqtt_message_t* will;
|
||||||
|
@ -47,7 +48,7 @@ struct mqtt_client_s {
|
||||||
// privdata
|
// privdata
|
||||||
hloop_t* loop;
|
hloop_t* loop;
|
||||||
hio_t* io;
|
hio_t* io;
|
||||||
htimer_t* reconn_timer;
|
htimer_t* timer;
|
||||||
// SSL/TLS
|
// SSL/TLS
|
||||||
hssl_ctx_t ssl_ctx;
|
hssl_ctx_t ssl_ctx;
|
||||||
// thread-safe
|
// thread-safe
|
||||||
|
@ -101,6 +102,7 @@ HV_EXPORT int mqtt_client_reconnect(mqtt_client_t* cli);
|
||||||
// on_connect -> mqtt_client_login ->
|
// on_connect -> mqtt_client_login ->
|
||||||
// on_connack
|
// on_connack
|
||||||
HV_EXPORT void mqtt_client_set_connect_timeout(mqtt_client_t* cli, int ms);
|
HV_EXPORT void mqtt_client_set_connect_timeout(mqtt_client_t* cli, int ms);
|
||||||
|
HV_EXPORT void mqtt_client_set_host(mqtt_client_t* cli, const char* host, int port, int ssl);
|
||||||
HV_EXPORT int mqtt_client_connect(mqtt_client_t* cli,
|
HV_EXPORT int mqtt_client_connect(mqtt_client_t* cli,
|
||||||
const char* host,
|
const char* host,
|
||||||
int port DEFAULT(DEFAULT_MQTT_PORT),
|
int port DEFAULT(DEFAULT_MQTT_PORT),
|
||||||
|
@ -125,4 +127,214 @@ HV_EXPORT int mqtt_client_unsubscribe(mqtt_client_t* cli,
|
||||||
|
|
||||||
END_EXTERN_C
|
END_EXTERN_C
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace hv {
|
||||||
|
|
||||||
|
// @usage examples/mqtt/mqtt_client_test.cpp
|
||||||
|
class MqttClient {
|
||||||
|
public:
|
||||||
|
mqtt_client_t* client;
|
||||||
|
// callbacks
|
||||||
|
typedef std::function<void(MqttClient*)> MqttCallback;
|
||||||
|
typedef std::function<void(MqttClient*, mqtt_message_t*)> MqttMessageCallback;
|
||||||
|
MqttCallback onConnect;
|
||||||
|
MqttCallback onClose;
|
||||||
|
MqttMessageCallback onMessage;
|
||||||
|
|
||||||
|
MqttClient(hloop_t* loop = NULL) {
|
||||||
|
client = mqtt_client_new(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
~MqttClient() {
|
||||||
|
if (client) {
|
||||||
|
mqtt_client_free(client);
|
||||||
|
client = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
mqtt_client_set_callback(client, on_mqtt);
|
||||||
|
mqtt_client_set_userdata(client, this);
|
||||||
|
mqtt_client_run(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
mqtt_client_stop(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setID(const char* id) {
|
||||||
|
mqtt_client_set_id(client, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWill(mqtt_message_t* will) {
|
||||||
|
mqtt_client_set_will(client, will);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAuth(const char* username, const char* password) {
|
||||||
|
mqtt_client_set_auth(client, username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPingInterval(int sec) {
|
||||||
|
client->keepalive = sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastError() {
|
||||||
|
return mqtt_client_get_last_error(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSL/TLS
|
||||||
|
int setSslCtx(hssl_ctx_t ssl_ctx) {
|
||||||
|
return mqtt_client_set_ssl_ctx(client, ssl_ctx);
|
||||||
|
}
|
||||||
|
int newSslCtx(hssl_ctx_opt_t* opt) {
|
||||||
|
return mqtt_client_new_ssl_ctx(client, opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setReconnect(reconn_setting_t* reconn) {
|
||||||
|
mqtt_client_set_reconnect(client, reconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setConnectTimeout(int ms) {
|
||||||
|
mqtt_client_set_connect_timeout(client, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHost(const char* host, int port = DEFAULT_MQTT_PORT, int ssl = 0) {
|
||||||
|
mqtt_client_set_host(client, host, port, ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect(const char* host, int port = DEFAULT_MQTT_PORT, int ssl = 0) {
|
||||||
|
return mqtt_client_connect(client, host, port, ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int reconnect() {
|
||||||
|
return mqtt_client_reconnect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
int disconnect() {
|
||||||
|
return mqtt_client_disconnect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isConnected() {
|
||||||
|
return mqtt_client_is_connected(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
int publish(mqtt_message_t* msg, MqttCallback ack_cb = NULL) {
|
||||||
|
int mid = mqtt_client_publish(client, msg);
|
||||||
|
if (msg->qos > 0 && mid >= 0 && ack_cb) {
|
||||||
|
setAckCallback(mid, ack_cb);
|
||||||
|
}
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int publish(const std::string& topic, const std::string& payload, int qos = 0, int retain = 0, MqttCallback ack_cb = NULL) {
|
||||||
|
mqtt_message_t msg;
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.topic_len = topic.size();
|
||||||
|
msg.topic = topic.c_str();
|
||||||
|
msg.payload_len = payload.size();
|
||||||
|
msg.payload = payload.c_str();
|
||||||
|
msg.qos = qos;
|
||||||
|
msg.retain = retain;
|
||||||
|
return publish(&msg, ack_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int subscribe(const char* topic, int qos = 0, MqttCallback ack_cb = NULL) {
|
||||||
|
int mid = mqtt_client_subscribe(client, topic, qos);
|
||||||
|
if (qos > 0 && mid >= 0 && ack_cb) {
|
||||||
|
setAckCallback(mid, ack_cb);
|
||||||
|
}
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unsubscribe(const char* topic, MqttCallback ack_cb = NULL) {
|
||||||
|
int mid = mqtt_client_unsubscribe(client, topic);
|
||||||
|
if (mid >= 0 && ack_cb) {
|
||||||
|
setAckCallback(mid, ack_cb);
|
||||||
|
}
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setAckCallback(int mid, MqttCallback cb) {
|
||||||
|
ack_cbs_mutex.lock();
|
||||||
|
ack_cbs[mid] = std::move(cb);
|
||||||
|
ack_cbs_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void invokeAckCallback(int mid) {
|
||||||
|
MqttCallback ack_cb = NULL;
|
||||||
|
ack_cbs_mutex.lock();
|
||||||
|
auto iter = ack_cbs.find(mid);
|
||||||
|
if (iter != ack_cbs.end()) {
|
||||||
|
ack_cb = std::move(iter->second);
|
||||||
|
ack_cbs.erase(iter);
|
||||||
|
}
|
||||||
|
ack_cbs_mutex.unlock();
|
||||||
|
if (ack_cb) ack_cb(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_mqtt(mqtt_client_t* cli, int type) {
|
||||||
|
MqttClient* client = (MqttClient*)mqtt_client_get_userdata(cli);
|
||||||
|
// printf("on_mqtt type=%d\n", type);
|
||||||
|
switch(type) {
|
||||||
|
case MQTT_TYPE_CONNECT:
|
||||||
|
// printf("mqtt connected!\n");
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_DISCONNECT:
|
||||||
|
// printf("mqtt disconnected!\n");
|
||||||
|
if (client->onClose) {
|
||||||
|
client->onClose(client);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_CONNACK:
|
||||||
|
// printf("mqtt connack!\n");
|
||||||
|
if (client->onConnect) {
|
||||||
|
client->onConnect(client);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_PUBLISH:
|
||||||
|
if (client->onMessage) {
|
||||||
|
client->onMessage(client, &cli->message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_PUBACK: /* qos = 1 */
|
||||||
|
// printf("mqtt puback mid=%d\n", cli->mid);
|
||||||
|
client->invokeAckCallback(cli->mid);
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_PUBREC: /* qos = 2 */
|
||||||
|
// printf("mqtt pubrec mid=%d\n", cli->mid);
|
||||||
|
// wait MQTT_TYPE_PUBCOMP
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_PUBCOMP: /* qos = 2 */
|
||||||
|
// printf("mqtt pubcomp mid=%d\n", cli->mid);
|
||||||
|
client->invokeAckCallback(cli->mid);
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_SUBACK:
|
||||||
|
// printf("mqtt suback mid=%d\n", cli->mid);
|
||||||
|
client->invokeAckCallback(cli->mid);
|
||||||
|
break;
|
||||||
|
case MQTT_TYPE_UNSUBACK:
|
||||||
|
// printf("mqtt unsuback mid=%d\n", cli->mid);
|
||||||
|
client->invokeAckCallback(cli->mid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// mid => ack callback
|
||||||
|
std::map<int, MqttCallback> ack_cbs;
|
||||||
|
std::mutex ack_cbs_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // HV_MQTT_CLIENT_H_
|
#endif // HV_MQTT_CLIENT_H_
|
||||||
|
|