forked from lthn/blockchain
Merge branch 'master' into develop
This commit is contained in:
commit
9c59ff35f7
437 changed files with 40813 additions and 232438 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "contrib/miniupnp"]
|
||||
path = contrib/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp
|
||||
|
|
@ -45,9 +45,14 @@ if (UNIX AND NOT APPLE)
|
|||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
# TODO(unassigned): expand on types and versions, and then refactor.
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(CLANG TRUE)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions("/bigobj /Zm1000 /Z7 /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4503 /wd4345 /wd4091 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /D__SSE4_1__")
|
||||
add_compile_options(/bigobj /Zm1000 /Z7 /MP2 /W3 /GS- /wd4996 /wd4503 /wd4345 /wd4091 /FIinline_c.h)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760 /DEBUG dbghelp.lib")
|
||||
if(STATIC)
|
||||
foreach(VAR CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
|
||||
|
|
@ -66,7 +71,6 @@ else()
|
|||
# if(NOT APPLE)
|
||||
# set(WARNINGS "${WARNINGS} -Werror")
|
||||
# endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set(WARNINGS "${WARNINGS} -Wno-shift-count-overflow -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
|
||||
else()
|
||||
|
|
@ -103,13 +107,15 @@ else()
|
|||
else()
|
||||
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
|
||||
endif()
|
||||
set(LINUX_LD_GOLD "")
|
||||
set(LINUX_STATIC_ICU "")
|
||||
if((NOT APPLE) AND (NOT MSVC))
|
||||
set(LINUX_LD_GOLD "-fuse-ld=gold")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -ftemplate-depth-1024 -std=c++11 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
|
||||
if (NOT APPLE AND NOT MSVC)
|
||||
if (CLANG)
|
||||
set(LLVM_USE_LINKER "gold")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LINUX_LD_GOLD} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LINUX_LD_GOLD} -fpermissive -ftemplate-depth-1024 -std=c++11 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8))
|
||||
set(DEBUG_FLAGS "-g3 -O0") #set(DEBUG_FLAGS "-g3 -Og")
|
||||
else()
|
||||
|
|
@ -152,7 +158,7 @@ endif()
|
|||
message(STATUS "Boost: ${Boost_VERSION} from ${Boost_LIBRARY_DIRS}")
|
||||
|
||||
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/contrib/ethereum/libethash)
|
||||
if(MINGW)
|
||||
set(Boost_LIBRARIES "${Boost_LIBRARIES};ws2_32;mswsock")
|
||||
elseif(NOT MSVC)
|
||||
|
|
@ -196,8 +202,11 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
set(BUILD_TESTS FALSE CACHE BOOL "Build Zano tests")
|
||||
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
|
|
|||
85
Makefile
85
Makefile
|
|
@ -1,28 +1,77 @@
|
|||
all: all-release
|
||||
# Copyright (c) 2014-2019 Zano Project
|
||||
# Copyright (c) 2014 The Cryptonote developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
cmake-debug:
|
||||
mkdir -p build/debug
|
||||
cd build/debug && cmake -D CMAKE_BUILD_TYPE=Debug ../..
|
||||
# Define CMake generator
|
||||
system := $(shell uname)
|
||||
ifneq (, $(findstring MINGW, $(system)))
|
||||
cmake_gen = -G 'MSYS Makefiles'
|
||||
endif
|
||||
|
||||
build-debug: cmake-debug
|
||||
cd build/debug && $(MAKE)
|
||||
cmake = cmake $(cmake_gen)
|
||||
|
||||
test-debug: build-debug
|
||||
cd build/debug && $(MAKE) test
|
||||
cmake_debug = $(cmake) -D CMAKE_BUILD_TYPE=Debug
|
||||
cmake_release = $(cmake) -D CMAKE_BUILD_TYPE=Release
|
||||
|
||||
all-debug: build-debug
|
||||
cmake_gui = -D BUILD_GUI=ON
|
||||
cmake_static = -D STATIC=ON
|
||||
cmake_tests = -D BUILD_TESTS=ON
|
||||
|
||||
cmake-release:
|
||||
mkdir -p build/release
|
||||
cd build/release && cmake -D CMAKE_BUILD_TYPE=Release ../..
|
||||
# Helper macro
|
||||
define CMAKE
|
||||
mkdir -p $1 && cd $1 && $2 ../../
|
||||
endef
|
||||
|
||||
build-release: cmake-release
|
||||
cd build/release && $(MAKE)
|
||||
build = build
|
||||
dir_debug = $(build)/debug
|
||||
dir_release = $(build)/release
|
||||
|
||||
test-release: build-release
|
||||
cd build/release && $(MAKE) test
|
||||
all: release
|
||||
|
||||
all-release: build-release
|
||||
release:
|
||||
$(eval command += $(cmake_release))
|
||||
$(call CMAKE,$(dir_release),$(command)) && $(MAKE)
|
||||
|
||||
debug:
|
||||
$(eval command += $(cmake_debug))
|
||||
$(call CMAKE,$(dir_debug),$(command)) && $(MAKE)
|
||||
|
||||
static: static-release
|
||||
static-release:
|
||||
$(eval command += $(cmake_release) $(cmake_static))
|
||||
$(call CMAKE,$(dir_release),$(command)) && $(MAKE)
|
||||
|
||||
#
|
||||
# GUI
|
||||
#
|
||||
|
||||
gui: gui-release
|
||||
gui-release:
|
||||
$(eval command += $(cmake_release) $(cmake_gui))
|
||||
$(call CMAKE,$(dir_release),$(command)) && $(MAKE)
|
||||
|
||||
gui-debug:
|
||||
$(eval command += $(cmake_debug) $(cmake_gui))
|
||||
$(call CMAKE,$(dir_debug),$(command)) && $(MAKE)
|
||||
|
||||
gui-static: gui-release-static
|
||||
gui-release-static:
|
||||
$(eval command += $(cmake_release) $(cmake_gui) $(cmake_static))
|
||||
$(call CMAKE,$(dir_release),$(command)) && $(MAKE)
|
||||
|
||||
#
|
||||
# Tests
|
||||
#
|
||||
|
||||
test: test-release
|
||||
test-release:
|
||||
$(eval command += $(cmake_release) $(cmake_tests))
|
||||
$(call CMAKE,$(dir_release),$(command)) && $(MAKE) && $(MAKE) test
|
||||
|
||||
test-debug:
|
||||
$(eval command += $(cmake_debug) $(cmake_tests))
|
||||
$(call CMAKE,$(dir_debug),$(command)) && $(MAKE) && $(MAKE) test
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
|
@ -30,4 +79,4 @@ clean:
|
|||
tags:
|
||||
ctags -R --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ src contrib tests/gtest
|
||||
|
||||
.PHONY: all cmake-debug build-debug test-debug all-debug cmake-release build-release test-release all-release clean tags
|
||||
.PHONY: all release debug static static-release gui gui-release gui-static gui-release-static gui-debug test test-release test-debug clean tags
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -1,10 +1,21 @@
|
|||
Building
|
||||
--------
|
||||
|
||||
### Cloning
|
||||
|
||||
Be sure to properly clone the repository:
|
||||
|
||||
`$ git clone --recursive https://github.com/hyle-team/zano.git`
|
||||
|
||||
or, if already cloned:
|
||||
|
||||
`$ cd zano/ && git submodule init && git submodule update`
|
||||
|
||||
### Dependencies
|
||||
| component / version | minimum <br>(not recommended but may work) | recommended | most recent of what we have ever tested |
|
||||
|--|--|--|--|
|
||||
| gcc (Linux) | 5.4.0 | 7.2.0 | 7.2.0 |
|
||||
| gcc (Linux) | 5.4.0 | 7.2.0 | 8.3.0 |
|
||||
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2015 (14.0 update 3) | 2017 (15.5.7) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 7.3.1 | 9.2 | 9.2 |
|
||||
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.4.1 | 3.11.0 |
|
||||
|
|
@ -12,12 +23,16 @@ Building
|
|||
| [Qt](https://download.qt.io/archive/qt/) (only for GUI) | 5.8.0 | 5.9.1 | 5.10.1 |
|
||||
|
||||
### Linux
|
||||
|
||||
Recommended OS version: Ubuntu 17.04 LTS.
|
||||
1. Install dependencies: `sudo apt-get install build-essential git cmake unzip libicu-dev ocl-icd-opencl-dev mesa-common-dev libglu1-mesa-dev`
|
||||
2. Install Qt and Boost
|
||||
3. Set `BOOST_ROOT` and `QT_PREFIX_PATH` environment variables
|
||||
4. `mkdir build` <br> `cd build` <br> `cmake -DBUILD_GUI=FALSE -DSTATIC=TRUE ..` <br> `make`
|
||||
5. In order to build GUI, revise and run script at `/utils/build_script_linux.sh`
|
||||
|
||||
1. For server version: \
|
||||
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen`\
|
||||
For GUI version:\
|
||||
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen mesa-common-dev libglu1-mesa-dev qt5-default qtwebengine5-dev`
|
||||
|
||||
2. `$ cd zano/ && make -j$(nproc) gui`
|
||||
3. Look for the binaries, including the `Zano` GUI, in the build directory
|
||||
|
||||
### Windows
|
||||
Recommended OS version: Windows 7 x64.
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
set(UPNPC_BUILD_STATIC ON CACHE BOOL "Build static library")
|
||||
set(UPNPC_BUILD_SHARED OFF CACHE BOOL "Build shared library")
|
||||
set(UPNPC_BUILD_TESTS OFF CACHE BOOL "Build test executables")
|
||||
add_subdirectory(miniupnpc)
|
||||
add_subdirectory(miniupnp/miniupnpc)
|
||||
add_subdirectory(zlib)
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(ethereum)
|
||||
|
||||
|
||||
|
||||
set_property(TARGET upnpc-static PROPERTY FOLDER "contrib")
|
||||
set_property(TARGET upnpc-static PROPERTY FOLDER "contrib/miniupnp")
|
||||
set_property(TARGET zlibstatic PROPERTY FOLDER "contrib")
|
||||
set_property(TARGET lmdb PROPERTY FOLDER "contrib")
|
||||
|
||||
|
||||
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ add_subdirectory(liblmdb)
|
|||
if(MSVC)
|
||||
target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172)
|
||||
else()
|
||||
target_compile_options(lmdb PRIVATE -Wno-discarded-qualifiers -Wno-empty-body -Wno-unused-but-set-variable)
|
||||
# Warnings as used by LMDB itself (LMDB_0.9.23)
|
||||
target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -35,12 +35,11 @@ namespace eos {
|
|||
|
||||
// version of the linked boost archive library
|
||||
const archive_version_type archive_version(
|
||||
11
|
||||
// #if BOOST_VERSION < 103700
|
||||
// boost::archive::ARCHIVE_VERSION()
|
||||
// #else
|
||||
// boost::archive::BOOST_ARCHIVE_VERSION()
|
||||
// #endif
|
||||
#if BOOST_VERSION < 103700
|
||||
boost::archive::ARCHIVE_VERSION()
|
||||
#else
|
||||
boost::archive::BOOST_ARCHIVE_VERSION()
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* \file portable_iarchive.hpp
|
||||
* \brief Provides an archive to read from portable binary files.
|
||||
* \author christian.pfligersdorffer@gmx.at
|
||||
* \version 5.0
|
||||
* \version 5.1
|
||||
*
|
||||
* This pair of archives brings the advantages of binary streams to the cross
|
||||
* platform boost::serialization user. While being almost as fast as the native
|
||||
|
|
@ -23,6 +23,9 @@
|
|||
* chance it will instantly work for your specific setup. If you encounter
|
||||
* problems or have suggestions please contact the author.
|
||||
*
|
||||
* \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to
|
||||
* ecotax for pointing to the issue with shared_ptr_helper.
|
||||
*
|
||||
* \note Version 5.0 is now compatible with boost up to version 1.49 and enables
|
||||
* serialization of std::wstring by converting it to/from utf8 (thanks to
|
||||
* Arash Abghari for this suggestion). With that all unit tests from the
|
||||
|
|
@ -89,9 +92,7 @@
|
|||
#include <boost/archive/basic_binary_iprimitive.hpp>
|
||||
#include <boost/archive/basic_binary_iarchive.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 105600
|
||||
#include <boost/serialization/shared_ptr_helper.hpp>
|
||||
#elif BOOST_VERSION >= 103500
|
||||
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
|
||||
#include <boost/archive/shared_ptr_helper.hpp>
|
||||
#endif
|
||||
|
||||
|
|
@ -115,14 +116,16 @@
|
|||
#include <boost/math/fpclassify.hpp>
|
||||
#elif BOOST_VERSION < 104800
|
||||
#include <boost/spirit/home/support/detail/integer/endian.hpp>
|
||||
// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math
|
||||
#elif BOOST_VERSION < 106900
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#include <boost/spirit/home/support/detail/endian/endian.hpp>
|
||||
#else
|
||||
#include <boost/spirit/home/support/detail/endian/endian.hpp>
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#endif
|
||||
|
||||
// namespace alias
|
||||
#if BOOST_VERSION < 103800
|
||||
#if BOOST_VERSION < 103800 || BOOST_VERSION >= 106900
|
||||
namespace fp = boost::math;
|
||||
#else
|
||||
namespace fp = boost::spirit::math;
|
||||
|
|
@ -135,7 +138,7 @@ namespace endian = boost::detail;
|
|||
namespace endian = boost::spirit::detail;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING
|
||||
// used for wstring to utf8 conversion
|
||||
#include <boost/program_options/config.hpp>
|
||||
#include <boost/program_options/detail/convert.hpp>
|
||||
|
|
@ -190,9 +193,7 @@ namespace eos {
|
|||
// load_override functions so we chose to stay one level higher
|
||||
, public boost::archive::basic_binary_iarchive<portable_iarchive>
|
||||
|
||||
#if BOOST_VERSION >= 105600
|
||||
// mix-in helper class for serializing shared_ptr does not exist anymore
|
||||
#elif BOOST_VERSION >= 103500
|
||||
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
|
||||
// mix-in helper class for serializing shared_ptr
|
||||
, public boost::archive::detail::shared_ptr_helper
|
||||
#endif
|
||||
|
|
@ -349,7 +350,7 @@ namespace eos {
|
|||
T temp = size < 0 ? -1 : 0;
|
||||
load_binary(&temp, abs(size));
|
||||
|
||||
// load the value from little endian - is is then converted
|
||||
// load the value from little endian - it is then converted
|
||||
// to the target type T and fits it because size <= sizeof(T)
|
||||
t = endian::load_little_endian<T, sizeof(T)>(&temp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* \file portable_oarchive.hpp
|
||||
* \brief Provides an archive to create portable binary files.
|
||||
* \author christian.pfligersdorffer@gmx.at
|
||||
* \version 5.0
|
||||
* \version 5.1
|
||||
*
|
||||
* This pair of archives brings the advantages of binary streams to the cross
|
||||
* platform boost::serialization user. While being almost as fast as the native
|
||||
|
|
@ -23,6 +23,9 @@
|
|||
* chance it will instantly work for your specific setup. If you encounter
|
||||
* problems or have suggestions please contact the author.
|
||||
*
|
||||
* \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to
|
||||
* ecotax for pointing to the issue with shared_ptr_helper.
|
||||
*
|
||||
* \note Version 5.0 is now compatible with boost up to version 1.49 and enables
|
||||
* serialization of std::wstring by converting it to/from utf8 (thanks to
|
||||
* Arash Abghari for this suggestion). With that all unit tests from the
|
||||
|
|
@ -91,15 +94,9 @@
|
|||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/archive/basic_binary_oprimitive.hpp>
|
||||
#include <boost/archive/basic_binary_oarchive.hpp>
|
||||
#if BOOST_VERSION >= 105600
|
||||
#include <boost/serialization/shared_ptr_helper.hpp>
|
||||
#elif BOOST_VERSION >= 103500
|
||||
#include <boost/archive/shared_ptr_helper.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION >= 104500
|
||||
#include <boost/program_options/config.hpp>
|
||||
#include <boost/program_options/detail/convert.hpp>
|
||||
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
|
||||
#include <boost/archive/shared_ptr_helper.hpp>
|
||||
#endif
|
||||
|
||||
// funny polymorphics
|
||||
|
|
@ -122,14 +119,16 @@
|
|||
#include <boost/math/fpclassify.hpp>
|
||||
#elif BOOST_VERSION < 104800
|
||||
#include <boost/spirit/home/support/detail/integer/endian.hpp>
|
||||
// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math
|
||||
#elif BOOST_VERSION < 106900
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#include <boost/spirit/home/support/detail/endian/endian.hpp>
|
||||
#else
|
||||
#include <boost/spirit/home/support/detail/endian/endian.hpp>
|
||||
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
|
||||
#endif
|
||||
|
||||
// namespace alias fp_classify
|
||||
#if BOOST_VERSION < 103800
|
||||
#if BOOST_VERSION < 103800 || BOOST_VERSION >= 106900
|
||||
namespace fp = boost::math;
|
||||
#else
|
||||
namespace fp = boost::spirit::math;
|
||||
|
|
@ -142,7 +141,7 @@ namespace endian = boost::detail;
|
|||
namespace endian = boost::spirit::detail;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING
|
||||
// used for wstring to utf8 conversion
|
||||
#include <boost/program_options/config.hpp>
|
||||
#include <boost/program_options/detail/convert.hpp>
|
||||
|
|
@ -195,9 +194,7 @@ namespace eos {
|
|||
// save_override functions so we chose to stay one level higher
|
||||
, public boost::archive::basic_binary_oarchive<portable_oarchive>
|
||||
|
||||
#if BOOST_VERSION >= 105600
|
||||
// mix-in helper class for serializing shared_ptr does not exist anymore
|
||||
#elif BOOST_VERSION >= 103500
|
||||
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
|
||||
// mix-in helper class for serializing shared_ptr
|
||||
, public boost::archive::detail::shared_ptr_helper
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -422,7 +422,6 @@ namespace epee
|
|||
std::string get_usage()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Commands: " << ENDL;
|
||||
size_t max_command_len = 0;
|
||||
for(auto& x:m_command_handlers)
|
||||
if(x.first.size() > max_command_len)
|
||||
|
|
@ -430,8 +429,7 @@ namespace epee
|
|||
|
||||
for(auto& x:m_command_handlers)
|
||||
{
|
||||
ss.width(max_command_len + 3);
|
||||
ss << " " << std::left << x.first << " " << x.second.second << ENDL;
|
||||
ss << " " << std::left << std::setw(max_command_len + 3) << x.first << " " << x.second.second << ENDL;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ namespace math_helper
|
|||
average()
|
||||
{
|
||||
m_base = default_base;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
bool set_base()
|
||||
|
|
@ -71,6 +72,7 @@ namespace math_helper
|
|||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
|
||||
//#ifndef DEBUG_STUB
|
||||
m_count++;
|
||||
m_list.push_back(vl);
|
||||
if(m_list.size() > m_base )
|
||||
m_list.pop_front();
|
||||
|
|
@ -106,9 +108,20 @@ namespace math_helper
|
|||
|
||||
return 0;
|
||||
}
|
||||
uint64_t& get_count()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_count = 0;
|
||||
m_list.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_base;
|
||||
unsigned int m_base;
|
||||
uint64_t m_count;
|
||||
std::list<value_type> m_list;
|
||||
mutable critical_section m_lock;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -389,22 +389,27 @@ namespace misc_utils
|
|||
auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type())));
|
||||
return res.first->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace misc_utils
|
||||
} // namespace epee
|
||||
|
||||
template<typename T>
|
||||
std::ostream& print_container_content(std::ostream& out, const T& v);
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v)
|
||||
namespace std
|
||||
{
|
||||
return print_container_content(out, v);
|
||||
}
|
||||
template<typename T>
|
||||
std::ostream& operator<< (std::ostream& out, const std::list<T>& v)
|
||||
{
|
||||
return print_container_content(out, v);
|
||||
}
|
||||
template<typename T>
|
||||
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v)
|
||||
{
|
||||
return print_container_content(out, v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<< (std::ostream& out, const std::list<T>& v)
|
||||
{
|
||||
return print_container_content(out, v);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
template<typename T>
|
||||
std::ostream& print_container_content(std::ostream& out, const T& v)
|
||||
|
|
|
|||
|
|
@ -893,12 +893,10 @@ namespace log_space
|
|||
FAST_CRITICAL_REGION_END();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string get_thread_prefix()
|
||||
{
|
||||
FAST_CRITICAL_REGION_LOCAL(m_critical_sec);
|
||||
return m_thr_prefix_strings[misc_utils::get_thread_string_id()];
|
||||
|
||||
}
|
||||
|
||||
std::string get_default_log_file()
|
||||
|
|
@ -1160,7 +1158,6 @@ namespace log_space
|
|||
|
||||
}
|
||||
|
||||
|
||||
static bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4 )
|
||||
{
|
||||
logger* plogger = get_or_create_instance();
|
||||
|
|
@ -1234,8 +1231,6 @@ POP_WARNINGS
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
|
||||
|
|
@ -1290,8 +1285,6 @@ POP_WARNINGS
|
|||
return plogger->get_thread_prefix();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static std::string get_prefix_entry()
|
||||
{
|
||||
std::stringstream str_prefix;
|
||||
|
|
@ -1587,8 +1580,6 @@ POP_WARNINGS
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#define LOG_PRINT_NO_POSTFIX(mess, level) LOG_PRINT_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level)
|
||||
#define LOG_PRINT_NO_PREFIX(mess, level) LOG_PRINT_NO_PREFIX2(LOG_DEFAULT_TARGET, mess, level)
|
||||
#define LOG_PRINT_NO_PREFIX_NO_POSTFIX(mess, level) LOG_PRINT_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level)
|
||||
|
|
@ -1694,7 +1685,6 @@ POP_WARNINGS
|
|||
#define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
POP_WARNINGS
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ namespace misc_utils
|
|||
|
||||
#if defined(__GNUC__)
|
||||
#include <execinfo.h>
|
||||
#include <boost/core/demangle.hpp>
|
||||
#endif
|
||||
inline std::string print_trace()
|
||||
{
|
||||
|
|
@ -125,9 +126,9 @@ namespace misc_utils
|
|||
stack_depth = backtrace(stack_addrs, max_depth);
|
||||
stack_strings = backtrace_symbols(stack_addrs, stack_depth);
|
||||
|
||||
|
||||
for (size_t i = 1; i < stack_depth; i++) {
|
||||
ss << stack_strings[i] << std::endl;
|
||||
for (size_t i = 1; i < stack_depth; i++)
|
||||
{
|
||||
ss << boost::core::demangle(stack_strings[i]) << std::endl;
|
||||
}
|
||||
free(stack_strings); // malloc()ed by backtrace_symbols
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ DISABLE_VS_WARNINGS(4355)
|
|||
send_guard.unlock();//manual unlock
|
||||
LOG_ERROR("send to [" << print_connection_context_short(context) << ", (" << (void*)this << ")] que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
|
||||
close();
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +352,8 @@ DISABLE_VS_WARNINGS(4355)
|
|||
template<class t_protocol_handler>
|
||||
bool connection<t_protocol_handler>::shutdown()
|
||||
{
|
||||
if (m_was_shutdown)
|
||||
return true;
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignored_ec;
|
||||
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ namespace net_utils
|
|||
bool m_is_stop_handling;
|
||||
http::http_request_info m_query_info;
|
||||
size_t m_len_summary, m_len_remain;
|
||||
size_t m_precommand_line_chars;
|
||||
config_type& m_config;
|
||||
bool m_want_close;
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@
|
|||
#include "file_io_utils.h"
|
||||
#include "net_parse_helpers.h"
|
||||
|
||||
#define HTTP_MAX_URI_LEN 9000
|
||||
#define HTTP_MAX_HEADER_LEN 100000
|
||||
#define HTTP_MAX_URI_LEN 9000
|
||||
#define HTTP_MAX_PRE_COMMAND_LINE_CHARS 20
|
||||
#define HTTP_MAX_HEADER_LEN 100000
|
||||
|
||||
PUSH_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
|
|
@ -204,7 +205,8 @@ namespace net_utils
|
|||
m_len_remain(0),
|
||||
m_config(config),
|
||||
m_want_close(false),
|
||||
m_psnd_hndlr(psnd_hndlr)
|
||||
m_psnd_hndlr(psnd_hndlr),
|
||||
m_precommand_line_chars(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -217,6 +219,7 @@ namespace net_utils
|
|||
m_body_transfer_type = http_body_transfer_undefined;
|
||||
m_query_info.clear();
|
||||
m_len_summary = 0;
|
||||
m_precommand_line_chars = 0;
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
|
@ -257,11 +260,19 @@ namespace net_utils
|
|||
if((m_cache[0] == '\r' || m_cache[0] == '\n'))
|
||||
{
|
||||
//some times it could be that before query line cold be few line breaks
|
||||
//so we have to be calm without panic with assers
|
||||
//so we have to be calm down without panic and asserts
|
||||
m_cache.erase(0, 1);
|
||||
|
||||
//fixed bug with possible '\r\n' chars flood, thanks to @anonimal (https://github.com/anonimal) for pointing this
|
||||
++m_precommand_line_chars;
|
||||
if (m_precommand_line_chars > HTTP_MAX_PRE_COMMAND_LINE_CHARS)
|
||||
{
|
||||
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line");
|
||||
m_state = http_state_error;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(std::string::npos != m_cache.find('\n', 0))
|
||||
handle_invoke_query_line();
|
||||
else
|
||||
|
|
@ -269,7 +280,7 @@ namespace net_utils
|
|||
m_is_stop_handling = true;
|
||||
if(m_cache.size() > HTTP_MAX_URI_LEN)
|
||||
{
|
||||
LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line");
|
||||
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line");
|
||||
m_state = http_state_error;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -297,10 +308,10 @@ namespace net_utils
|
|||
case http_state_connection_close:
|
||||
return false;
|
||||
default:
|
||||
LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
|
||||
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Wrong state: " << m_state);
|
||||
return false;
|
||||
case http_state_error:
|
||||
LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!");
|
||||
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Error state!!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -334,10 +345,10 @@ namespace net_utils
|
|||
template<class t_connection_context>
|
||||
bool simple_http_connection_handler<t_connection_context>::handle_invoke_query_line()
|
||||
{
|
||||
LOG_FRAME("simple_http_connection_handler<t_connection_context>::handle_recognize_protocol_out(*)", LOG_LEVEL_3);
|
||||
LOG_FRAME("simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(*)", LOG_LEVEL_3);
|
||||
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+).(\\d+))\r?\n", boost::regex::icase | boost::regex::normal);
|
||||
// 123 4 5 6 7 8 9 10 11 12
|
||||
// 123 4 5 6 7 8 9 10 11 12
|
||||
//size_t match_len = 0;
|
||||
boost::smatch result;
|
||||
if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched)
|
||||
|
|
@ -682,4 +693,4 @@ namespace net_utils
|
|||
POP_WARNINGS
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ namespace epee
|
|||
{
|
||||
namespace string_tools
|
||||
{
|
||||
inline std::string print_fixed_decimal_point(uint64_t amount, size_t decimal_point)
|
||||
template<typename t_number>
|
||||
inline std::string print_fixed_decimal_point(t_number amount, size_t decimal_point)
|
||||
{
|
||||
std::string s = std::to_string(amount);
|
||||
std::string s = boost::lexical_cast<std::string>(amount);
|
||||
if (s.size() < decimal_point + 1)
|
||||
{
|
||||
s.insert(0, decimal_point + 1 - s.size(), '0');
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ namespace epee
|
|||
template<class stl_container, class t_storage>
|
||||
static bool serialize_stl_container_pod_val_as_blob(const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
static_assert(std::is_trivial<typename stl_container::value_type>::value, "Item supposed to be 'trivial'(trivially copyable)");
|
||||
if(!container.size()) return true;
|
||||
std::string mb;
|
||||
mb.resize(sizeof(typename stl_container::value_type)*container.size());
|
||||
|
|
@ -140,6 +141,7 @@ namespace epee
|
|||
template<class stl_container, class t_storage>
|
||||
static bool unserialize_stl_container_pod_val_as_blob(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
static_assert(std::is_trivial<typename stl_container::value_type>::value, "Item supposed to be 'trivial'(trivially copyable)");
|
||||
container.clear();
|
||||
std::string buff;
|
||||
bool res = stg.get_value(pname, buff, hparent_section);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace epee
|
|||
bool load_from_binary(const binarybuffer& target);
|
||||
template<class trace_policy>
|
||||
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
||||
bool dump_as_json(std::string& targetObj, size_t indent = 0);
|
||||
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
|
||||
bool load_from_json(const std::string& source);
|
||||
|
||||
private:
|
||||
|
|
@ -106,11 +106,11 @@ namespace epee
|
|||
#pragma pack(pop)
|
||||
};
|
||||
inline
|
||||
bool portable_storage::dump_as_json(std::string& buff, size_t indent)
|
||||
bool portable_storage::dump_as_json(std::string& buff, size_t indent /* = 0 */, end_of_line_t eol /* = eol_crlf */)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
epee::serialization::dump_as_json(ss, m_root, indent);
|
||||
epee::serialization::dump_as_json(ss, m_root, indent, eol);
|
||||
buff = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::dump_as_json", false)
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ namespace epee
|
|||
{
|
||||
namespace serialization
|
||||
{
|
||||
enum end_of_line_t { eol_crlf = 0, eol_lf = 1, eol_cr = 2, eol_space = 3 };
|
||||
|
||||
struct section;
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
|||
|
|
@ -56,16 +56,16 @@ namespace epee
|
|||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool store_t_to_json(const t_struct& str_in, std::string& json_buff, size_t indent = 0)
|
||||
bool store_t_to_json(const t_struct& str_in, std::string& json_buff, size_t indent = 0, end_of_line_t eol = eol_crlf)
|
||||
{
|
||||
portable_storage ps;
|
||||
str_in.store(ps);
|
||||
ps.dump_as_json(json_buff, indent);
|
||||
ps.dump_as_json(json_buff, indent, eol);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
std::string store_t_to_json(const t_struct& str_in, size_t indent = 0)
|
||||
std::string store_t_to_json(const t_struct& str_in, size_t indent = 0, end_of_line_t eol = eol_crlf)
|
||||
{
|
||||
std::string json_buff;
|
||||
store_t_to_json(str_in, json_buff, indent);
|
||||
|
|
|
|||
|
|
@ -37,23 +37,23 @@ namespace epee
|
|||
{
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const double& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream, class t_type>
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent);
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol = eol_crlf);
|
||||
|
||||
|
||||
inline std::string make_indent(size_t indent)
|
||||
|
|
@ -66,7 +66,13 @@ namespace epee
|
|||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
array_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent){}
|
||||
end_of_line_t m_eol;
|
||||
|
||||
array_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
, m_eol(eol)
|
||||
{}
|
||||
|
||||
template<class t_type>
|
||||
void operator()(const array_entry_t<t_type>& a)
|
||||
|
|
@ -77,7 +83,7 @@ namespace epee
|
|||
auto last_it = --a.m_array.end();
|
||||
for(auto it = a.m_array.begin(); it != a.m_array.end(); it++)
|
||||
{
|
||||
dump_as_json(m_strm, *it, m_indent);
|
||||
dump_as_json(m_strm, *it, m_indent, m_eol);
|
||||
if(it != last_it)
|
||||
m_strm << ",";
|
||||
}
|
||||
|
|
@ -91,50 +97,56 @@ namespace epee
|
|||
{
|
||||
t_stream& m_strm;
|
||||
size_t m_indent;
|
||||
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent)
|
||||
end_of_line_t m_eol;
|
||||
|
||||
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol)
|
||||
: m_strm(strm)
|
||||
, m_indent(indent)
|
||||
, m_eol(eol)
|
||||
{}
|
||||
|
||||
//section, array_entry
|
||||
template<class visited_type>
|
||||
void operator()(const visited_type& v)
|
||||
{
|
||||
dump_as_json(m_strm, v, m_indent);
|
||||
dump_as_json(m_strm, v, m_indent, m_eol);
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent);
|
||||
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent, eol);
|
||||
boost::apply_visitor(aesv, ae);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent);
|
||||
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent, eol);
|
||||
boost::apply_visitor(sv, se);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << "\"" << misc_utils::parse::transform_to_json_escape_sequence(v) << "\"";
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
if(v)
|
||||
strm << "true";
|
||||
|
|
@ -143,23 +155,34 @@ namespace epee
|
|||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const double& v, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm.precision(8);
|
||||
strm << std::fixed << v;
|
||||
}
|
||||
|
||||
template<class t_stream, class t_type>
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t /*indent*/)
|
||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
strm << v;
|
||||
}
|
||||
|
||||
template<class t_stream>
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent)
|
||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol)
|
||||
{
|
||||
auto put_eol = [&]() {
|
||||
switch (eol)
|
||||
{
|
||||
case eol_lf: strm << "\n"; break;
|
||||
case eol_cr: strm << "\r"; break;
|
||||
case eol_space: strm << " "; break;
|
||||
default: strm << "\r\n"; break;
|
||||
}
|
||||
};
|
||||
|
||||
size_t local_indent = indent + 1;
|
||||
strm << "{\r\n";
|
||||
strm << "{";
|
||||
put_eol();
|
||||
std::string indent_str = make_indent(local_indent);
|
||||
if(sec.m_entries.size())
|
||||
{
|
||||
|
|
@ -167,10 +190,10 @@ namespace epee
|
|||
for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++)
|
||||
{
|
||||
strm << indent_str << "\"" << misc_utils::parse::transform_to_json_escape_sequence(it->first) << "\"" << ": ";
|
||||
dump_as_json(strm, it->second, local_indent);
|
||||
dump_as_json(strm, it->second, local_indent, eol);
|
||||
if(it_last != it)
|
||||
strm << ",";
|
||||
strm << "\r\n";
|
||||
put_eol();
|
||||
}
|
||||
}
|
||||
strm << make_indent(indent) << "}";
|
||||
|
|
|
|||
|
|
@ -648,9 +648,6 @@ POP_WARNINGS
|
|||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
inline std::string cut_off_extension(const std::string& str)
|
||||
{
|
||||
std::string res;
|
||||
|
|
@ -661,7 +658,17 @@ POP_WARNINGS
|
|||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::wstring cut_off_extension(const std::wstring& str)
|
||||
{
|
||||
std::wstring res;
|
||||
std::wstring::size_type pos = str.rfind('.');
|
||||
if (std::wstring::npos == pos)
|
||||
return str;
|
||||
|
||||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
// replaces all non-ascii characters with mask_character
|
||||
inline std::string mask_non_ascii_chars(const std::string& str, const char mask_character = '?')
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace epee
|
|||
{
|
||||
|
||||
t_object t;
|
||||
std::recursive_mutex m;
|
||||
mutable std::recursive_mutex m;
|
||||
template<typename t_proxy_object, typename t_proxy_lock_time_watching_policy>
|
||||
friend class locked_object_proxy;
|
||||
public:
|
||||
|
|
@ -106,6 +106,16 @@ namespace epee
|
|||
return locked_object_proxy<t_object, lock_time_watching_policy>(t, m);
|
||||
}
|
||||
|
||||
locked_object_proxy<const t_object, lock_time_watching_policy> operator->() const
|
||||
{
|
||||
return locked_object_proxy<const t_object, lock_time_watching_policy>(t, m);
|
||||
}
|
||||
|
||||
locked_object_proxy<const t_object, lock_time_watching_policy> operator*() const
|
||||
{
|
||||
return locked_object_proxy<const t_object, lock_time_watching_policy>(t, m);
|
||||
}
|
||||
|
||||
/*locked_object_proxy<t_object> operator()()
|
||||
{
|
||||
return locked_object_proxy<t_object>(t, m);
|
||||
|
|
|
|||
|
|
@ -701,6 +701,11 @@ namespace epee
|
|||
#define CRITICAL_REGION_BEGIN1(x) CRITICAL_REGION_BEGIN_VAR(x, critical_region_var1)
|
||||
#define CRITICAL_REGION_END() }
|
||||
|
||||
#define SHARED_CRITICAL_REGION_LOCAL(x) boost::shared_lock< boost::shared_mutex > critical_region_var(x)
|
||||
#define EXCLUSIVE_CRITICAL_REGION_LOCAL(x) boost::unique_lock< boost::shared_mutex > critical_region_var(x)
|
||||
|
||||
#define SHARED_CRITICAL_REGION_BEGIN(x) { SHARED_CRITICAL_REGION_LOCAL(x)
|
||||
#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { EXCLUSIVE_CRITICAL_REGION_LOCAL(x)
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
10
contrib/ethereum/CMakeLists.txt
Normal file
10
contrib/ethereum/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
add_subdirectory(libethash)
|
||||
|
||||
set_property(TARGET ethash PROPERTY FOLDER "contrib")
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(ethash PRIVATE /wd4477 /wd4267)
|
||||
else()
|
||||
target_compile_options(ethash PRIVATE -Wno-format -Wno-aggregate-return -Wno-empty-body)
|
||||
endif()
|
||||
|
||||
33
contrib/ethereum/libethash/CMakeLists.txt
Normal file
33
contrib/ethereum/libethash/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
# Copyright 2018 Pawel Bylica.
|
||||
# Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
# set(include_dir ${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
|
||||
add_library(
|
||||
ethash
|
||||
bit_manipulation.h
|
||||
builtins.h
|
||||
endianness.hpp
|
||||
ethash/ethash.h
|
||||
ethash/ethash.hpp
|
||||
ethash-internal.hpp
|
||||
ethash.cpp
|
||||
ethash/hash_types.h
|
||||
managed.cpp
|
||||
ethash/keccak.h
|
||||
ethash/keccak.hpp
|
||||
keccak.c
|
||||
keccakf800.c
|
||||
keccakf1600.c
|
||||
kiss99.hpp
|
||||
primes.h
|
||||
primes.c
|
||||
ethash/progpow.hpp
|
||||
progpow.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
81
contrib/ethereum/libethash/bit_manipulation.h
Normal file
81
contrib/ethereum/libethash/bit_manipulation.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builtins.h"
|
||||
#include "support/attributes.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline uint32_t rotl32(uint32_t n, unsigned int c)
|
||||
{
|
||||
const unsigned int mask = 31;
|
||||
|
||||
c &= mask;
|
||||
unsigned int neg_c = (unsigned int)(-(int)c);
|
||||
return (n << c) | (n >> (neg_c & mask));
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32(uint32_t n, unsigned int c)
|
||||
{
|
||||
const unsigned int mask = 31;
|
||||
|
||||
c &= mask;
|
||||
unsigned int neg_c = (unsigned int)(-(int)c);
|
||||
return (n >> c) | (n << (neg_c & mask));
|
||||
}
|
||||
|
||||
static inline uint32_t clz32(uint32_t x)
|
||||
{
|
||||
return x ? (uint32_t)__builtin_clz(x) : 32;
|
||||
}
|
||||
|
||||
static inline uint32_t popcount32(uint32_t x)
|
||||
{
|
||||
return (uint32_t)__builtin_popcount(x);
|
||||
}
|
||||
|
||||
static inline uint32_t mul_hi32(uint32_t x, uint32_t y)
|
||||
{
|
||||
return (uint32_t)(((uint64_t)x * (uint64_t)y) >> 32);
|
||||
}
|
||||
|
||||
|
||||
/** FNV 32-bit prime. */
|
||||
static const uint32_t fnv_prime = 0x01000193;
|
||||
|
||||
/** FNV 32-bit offset basis. */
|
||||
static const uint32_t fnv_offset_basis = 0x811c9dc5;
|
||||
|
||||
/**
|
||||
* The implementation of FNV-1 hash.
|
||||
*
|
||||
* See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1_hash.
|
||||
*/
|
||||
NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline uint32_t fnv1(uint32_t u, uint32_t v) noexcept
|
||||
{
|
||||
return (u * fnv_prime) ^ v;
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementation of FNV-1a hash.
|
||||
*
|
||||
* See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash.
|
||||
*/
|
||||
NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline uint32_t fnv1a(uint32_t u, uint32_t v) noexcept
|
||||
{
|
||||
return (u ^ v) * fnv_prime;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
43
contrib/ethereum/libethash/builtins.h
Normal file
43
contrib/ethereum/libethash/builtins.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implementation of GCC/clang builtins for MSVC compiler.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the number of leading 0-bits in `x`, starting at the most significant bit position.
|
||||
* If `x` is 0, the result is undefined.
|
||||
*/
|
||||
static inline int __builtin_clz(unsigned int x)
|
||||
{
|
||||
unsigned long most_significant_bit;
|
||||
_BitScanReverse(&most_significant_bit, x);
|
||||
return 31 - (int)most_significant_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of 1-bits in `x`.
|
||||
*/
|
||||
static inline int __builtin_popcount(unsigned int x)
|
||||
{
|
||||
return (int)__popcnt(x);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
contrib/ethereum/libethash/endianness.hpp
Normal file
98
contrib/ethereum/libethash/endianness.hpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
/// @file
|
||||
/// This file contains helper functions to handle big-endian architectures.
|
||||
/// The Ethash algorithm is naturally defined for little-endian architectures
|
||||
/// so for those the helpers are just no-op empty functions.
|
||||
/// For big-endian architectures we need 32-bit and 64-bit byte swapping in
|
||||
/// some places.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/ethash.hpp>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define bswap32 _byteswap_ulong
|
||||
#define bswap64 _byteswap_uint64
|
||||
|
||||
// On Windows assume little endian.
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
#elif __APPLE__
|
||||
|
||||
#include <machine/endian.h>
|
||||
|
||||
#define bswap32 __builtin_bswap32
|
||||
#define bswap64 __builtin_bswap64
|
||||
|
||||
#else
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#define bswap32 __builtin_bswap32
|
||||
#define bswap64 __builtin_bswap64
|
||||
|
||||
#endif
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
||||
struct le
|
||||
{
|
||||
static uint32_t uint32(uint32_t x) noexcept { return x; }
|
||||
static uint64_t uint64(uint64_t x) noexcept { return x; }
|
||||
|
||||
static const hash1024& uint32s(const hash1024& h) noexcept { return h; }
|
||||
static const hash512& uint32s(const hash512& h) noexcept { return h; }
|
||||
static const hash256& uint32s(const hash256& h) noexcept { return h; }
|
||||
};
|
||||
|
||||
struct be
|
||||
{
|
||||
static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); }
|
||||
};
|
||||
|
||||
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
struct le
|
||||
{
|
||||
static uint32_t uint32(uint32_t x) noexcept { return bswap32(x); }
|
||||
static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); }
|
||||
|
||||
static hash1024 uint32s(hash1024 h) noexcept
|
||||
{
|
||||
for (auto& w : h.word32s)
|
||||
w = uint32(w);
|
||||
return h;
|
||||
}
|
||||
|
||||
static hash512 uint32s(hash512 h) noexcept
|
||||
{
|
||||
for (auto& w : h.word32s)
|
||||
w = uint32(w);
|
||||
return h;
|
||||
}
|
||||
|
||||
static hash256 uint32s(hash256 h) noexcept
|
||||
{
|
||||
for (auto& w : h.word32s)
|
||||
w = uint32(w);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct be
|
||||
{
|
||||
static uint64_t uint64(uint64_t x) noexcept { return x; }
|
||||
};
|
||||
|
||||
#endif
|
||||
} // namespace ethash
|
||||
69
contrib/ethereum/libethash/ethash-internal.hpp
Normal file
69
contrib/ethereum/libethash/ethash-internal.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
/// @file
|
||||
/// Contains declarations of internal ethash functions to allow them to be
|
||||
/// unit-tested.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/ethash.hpp>
|
||||
|
||||
#include "endianness.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
extern "C" struct ethash_epoch_context_full : ethash_epoch_context
|
||||
{
|
||||
ethash_hash1024* full_dataset;
|
||||
|
||||
constexpr ethash_epoch_context_full(int epoch_number, int light_cache_num_items,
|
||||
const ethash_hash512* light_cache, const uint32_t* l1_cache, int full_dataset_num_items,
|
||||
ethash_hash1024* full_dataset) noexcept
|
||||
: ethash_epoch_context{epoch_number, light_cache_num_items, light_cache, l1_cache,
|
||||
full_dataset_num_items},
|
||||
full_dataset{full_dataset}
|
||||
{}
|
||||
};
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
inline bool is_less_or_equal(const hash256& a, const hash256& b) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < (sizeof(a) / sizeof(a.word64s[0])); ++i)
|
||||
{
|
||||
if (be::uint64(a.word64s[i]) > be::uint64(b.word64s[i]))
|
||||
return false;
|
||||
if (be::uint64(a.word64s[i]) < be::uint64(b.word64s[i]))
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_equal(const hash256& a, const hash256& b) noexcept
|
||||
{
|
||||
return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0;
|
||||
}
|
||||
|
||||
void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept;
|
||||
|
||||
hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept;
|
||||
hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept;
|
||||
hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept;
|
||||
|
||||
namespace generic
|
||||
{
|
||||
using hash_fn_512 = hash512 (*)(const uint8_t* data, size_t size);
|
||||
using build_light_cache_fn = void (*)(hash512 cache[], int num_items, const hash256& seed);
|
||||
|
||||
void build_light_cache(
|
||||
hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept;
|
||||
|
||||
epoch_context_full* create_epoch_context(
|
||||
build_light_cache_fn build_fn, int epoch_number, bool full) noexcept;
|
||||
|
||||
} // namespace generic
|
||||
|
||||
} // namespace ethash
|
||||
441
contrib/ethereum/libethash/ethash.cpp
Normal file
441
contrib/ethereum/libethash/ethash.cpp
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
#include "ethash-internal.hpp"
|
||||
|
||||
#include "bit_manipulation.h"
|
||||
#include "endianness.hpp"
|
||||
#include "primes.h"
|
||||
#include "support/attributes.h"
|
||||
#include <ethash/keccak.hpp>
|
||||
#include <ethash/progpow.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
// Internal constants:
|
||||
constexpr static int light_cache_init_size = 1 << 24;
|
||||
constexpr static int light_cache_growth = 1 << 17;
|
||||
constexpr static int light_cache_rounds = 3;
|
||||
constexpr static int full_dataset_init_size = 1 << 30;
|
||||
constexpr static int full_dataset_growth = 1 << 23;
|
||||
constexpr static int full_dataset_item_parents = 256;
|
||||
|
||||
// Verify constants:
|
||||
static_assert(sizeof(hash512) == ETHASH_LIGHT_CACHE_ITEM_SIZE, "");
|
||||
static_assert(sizeof(hash1024) == ETHASH_FULL_DATASET_ITEM_SIZE, "");
|
||||
static_assert(light_cache_item_size == ETHASH_LIGHT_CACHE_ITEM_SIZE, "");
|
||||
static_assert(full_dataset_item_size == ETHASH_FULL_DATASET_ITEM_SIZE, "");
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
using ::fnv1;
|
||||
|
||||
inline hash512 fnv1(const hash512& u, const hash512& v) noexcept
|
||||
{
|
||||
hash512 r;
|
||||
for (size_t i = 0; i < sizeof(r) / sizeof(r.word32s[0]); ++i)
|
||||
r.word32s[i] = fnv1(u.word32s[i], v.word32s[i]);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline hash512 bitwise_xor(const hash512& x, const hash512& y) noexcept
|
||||
{
|
||||
hash512 z;
|
||||
for (size_t i = 0; i < sizeof(z) / sizeof(z.word64s[0]); ++i)
|
||||
z.word64s[i] = x.word64s[i] ^ y.word64s[i];
|
||||
return z;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int find_epoch_number(const hash256& seed) noexcept
|
||||
{
|
||||
static constexpr int num_tries = 30000; // Divisible by 16.
|
||||
|
||||
// Thread-local cache of the last search.
|
||||
static thread_local int cached_epoch_number = 0;
|
||||
static thread_local hash256 cached_seed = {};
|
||||
|
||||
// Load from memory once (memory will be clobbered by keccak256()).
|
||||
const uint32_t seed_part = seed.word32s[0];
|
||||
const int e = cached_epoch_number;
|
||||
hash256 s = cached_seed;
|
||||
|
||||
if (s.word32s[0] == seed_part)
|
||||
return e;
|
||||
|
||||
// Try the next seed, will match for sequential epoch access.
|
||||
s = keccak256(s);
|
||||
if (s.word32s[0] == seed_part)
|
||||
{
|
||||
cached_seed = s;
|
||||
cached_epoch_number = e + 1;
|
||||
return e + 1;
|
||||
}
|
||||
|
||||
// Search for matching seed starting from epoch 0.
|
||||
s = {};
|
||||
for (int i = 0; i < num_tries; ++i)
|
||||
{
|
||||
if (s.word32s[0] == seed_part)
|
||||
{
|
||||
cached_seed = s;
|
||||
cached_epoch_number = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
s = keccak256(s);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace generic
|
||||
{
|
||||
void build_light_cache(
|
||||
hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept
|
||||
{
|
||||
hash512 item = hash_fn(seed.bytes, sizeof(seed));
|
||||
cache[0] = item;
|
||||
for (int i = 1; i < num_items; ++i)
|
||||
{
|
||||
item = hash_fn(item.bytes, sizeof(item));
|
||||
cache[i] = item;
|
||||
}
|
||||
|
||||
for (int q = 0; q < light_cache_rounds; ++q)
|
||||
{
|
||||
for (int i = 0; i < num_items; ++i)
|
||||
{
|
||||
const uint32_t index_limit = static_cast<uint32_t>(num_items);
|
||||
|
||||
// Fist index: 4 first bytes of the item as little-endian integer.
|
||||
const uint32_t t = le::uint32(cache[i].word32s[0]);
|
||||
const uint32_t v = t % index_limit;
|
||||
|
||||
// Second index.
|
||||
const uint32_t w = static_cast<uint32_t>(num_items + (i - 1)) % index_limit;
|
||||
|
||||
const hash512 x = bitwise_xor(cache[v], cache[w]);
|
||||
cache[i] = hash_fn(x.bytes, sizeof(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
epoch_context_full* create_epoch_context(
|
||||
build_light_cache_fn build_fn, int epoch_number, bool full) noexcept
|
||||
{
|
||||
static_assert(sizeof(epoch_context_full) < sizeof(hash512), "epoch_context too big");
|
||||
static constexpr size_t context_alloc_size = sizeof(hash512);
|
||||
|
||||
const int light_cache_num_items = calculate_light_cache_num_items(epoch_number);
|
||||
const int full_dataset_num_items = calculate_full_dataset_num_items(epoch_number);
|
||||
const size_t light_cache_size = get_light_cache_size(light_cache_num_items);
|
||||
const size_t full_dataset_size =
|
||||
full ? static_cast<size_t>(full_dataset_num_items) * sizeof(hash1024) :
|
||||
progpow::l1_cache_size;
|
||||
|
||||
const size_t alloc_size = context_alloc_size + light_cache_size + full_dataset_size;
|
||||
|
||||
char* const alloc_data = static_cast<char*>(std::calloc(1, alloc_size));
|
||||
if (!alloc_data)
|
||||
return nullptr; // Signal out-of-memory by returning null pointer.
|
||||
|
||||
hash512* const light_cache = reinterpret_cast<hash512*>(alloc_data + context_alloc_size);
|
||||
const hash256 epoch_seed = calculate_epoch_seed(epoch_number);
|
||||
build_fn(light_cache, light_cache_num_items, epoch_seed);
|
||||
|
||||
uint32_t* const l1_cache =
|
||||
reinterpret_cast<uint32_t*>(alloc_data + context_alloc_size + light_cache_size);
|
||||
|
||||
hash1024* full_dataset = full ? reinterpret_cast<hash1024*>(l1_cache) : nullptr;
|
||||
|
||||
epoch_context_full* const context = new (alloc_data) epoch_context_full{
|
||||
epoch_number,
|
||||
light_cache_num_items,
|
||||
light_cache,
|
||||
l1_cache,
|
||||
full_dataset_num_items,
|
||||
full_dataset,
|
||||
};
|
||||
|
||||
auto* full_dataset_2048 = reinterpret_cast<hash2048*>(l1_cache);
|
||||
for (uint32_t i = 0; i < progpow::l1_cache_size / sizeof(full_dataset_2048[0]); ++i)
|
||||
full_dataset_2048[i] = calculate_dataset_item_2048(*context, i);
|
||||
return context;
|
||||
}
|
||||
} // namespace generic
|
||||
|
||||
void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept
|
||||
{
|
||||
return generic::build_light_cache(keccak512, cache, num_items, seed);
|
||||
}
|
||||
|
||||
struct item_state
|
||||
{
|
||||
const hash512* const cache;
|
||||
const int64_t num_cache_items;
|
||||
const uint32_t seed;
|
||||
|
||||
hash512 mix;
|
||||
|
||||
ALWAYS_INLINE item_state(const epoch_context& context, int64_t index) noexcept
|
||||
: cache{context.light_cache},
|
||||
num_cache_items{context.light_cache_num_items},
|
||||
seed{static_cast<uint32_t>(index)}
|
||||
{
|
||||
mix = cache[index % num_cache_items];
|
||||
mix.word32s[0] ^= le::uint32(seed);
|
||||
mix = le::uint32s(keccak512(mix));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void update(uint32_t round) noexcept
|
||||
{
|
||||
static constexpr size_t num_words = sizeof(mix) / sizeof(uint32_t);
|
||||
const uint32_t t = fnv1(seed ^ round, mix.word32s[round % num_words]);
|
||||
const int64_t parent_index = t % num_cache_items;
|
||||
mix = fnv1(mix, le::uint32s(cache[parent_index]));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE hash512 final() noexcept { return keccak512(le::uint32s(mix)); }
|
||||
};
|
||||
|
||||
hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept
|
||||
{
|
||||
item_state item0{context, index};
|
||||
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
|
||||
item0.update(j);
|
||||
return item0.final();
|
||||
}
|
||||
|
||||
/// Calculates a full dataset item
|
||||
///
|
||||
/// This consist of two 512-bit items produced by calculate_dataset_item_partial().
|
||||
/// Here the computation is done interleaved for better performance.
|
||||
hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept
|
||||
{
|
||||
item_state item0{context, int64_t(index) * 2};
|
||||
item_state item1{context, int64_t(index) * 2 + 1};
|
||||
|
||||
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
|
||||
{
|
||||
item0.update(j);
|
||||
item1.update(j);
|
||||
}
|
||||
|
||||
return hash1024{{item0.final(), item1.final()}};
|
||||
}
|
||||
|
||||
hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept
|
||||
{
|
||||
item_state item0{context, int64_t(index) * 4};
|
||||
item_state item1{context, int64_t(index) * 4 + 1};
|
||||
item_state item2{context, int64_t(index) * 4 + 2};
|
||||
item_state item3{context, int64_t(index) * 4 + 3};
|
||||
|
||||
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
|
||||
{
|
||||
item0.update(j);
|
||||
item1.update(j);
|
||||
item2.update(j);
|
||||
item3.update(j);
|
||||
}
|
||||
|
||||
return hash2048{{item0.final(), item1.final(), item2.final(), item3.final()}};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using lookup_fn = hash1024 (*)(const epoch_context&, uint32_t);
|
||||
|
||||
inline hash512 hash_seed(const hash256& header_hash, uint64_t nonce) noexcept
|
||||
{
|
||||
nonce = le::uint64(nonce);
|
||||
uint8_t init_data[sizeof(header_hash) + sizeof(nonce)];
|
||||
std::memcpy(&init_data[0], &header_hash, sizeof(header_hash));
|
||||
std::memcpy(&init_data[sizeof(header_hash)], &nonce, sizeof(nonce));
|
||||
|
||||
return keccak512(init_data, sizeof(init_data));
|
||||
}
|
||||
|
||||
inline hash256 hash_final(const hash512& seed, const hash256& mix_hash)
|
||||
{
|
||||
uint8_t final_data[sizeof(seed) + sizeof(mix_hash)];
|
||||
std::memcpy(&final_data[0], seed.bytes, sizeof(seed));
|
||||
std::memcpy(&final_data[sizeof(seed)], mix_hash.bytes, sizeof(mix_hash));
|
||||
return keccak256(final_data, sizeof(final_data));
|
||||
}
|
||||
|
||||
inline hash256 hash_kernel(
|
||||
const epoch_context& context, const hash512& seed, lookup_fn lookup) noexcept
|
||||
{
|
||||
static constexpr size_t num_words = sizeof(hash1024) / sizeof(uint32_t);
|
||||
const uint32_t index_limit = static_cast<uint32_t>(context.full_dataset_num_items);
|
||||
const uint32_t seed_init = le::uint32(seed.word32s[0]);
|
||||
|
||||
hash1024 mix{{le::uint32s(seed), le::uint32s(seed)}};
|
||||
|
||||
for (uint32_t i = 0; i < num_dataset_accesses; ++i)
|
||||
{
|
||||
const uint32_t p = fnv1(i ^ seed_init, mix.word32s[i % num_words]) % index_limit;
|
||||
const hash1024 newdata = le::uint32s(lookup(context, p));
|
||||
|
||||
for (size_t j = 0; j < num_words; ++j)
|
||||
mix.word32s[j] = fnv1(mix.word32s[j], newdata.word32s[j]);
|
||||
}
|
||||
|
||||
hash256 mix_hash;
|
||||
for (size_t i = 0; i < num_words; i += 4)
|
||||
{
|
||||
const uint32_t h1 = fnv1(mix.word32s[i], mix.word32s[i + 1]);
|
||||
const uint32_t h2 = fnv1(h1, mix.word32s[i + 2]);
|
||||
const uint32_t h3 = fnv1(h2, mix.word32s[i + 3]);
|
||||
mix_hash.word32s[i / 4] = h3;
|
||||
}
|
||||
|
||||
return le::uint32s(mix_hash);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept
|
||||
{
|
||||
const hash512 seed = hash_seed(header_hash, nonce);
|
||||
const hash256 mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024);
|
||||
return {hash_final(seed, mix_hash), mix_hash};
|
||||
}
|
||||
|
||||
result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept
|
||||
{
|
||||
static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept
|
||||
{
|
||||
auto full_dataset = static_cast<const epoch_context_full&>(context).full_dataset;
|
||||
hash1024& item = full_dataset[index];
|
||||
if (item.word64s[0] == 0)
|
||||
{
|
||||
// TODO: Copy elision here makes it thread-safe?
|
||||
item = calculate_dataset_item_1024(context, index);
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
const hash512 seed = hash_seed(header_hash, nonce);
|
||||
const hash256 mix_hash = hash_kernel(context, seed, lazy_lookup);
|
||||
return {hash_final(seed, mix_hash), mix_hash};
|
||||
}
|
||||
|
||||
bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce,
|
||||
const hash256& boundary) noexcept
|
||||
{
|
||||
const hash512 seed = hash_seed(header_hash, nonce);
|
||||
return is_less_or_equal(hash_final(seed, mix_hash), boundary);
|
||||
}
|
||||
|
||||
bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash,
|
||||
uint64_t nonce, const hash256& boundary) noexcept
|
||||
{
|
||||
const hash512 seed = hash_seed(header_hash, nonce);
|
||||
if (!is_less_or_equal(hash_final(seed, mix_hash), boundary))
|
||||
return false;
|
||||
|
||||
const hash256 expected_mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024);
|
||||
return is_equal(expected_mix_hash, mix_hash);
|
||||
}
|
||||
|
||||
search_result search_light(const epoch_context& context, const hash256& header_hash,
|
||||
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept
|
||||
{
|
||||
const uint64_t end_nonce = start_nonce + iterations;
|
||||
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
|
||||
{
|
||||
result r = hash(context, header_hash, nonce);
|
||||
if (is_less_or_equal(r.final_hash, boundary))
|
||||
return {r, nonce};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
search_result search(const epoch_context_full& context, const hash256& header_hash,
|
||||
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept
|
||||
{
|
||||
const uint64_t end_nonce = start_nonce + iterations;
|
||||
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
|
||||
{
|
||||
result r = hash(context, header_hash, nonce);
|
||||
if (is_less_or_equal(r.final_hash, boundary))
|
||||
return {r, nonce};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} // namespace ethash
|
||||
|
||||
using namespace ethash;
|
||||
|
||||
extern "C" {
|
||||
|
||||
ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) noexcept
|
||||
{
|
||||
ethash_hash256 epoch_seed = {};
|
||||
for (int i = 0; i < epoch_number; ++i)
|
||||
epoch_seed = ethash_keccak256_32(epoch_seed.bytes);
|
||||
return epoch_seed;
|
||||
}
|
||||
|
||||
int ethash_calculate_light_cache_num_items(int epoch_number) noexcept
|
||||
{
|
||||
static constexpr int item_size = sizeof(hash512);
|
||||
static constexpr int num_items_init = light_cache_init_size / item_size;
|
||||
static constexpr int num_items_growth = light_cache_growth / item_size;
|
||||
static_assert(
|
||||
light_cache_init_size % item_size == 0, "light_cache_init_size not multiple of item size");
|
||||
static_assert(
|
||||
light_cache_growth % item_size == 0, "light_cache_growth not multiple of item size");
|
||||
|
||||
int num_items_upper_bound = num_items_init + epoch_number * num_items_growth;
|
||||
int num_items = ethash_find_largest_prime(num_items_upper_bound);
|
||||
return num_items;
|
||||
}
|
||||
|
||||
int ethash_calculate_full_dataset_num_items(int epoch_number) noexcept
|
||||
{
|
||||
static constexpr int item_size = sizeof(hash1024);
|
||||
static constexpr int num_items_init = full_dataset_init_size / item_size;
|
||||
static constexpr int num_items_growth = full_dataset_growth / item_size;
|
||||
static_assert(full_dataset_init_size % item_size == 0,
|
||||
"full_dataset_init_size not multiple of item size");
|
||||
static_assert(
|
||||
full_dataset_growth % item_size == 0, "full_dataset_growth not multiple of item size");
|
||||
|
||||
int num_items_upper_bound = num_items_init + epoch_number * num_items_growth;
|
||||
int num_items = ethash_find_largest_prime(num_items_upper_bound);
|
||||
return num_items;
|
||||
}
|
||||
|
||||
epoch_context* ethash_create_epoch_context(int epoch_number) noexcept
|
||||
{
|
||||
return generic::create_epoch_context(build_light_cache, epoch_number, false);
|
||||
}
|
||||
|
||||
epoch_context_full* ethash_create_epoch_context_full(int epoch_number) noexcept
|
||||
{
|
||||
return generic::create_epoch_context(build_light_cache, epoch_number, true);
|
||||
}
|
||||
|
||||
void ethash_destroy_epoch_context_full(epoch_context_full* context) noexcept
|
||||
{
|
||||
ethash_destroy_epoch_context(context);
|
||||
}
|
||||
|
||||
void ethash_destroy_epoch_context(epoch_context* context) noexcept
|
||||
{
|
||||
context->~epoch_context();
|
||||
std::free(context);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
99
contrib/ethereum/libethash/ethash/ethash.h
Normal file
99
contrib/ethereum/libethash/ethash/ethash.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/hash_types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NOEXCEPT noexcept
|
||||
#else
|
||||
#define NOEXCEPT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The Ethash algorithm revision implemented as specified in the Ethash spec
|
||||
* https://github.com/ethereum/wiki/wiki/Ethash.
|
||||
*/
|
||||
#define ETHASH_REVISION "23"
|
||||
|
||||
#define ETHASH_EPOCH_LENGTH 30000
|
||||
#define ETHASH_LIGHT_CACHE_ITEM_SIZE 64
|
||||
#define ETHASH_FULL_DATASET_ITEM_SIZE 128
|
||||
#define ETHASH_NUM_DATASET_ACCESSES 64
|
||||
|
||||
|
||||
struct ethash_epoch_context
|
||||
{
|
||||
const int epoch_number;
|
||||
const int light_cache_num_items;
|
||||
const union ethash_hash512* const light_cache;
|
||||
const uint32_t* const l1_cache;
|
||||
const int full_dataset_num_items;
|
||||
};
|
||||
|
||||
|
||||
struct ethash_epoch_context_full;
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of items in the light cache for given epoch.
|
||||
*
|
||||
* This function will search for a prime number matching the criteria given
|
||||
* by the Ethash so the execution time is not constant. It takes ~ 0.01 ms.
|
||||
*
|
||||
* @param epoch_number The epoch number.
|
||||
* @return The number items in the light cache.
|
||||
*/
|
||||
int ethash_calculate_light_cache_num_items(int epoch_number) NOEXCEPT;
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of items in the full dataset for given epoch.
|
||||
*
|
||||
* This function will search for a prime number matching the criteria given
|
||||
* by the Ethash so the execution time is not constant. It takes ~ 0.05 ms.
|
||||
*
|
||||
* @param epoch_number The epoch number.
|
||||
* @return The number items in the full dataset.
|
||||
*/
|
||||
int ethash_calculate_full_dataset_num_items(int epoch_number) NOEXCEPT;
|
||||
|
||||
/**
|
||||
* Calculates the epoch seed hash.
|
||||
* @param epoch_number The epoch number.
|
||||
* @return The epoch seed hash.
|
||||
*/
|
||||
union ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) NOEXCEPT;
|
||||
|
||||
|
||||
struct ethash_epoch_context* ethash_create_epoch_context(int epoch_number) NOEXCEPT;
|
||||
|
||||
/**
|
||||
* Creates the epoch context with the full dataset initialized.
|
||||
*
|
||||
* The memory for the full dataset is only allocated and marked as "not-generated".
|
||||
* The items of the full dataset are generated on the fly when hit for the first time.
|
||||
*
|
||||
* The memory allocated in the context MUST be freed with ethash_destroy_epoch_context_full().
|
||||
*
|
||||
* @param epoch_number The epoch number.
|
||||
* @return Pointer to the context or null in case of memory allocation failure.
|
||||
*/
|
||||
struct ethash_epoch_context_full* ethash_create_epoch_context_full(int epoch_number) NOEXCEPT;
|
||||
|
||||
void ethash_destroy_epoch_context(struct ethash_epoch_context* context) NOEXCEPT;
|
||||
|
||||
void ethash_destroy_epoch_context_full(struct ethash_epoch_context_full* context) NOEXCEPT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
160
contrib/ethereum/libethash/ethash/ethash.hpp
Normal file
160
contrib/ethereum/libethash/ethash/ethash.hpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// API design decisions:
|
||||
///
|
||||
/// 1. Signed integer type is used whenever the size of the type is not
|
||||
/// restricted by the Ethash specification.
|
||||
/// See http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf.
|
||||
/// See https://stackoverflow.com/questions/10168079/why-is-size-t-unsigned/.
|
||||
/// See https://github.com/Microsoft/GSL/issues/171.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/ethash.h>
|
||||
#include <ethash/hash_types.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
constexpr auto revision = ETHASH_REVISION;
|
||||
|
||||
static constexpr int epoch_length = ETHASH_EPOCH_LENGTH;
|
||||
static constexpr int light_cache_item_size = ETHASH_LIGHT_CACHE_ITEM_SIZE;
|
||||
static constexpr int full_dataset_item_size = ETHASH_FULL_DATASET_ITEM_SIZE;
|
||||
static constexpr int num_dataset_accesses = ETHASH_NUM_DATASET_ACCESSES;
|
||||
|
||||
using epoch_context = ethash_epoch_context;
|
||||
using epoch_context_full = ethash_epoch_context_full;
|
||||
|
||||
/// Constructs a 256-bit hash from an array of bytes.
|
||||
///
|
||||
/// @param bytes A pointer to array of at least 32 bytes.
|
||||
/// @return The constructed hash.
|
||||
inline hash256 hash256_from_bytes(const uint8_t bytes[32]) noexcept
|
||||
{
|
||||
hash256 h;
|
||||
std::memcpy(&h, bytes, sizeof(h));
|
||||
return h;
|
||||
}
|
||||
|
||||
struct result
|
||||
{
|
||||
hash256 final_hash;
|
||||
hash256 mix_hash;
|
||||
};
|
||||
|
||||
struct search_result
|
||||
{
|
||||
bool solution_found = false;
|
||||
uint64_t nonce = 0;
|
||||
hash256 final_hash = {};
|
||||
hash256 mix_hash = {};
|
||||
|
||||
search_result() noexcept = default;
|
||||
|
||||
search_result(result res, uint64_t nonce) noexcept
|
||||
: solution_found(true), nonce(nonce), final_hash(res.final_hash), mix_hash(res.mix_hash)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/// Alias for ethash_calculate_light_cache_num_items().
|
||||
static constexpr auto calculate_light_cache_num_items = ethash_calculate_light_cache_num_items;
|
||||
|
||||
/// Alias for ethash_calculate_full_dataset_num_items().
|
||||
static constexpr auto calculate_full_dataset_num_items = ethash_calculate_full_dataset_num_items;
|
||||
|
||||
/// Alias for ethash_calculate_epoch_seed().
|
||||
static constexpr auto calculate_epoch_seed = ethash_calculate_epoch_seed;
|
||||
|
||||
|
||||
/// Calculates the epoch number out of the block number.
|
||||
inline constexpr int get_epoch_number(int block_number) noexcept
|
||||
{
|
||||
return block_number / epoch_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coverts the number of items of a light cache to size in bytes.
|
||||
*
|
||||
* @param num_items The number of items in the light cache.
|
||||
* @return The size of the light cache in bytes.
|
||||
*/
|
||||
inline constexpr size_t get_light_cache_size(int num_items) noexcept
|
||||
{
|
||||
return static_cast<size_t>(num_items) * light_cache_item_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coverts the number of items of a full dataset to size in bytes.
|
||||
*
|
||||
* @param num_items The number of items in the full dataset.
|
||||
* @return The size of the full dataset in bytes.
|
||||
*/
|
||||
inline constexpr uint64_t get_full_dataset_size(int num_items) noexcept
|
||||
{
|
||||
return static_cast<uint64_t>(num_items) * full_dataset_item_size;
|
||||
}
|
||||
|
||||
/// Owned unique pointer to an epoch context.
|
||||
using epoch_context_ptr = std::unique_ptr<epoch_context, decltype(ðash_destroy_epoch_context)>;
|
||||
|
||||
using epoch_context_full_ptr =
|
||||
std::unique_ptr<epoch_context_full, decltype(ðash_destroy_epoch_context_full)>;
|
||||
|
||||
/// Creates Ethash epoch context.
|
||||
///
|
||||
/// This is a wrapper for ethash_create_epoch_number C function that returns
|
||||
/// the context as a smart pointer which handles the destruction of the context.
|
||||
inline epoch_context_ptr create_epoch_context(int epoch_number) noexcept
|
||||
{
|
||||
return {ethash_create_epoch_context(epoch_number), ethash_destroy_epoch_context};
|
||||
}
|
||||
|
||||
inline epoch_context_full_ptr create_epoch_context_full(int epoch_number) noexcept
|
||||
{
|
||||
return {ethash_create_epoch_context_full(epoch_number), ethash_destroy_epoch_context_full};
|
||||
}
|
||||
|
||||
|
||||
result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept;
|
||||
|
||||
result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept;
|
||||
|
||||
bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce,
|
||||
const hash256& boundary) noexcept;
|
||||
|
||||
bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash,
|
||||
uint64_t nonce, const hash256& boundary) noexcept;
|
||||
|
||||
search_result search_light(const epoch_context& context, const hash256& header_hash,
|
||||
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
|
||||
|
||||
search_result search(const epoch_context_full& context, const hash256& header_hash,
|
||||
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
|
||||
|
||||
|
||||
/// Tries to find the epoch number matching the given seed hash.
|
||||
///
|
||||
/// Mining pool protocols (many variants of stratum and "getwork") send out
|
||||
/// seed hash instead of epoch number to workers. This function tries to recover
|
||||
/// the epoch number from this seed hash.
|
||||
///
|
||||
/// @param seed Ethash seed hash.
|
||||
/// @return The epoch number or -1 if not found.
|
||||
int find_epoch_number(const hash256& seed) noexcept;
|
||||
|
||||
|
||||
/// Get global shared epoch context.
|
||||
const epoch_context& get_global_epoch_context(int epoch_number);
|
||||
|
||||
/// Get global shared epoch context with full dataset initialized.
|
||||
const epoch_context_full& get_global_epoch_context_full(int epoch_number);
|
||||
} // namespace ethash
|
||||
46
contrib/ethereum/libethash/ethash/hash_types.h
Normal file
46
contrib/ethereum/libethash/ethash/hash_types.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
union ethash_hash256
|
||||
{
|
||||
uint64_t word64s[4];
|
||||
uint32_t word32s[8];
|
||||
uint8_t bytes[32];
|
||||
};
|
||||
|
||||
union ethash_hash512
|
||||
{
|
||||
uint64_t word64s[8];
|
||||
uint32_t word32s[16];
|
||||
uint8_t bytes[64];
|
||||
};
|
||||
|
||||
union ethash_hash1024
|
||||
{
|
||||
union ethash_hash512 hash512s[2];
|
||||
uint64_t word64s[16];
|
||||
uint32_t word32s[32];
|
||||
uint8_t bytes[128];
|
||||
};
|
||||
|
||||
union ethash_hash2048
|
||||
{
|
||||
union ethash_hash512 hash512s[4];
|
||||
uint64_t word64s[32];
|
||||
uint32_t word32s[64];
|
||||
uint8_t bytes[256];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
15
contrib/ethereum/libethash/ethash/hash_types.hpp
Normal file
15
contrib/ethereum/libethash/ethash/hash_types.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/hash_types.h>
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
using hash256 = ethash_hash256;
|
||||
using hash512 = ethash_hash512;
|
||||
using hash1024 = ethash_hash1024;
|
||||
using hash2048 = ethash_hash2048;
|
||||
} // namespace ethash
|
||||
49
contrib/ethereum/libethash/ethash/keccak.h
Normal file
49
contrib/ethereum/libethash/ethash/keccak.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/hash_types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NOEXCEPT noexcept
|
||||
#else
|
||||
#define NOEXCEPT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The Keccak-f[1600] function.
|
||||
*
|
||||
* The implementation of the Keccak-f function with 1600-bit width of the permutation (b).
|
||||
* The size of the state is also 1600 bit what gives 25 64-bit words.
|
||||
*
|
||||
* @param state The state of 25 64-bit words on which the permutation is to be performed.
|
||||
*/
|
||||
void ethash_keccakf1600(uint64_t state[25]) NOEXCEPT;
|
||||
|
||||
/**
|
||||
* The Keccak-f[800] function.
|
||||
*
|
||||
* The implementation of the Keccak-f function with 800-bit width of the permutation (b).
|
||||
* The size of the state is also 800 bit what gives 25 32-bit words.
|
||||
*
|
||||
* @param state The state of 25 32-bit words on which the permutation is to be performed.
|
||||
*/
|
||||
void ethash_keccakf800(uint32_t state[25]) NOEXCEPT;
|
||||
|
||||
union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) NOEXCEPT;
|
||||
union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) NOEXCEPT;
|
||||
union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) NOEXCEPT;
|
||||
union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) NOEXCEPT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
35
contrib/ethereum/libethash/ethash/keccak.hpp
Normal file
35
contrib/ethereum/libethash/ethash/keccak.hpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/keccak.h>
|
||||
#include <ethash/hash_types.hpp>
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
inline hash256 keccak256(const uint8_t* data, size_t size) noexcept
|
||||
{
|
||||
return ethash_keccak256(data, size);
|
||||
}
|
||||
|
||||
inline hash256 keccak256(const hash256& input) noexcept
|
||||
{
|
||||
return ethash_keccak256_32(input.bytes);
|
||||
}
|
||||
|
||||
inline hash512 keccak512(const uint8_t* data, size_t size) noexcept
|
||||
{
|
||||
return ethash_keccak512(data, size);
|
||||
}
|
||||
|
||||
inline hash512 keccak512(const hash512& input) noexcept
|
||||
{
|
||||
return ethash_keccak512_64(input.bytes);
|
||||
}
|
||||
|
||||
static constexpr auto keccak256_32 = ethash_keccak256_32;
|
||||
static constexpr auto keccak512_64 = ethash_keccak512_64;
|
||||
|
||||
} // namespace ethash
|
||||
47
contrib/ethereum/libethash/ethash/progpow.hpp
Normal file
47
contrib/ethereum/libethash/ethash/progpow.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// ProgPoW API
|
||||
///
|
||||
/// This file provides the public API for ProgPoW as the Ethash API extension.
|
||||
|
||||
#include <ethash/ethash.hpp>
|
||||
|
||||
namespace progpow
|
||||
{
|
||||
using namespace ethash; // Include ethash namespace.
|
||||
|
||||
|
||||
/// The ProgPoW algorithm revision implemented as specified in the spec
|
||||
/// https://github.com/ifdefelse/ProgPOW#change-history.
|
||||
constexpr auto revision = "0.9.2";
|
||||
|
||||
constexpr int period_length = 50;
|
||||
constexpr uint32_t num_regs = 32;
|
||||
constexpr size_t num_lanes = 16;
|
||||
constexpr int num_cache_accesses = 12;
|
||||
constexpr int num_math_operations = 20;
|
||||
constexpr size_t l1_cache_size = 16 * 1024;
|
||||
constexpr size_t l1_cache_num_items = l1_cache_size / sizeof(uint32_t);
|
||||
|
||||
result hash(const epoch_context& context, int block_number, const hash256& header_hash,
|
||||
uint64_t nonce) noexcept;
|
||||
|
||||
result hash(const epoch_context_full& context, int block_number, const hash256& header_hash,
|
||||
uint64_t nonce) noexcept;
|
||||
|
||||
bool verify(const epoch_context& context, int block_number, const hash256& header_hash,
|
||||
const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept;
|
||||
|
||||
search_result search_light(const epoch_context& context, int block_number,
|
||||
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
|
||||
size_t iterations) noexcept;
|
||||
|
||||
search_result search(const epoch_context_full& context, int block_number,
|
||||
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
|
||||
size_t iterations) noexcept;
|
||||
|
||||
} // namespace progpow
|
||||
18
contrib/ethereum/libethash/ethash/version.h
Normal file
18
contrib/ethereum/libethash/ethash/version.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2019 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** The ethash library version. */
|
||||
#define ETHASH_VERSION "0.4.3"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace ethash
|
||||
{
|
||||
/// The ethash library version.
|
||||
constexpr auto version = ETHASH_VERSION;
|
||||
|
||||
} // namespace ethash
|
||||
#endif
|
||||
123
contrib/ethereum/libethash/keccak.c
Normal file
123
contrib/ethereum/libethash/keccak.c
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <ethash/keccak.h>
|
||||
|
||||
#include "support/attributes.h"
|
||||
#include <string.h>
|
||||
|
||||
#if _WIN32
|
||||
/* On Windows assume little endian. */
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#elif __APPLE__
|
||||
#include <machine/endian.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define to_le64(X) X
|
||||
#else
|
||||
#define to_le64(X) __builtin_bswap64(X)
|
||||
#endif
|
||||
|
||||
|
||||
/** Loads 64-bit integer from given memory location as little-endian number. */
|
||||
static INLINE ALWAYS_INLINE uint64_t load_le(const uint8_t* data)
|
||||
{
|
||||
/* memcpy is the best way of expressing the intention. Every compiler will
|
||||
optimize is to single load instruction if the target architecture
|
||||
supports unaligned memory access (GCC and clang even in O0).
|
||||
This is great trick because we are violating C/C++ memory alignment
|
||||
restrictions with no performance penalty. */
|
||||
uint64_t word;
|
||||
memcpy(&word, data, sizeof(word));
|
||||
return to_le64(word);
|
||||
}
|
||||
|
||||
static INLINE ALWAYS_INLINE void keccak(
|
||||
uint64_t* out, size_t bits, const uint8_t* data, size_t size)
|
||||
{
|
||||
static const size_t word_size = sizeof(uint64_t);
|
||||
const size_t hash_size = bits / 8;
|
||||
const size_t block_size = (1600 - bits * 2) / 8;
|
||||
|
||||
size_t i;
|
||||
uint64_t* state_iter;
|
||||
uint64_t last_word = 0;
|
||||
uint8_t* last_word_iter = (uint8_t*)&last_word;
|
||||
|
||||
uint64_t state[25] = {0};
|
||||
|
||||
while (size >= block_size)
|
||||
{
|
||||
for (i = 0; i < (block_size / word_size); ++i)
|
||||
{
|
||||
state[i] ^= load_le(data);
|
||||
data += word_size;
|
||||
}
|
||||
|
||||
ethash_keccakf1600(state);
|
||||
|
||||
size -= block_size;
|
||||
}
|
||||
|
||||
state_iter = state;
|
||||
|
||||
while (size >= word_size)
|
||||
{
|
||||
*state_iter ^= load_le(data);
|
||||
++state_iter;
|
||||
data += word_size;
|
||||
size -= word_size;
|
||||
}
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
*last_word_iter = *data;
|
||||
++last_word_iter;
|
||||
++data;
|
||||
--size;
|
||||
}
|
||||
*last_word_iter = 0x01;
|
||||
*state_iter ^= to_le64(last_word);
|
||||
|
||||
state[(block_size / word_size) - 1] ^= 0x8000000000000000;
|
||||
|
||||
ethash_keccakf1600(state);
|
||||
|
||||
for (i = 0; i < (hash_size / word_size); ++i)
|
||||
out[i] = to_le64(state[i]);
|
||||
}
|
||||
|
||||
union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size)
|
||||
{
|
||||
union ethash_hash256 hash;
|
||||
keccak(hash.word64s, 256, data, size);
|
||||
return hash;
|
||||
}
|
||||
|
||||
union ethash_hash256 ethash_keccak256_32(const uint8_t data[32])
|
||||
{
|
||||
union ethash_hash256 hash;
|
||||
keccak(hash.word64s, 256, data, 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size)
|
||||
{
|
||||
union ethash_hash512 hash;
|
||||
keccak(hash.word64s, 512, data, size);
|
||||
return hash;
|
||||
}
|
||||
|
||||
union ethash_hash512 ethash_keccak512_64(const uint8_t data[64])
|
||||
{
|
||||
union ethash_hash512 hash;
|
||||
keccak(hash.word64s, 512, data, 64);
|
||||
return hash;
|
||||
}
|
||||
255
contrib/ethereum/libethash/keccakf1600.c
Normal file
255
contrib/ethereum/libethash/keccakf1600.c
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static uint64_t rol(uint64_t x, unsigned s)
|
||||
{
|
||||
return (x << s) | (x >> (64 - s));
|
||||
}
|
||||
|
||||
static const uint64_t round_constants[24] = {
|
||||
0x0000000000000001,
|
||||
0x0000000000008082,
|
||||
0x800000000000808a,
|
||||
0x8000000080008000,
|
||||
0x000000000000808b,
|
||||
0x0000000080000001,
|
||||
0x8000000080008081,
|
||||
0x8000000000008009,
|
||||
0x000000000000008a,
|
||||
0x0000000000000088,
|
||||
0x0000000080008009,
|
||||
0x000000008000000a,
|
||||
0x000000008000808b,
|
||||
0x800000000000008b,
|
||||
0x8000000000008089,
|
||||
0x8000000000008003,
|
||||
0x8000000000008002,
|
||||
0x8000000000000080,
|
||||
0x000000000000800a,
|
||||
0x800000008000000a,
|
||||
0x8000000080008081,
|
||||
0x8000000000008080,
|
||||
0x0000000080000001,
|
||||
0x8000000080008008,
|
||||
};
|
||||
|
||||
void ethash_keccakf1600(uint64_t state[25])
|
||||
{
|
||||
/* The implementation based on the "simple" implementation by Ronny Van Keer. */
|
||||
|
||||
int round;
|
||||
|
||||
uint64_t Aba, Abe, Abi, Abo, Abu;
|
||||
uint64_t Aga, Age, Agi, Ago, Agu;
|
||||
uint64_t Aka, Ake, Aki, Ako, Aku;
|
||||
uint64_t Ama, Ame, Ami, Amo, Amu;
|
||||
uint64_t Asa, Ase, Asi, Aso, Asu;
|
||||
|
||||
uint64_t Eba, Ebe, Ebi, Ebo, Ebu;
|
||||
uint64_t Ega, Ege, Egi, Ego, Egu;
|
||||
uint64_t Eka, Eke, Eki, Eko, Eku;
|
||||
uint64_t Ema, Eme, Emi, Emo, Emu;
|
||||
uint64_t Esa, Ese, Esi, Eso, Esu;
|
||||
|
||||
uint64_t Ba, Be, Bi, Bo, Bu;
|
||||
|
||||
uint64_t Da, De, Di, Do, Du;
|
||||
|
||||
Aba = state[0];
|
||||
Abe = state[1];
|
||||
Abi = state[2];
|
||||
Abo = state[3];
|
||||
Abu = state[4];
|
||||
Aga = state[5];
|
||||
Age = state[6];
|
||||
Agi = state[7];
|
||||
Ago = state[8];
|
||||
Agu = state[9];
|
||||
Aka = state[10];
|
||||
Ake = state[11];
|
||||
Aki = state[12];
|
||||
Ako = state[13];
|
||||
Aku = state[14];
|
||||
Ama = state[15];
|
||||
Ame = state[16];
|
||||
Ami = state[17];
|
||||
Amo = state[18];
|
||||
Amu = state[19];
|
||||
Asa = state[20];
|
||||
Ase = state[21];
|
||||
Asi = state[22];
|
||||
Aso = state[23];
|
||||
Asu = state[24];
|
||||
|
||||
for (round = 0; round < 24; round += 2)
|
||||
{
|
||||
/* Round (round + 0): Axx -> Exx */
|
||||
|
||||
Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
|
||||
Be = Abe ^ Age ^ Ake ^ Ame ^ Ase;
|
||||
Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
|
||||
Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
|
||||
Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;
|
||||
|
||||
Da = Bu ^ rol(Be, 1);
|
||||
De = Ba ^ rol(Bi, 1);
|
||||
Di = Be ^ rol(Bo, 1);
|
||||
Do = Bi ^ rol(Bu, 1);
|
||||
Du = Bo ^ rol(Ba, 1);
|
||||
|
||||
Ba = Aba ^ Da;
|
||||
Be = rol(Age ^ De, 44);
|
||||
Bi = rol(Aki ^ Di, 43);
|
||||
Bo = rol(Amo ^ Do, 21);
|
||||
Bu = rol(Asu ^ Du, 14);
|
||||
Eba = Ba ^ (~Be & Bi) ^ round_constants[round];
|
||||
Ebe = Be ^ (~Bi & Bo);
|
||||
Ebi = Bi ^ (~Bo & Bu);
|
||||
Ebo = Bo ^ (~Bu & Ba);
|
||||
Ebu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abo ^ Do, 28);
|
||||
Be = rol(Agu ^ Du, 20);
|
||||
Bi = rol(Aka ^ Da, 3);
|
||||
Bo = rol(Ame ^ De, 45);
|
||||
Bu = rol(Asi ^ Di, 61);
|
||||
Ega = Ba ^ (~Be & Bi);
|
||||
Ege = Be ^ (~Bi & Bo);
|
||||
Egi = Bi ^ (~Bo & Bu);
|
||||
Ego = Bo ^ (~Bu & Ba);
|
||||
Egu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abe ^ De, 1);
|
||||
Be = rol(Agi ^ Di, 6);
|
||||
Bi = rol(Ako ^ Do, 25);
|
||||
Bo = rol(Amu ^ Du, 8);
|
||||
Bu = rol(Asa ^ Da, 18);
|
||||
Eka = Ba ^ (~Be & Bi);
|
||||
Eke = Be ^ (~Bi & Bo);
|
||||
Eki = Bi ^ (~Bo & Bu);
|
||||
Eko = Bo ^ (~Bu & Ba);
|
||||
Eku = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abu ^ Du, 27);
|
||||
Be = rol(Aga ^ Da, 36);
|
||||
Bi = rol(Ake ^ De, 10);
|
||||
Bo = rol(Ami ^ Di, 15);
|
||||
Bu = rol(Aso ^ Do, 56);
|
||||
Ema = Ba ^ (~Be & Bi);
|
||||
Eme = Be ^ (~Bi & Bo);
|
||||
Emi = Bi ^ (~Bo & Bu);
|
||||
Emo = Bo ^ (~Bu & Ba);
|
||||
Emu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abi ^ Di, 62);
|
||||
Be = rol(Ago ^ Do, 55);
|
||||
Bi = rol(Aku ^ Du, 39);
|
||||
Bo = rol(Ama ^ Da, 41);
|
||||
Bu = rol(Ase ^ De, 2);
|
||||
Esa = Ba ^ (~Be & Bi);
|
||||
Ese = Be ^ (~Bi & Bo);
|
||||
Esi = Bi ^ (~Bo & Bu);
|
||||
Eso = Bo ^ (~Bu & Ba);
|
||||
Esu = Bu ^ (~Ba & Be);
|
||||
|
||||
|
||||
/* Round (round + 1): Exx -> Axx */
|
||||
|
||||
Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
|
||||
Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
|
||||
Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
|
||||
Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
|
||||
Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;
|
||||
|
||||
Da = Bu ^ rol(Be, 1);
|
||||
De = Ba ^ rol(Bi, 1);
|
||||
Di = Be ^ rol(Bo, 1);
|
||||
Do = Bi ^ rol(Bu, 1);
|
||||
Du = Bo ^ rol(Ba, 1);
|
||||
|
||||
Ba = Eba ^ Da;
|
||||
Be = rol(Ege ^ De, 44);
|
||||
Bi = rol(Eki ^ Di, 43);
|
||||
Bo = rol(Emo ^ Do, 21);
|
||||
Bu = rol(Esu ^ Du, 14);
|
||||
Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1];
|
||||
Abe = Be ^ (~Bi & Bo);
|
||||
Abi = Bi ^ (~Bo & Bu);
|
||||
Abo = Bo ^ (~Bu & Ba);
|
||||
Abu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebo ^ Do, 28);
|
||||
Be = rol(Egu ^ Du, 20);
|
||||
Bi = rol(Eka ^ Da, 3);
|
||||
Bo = rol(Eme ^ De, 45);
|
||||
Bu = rol(Esi ^ Di, 61);
|
||||
Aga = Ba ^ (~Be & Bi);
|
||||
Age = Be ^ (~Bi & Bo);
|
||||
Agi = Bi ^ (~Bo & Bu);
|
||||
Ago = Bo ^ (~Bu & Ba);
|
||||
Agu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebe ^ De, 1);
|
||||
Be = rol(Egi ^ Di, 6);
|
||||
Bi = rol(Eko ^ Do, 25);
|
||||
Bo = rol(Emu ^ Du, 8);
|
||||
Bu = rol(Esa ^ Da, 18);
|
||||
Aka = Ba ^ (~Be & Bi);
|
||||
Ake = Be ^ (~Bi & Bo);
|
||||
Aki = Bi ^ (~Bo & Bu);
|
||||
Ako = Bo ^ (~Bu & Ba);
|
||||
Aku = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebu ^ Du, 27);
|
||||
Be = rol(Ega ^ Da, 36);
|
||||
Bi = rol(Eke ^ De, 10);
|
||||
Bo = rol(Emi ^ Di, 15);
|
||||
Bu = rol(Eso ^ Do, 56);
|
||||
Ama = Ba ^ (~Be & Bi);
|
||||
Ame = Be ^ (~Bi & Bo);
|
||||
Ami = Bi ^ (~Bo & Bu);
|
||||
Amo = Bo ^ (~Bu & Ba);
|
||||
Amu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebi ^ Di, 62);
|
||||
Be = rol(Ego ^ Do, 55);
|
||||
Bi = rol(Eku ^ Du, 39);
|
||||
Bo = rol(Ema ^ Da, 41);
|
||||
Bu = rol(Ese ^ De, 2);
|
||||
Asa = Ba ^ (~Be & Bi);
|
||||
Ase = Be ^ (~Bi & Bo);
|
||||
Asi = Bi ^ (~Bo & Bu);
|
||||
Aso = Bo ^ (~Bu & Ba);
|
||||
Asu = Bu ^ (~Ba & Be);
|
||||
}
|
||||
|
||||
state[0] = Aba;
|
||||
state[1] = Abe;
|
||||
state[2] = Abi;
|
||||
state[3] = Abo;
|
||||
state[4] = Abu;
|
||||
state[5] = Aga;
|
||||
state[6] = Age;
|
||||
state[7] = Agi;
|
||||
state[8] = Ago;
|
||||
state[9] = Agu;
|
||||
state[10] = Aka;
|
||||
state[11] = Ake;
|
||||
state[12] = Aki;
|
||||
state[13] = Ako;
|
||||
state[14] = Aku;
|
||||
state[15] = Ama;
|
||||
state[16] = Ame;
|
||||
state[17] = Ami;
|
||||
state[18] = Amo;
|
||||
state[19] = Amu;
|
||||
state[20] = Asa;
|
||||
state[21] = Ase;
|
||||
state[22] = Asi;
|
||||
state[23] = Aso;
|
||||
state[24] = Asu;
|
||||
}
|
||||
253
contrib/ethereum/libethash/keccakf800.c
Normal file
253
contrib/ethereum/libethash/keccakf800.c
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static uint32_t rol(uint32_t x, unsigned s)
|
||||
{
|
||||
return (x << s) | (x >> (32 - s));
|
||||
}
|
||||
|
||||
static const uint32_t round_constants[22] = {
|
||||
0x00000001,
|
||||
0x00008082,
|
||||
0x0000808A,
|
||||
0x80008000,
|
||||
0x0000808B,
|
||||
0x80000001,
|
||||
0x80008081,
|
||||
0x00008009,
|
||||
0x0000008A,
|
||||
0x00000088,
|
||||
0x80008009,
|
||||
0x8000000A,
|
||||
0x8000808B,
|
||||
0x0000008B,
|
||||
0x00008089,
|
||||
0x00008003,
|
||||
0x00008002,
|
||||
0x00000080,
|
||||
0x0000800A,
|
||||
0x8000000A,
|
||||
0x80008081,
|
||||
0x00008080,
|
||||
};
|
||||
|
||||
void ethash_keccakf800(uint32_t state[25])
|
||||
{
|
||||
/* The implementation directly translated from ethash_keccakf1600. */
|
||||
|
||||
int round;
|
||||
|
||||
uint32_t Aba, Abe, Abi, Abo, Abu;
|
||||
uint32_t Aga, Age, Agi, Ago, Agu;
|
||||
uint32_t Aka, Ake, Aki, Ako, Aku;
|
||||
uint32_t Ama, Ame, Ami, Amo, Amu;
|
||||
uint32_t Asa, Ase, Asi, Aso, Asu;
|
||||
|
||||
uint32_t Eba, Ebe, Ebi, Ebo, Ebu;
|
||||
uint32_t Ega, Ege, Egi, Ego, Egu;
|
||||
uint32_t Eka, Eke, Eki, Eko, Eku;
|
||||
uint32_t Ema, Eme, Emi, Emo, Emu;
|
||||
uint32_t Esa, Ese, Esi, Eso, Esu;
|
||||
|
||||
uint32_t Ba, Be, Bi, Bo, Bu;
|
||||
|
||||
uint32_t Da, De, Di, Do, Du;
|
||||
|
||||
Aba = state[0];
|
||||
Abe = state[1];
|
||||
Abi = state[2];
|
||||
Abo = state[3];
|
||||
Abu = state[4];
|
||||
Aga = state[5];
|
||||
Age = state[6];
|
||||
Agi = state[7];
|
||||
Ago = state[8];
|
||||
Agu = state[9];
|
||||
Aka = state[10];
|
||||
Ake = state[11];
|
||||
Aki = state[12];
|
||||
Ako = state[13];
|
||||
Aku = state[14];
|
||||
Ama = state[15];
|
||||
Ame = state[16];
|
||||
Ami = state[17];
|
||||
Amo = state[18];
|
||||
Amu = state[19];
|
||||
Asa = state[20];
|
||||
Ase = state[21];
|
||||
Asi = state[22];
|
||||
Aso = state[23];
|
||||
Asu = state[24];
|
||||
|
||||
for (round = 0; round < 22; round += 2)
|
||||
{
|
||||
/* Round (round + 0): Axx -> Exx */
|
||||
|
||||
Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
|
||||
Be = Abe ^ Age ^ Ake ^ Ame ^ Ase;
|
||||
Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
|
||||
Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
|
||||
Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;
|
||||
|
||||
Da = Bu ^ rol(Be, 1);
|
||||
De = Ba ^ rol(Bi, 1);
|
||||
Di = Be ^ rol(Bo, 1);
|
||||
Do = Bi ^ rol(Bu, 1);
|
||||
Du = Bo ^ rol(Ba, 1);
|
||||
|
||||
Ba = Aba ^ Da;
|
||||
Be = rol(Age ^ De, 12);
|
||||
Bi = rol(Aki ^ Di, 11);
|
||||
Bo = rol(Amo ^ Do, 21);
|
||||
Bu = rol(Asu ^ Du, 14);
|
||||
Eba = Ba ^ (~Be & Bi) ^ round_constants[round];
|
||||
Ebe = Be ^ (~Bi & Bo);
|
||||
Ebi = Bi ^ (~Bo & Bu);
|
||||
Ebo = Bo ^ (~Bu & Ba);
|
||||
Ebu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abo ^ Do, 28);
|
||||
Be = rol(Agu ^ Du, 20);
|
||||
Bi = rol(Aka ^ Da, 3);
|
||||
Bo = rol(Ame ^ De, 13);
|
||||
Bu = rol(Asi ^ Di, 29);
|
||||
Ega = Ba ^ (~Be & Bi);
|
||||
Ege = Be ^ (~Bi & Bo);
|
||||
Egi = Bi ^ (~Bo & Bu);
|
||||
Ego = Bo ^ (~Bu & Ba);
|
||||
Egu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abe ^ De, 1);
|
||||
Be = rol(Agi ^ Di, 6);
|
||||
Bi = rol(Ako ^ Do, 25);
|
||||
Bo = rol(Amu ^ Du, 8);
|
||||
Bu = rol(Asa ^ Da, 18);
|
||||
Eka = Ba ^ (~Be & Bi);
|
||||
Eke = Be ^ (~Bi & Bo);
|
||||
Eki = Bi ^ (~Bo & Bu);
|
||||
Eko = Bo ^ (~Bu & Ba);
|
||||
Eku = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abu ^ Du, 27);
|
||||
Be = rol(Aga ^ Da, 4);
|
||||
Bi = rol(Ake ^ De, 10);
|
||||
Bo = rol(Ami ^ Di, 15);
|
||||
Bu = rol(Aso ^ Do, 24);
|
||||
Ema = Ba ^ (~Be & Bi);
|
||||
Eme = Be ^ (~Bi & Bo);
|
||||
Emi = Bi ^ (~Bo & Bu);
|
||||
Emo = Bo ^ (~Bu & Ba);
|
||||
Emu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Abi ^ Di, 30);
|
||||
Be = rol(Ago ^ Do, 23);
|
||||
Bi = rol(Aku ^ Du, 7);
|
||||
Bo = rol(Ama ^ Da, 9);
|
||||
Bu = rol(Ase ^ De, 2);
|
||||
Esa = Ba ^ (~Be & Bi);
|
||||
Ese = Be ^ (~Bi & Bo);
|
||||
Esi = Bi ^ (~Bo & Bu);
|
||||
Eso = Bo ^ (~Bu & Ba);
|
||||
Esu = Bu ^ (~Ba & Be);
|
||||
|
||||
|
||||
/* Round (round + 1): Exx -> Axx */
|
||||
|
||||
Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
|
||||
Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
|
||||
Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
|
||||
Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
|
||||
Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;
|
||||
|
||||
Da = Bu ^ rol(Be, 1);
|
||||
De = Ba ^ rol(Bi, 1);
|
||||
Di = Be ^ rol(Bo, 1);
|
||||
Do = Bi ^ rol(Bu, 1);
|
||||
Du = Bo ^ rol(Ba, 1);
|
||||
|
||||
Ba = Eba ^ Da;
|
||||
Be = rol(Ege ^ De, 12);
|
||||
Bi = rol(Eki ^ Di, 11);
|
||||
Bo = rol(Emo ^ Do, 21);
|
||||
Bu = rol(Esu ^ Du, 14);
|
||||
Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1];
|
||||
Abe = Be ^ (~Bi & Bo);
|
||||
Abi = Bi ^ (~Bo & Bu);
|
||||
Abo = Bo ^ (~Bu & Ba);
|
||||
Abu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebo ^ Do, 28);
|
||||
Be = rol(Egu ^ Du, 20);
|
||||
Bi = rol(Eka ^ Da, 3);
|
||||
Bo = rol(Eme ^ De, 13);
|
||||
Bu = rol(Esi ^ Di, 29);
|
||||
Aga = Ba ^ (~Be & Bi);
|
||||
Age = Be ^ (~Bi & Bo);
|
||||
Agi = Bi ^ (~Bo & Bu);
|
||||
Ago = Bo ^ (~Bu & Ba);
|
||||
Agu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebe ^ De, 1);
|
||||
Be = rol(Egi ^ Di, 6);
|
||||
Bi = rol(Eko ^ Do, 25);
|
||||
Bo = rol(Emu ^ Du, 8);
|
||||
Bu = rol(Esa ^ Da, 18);
|
||||
Aka = Ba ^ (~Be & Bi);
|
||||
Ake = Be ^ (~Bi & Bo);
|
||||
Aki = Bi ^ (~Bo & Bu);
|
||||
Ako = Bo ^ (~Bu & Ba);
|
||||
Aku = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebu ^ Du, 27);
|
||||
Be = rol(Ega ^ Da, 4);
|
||||
Bi = rol(Eke ^ De, 10);
|
||||
Bo = rol(Emi ^ Di, 15);
|
||||
Bu = rol(Eso ^ Do, 24);
|
||||
Ama = Ba ^ (~Be & Bi);
|
||||
Ame = Be ^ (~Bi & Bo);
|
||||
Ami = Bi ^ (~Bo & Bu);
|
||||
Amo = Bo ^ (~Bu & Ba);
|
||||
Amu = Bu ^ (~Ba & Be);
|
||||
|
||||
Ba = rol(Ebi ^ Di, 30);
|
||||
Be = rol(Ego ^ Do, 23);
|
||||
Bi = rol(Eku ^ Du, 7);
|
||||
Bo = rol(Ema ^ Da, 9);
|
||||
Bu = rol(Ese ^ De, 2);
|
||||
Asa = Ba ^ (~Be & Bi);
|
||||
Ase = Be ^ (~Bi & Bo);
|
||||
Asi = Bi ^ (~Bo & Bu);
|
||||
Aso = Bo ^ (~Bu & Ba);
|
||||
Asu = Bu ^ (~Ba & Be);
|
||||
}
|
||||
|
||||
state[0] = Aba;
|
||||
state[1] = Abe;
|
||||
state[2] = Abi;
|
||||
state[3] = Abo;
|
||||
state[4] = Abu;
|
||||
state[5] = Aga;
|
||||
state[6] = Age;
|
||||
state[7] = Agi;
|
||||
state[8] = Ago;
|
||||
state[9] = Agu;
|
||||
state[10] = Aka;
|
||||
state[11] = Ake;
|
||||
state[12] = Aki;
|
||||
state[13] = Ako;
|
||||
state[14] = Aku;
|
||||
state[15] = Ama;
|
||||
state[16] = Ame;
|
||||
state[17] = Ami;
|
||||
state[18] = Amo;
|
||||
state[19] = Amu;
|
||||
state[20] = Asa;
|
||||
state[21] = Ase;
|
||||
state[22] = Asi;
|
||||
state[23] = Aso;
|
||||
state[24] = Asu;
|
||||
}
|
||||
64
contrib/ethereum/libethash/kiss99.hpp
Normal file
64
contrib/ethereum/libethash/kiss99.hpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "support/attributes.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* KISS PRNG by the spec from 1999.
|
||||
*
|
||||
* The implementation of KISS pseudo-random number generator
|
||||
* by the specification published on 21 Jan 1999 in
|
||||
* http://www.cse.yorku.ca/~oz/marsaglia-rng.html.
|
||||
* The KISS is not versioned so here we are using `kiss99` prefix to indicate
|
||||
* the version from 1999.
|
||||
*
|
||||
* The specification uses `unsigned long` type with the intention for 32-bit
|
||||
* values. Because in GCC/clang for 64-bit architectures `unsigned long` is
|
||||
* 64-bit size type, here the explicit `uint32_t` type is used.
|
||||
*
|
||||
* @defgroup kiss99 KISS99
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The KISS generator.
|
||||
*/
|
||||
class kiss99
|
||||
{
|
||||
uint32_t z = 362436069;
|
||||
uint32_t w = 521288629;
|
||||
uint32_t jsr = 123456789;
|
||||
uint32_t jcong = 380116160;
|
||||
|
||||
public:
|
||||
/** Creates KISS generator state with default values provided by the specification. */
|
||||
kiss99() noexcept = default;
|
||||
|
||||
/** Creates KISS generator state with provided init values.*/
|
||||
kiss99(uint32_t z, uint32_t w, uint32_t jsr, uint32_t jcong) noexcept
|
||||
: z{z}, w{w}, jsr{jsr}, jcong{jcong}
|
||||
{}
|
||||
|
||||
/** Generates next number from the KISS generator. */
|
||||
NO_SANITIZE("unsigned-integer-overflow")
|
||||
uint32_t operator()() noexcept
|
||||
{
|
||||
z = 36969 * (z & 0xffff) + (z >> 16);
|
||||
w = 18000 * (w & 0xffff) + (w >> 16);
|
||||
|
||||
jcong = 69069 * jcong + 1234567;
|
||||
|
||||
jsr ^= (jsr << 17);
|
||||
jsr ^= (jsr >> 13);
|
||||
jsr ^= (jsr << 5);
|
||||
|
||||
return (((z << 16) + w) ^ jcong) + jsr;
|
||||
}
|
||||
};
|
||||
|
||||
/** @} */
|
||||
100
contrib/ethereum/libethash/managed.cpp
Normal file
100
contrib/ethereum/libethash/managed.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
#include "ethash-internal.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#if !defined(__has_cpp_attribute)
|
||||
#define __has_cpp_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_cpp_attribute(gnu::noinline)
|
||||
#define ATTRIBUTE_NOINLINE [[gnu::noinline]]
|
||||
#elif _MSC_VER
|
||||
#define ATTRIBUTE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::mutex shared_context_mutex;
|
||||
std::shared_ptr<epoch_context> shared_context;
|
||||
thread_local std::shared_ptr<epoch_context> thread_local_context;
|
||||
|
||||
std::mutex shared_context_full_mutex;
|
||||
std::shared_ptr<epoch_context_full> shared_context_full;
|
||||
thread_local std::shared_ptr<epoch_context_full> thread_local_context_full;
|
||||
|
||||
/// Update thread local epoch context.
|
||||
///
|
||||
/// This function is on the slow path. It's separated to allow inlining the fast
|
||||
/// path.
|
||||
///
|
||||
/// @todo: Redesign to guarantee deallocation before new allocation.
|
||||
ATTRIBUTE_NOINLINE
|
||||
void update_local_context(int epoch_number)
|
||||
{
|
||||
// Release the shared pointer of the obsoleted context.
|
||||
thread_local_context.reset();
|
||||
|
||||
// Local context invalid, check the shared context.
|
||||
std::lock_guard<std::mutex> lock{shared_context_mutex};
|
||||
|
||||
if (!shared_context || shared_context->epoch_number != epoch_number)
|
||||
{
|
||||
// Release the shared pointer of the obsoleted context.
|
||||
shared_context.reset();
|
||||
|
||||
// Build new context.
|
||||
shared_context = create_epoch_context(epoch_number);
|
||||
}
|
||||
|
||||
thread_local_context = shared_context;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NOINLINE
|
||||
void update_local_context_full(int epoch_number)
|
||||
{
|
||||
// Release the shared pointer of the obsoleted context.
|
||||
thread_local_context_full.reset();
|
||||
|
||||
// Local context invalid, check the shared context.
|
||||
std::lock_guard<std::mutex> lock{shared_context_full_mutex};
|
||||
|
||||
if (!shared_context_full || shared_context_full->epoch_number != epoch_number)
|
||||
{
|
||||
// Release the shared pointer of the obsoleted context.
|
||||
shared_context_full.reset();
|
||||
|
||||
// Build new context.
|
||||
shared_context_full = create_epoch_context_full(epoch_number);
|
||||
}
|
||||
|
||||
thread_local_context_full = shared_context_full;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const epoch_context& get_global_epoch_context(int epoch_number)
|
||||
{
|
||||
// Check if local context matches epoch number.
|
||||
if (!thread_local_context || thread_local_context->epoch_number != epoch_number)
|
||||
update_local_context(epoch_number);
|
||||
|
||||
return *thread_local_context;
|
||||
}
|
||||
|
||||
const epoch_context_full& get_global_epoch_context_full(int epoch_number)
|
||||
{
|
||||
// Check if local context matches epoch number.
|
||||
if (!thread_local_context_full || thread_local_context_full->epoch_number != epoch_number)
|
||||
update_local_context_full(epoch_number);
|
||||
|
||||
return *thread_local_context_full;
|
||||
}
|
||||
} // namespace ethash
|
||||
43
contrib/ethereum/libethash/primes.c
Normal file
43
contrib/ethereum/libethash/primes.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "primes.h"
|
||||
|
||||
/** Checks if the number is prime. Requires the number to be > 2 and odd. */
|
||||
static int is_odd_prime(int number)
|
||||
{
|
||||
int d;
|
||||
|
||||
/* Check factors up to sqrt(number).
|
||||
To avoid computing sqrt, compare d*d <= number with 64-bit precision. */
|
||||
for (d = 3; (int64_t)d * (int64_t)d <= (int64_t)number; d += 2)
|
||||
{
|
||||
if (number % d == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ethash_find_largest_prime(int upper_bound)
|
||||
{
|
||||
int n = upper_bound;
|
||||
|
||||
if (n < 2)
|
||||
return 0;
|
||||
|
||||
if (n == 2)
|
||||
return 2;
|
||||
|
||||
/* If even number, skip it. */
|
||||
if (n % 2 == 0)
|
||||
--n;
|
||||
|
||||
/* Test descending odd numbers. */
|
||||
while (!is_odd_prime(n))
|
||||
n -= 2;
|
||||
|
||||
return n;
|
||||
}
|
||||
25
contrib/ethereum/libethash/primes.h
Normal file
25
contrib/ethereum/libethash/primes.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ethash/ethash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Finds the largest prime number not greater than the provided upper bound.
|
||||
*
|
||||
* @param upper_bound The upper bound. SHOULD be greater than 1.
|
||||
* @return The largest prime number `p` such `p <= upper_bound`.
|
||||
* In case `upper_bound <= 1`, returns 0.
|
||||
*/
|
||||
int ethash_find_largest_prime(int upper_bound) NOEXCEPT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
360
contrib/ethereum/libethash/progpow.cpp
Normal file
360
contrib/ethereum/libethash/progpow.cpp
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
// Copyright 2018 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
|
||||
#include <ethash/progpow.hpp>
|
||||
|
||||
#include "bit_manipulation.h"
|
||||
#include "endianness.hpp"
|
||||
#include "ethash-internal.hpp"
|
||||
#include "kiss99.hpp"
|
||||
#include <ethash/keccak.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace progpow
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/// A variant of Keccak hash function for ProgPoW.
|
||||
///
|
||||
/// This Keccak hash function uses 800-bit permutation (Keccak-f[800]) with 576 bitrate.
|
||||
/// It take exactly 576 bits of input (split across 3 arguments) and adds no padding.
|
||||
///
|
||||
/// @param header_hash The 256-bit header hash.
|
||||
/// @param nonce The 64-bit nonce.
|
||||
/// @param mix_hash Additional 256-bits of data.
|
||||
/// @return The 256-bit output of the hash function.
|
||||
hash256 keccak_progpow_256(
|
||||
const hash256& header_hash, uint64_t nonce, const hash256& mix_hash) noexcept
|
||||
{
|
||||
static constexpr size_t num_words =
|
||||
sizeof(header_hash.word32s) / sizeof(header_hash.word32s[0]);
|
||||
|
||||
uint32_t state[25] = {};
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < num_words; ++i)
|
||||
state[i] = le::uint32(header_hash.word32s[i]);
|
||||
|
||||
state[i++] = static_cast<uint32_t>(nonce);
|
||||
state[i++] = static_cast<uint32_t>(nonce >> 32);
|
||||
|
||||
for (uint32_t mix_word : mix_hash.word32s)
|
||||
state[i++] = le::uint32(mix_word);
|
||||
|
||||
ethash_keccakf800(state);
|
||||
|
||||
hash256 output;
|
||||
for (i = 0; i < num_words; ++i)
|
||||
output.word32s[i] = le::uint32(state[i]);
|
||||
return output;
|
||||
}
|
||||
|
||||
/// The same as keccak_progpow_256() but uses null mix
|
||||
/// and returns top 64 bits of the output being a big-endian prefix of the 256-bit hash.
|
||||
inline uint64_t keccak_progpow_64(const hash256& header_hash, uint64_t nonce) noexcept
|
||||
{
|
||||
const hash256 h = keccak_progpow_256(header_hash, nonce, {});
|
||||
return be::uint64(h.word64s[0]);
|
||||
}
|
||||
|
||||
|
||||
/// ProgPoW mix RNG state.
|
||||
///
|
||||
/// Encapsulates the state of the random number generator used in computing ProgPoW mix.
|
||||
/// This includes the state of the KISS99 RNG and the precomputed random permutation of the
|
||||
/// sequence of mix item indexes.
|
||||
class mix_rng_state
|
||||
{
|
||||
public:
|
||||
inline explicit mix_rng_state(uint64_t seed) noexcept;
|
||||
|
||||
uint32_t next_dst() noexcept { return dst_seq[(dst_counter++) % num_regs]; }
|
||||
uint32_t next_src() noexcept { return src_seq[(src_counter++) % num_regs]; }
|
||||
|
||||
kiss99 rng;
|
||||
|
||||
private:
|
||||
size_t dst_counter = 0;
|
||||
std::array<uint32_t, num_regs> dst_seq;
|
||||
size_t src_counter = 0;
|
||||
std::array<uint32_t, num_regs> src_seq;
|
||||
};
|
||||
|
||||
mix_rng_state::mix_rng_state(uint64_t seed) noexcept
|
||||
{
|
||||
const auto seed_lo = static_cast<uint32_t>(seed);
|
||||
const auto seed_hi = static_cast<uint32_t>(seed >> 32);
|
||||
|
||||
const auto z = fnv1a(fnv_offset_basis, seed_lo);
|
||||
const auto w = fnv1a(z, seed_hi);
|
||||
const auto jsr = fnv1a(w, seed_lo);
|
||||
const auto jcong = fnv1a(jsr, seed_hi);
|
||||
|
||||
rng = kiss99{z, w, jsr, jcong};
|
||||
|
||||
// Create random permutations of mix destinations / sources.
|
||||
// Uses Fisher-Yates shuffle.
|
||||
for (uint32_t i = 0; i < num_regs; ++i)
|
||||
{
|
||||
dst_seq[i] = i;
|
||||
src_seq[i] = i;
|
||||
}
|
||||
|
||||
for (uint32_t i = num_regs; i > 1; --i)
|
||||
{
|
||||
std::swap(dst_seq[i - 1], dst_seq[rng() % i]);
|
||||
std::swap(src_seq[i - 1], src_seq[rng() % i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NO_SANITIZE("unsigned-integer-overflow")
|
||||
inline uint32_t random_math(uint32_t a, uint32_t b, uint32_t selector) noexcept
|
||||
{
|
||||
switch (selector % 11)
|
||||
{
|
||||
default:
|
||||
case 2:
|
||||
return a + b;
|
||||
case 3:
|
||||
return a * b;
|
||||
case 4:
|
||||
return mul_hi32(a, b);
|
||||
case 5:
|
||||
return std::min(a, b);
|
||||
case 6:
|
||||
return rotl32(a, b);
|
||||
case 7:
|
||||
return rotr32(a, b);
|
||||
case 8:
|
||||
return a & b;
|
||||
case 9:
|
||||
return a | b;
|
||||
case 10:
|
||||
return a ^ b;
|
||||
case 0:
|
||||
return clz32(a) + clz32(b);
|
||||
case 1:
|
||||
return popcount32(a) + popcount32(b);
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge data from `b` and `a`.
|
||||
/// Assuming `a` has high entropy, only do ops that retain entropy even if `b`
|
||||
/// has low entropy (i.e. do not do `a & b`).
|
||||
NO_SANITIZE("unsigned-integer-overflow")
|
||||
inline void random_merge(uint32_t& a, uint32_t b, uint32_t selector) noexcept
|
||||
{
|
||||
const auto x = (selector >> 16) % 31 + 1; // Additional non-zero selector from higher bits.
|
||||
switch (selector % 4)
|
||||
{
|
||||
case 0:
|
||||
a = (a * 33) + b;
|
||||
break;
|
||||
case 1:
|
||||
a = (a ^ b) * 33;
|
||||
break;
|
||||
case 2:
|
||||
a = rotl32(a, x) ^ b;
|
||||
break;
|
||||
case 3:
|
||||
a = rotr32(a, x) ^ b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
using lookup_fn = hash2048 (*)(const epoch_context&, uint32_t);
|
||||
|
||||
using mix_array = std::array<std::array<uint32_t, num_regs>, num_lanes>;
|
||||
|
||||
void round(
|
||||
const epoch_context& context, uint32_t r, mix_array& mix, mix_rng_state state, lookup_fn lookup)
|
||||
{
|
||||
const uint32_t num_items = static_cast<uint32_t>(context.full_dataset_num_items / 2);
|
||||
const uint32_t item_index = mix[r % num_lanes][0] % num_items;
|
||||
const hash2048 item = lookup(context, item_index);
|
||||
|
||||
constexpr size_t num_words_per_lane = sizeof(item) / (sizeof(uint32_t) * num_lanes);
|
||||
constexpr int max_operations =
|
||||
num_cache_accesses > num_math_operations ? num_cache_accesses : num_math_operations;
|
||||
|
||||
// Process lanes.
|
||||
for (int i = 0; i < max_operations; ++i)
|
||||
{
|
||||
if (i < num_cache_accesses) // Random access to cached memory.
|
||||
{
|
||||
const auto src = state.next_src();
|
||||
const auto dst = state.next_dst();
|
||||
const auto sel = state.rng();
|
||||
|
||||
for (size_t l = 0; l < num_lanes; ++l)
|
||||
{
|
||||
const size_t offset = mix[l][src] % l1_cache_num_items;
|
||||
random_merge(mix[l][dst], le::uint32(context.l1_cache[offset]), sel);
|
||||
}
|
||||
}
|
||||
if (i < num_math_operations) // Random math.
|
||||
{
|
||||
// Generate 2 unique source indexes.
|
||||
const auto src_rnd = state.rng() % (num_regs * (num_regs - 1));
|
||||
const auto src1 = src_rnd % num_regs; // O <= src1 < num_regs
|
||||
auto src2 = src_rnd / num_regs; // 0 <= src2 < num_regs - 1
|
||||
if (src2 >= src1)
|
||||
++src2;
|
||||
|
||||
const auto sel1 = state.rng();
|
||||
const auto dst = state.next_dst();
|
||||
const auto sel2 = state.rng();
|
||||
|
||||
for (size_t l = 0; l < num_lanes; ++l)
|
||||
{
|
||||
const uint32_t data = random_math(mix[l][src1], mix[l][src2], sel1);
|
||||
random_merge(mix[l][dst], data, sel2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DAG access pattern.
|
||||
uint32_t dsts[num_words_per_lane];
|
||||
uint32_t sels[num_words_per_lane];
|
||||
for (size_t i = 0; i < num_words_per_lane; ++i)
|
||||
{
|
||||
dsts[i] = i == 0 ? 0 : state.next_dst();
|
||||
sels[i] = state.rng();
|
||||
}
|
||||
|
||||
// DAG access.
|
||||
for (size_t l = 0; l < num_lanes; ++l)
|
||||
{
|
||||
const auto offset = ((l ^ r) % num_lanes) * num_words_per_lane;
|
||||
for (size_t i = 0; i < num_words_per_lane; ++i)
|
||||
{
|
||||
const auto word = le::uint32(item.word32s[offset + i]);
|
||||
random_merge(mix[l][dsts[i]], word, sels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mix_array init_mix(uint64_t seed)
|
||||
{
|
||||
const uint32_t z = fnv1a(fnv_offset_basis, static_cast<uint32_t>(seed));
|
||||
const uint32_t w = fnv1a(z, static_cast<uint32_t>(seed >> 32));
|
||||
|
||||
mix_array mix;
|
||||
for (uint32_t l = 0; l < mix.size(); ++l)
|
||||
{
|
||||
const uint32_t jsr = fnv1a(w, l);
|
||||
const uint32_t jcong = fnv1a(jsr, l);
|
||||
kiss99 rng{z, w, jsr, jcong};
|
||||
|
||||
for (auto& row : mix[l])
|
||||
row = rng();
|
||||
}
|
||||
return mix;
|
||||
}
|
||||
|
||||
hash256 hash_mix(
|
||||
const epoch_context& context, int block_number, uint64_t seed, lookup_fn lookup) noexcept
|
||||
{
|
||||
auto mix = init_mix(seed);
|
||||
mix_rng_state state{uint64_t(block_number / period_length)};
|
||||
|
||||
for (uint32_t i = 0; i < 64; ++i)
|
||||
round(context, i, mix, state, lookup);
|
||||
|
||||
// Reduce mix data to a single per-lane result.
|
||||
uint32_t lane_hash[num_lanes];
|
||||
for (size_t l = 0; l < num_lanes; ++l)
|
||||
{
|
||||
lane_hash[l] = fnv_offset_basis;
|
||||
for (uint32_t i = 0; i < num_regs; ++i)
|
||||
lane_hash[l] = fnv1a(lane_hash[l], mix[l][i]);
|
||||
}
|
||||
|
||||
// Reduce all lanes to a single 256-bit result.
|
||||
static constexpr size_t num_words = sizeof(hash256) / sizeof(uint32_t);
|
||||
hash256 mix_hash;
|
||||
for (uint32_t& w : mix_hash.word32s)
|
||||
w = fnv_offset_basis;
|
||||
for (size_t l = 0; l < num_lanes; ++l)
|
||||
mix_hash.word32s[l % num_words] = fnv1a(mix_hash.word32s[l % num_words], lane_hash[l]);
|
||||
return le::uint32s(mix_hash);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
result hash(const epoch_context& context, int block_number, const hash256& header_hash,
|
||||
uint64_t nonce) noexcept
|
||||
{
|
||||
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
|
||||
const hash256 mix_hash = hash_mix(context, block_number, seed, calculate_dataset_item_2048);
|
||||
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
|
||||
return {final_hash, mix_hash};
|
||||
}
|
||||
|
||||
result hash(const epoch_context_full& context, int block_number, const hash256& header_hash,
|
||||
uint64_t nonce) noexcept
|
||||
{
|
||||
static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept
|
||||
{
|
||||
auto* full_dataset_1024 = static_cast<const epoch_context_full&>(context).full_dataset;
|
||||
auto* full_dataset_2048 = reinterpret_cast<hash2048*>(full_dataset_1024);
|
||||
hash2048& item = full_dataset_2048[index];
|
||||
if (item.word64s[0] == 0)
|
||||
{
|
||||
// TODO: Copy elision here makes it thread-safe?
|
||||
item = calculate_dataset_item_2048(context, index);
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
|
||||
const hash256 mix_hash = hash_mix(context, block_number, seed, lazy_lookup);
|
||||
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
|
||||
return {final_hash, mix_hash};
|
||||
}
|
||||
|
||||
bool verify(const epoch_context& context, int block_number, const hash256& header_hash,
|
||||
const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept
|
||||
{
|
||||
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
|
||||
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
|
||||
if (!is_less_or_equal(final_hash, boundary))
|
||||
return false;
|
||||
|
||||
const hash256 expected_mix_hash =
|
||||
hash_mix(context, block_number, seed, calculate_dataset_item_2048);
|
||||
return is_equal(expected_mix_hash, mix_hash);
|
||||
}
|
||||
|
||||
search_result search_light(const epoch_context& context, int block_number,
|
||||
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
|
||||
size_t iterations) noexcept
|
||||
{
|
||||
const uint64_t end_nonce = start_nonce + iterations;
|
||||
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
|
||||
{
|
||||
result r = hash(context, block_number, header_hash, nonce);
|
||||
if (is_less_or_equal(r.final_hash, boundary))
|
||||
return {r, nonce};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
search_result search(const epoch_context_full& context, int block_number,
|
||||
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
|
||||
size_t iterations) noexcept
|
||||
{
|
||||
const uint64_t end_nonce = start_nonce + iterations;
|
||||
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
|
||||
{
|
||||
result r = hash(context, block_number, header_hash, nonce);
|
||||
if (is_less_or_equal(r.final_hash, boundary))
|
||||
return {r, nonce};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace progpow
|
||||
33
contrib/ethereum/libethash/support/attributes.h
Normal file
33
contrib/ethereum/libethash/support/attributes.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
|
||||
* Copyright 2018 Pawel Bylica.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** inline */
|
||||
#if _MSC_VER || __STDC_VERSION__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
/** [[always_inline]] */
|
||||
#if _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#elif defined(__has_attribute) && __STDC_VERSION__
|
||||
#if __has_attribute(always_inline)
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(ALWAYS_INLINE)
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
/** [[no_sanitize()]] */
|
||||
#if __clang__
|
||||
#define NO_SANITIZE(sanitizer) \
|
||||
__attribute__((no_sanitize(sanitizer)))
|
||||
#else
|
||||
#define NO_SANITIZE(sanitizer)
|
||||
#endif
|
||||
1
contrib/miniupnp
Submodule
1
contrib/miniupnp
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit bd836936f7ed7e697f36dff709d00a907644172a
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
project (miniupnpc C)
|
||||
set (MINIUPNPC_VERSION 1.9)
|
||||
set (MINIUPNPC_API_VERSION 10)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
if (WIN32)
|
||||
set (DEFAULT_BUILD_TYPE MinSizeRel)
|
||||
else (WIN32)
|
||||
set (DEFAULT_BUILD_TYPE RelWithDebInfo)
|
||||
endif(WIN32)
|
||||
set (CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING
|
||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
option (UPNPC_BUILD_STATIC "Build static library" TRUE)
|
||||
option (UPNPC_BUILD_SHARED "Build shared library" TRUE)
|
||||
if (NOT WIN32)
|
||||
option (UPNPC_BUILD_TESTS "Build test executables" TRUE)
|
||||
endif (NOT WIN32)
|
||||
option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
|
||||
|
||||
mark_as_advanced (NO_GETADDRINFO)
|
||||
|
||||
if (NO_GETADDRINFO)
|
||||
add_definitions (-DNO_GETADDRINFO)
|
||||
endif (NO_GETADDRINFO)
|
||||
|
||||
if (NOT WIN32)
|
||||
add_definitions (-DMINIUPNPC_SET_SOCKET_TIMEOUT)
|
||||
add_definitions (-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=1)
|
||||
else (NOT WIN32)
|
||||
add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends
|
||||
endif (NOT WIN32)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
add_definitions (-DMACOSX -D_DARWIN_C_SOURCE)
|
||||
endif ()
|
||||
|
||||
# Set compiler specific build flags
|
||||
if (CMAKE_COMPILER_IS_GNUC)
|
||||
# Set our own default flags at first run.
|
||||
if (NOT CONFIGURED)
|
||||
|
||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
|
||||
set (_PIC -fPIC)
|
||||
endif (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
|
||||
|
||||
set (CMAKE_C_FLAGS "${_PIC} -Wall $ENV{CFLAGS}" # CMAKE_C_FLAGS gets appended to the other C flags
|
||||
CACHE STRING "Flags used by the C compiler during normal builds." FORCE)
|
||||
set (CMAKE_C_FLAGS_DEBUG "-g -DDDEBUG"
|
||||
CACHE STRING "Flags used by the C compiler during debug builds." FORCE)
|
||||
set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG"
|
||||
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
|
||||
set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG"
|
||||
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
|
||||
set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG"
|
||||
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
|
||||
|
||||
endif (NOT CONFIGURED)
|
||||
endif ()
|
||||
|
||||
configure_file (miniupnpcstrings.h.cmake ${CMAKE_BINARY_DIR}/miniupnpcstrings.h)
|
||||
include_directories (${CMAKE_BINARY_DIR})
|
||||
|
||||
set (MINIUPNPC_SOURCES
|
||||
igd_desc_parse.c
|
||||
miniupnpc.c
|
||||
minixml.c
|
||||
minisoap.c
|
||||
miniwget.c
|
||||
upnpc.c
|
||||
upnpcommands.c
|
||||
upnpreplyparse.c
|
||||
upnperrors.c
|
||||
connecthostport.c
|
||||
portlistingparse.c
|
||||
receivedata.c
|
||||
)
|
||||
|
||||
if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
|
||||
set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c)
|
||||
endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
|
||||
|
||||
if (WIN32)
|
||||
set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES
|
||||
COMPILE_DEFINITIONS STATICLIB
|
||||
COMPILE_DEFINITIONS MINIUPNP_EXPORTS
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (WIN32)
|
||||
# find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32)
|
||||
# find_library (IPHLPAPI_LIBRARY NAMES iphlpapi)
|
||||
set(WINSOCK2_LIBRARY ws2_32)
|
||||
set(IPHLPAPI_LIBRARY iphlpapi)
|
||||
set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS})
|
||||
#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris")
|
||||
# find_library (SOCKET_LIBRARY NAMES socket)
|
||||
# find_library (NSL_LIBRARY NAMES nsl)
|
||||
# find_library (RESOLV_LIBRARY NAMES resolv)
|
||||
# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS})
|
||||
endif (WIN32)
|
||||
|
||||
if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED)
|
||||
message (FATAL "Both shared and static libraries are disabled!")
|
||||
endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED)
|
||||
|
||||
if (UPNPC_BUILD_STATIC)
|
||||
add_library (upnpc-static STATIC ${MINIUPNPC_SOURCES})
|
||||
set_target_properties (upnpc-static PROPERTIES OUTPUT_NAME "miniupnpc")
|
||||
target_link_libraries (upnpc-static ${LDLIBS})
|
||||
set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-static)
|
||||
set (UPNPC_LIBRARY_TARGET upnpc-static)
|
||||
endif (UPNPC_BUILD_STATIC)
|
||||
|
||||
if (UPNPC_BUILD_SHARED)
|
||||
add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES})
|
||||
set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc")
|
||||
set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION})
|
||||
set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION})
|
||||
target_link_libraries (upnpc-shared ${LDLIBS})
|
||||
set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-shared)
|
||||
set (UPNPC_LIBRARY_TARGET upnpc-shared)
|
||||
endif (UPNPC_BUILD_SHARED)
|
||||
|
||||
if (UPNPC_BUILD_TESTS)
|
||||
add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c)
|
||||
target_link_libraries (testminixml ${LDLIBS})
|
||||
|
||||
add_executable (minixmlvalid minixmlvalid.c minixml.c)
|
||||
target_link_libraries (minixmlvalid ${LDLIBS})
|
||||
|
||||
add_executable (testupnpreplyparse testupnpreplyparse.c
|
||||
minixml.c upnpreplyparse.c)
|
||||
target_link_libraries (testupnpreplyparse ${LDLIBS})
|
||||
|
||||
add_executable (testigddescparse testigddescparse.c
|
||||
igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c
|
||||
upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c
|
||||
portlistingparse.c receivedata.c
|
||||
)
|
||||
target_link_libraries (testigddescparse ${LDLIBS})
|
||||
|
||||
add_executable (testminiwget testminiwget.c
|
||||
miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c
|
||||
upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c
|
||||
portlistingparse.c receivedata.c
|
||||
)
|
||||
target_link_libraries (testminiwget ${LDLIBS})
|
||||
|
||||
# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget)
|
||||
endif (UPNPC_BUILD_TESTS)
|
||||
|
||||
|
||||
install (TARGETS ${UPNPC_INSTALL_TARGETS}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
||||
)
|
||||
install (FILES
|
||||
miniupnpc.h
|
||||
miniwget.h
|
||||
upnpcommands.h
|
||||
igd_desc_parse.h
|
||||
upnpreplyparse.h
|
||||
upnperrors.h
|
||||
declspec.h
|
||||
DESTINATION include/miniupnpc
|
||||
)
|
||||
|
||||
set (CONFIGURED YES CACHE INTERNAL "")
|
||||
|
||||
# vim: ts=2:sw=2
|
||||
|
|
@ -1,585 +0,0 @@
|
|||
$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $
|
||||
miniUPnP client Changelog.
|
||||
|
||||
2014/02/05:
|
||||
handle EINPROGRESS after connect()
|
||||
|
||||
2014/02/03:
|
||||
minixml now handle XML comments
|
||||
|
||||
VERSION 1.9 : released 2014/01/31
|
||||
|
||||
2014/01/31:
|
||||
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
|
||||
increment API_VERSION to 10
|
||||
|
||||
2013/12/09:
|
||||
--help and -h arguments in upnpc.c
|
||||
|
||||
2013/10/07:
|
||||
fixed potential buffer overrun in miniwget.c
|
||||
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
|
||||
|
||||
2013/08/01:
|
||||
define MAXHOSTNAMELEN if not already done
|
||||
|
||||
2013/06/06:
|
||||
update upnpreplyparse to allow larger values (128 chars instead of 64)
|
||||
|
||||
2013/05/14:
|
||||
Update upnpreplyparse to take into account "empty" elements
|
||||
validate upnpreplyparse.c code with "make check"
|
||||
|
||||
2013/05/03:
|
||||
Fix Solaris build thanks to Maciej Małecki
|
||||
|
||||
2013/04/27:
|
||||
Fix testminiwget.sh for BSD
|
||||
|
||||
2013/03/23:
|
||||
Fixed Makefile for *BSD
|
||||
|
||||
2013/03/11:
|
||||
Update Makefile to use JNAerator version 0.11
|
||||
|
||||
2013/02/11:
|
||||
Fix testminiwget.sh for use with dash
|
||||
Use $(DESTDIR) in Makefile
|
||||
|
||||
VERSION 1.8 : released 2013/02/06
|
||||
|
||||
2012/10/16:
|
||||
fix testminiwget with no IPv6 support
|
||||
|
||||
2012/09/27:
|
||||
Rename all include guards to not clash with C99
|
||||
(7.1.3 Reserved identifiers).
|
||||
|
||||
2012/08/30:
|
||||
Added -e option to upnpc program (set description for port mappings)
|
||||
|
||||
2012/08/29:
|
||||
Python 3 support (thanks to Christopher Foo)
|
||||
|
||||
2012/08/11:
|
||||
Fix a memory link in UPNP_GetValidIGD()
|
||||
Try to handle scope id in link local IPv6 URL under MS Windows
|
||||
|
||||
2012/07/20:
|
||||
Disable HAS_IP_MREQN on DragonFly BSD
|
||||
|
||||
2012/06/28:
|
||||
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
|
||||
|
||||
2012/06/23:
|
||||
More error return checks in upnpc.c
|
||||
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
|
||||
parseURL() now parses IPv6 addresses scope
|
||||
new parameter for miniwget() : IPv6 address scope
|
||||
increment API_VERSION to 9
|
||||
|
||||
2012/06/20:
|
||||
fixed CMakeLists.txt
|
||||
|
||||
2012/05/29
|
||||
Improvements in testminiwget.sh
|
||||
|
||||
VERSION 1.7 : released 2012/05/24
|
||||
|
||||
2012/05/01:
|
||||
Cleanup settings of CFLAGS in Makefile
|
||||
Fix signed/unsigned integer comparaisons
|
||||
|
||||
2012/04/20:
|
||||
Allow to specify protocol with TCP or UDP for -A option
|
||||
|
||||
2012/04/09:
|
||||
Only try to fetch XML description once in UPNP_GetValidIGD()
|
||||
Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
|
||||
|
||||
2012/04/05:
|
||||
minor improvements to minihttptestserver.c
|
||||
|
||||
2012/03/15:
|
||||
upnperrors.c returns valid error string for unrecognized error codes
|
||||
|
||||
2012/03/08:
|
||||
make minihttptestserver listen on loopback interface instead of 0.0.0.0
|
||||
|
||||
2012/01/25:
|
||||
Maven installation thanks to Alexey Kuznetsov
|
||||
|
||||
2012/01/21:
|
||||
Replace WIN32 macro by _WIN32
|
||||
|
||||
2012/01/19:
|
||||
Fixes in java wrappers thanks to Alexey Kuznetsov :
|
||||
https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
|
||||
Make and install .deb packages (python) thanks to Alexey Kuznetsov :
|
||||
https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
|
||||
|
||||
2012/01/07:
|
||||
The multicast interface can now be specified by name with IPv4.
|
||||
|
||||
2012/01/02:
|
||||
Install man page
|
||||
|
||||
2011/11/25:
|
||||
added header to Port Mappings list in upnpc.c
|
||||
|
||||
2011/10/09:
|
||||
Makefile : make clean now removes jnaerator generated files.
|
||||
MINIUPNPC_VERSION in miniupnpc.h (updated by make)
|
||||
|
||||
2011/09/12:
|
||||
added rootdescURL to UPNPUrls structure.
|
||||
|
||||
VERSION 1.6 : released 2011/07/25
|
||||
|
||||
2011/07/25:
|
||||
Update doc for version 1.6 release
|
||||
|
||||
2011/06/18:
|
||||
Fix for windows in miniwget.c
|
||||
|
||||
2011/06/04:
|
||||
display remote host in port mapping listing
|
||||
|
||||
2011/06/03:
|
||||
Fix in make install : there were missing headers
|
||||
|
||||
2011/05/26:
|
||||
Fix the socket leak in miniwget thanks to Richard Marsh.
|
||||
Permit to add leaseduration in -a command. Display lease duration.
|
||||
|
||||
2011/05/15:
|
||||
Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6
|
||||
|
||||
2011/05/09:
|
||||
add a test in testminiwget.sh.
|
||||
more error checking in miniwget.c
|
||||
|
||||
2011/05/06:
|
||||
Adding some tool to test and validate miniwget.c
|
||||
simplified and debugged miniwget.c
|
||||
|
||||
2011/04/11:
|
||||
moving ReceiveData() to a receivedata.c file.
|
||||
parsing presentation url
|
||||
adding IGD v2 WANIPv6FirewallControl commands
|
||||
|
||||
2011/04/10:
|
||||
update of miniupnpcmodule.c
|
||||
comments in miniwget.c, update in testminiwget
|
||||
Adding errors codes from IGD v2
|
||||
new functions in upnpc.c for IGD v2
|
||||
|
||||
2011/04/09:
|
||||
Support for litteral ip v6 address in miniwget
|
||||
|
||||
2011/04/08:
|
||||
Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
Updating APIVERSION
|
||||
Supporting IPV6 in upnpDiscover()
|
||||
Adding a -6 option to upnpc command line tool
|
||||
|
||||
2011/03/18:
|
||||
miniwget/parseURL() : return an error when url param is null.
|
||||
fixing GetListOfPortMappings()
|
||||
|
||||
2011/03/14:
|
||||
upnpDiscover() now reporting an error code.
|
||||
improvements in comments.
|
||||
|
||||
2011/03/11:
|
||||
adding miniupnpcstrings.h.cmake and CMakeLists.txt files.
|
||||
|
||||
2011/02/15:
|
||||
Implementation of GetListOfPortMappings()
|
||||
|
||||
2011/02/07:
|
||||
updates to minixml to support character data starting with spaces
|
||||
minixml now support CDATA
|
||||
upnpreplyparse treats <NewPortListing> specificaly
|
||||
change in simpleUPnPcommand to return the buffer (simplification)
|
||||
|
||||
2011/02/06:
|
||||
Added leaseDuration argument to AddPortMapping()
|
||||
Starting to implement GetListOfPortMappings()
|
||||
|
||||
2011/01/11:
|
||||
updating wingenminiupnpcstrings.c
|
||||
|
||||
2011/01/04:
|
||||
improving updateminiupnpcstrings.sh
|
||||
|
||||
VERSION 1.5 : released 2011/01/01
|
||||
|
||||
2010/12/21:
|
||||
use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
|
||||
|
||||
2010/12/11:
|
||||
Improvements on getHTTPResponse() code.
|
||||
|
||||
2010/12/09:
|
||||
new code for miniwget that handle Chunked transfer encoding
|
||||
using getHTTPResponse() in SOAP call code
|
||||
Adding MANIFEST.in for 'python setup.py bdist_rpm'
|
||||
|
||||
2010/11/25:
|
||||
changes to minissdpc.c to compile under Win32.
|
||||
see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729
|
||||
|
||||
2010/09/17:
|
||||
Various improvement to Makefile from Michał Górny
|
||||
|
||||
2010/08/05:
|
||||
Adding the script "external-ip.sh" from Reuben Hawkins
|
||||
|
||||
2010/06/09:
|
||||
update to python module to match modification made on 2010/04/05
|
||||
update to Java test code to match modification made on 2010/04/05
|
||||
all UPNP_* function now return an error if the SOAP request failed
|
||||
at HTTP level.
|
||||
|
||||
2010/04/17:
|
||||
Using GetBestRoute() under win32 in order to find the
|
||||
right interface to use.
|
||||
|
||||
2010/04/12:
|
||||
Retrying with HTTP/1.1 if HTTP/1.0 failed. see
|
||||
http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703
|
||||
|
||||
2010/04/07:
|
||||
avoid returning duplicates in upnpDiscover()
|
||||
|
||||
2010/04/05:
|
||||
Create a connecthostport.h/.c with connecthostport() function
|
||||
and use it in miniwget and miniupnpc.
|
||||
Use getnameinfo() instead of inet_ntop or inet_ntoa
|
||||
Work to make miniupnpc IPV6 compatible...
|
||||
Add java test code.
|
||||
Big changes in order to support device having both WANIPConnection
|
||||
and WANPPPConnection.
|
||||
|
||||
2010/04/04:
|
||||
Use getaddrinfo() instead of gethostbyname() in miniwget.
|
||||
|
||||
2010/01/06:
|
||||
#define _DARWIN_C_SOURCE for Mac OS X
|
||||
|
||||
2009/12/19:
|
||||
Improve MinGW32 build
|
||||
|
||||
2009/12/11:
|
||||
adding a MSVC9 project to build the static library and executable
|
||||
|
||||
2009/12/10:
|
||||
Fixing some compilation stuff for Windows/MinGW
|
||||
|
||||
2009/12/07:
|
||||
adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS
|
||||
some fixes for Windows when using virtual ethernet adapters (it is the
|
||||
case with VMWare installed).
|
||||
|
||||
2009/12/04:
|
||||
some fixes for AmigaOS compilation
|
||||
Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked
|
||||
transfer encoding)
|
||||
|
||||
2009/12/03:
|
||||
updating printIDG and testigddescparse.c for debug.
|
||||
modifications to compile under AmigaOS
|
||||
adding a testminiwget program
|
||||
Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked
|
||||
transfer encoding
|
||||
|
||||
2009/11/26:
|
||||
fixing updateminiupnpcstrings.sh to take into account
|
||||
which command that does not return an error code.
|
||||
|
||||
VERSION 1.4 : released 2009/10/30
|
||||
|
||||
2009/10/16:
|
||||
using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module.
|
||||
|
||||
2009/10/10:
|
||||
Some fixes for compilation under Solaris
|
||||
compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464
|
||||
|
||||
2009/09/21:
|
||||
fixing the code to ignore EINTR during connect() calls.
|
||||
|
||||
2009/08/07:
|
||||
Set socket timeout for connect()
|
||||
Some cleanup in miniwget.c
|
||||
|
||||
2009/08/04:
|
||||
remove multiple redirections with -d in upnpc.c
|
||||
Print textual error code in upnpc.c
|
||||
Ignore EINTR during the connect() and poll() calls.
|
||||
|
||||
2009/07/29:
|
||||
fix in updateminiupnpcstrings.sh if OS name contains "/"
|
||||
Sending a correct value for MX: field in SSDP request
|
||||
|
||||
2009/07/20:
|
||||
Change the Makefile to compile under Mac OS X
|
||||
Fixed a stackoverflow in getDevicesFromMiniSSDPD()
|
||||
|
||||
2009/07/09:
|
||||
Compile under Haiku
|
||||
generate miniupnpcstrings.h.in from miniupnpcstrings.h
|
||||
|
||||
2009/06/04:
|
||||
patching to compile under CygWin and cross compile for minGW
|
||||
|
||||
VERSION 1.3 :
|
||||
|
||||
2009/04/17:
|
||||
updating python module
|
||||
Use strtoull() when using C99
|
||||
|
||||
2009/02/28:
|
||||
Fixed miniwget.c for compiling under sun
|
||||
|
||||
2008/12/18:
|
||||
cleanup in Makefile (thanks to Paul de Weerd)
|
||||
minissdpc.c : win32 compatibility
|
||||
miniupnpc.c : changed xmlns prefix from 'm' to 'u'
|
||||
Removed NDEBUG (using DEBUG)
|
||||
|
||||
2008/10/14:
|
||||
Added the ExternalHost argument to DeletePortMapping()
|
||||
|
||||
2008/10/11:
|
||||
Added the ExternalHost argument to AddPortMapping()
|
||||
Put a correct User-Agent: header in HTTP requests.
|
||||
|
||||
VERSION 1.2 :
|
||||
|
||||
2008/10/07:
|
||||
Update docs
|
||||
|
||||
2008/09/25:
|
||||
Integrated sameport patch from Dario Meloni : Added a "sameport"
|
||||
argument to upnpDiscover().
|
||||
|
||||
2008/07/18:
|
||||
small modif to make Clang happy :)
|
||||
|
||||
2008/07/17:
|
||||
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
|
||||
|
||||
2008/07/14:
|
||||
include declspec.h in installation (to /usr/include/miniupnpc)
|
||||
|
||||
VERSION 1.1 :
|
||||
|
||||
2008/07/04:
|
||||
standard options for install/ln instead of gnu-specific stuff.
|
||||
|
||||
2008/07/03:
|
||||
now builds a .dll and .lib with win32. (mingw32)
|
||||
|
||||
2008/04/28:
|
||||
make install now install the binary of the upnpc tool
|
||||
|
||||
2008/04/27:
|
||||
added testupnpigd.py
|
||||
added error strings for miniupnpc "internal" errors
|
||||
improved python module error/exception reporting.
|
||||
|
||||
2008/04/23:
|
||||
Completely rewrite igd_desc_parse.c in order to be compatible with
|
||||
Linksys WAG200G
|
||||
Added testigddescparse
|
||||
updated python module
|
||||
|
||||
VERSION 1.0 :
|
||||
|
||||
2008/02/21:
|
||||
put some #ifdef DEBUG around DisplayNameValueList()
|
||||
|
||||
2008/02/18:
|
||||
Improved error reporting in upnpcommands.c
|
||||
UPNP_GetStatusInfo() returns LastConnectionError
|
||||
|
||||
2008/02/16:
|
||||
better error handling in minisoap.c
|
||||
improving display of "valid IGD found" in upnpc.c
|
||||
|
||||
2008/02/03:
|
||||
Fixing UPNP_GetValidIGD()
|
||||
improved make install :)
|
||||
|
||||
2007/12/22:
|
||||
Adding upnperrors.c/h to provide a strupnperror() function
|
||||
used to translate UPnP error codes to string.
|
||||
|
||||
2007/12/19:
|
||||
Fixing getDevicesFromMiniSSDPD()
|
||||
improved error reporting of UPnP functions
|
||||
|
||||
2007/12/18:
|
||||
It is now possible to specify a different location for MiniSSDPd socket.
|
||||
working with MiniSSDPd is now more efficient.
|
||||
python module improved.
|
||||
|
||||
2007/12/16:
|
||||
improving error reporting
|
||||
|
||||
2007/12/13:
|
||||
Try to improve compatibility by using HTTP/1.0 instead of 1.1 and
|
||||
XML a bit different for SOAP.
|
||||
|
||||
2007/11/25:
|
||||
fixed select() call for linux
|
||||
|
||||
2007/11/15:
|
||||
Added -fPIC to CFLAG for better shared library code.
|
||||
|
||||
2007/11/02:
|
||||
Fixed a potential socket leak in miniwget2()
|
||||
|
||||
2007/10/16:
|
||||
added a parameter to upnpDiscover() in order to allow the use of another
|
||||
interface than the default multicast interface.
|
||||
|
||||
2007/10/12:
|
||||
Fixed the creation of symbolic link in Makefile
|
||||
|
||||
2007/10/08:
|
||||
Added man page
|
||||
|
||||
2007/10/02:
|
||||
fixed memory bug in GetUPNPUrls()
|
||||
|
||||
2007/10/01:
|
||||
fixes in the Makefile
|
||||
Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly.
|
||||
Added SONAME in the shared library to please debian :)
|
||||
fixed MS Windows compilation (minissdpd is not available under MS Windows).
|
||||
|
||||
2007/09/25:
|
||||
small change to Makefile to be able to install in a different location
|
||||
(default is /usr)
|
||||
|
||||
2007/09/24:
|
||||
now compiling both shared and static library
|
||||
|
||||
2007/09/19:
|
||||
Cosmetic changes on upnpc.c
|
||||
|
||||
2007/09/02:
|
||||
adapting to new miniSSDPd (release version ?)
|
||||
|
||||
2007/08/31:
|
||||
Usage of miniSSDPd to skip discovery process.
|
||||
|
||||
2007/08/27:
|
||||
fixed python module to allow compilation with Python older than Python 2.4
|
||||
|
||||
2007/06/12:
|
||||
Added a python module.
|
||||
|
||||
2007/05/19:
|
||||
Fixed compilation under MinGW
|
||||
|
||||
2007/05/15:
|
||||
fixed a memory leak in AddPortMapping()
|
||||
Added testupnpreplyparse executable to check the parsing of
|
||||
upnp soap messages
|
||||
minixml now ignore namespace prefixes.
|
||||
|
||||
2007/04/26:
|
||||
upnpc now displays external ip address with -s or -l
|
||||
|
||||
2007/04/11:
|
||||
changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
|
||||
|
||||
2007/03/19:
|
||||
cleanup in miniwget.c
|
||||
|
||||
2007/03/01:
|
||||
Small typo fix...
|
||||
|
||||
2007/01/30:
|
||||
Now parsing the HTTP header from SOAP responses in order to
|
||||
get content-length value.
|
||||
|
||||
2007/01/29:
|
||||
Fixed the Soap Query to speedup the HTTP request.
|
||||
added some Win32 DLL stuff...
|
||||
|
||||
2007/01/27:
|
||||
Fixed some WIN32 compatibility issues
|
||||
|
||||
2006/12/14:
|
||||
Added UPNPIGD_IsConnected() function in miniupnp.c/.h
|
||||
Added UPNP_GetValidIGD() in miniupnp.c/.h
|
||||
cleaned upnpc.c main(). now using UPNP_GetValidIGD()
|
||||
|
||||
2006/12/07:
|
||||
Version 1.0-RC1 released
|
||||
|
||||
2006/12/03:
|
||||
Minor changes to compile under SunOS/Solaris
|
||||
|
||||
2006/11/30:
|
||||
made a minixml parser validator program
|
||||
updated minixml to handle attributes correctly
|
||||
|
||||
2006/11/22:
|
||||
Added a -r option to the upnpc sample thanks to Alexander Hubmann.
|
||||
|
||||
2006/11/19:
|
||||
Cleanup code to make it more ANSI C compliant
|
||||
|
||||
2006/11/10:
|
||||
detect and display local lan address.
|
||||
|
||||
2006/11/04:
|
||||
Packets and Bytes Sent/Received are now unsigned int.
|
||||
|
||||
2006/11/01:
|
||||
Bug fix thanks to Giuseppe D'Angelo
|
||||
|
||||
2006/10/31:
|
||||
C++ compatibility for .h files.
|
||||
Added a way to get ip Address on the LAN used to reach the IGD.
|
||||
|
||||
2006/10/25:
|
||||
Added M-SEARCH to the services in the discovery process.
|
||||
|
||||
2006/10/22:
|
||||
updated the Makefile to use makedepend, added a "make install"
|
||||
update Makefile
|
||||
|
||||
2006/10/20:
|
||||
fixing the description url parsing thanks to patch sent by
|
||||
Wayne Dawe.
|
||||
Fixed/translated some comments.
|
||||
Implemented a better discover process, first looking
|
||||
for IGD then for root devices (as some devices only reply to
|
||||
M-SEARCH for root devices).
|
||||
|
||||
2006/09/02:
|
||||
added freeUPNPDevlist() function.
|
||||
|
||||
2006/08/04:
|
||||
More command line arguments checking
|
||||
|
||||
2006/08/01:
|
||||
Added the .bat file to compile under Win32 with minGW32
|
||||
|
||||
2006/07/31:
|
||||
Fixed the rootdesc parser (igd_desc_parse.c)
|
||||
|
||||
2006/07/20:
|
||||
parseMSEARCHReply() is now returning the ST: line as well
|
||||
starting changes to detect several UPnP devices on the network
|
||||
|
||||
2006/07/19:
|
||||
using GetCommonLinkProperties to get down/upload bitrate
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
MiniUPnPc
|
||||
Copyright (c) 2005-2011, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
* The name of the author may not 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.
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
include README
|
||||
include miniupnpcmodule.c
|
||||
include setup.py
|
||||
include *.h
|
||||
include libminiupnpc.a
|
||||
|
|
@ -1,319 +0,0 @@
|
|||
# $Id: Makefile,v 1.107 2014/01/31 14:19:12 nanard Exp $
|
||||
# MiniUPnP Project
|
||||
# http://miniupnp.free.fr/
|
||||
# http://miniupnp.tuxfamily.org/
|
||||
# https://github.com/miniupnp/miniupnp
|
||||
# (c) 2005-2014 Thomas Bernard
|
||||
# to install use :
|
||||
# $ make DESTDIR=/tmp/dummylocation install
|
||||
# or
|
||||
# $ INSTALLPREFIX=/usr/local make install
|
||||
# or
|
||||
# $ make install (default INSTALLPREFIX is /usr)
|
||||
OS = $(shell uname -s)
|
||||
VERSION = $(shell cat VERSION)
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
JARSUFFIX=mac
|
||||
endif
|
||||
ifeq ($(OS), Linux)
|
||||
JARSUFFIX=linux
|
||||
endif
|
||||
ifneq (,$(findstring NT-5.1,$(OS)))
|
||||
JARSUFFIX=win32
|
||||
endif
|
||||
|
||||
HAVE_IPV6 ?= yes
|
||||
export HAVE_IPV6
|
||||
|
||||
CC ?= gcc
|
||||
#AR = gar
|
||||
#CFLAGS = -O -g -DDEBUG
|
||||
CFLAGS ?= -O
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -W -Wstrict-prototypes
|
||||
CFLAGS += -fno-common
|
||||
CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
CFLAGS += -DMINIUPNPC_GET_SRC_ADDR
|
||||
CFLAGS += -D_BSD_SOURCE -D_POSIX_C_SOURCE=1
|
||||
CFLAGS += -ansi
|
||||
# -DNO_GETADDRINFO
|
||||
INSTALL = install
|
||||
SH = /bin/sh
|
||||
JAVA = java
|
||||
# see http://code.google.com/p/jnaerator/
|
||||
#JNAERATOR = jnaerator-0.9.7.jar
|
||||
#JNAERATOR = jnaerator-0.9.8-shaded.jar
|
||||
#JNAERATORARGS = -library miniupnpc
|
||||
#JNAERATOR = jnaerator-0.10-shaded.jar
|
||||
JNAERATOR = jnaerator-0.11-shaded.jar
|
||||
JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc
|
||||
JNAERATORBASEURL = http://jnaerator.googlecode.com/files/
|
||||
|
||||
ifeq (SunOS, $(OS))
|
||||
LDFLAGS=-lsocket -lnsl -lresolv
|
||||
endif
|
||||
|
||||
# APIVERSION is used to build SONAME
|
||||
APIVERSION = 10
|
||||
|
||||
SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
|
||||
upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \
|
||||
minixmlvalid.c testupnpreplyparse.c minissdpc.c \
|
||||
upnperrors.c testigddescparse.c testminiwget.c \
|
||||
connecthostport.c portlistingparse.c receivedata.c
|
||||
|
||||
LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \
|
||||
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
|
||||
connecthostport.o portlistingparse.o receivedata.o
|
||||
|
||||
ifneq ($(OS), AmigaOS)
|
||||
CFLAGS := -fPIC $(CFLAGS)
|
||||
LIBOBJS := $(LIBOBJS) minissdpc.o
|
||||
endif
|
||||
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
# HEADERS to install
|
||||
HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
|
||||
upnpreplyparse.h upnperrors.h miniupnpctypes.h \
|
||||
portlistingparse.h \
|
||||
declspec.h
|
||||
|
||||
# library names
|
||||
LIBRARY = libminiupnpc.a
|
||||
ifeq ($(OS), Darwin)
|
||||
SHAREDLIBRARY = libminiupnpc.dylib
|
||||
SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib
|
||||
CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS)
|
||||
else
|
||||
ifeq ($(JARSUFFIX), win32)
|
||||
SHAREDLIBRARY = miniupnpc.dll
|
||||
else
|
||||
# Linux/BSD/etc.
|
||||
SHAREDLIBRARY = libminiupnpc.so
|
||||
SONAME = $(SHAREDLIBRARY).$(APIVERSION)
|
||||
endif
|
||||
endif
|
||||
|
||||
EXECUTABLES = upnpc-static
|
||||
EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \
|
||||
testigddescparse testminiwget
|
||||
|
||||
TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o
|
||||
|
||||
TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o
|
||||
|
||||
TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o
|
||||
|
||||
TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \
|
||||
miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \
|
||||
minisoap.o connecthostport.o receivedata.o \
|
||||
portlistingparse.o
|
||||
|
||||
ifneq ($(OS), AmigaOS)
|
||||
EXECUTABLES := $(EXECUTABLES) upnpc-shared
|
||||
TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o
|
||||
TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o
|
||||
endif
|
||||
|
||||
LIBDIR ?= lib
|
||||
# install directories
|
||||
INSTALLPREFIX ?= $(PREFIX)/usr
|
||||
INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
|
||||
INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR)
|
||||
INSTALLDIRBIN = $(INSTALLPREFIX)/bin
|
||||
INSTALLDIRMAN = $(INSTALLPREFIX)/share/man
|
||||
|
||||
FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES)
|
||||
ifneq ($(OS), AmigaOS)
|
||||
FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY)
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: install clean depend all check test everything \
|
||||
installpythonmodule updateversion
|
||||
# validateminixml validateminiwget
|
||||
|
||||
all: $(LIBRARY) $(EXECUTABLES)
|
||||
|
||||
test: check
|
||||
|
||||
check: validateminixml validateminiwget validateupnpreplyparse
|
||||
|
||||
everything: all $(EXECUTABLES_ADDTESTS)
|
||||
|
||||
pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py
|
||||
python setup.py build
|
||||
touch $@
|
||||
|
||||
installpythonmodule: pythonmodule
|
||||
python setup.py install
|
||||
|
||||
pythonmodule3: $(LIBRARY) miniupnpcmodule.c setup.py
|
||||
python3 setup.py build
|
||||
touch $@
|
||||
|
||||
installpythonmodule3: pythonmodule3
|
||||
python3 setup.py install
|
||||
|
||||
validateminixml: minixmlvalid
|
||||
@echo "minixml validation test"
|
||||
./minixmlvalid
|
||||
touch $@
|
||||
|
||||
validateminiwget: testminiwget minihttptestserver testminiwget.sh
|
||||
@echo "miniwget validation test"
|
||||
./testminiwget.sh
|
||||
touch $@
|
||||
|
||||
validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh
|
||||
@echo "upnpreplyparse validation test"
|
||||
./testupnpreplyparse.sh
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h
|
||||
# clean python stuff
|
||||
$(RM) pythonmodule pythonmodule3
|
||||
$(RM) validateminixml validateminiwget validateupnpreplyparse
|
||||
$(RM) -r build/ dist/
|
||||
#python setup.py clean
|
||||
# clean jnaerator stuff
|
||||
$(RM) _jnaerator.* java/miniupnpc_$(OS).jar
|
||||
|
||||
distclean: clean
|
||||
$(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt
|
||||
|
||||
updateversion: miniupnpc.h
|
||||
cp miniupnpc.h miniupnpc.h.bak
|
||||
sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h
|
||||
|
||||
install: updateversion $(FILESTOINSTALL)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
|
||||
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
|
||||
ifneq ($(OS), AmigaOS)
|
||||
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME)
|
||||
ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
|
||||
endif
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
|
||||
ifeq ($(OS), AmigaOS)
|
||||
$(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
|
||||
else
|
||||
$(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
|
||||
endif
|
||||
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
|
||||
ifneq ($(OS), AmigaOS)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3
|
||||
$(INSTALL) man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
|
||||
ifeq ($(OS), Linux)
|
||||
gzip $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
cleaninstall:
|
||||
$(RM) -r $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
|
||||
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
|
||||
|
||||
depend:
|
||||
makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
|
||||
|
||||
$(LIBRARY): $(LIBOBJS)
|
||||
$(AR) crs $@ $?
|
||||
|
||||
$(SHAREDLIBRARY): $(LIBOBJS)
|
||||
ifeq ($(OS), Darwin)
|
||||
# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^
|
||||
$(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^
|
||||
else
|
||||
$(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^
|
||||
endif
|
||||
|
||||
upnpc-static: upnpc.o $(LIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
upnpc-shared: upnpc.o $(SHAREDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
testminixml: $(TESTMINIXMLOBJS)
|
||||
|
||||
testminiwget: $(TESTMINIWGETOBJS)
|
||||
|
||||
minixmlvalid: minixml.o minixmlvalid.o
|
||||
|
||||
testupnpreplyparse: $(TESTUPNPREPLYPARSE)
|
||||
|
||||
testigddescparse: $(TESTIGDDESCPARSE)
|
||||
|
||||
miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION
|
||||
$(SH) updateminiupnpcstrings.sh
|
||||
|
||||
# ftp tool supplied with OpenBSD can download files from http.
|
||||
jnaerator-%.jar:
|
||||
wget $(JNAERATORBASEURL)/$@ || \
|
||||
curl -o $@ $(JNAERATORBASEURL)/$@ || \
|
||||
ftp $(JNAERATORBASEURL)/$@
|
||||
|
||||
jar: $(SHAREDLIBRARY) $(JNAERATOR)
|
||||
$(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \
|
||||
miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h \
|
||||
igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \
|
||||
-package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v
|
||||
|
||||
mvn_install:
|
||||
mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \
|
||||
-DgroupId=com.github \
|
||||
-DartifactId=miniupnp \
|
||||
-Dversion=$(VERSION) \
|
||||
-Dpackaging=jar \
|
||||
-Dclassifier=$(JARSUFFIX) \
|
||||
-DgeneratePom=true \
|
||||
-DcreateChecksum=true
|
||||
|
||||
# make .deb packages
|
||||
deb: /usr/share/pyshared/stdeb all
|
||||
(python setup.py --command-packages=stdeb.command bdist_deb)
|
||||
|
||||
# install .deb packages
|
||||
ideb:
|
||||
(sudo dpkg -i deb_dist/*.deb)
|
||||
|
||||
/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev
|
||||
(sudo apt-get install python-stdeb)
|
||||
|
||||
/usr/share/doc/python-all-dev:
|
||||
(sudo apt-get install python-all-dev)
|
||||
|
||||
minihttptestserver: minihttptestserver.o
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
igd_desc_parse.o: igd_desc_parse.h
|
||||
miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h
|
||||
miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h
|
||||
miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h
|
||||
miniupnpc.o: receivedata.h
|
||||
minixml.o: minixml.h
|
||||
minisoap.o: minisoap.h miniupnpcstrings.h
|
||||
miniwget.o: miniupnpcstrings.h miniwget.h declspec.h connecthostport.h
|
||||
miniwget.o: receivedata.h
|
||||
upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h
|
||||
upnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h upnperrors.h
|
||||
upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h declspec.h
|
||||
upnpcommands.o: miniupnpctypes.h miniupnpc.h igd_desc_parse.h
|
||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
||||
testminixml.o: minixml.h igd_desc_parse.h
|
||||
minixmlvalid.o: minixml.h
|
||||
testupnpreplyparse.o: upnpreplyparse.h
|
||||
minissdpc.o: minissdpc.h miniupnpc.h declspec.h igd_desc_parse.h codelength.h
|
||||
upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h
|
||||
upnperrors.o: portlistingparse.h miniupnpctypes.h miniupnpc.h
|
||||
upnperrors.o: igd_desc_parse.h
|
||||
testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h declspec.h
|
||||
testminiwget.o: miniwget.h declspec.h
|
||||
connecthostport.o: connecthostport.h
|
||||
receivedata.o: receivedata.h
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
# $Id: Makefile.mingw,v 1.18 2014/01/17 09:04:01 nanard Exp $
|
||||
# Miniupnp project.
|
||||
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
# (c) 2005-2014 Thomas Bernard
|
||||
# This Makefile is made for MinGW
|
||||
#
|
||||
CC = gcc
|
||||
#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501
|
||||
CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501
|
||||
LDLIBS = -lws2_32 -liphlpapi
|
||||
# -lwsock32
|
||||
# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable()
|
||||
PYTHON=\utils\python25\python
|
||||
OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \
|
||||
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
|
||||
connecthostport.o portlistingparse.o receivedata.o
|
||||
OBJSDLL=$(addprefix dll/, $(OBJS))
|
||||
|
||||
all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll
|
||||
|
||||
init:
|
||||
mkdir dll
|
||||
echo init > init
|
||||
|
||||
clean:
|
||||
del upnpc testminixml *.o
|
||||
del dll\*.o
|
||||
del *.exe
|
||||
del miniupnpc.dll
|
||||
del libminiupnpc.a
|
||||
|
||||
libminiupnpc.a: $(OBJS)
|
||||
$(AR) cr $@ $?
|
||||
|
||||
pythonmodule: libminiupnpc.a
|
||||
$(PYTHON) setupmingw32.py build --compiler=mingw32
|
||||
$(PYTHON) setupmingw32.py install --skip-build
|
||||
|
||||
miniupnpc.dll: libminiupnpc.a $(OBJSDLL)
|
||||
dllwrap -k --driver-name gcc \
|
||||
--def miniupnpc.def \
|
||||
--output-def miniupnpc.dll.def \
|
||||
--implib miniupnpc.lib -o $@ \
|
||||
$(OBJSDLL) $(LDLIBS)
|
||||
|
||||
miniupnpc.lib: miniupnpc.dll
|
||||
echo $@ generated with $<
|
||||
|
||||
dll/upnpc.o: upnpc.o
|
||||
echo $@ generated with $<
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $<
|
||||
$(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $<
|
||||
|
||||
upnpc.o:
|
||||
$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $<
|
||||
$(CC) $(CFLAGS) -c -o dll/$@ $<
|
||||
|
||||
# --enable-stdcall-fixup
|
||||
upnpc-static: upnpc.o libminiupnpc.a
|
||||
$(CC) -o $@ $^ $(LDLIBS)
|
||||
|
||||
upnpc-shared: dll/upnpc.o miniupnpc.lib
|
||||
$(CC) -o $@ $^ $(LDLIBS)
|
||||
|
||||
wingenminiupnpcstrings: wingenminiupnpcstrings.o
|
||||
|
||||
wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
|
||||
|
||||
miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
|
||||
wingenminiupnpcstrings $< $@
|
||||
|
||||
minixml.o: minixml.c minixml.h miniupnpcstrings.h
|
||||
|
||||
upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h upnperrors.h
|
||||
|
||||
miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h
|
||||
|
||||
minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h
|
||||
|
||||
miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h
|
||||
|
||||
igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h
|
||||
|
||||
testminixml: minixml.o igd_desc_parse.o testminixml.c
|
||||
|
||||
upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h
|
||||
|
||||
upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h
|
||||
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
Project: miniupnp
|
||||
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
github: https://github.com/miniupnp/miniupnp
|
||||
freecode: http://freecode.com/projects/miniupnp
|
||||
Author: Thomas Bernard
|
||||
Copyright (c) 2005-2012 Thomas Bernard
|
||||
This software is subject to the conditions detailed in the
|
||||
LICENSE file provided within this distribution.
|
||||
|
||||
|
||||
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
|
||||
Its licence is included in the header of the file.
|
||||
bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
|
||||
|
||||
|
||||
* miniUPnP Client - miniUPnPc *
|
||||
|
||||
To compile, simply run 'gmake' (could be 'make' on your system).
|
||||
Under win32, to compile with MinGW, type "mingw32make.bat".
|
||||
MS Visual C solution and project files are supplied in the msvc/ subdirectory.
|
||||
|
||||
The compilation is known to work under linux, FreeBSD,
|
||||
OpenBSD, MacOS X, AmigaOS and cygwin.
|
||||
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
|
||||
upx (http://upx.sourceforge.net) is used to compress the win32 .exe files.
|
||||
|
||||
To install the library and headers on the system use :
|
||||
> su
|
||||
> make install
|
||||
> exit
|
||||
|
||||
alternatively, to install into a specific location, use :
|
||||
> INSTALLPREFIX=/usr/local make install
|
||||
|
||||
upnpc.c is a sample client using the libminiupnpc.
|
||||
To use the libminiupnpc in your application, link it with
|
||||
libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
|
||||
upnpcommands.h and miniwget.h :
|
||||
- upnpDiscover()
|
||||
- miniwget()
|
||||
- parserootdesc()
|
||||
- GetUPNPUrls()
|
||||
- UPNP_* (calling UPNP methods)
|
||||
|
||||
Note : use #include <miniupnpc/miniupnpc.h> etc... for the includes
|
||||
and -lminiupnpc for the link
|
||||
|
||||
Discovery process is speeded up when MiniSSDPd is running on the machine.
|
||||
|
||||
|
||||
* Python module *
|
||||
|
||||
you can build a python module with 'make pythonmodule'
|
||||
and install it with 'make installpythonmodule'.
|
||||
setup.py (and setupmingw32.py) are included in the distribution.
|
||||
|
||||
|
||||
Feel free to contact me if you have any problem :
|
||||
e-mail : miniupnp@free.fr
|
||||
|
||||
If you are using libminiupnpc in your application, please
|
||||
send me an email !
|
||||
|
||||
For any question, you can use the web forum :
|
||||
http://miniupnp.tuxfamily.org/forum/
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
1.9
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $
|
||||
|
||||
Differences in API between miniUPnPc versions
|
||||
|
||||
====================== miniUPnPc version 1.9 ======================
|
||||
API version 10
|
||||
|
||||
upnpcommands.h:
|
||||
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
|
||||
|
||||
miniupnpc.h:
|
||||
updated macros :
|
||||
#define MINIUPNPC_VERSION "1.9"
|
||||
#define MINIUPNPC_API_VERSION 10
|
||||
|
||||
====================== miniUPnPc version 1.8 ======================
|
||||
API version 9
|
||||
|
||||
miniupnpc.h:
|
||||
updated macros :
|
||||
#define MINIUPNPC_VERSION "1.8"
|
||||
#define MINIUPNPC_API_VERSION 9
|
||||
added "unsigned int scope_id;" to struct UPNPDev
|
||||
added scope_id argument to GetUPNPUrls()
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.7 ======================
|
||||
API version 8
|
||||
|
||||
miniupnpc.h :
|
||||
add new macros :
|
||||
#define MINIUPNPC_VERSION "1.7"
|
||||
#define MINIUPNPC_API_VERSION 8
|
||||
add rootdescURL to struct UPNPUrls
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.6 ======================
|
||||
API version 8
|
||||
|
||||
Adding support for IPv6.
|
||||
igd_desc_parse.h :
|
||||
struct IGDdatas_service :
|
||||
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
struct IGDdatas :
|
||||
add struct IGDdatas_service IPv6FC;
|
||||
miniupnpc.h :
|
||||
new macros :
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
|
||||
add arguments ipv6 and error to upnpDiscover() :
|
||||
struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
int ipv6,
|
||||
int * error);
|
||||
add controlURL_6FC member to struct UPNPUrls :
|
||||
struct UPNPUrls {
|
||||
char * controlURL;
|
||||
char * ipcondescURL;
|
||||
char * controlURL_CIF;
|
||||
char * controlURL_6FC;
|
||||
};
|
||||
|
||||
upnpcommands.h :
|
||||
add leaseDuration argument to UPNP_AddPortMapping()
|
||||
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
|
||||
add UPNP_GetListOfPortMappings() function (IGDv2)
|
||||
add IGDv2 IPv6 related functions :
|
||||
UPNP_GetFirewallStatus()
|
||||
UPNP_GetOutboundPinholeTimeout()
|
||||
UPNP_AddPinhole()
|
||||
UPNP_UpdatePinhole()
|
||||
UPNP_DeletePinhole()
|
||||
UPNP_CheckPinholeWorking()
|
||||
UPNP_GetPinholePackets()
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.5 ======================
|
||||
API version 5
|
||||
|
||||
new function :
|
||||
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
|
||||
new macro in upnpcommands.h :
|
||||
#define UPNPCOMMAND_HTTP_ERROR
|
||||
|
||||
====================== miniUPnPc version 1.4 ======================
|
||||
Same API as version 1.3
|
||||
|
||||
====================== miniUPnPc version 1.3 ======================
|
||||
API version 4
|
||||
|
||||
Use UNSIGNED_INTEGER type for
|
||||
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
|
||||
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
|
||||
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
|
||||
|
||||
====================== miniUPnPc version 1.2 ======================
|
||||
API version 3
|
||||
|
||||
added sameport argument to upnpDiscover()
|
||||
struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport);
|
||||
|
||||
====================== miniUPnPc Version 1.1 ======================
|
||||
Same API as 1.0
|
||||
|
||||
|
||||
====================== miniUPnPc Version 1.0 ======================
|
||||
API version 2
|
||||
|
||||
|
||||
struct UPNPDev {
|
||||
struct UPNPDev * pNext;
|
||||
char * descURL;
|
||||
char * st;
|
||||
char buffer[2];
|
||||
};
|
||||
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock);
|
||||
|
||||
|
|
@ -1,531 +0,0 @@
|
|||
/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
|
||||
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* lists, simple queues, tail queues, and circular queues.
|
||||
*
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
#ifdef QUEUE_MACRO_DEBUG
|
||||
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
|
||||
#else
|
||||
#define _Q_INVALIDATE(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#ifdef SLIST_ENTRY
|
||||
#undef SLIST_ENTRY
|
||||
#endif
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
#define SLIST_END(head) NULL
|
||||
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for((var) = SLIST_FIRST(head); \
|
||||
(var) != SLIST_END(head); \
|
||||
(var) = SLIST_NEXT(var, field))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != SLIST_END(head); \
|
||||
(varp) = &SLIST_NEXT((var), field))
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_INIT(head) { \
|
||||
SLIST_FIRST(head) = SLIST_END(head); \
|
||||
}
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_NEXT(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->slh_first == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->slh_first; \
|
||||
\
|
||||
while (curelm->field.sle_next != (elm)) \
|
||||
curelm = curelm->field.sle_next; \
|
||||
curelm->field.sle_next = \
|
||||
curelm->field.sle_next->field.sle_next; \
|
||||
_Q_INVALIDATE((elm)->field.sle_next); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List access methods
|
||||
*/
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
#define LIST_END(head) NULL
|
||||
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for((var) = LIST_FIRST(head); \
|
||||
(var)!= LIST_END(head); \
|
||||
(var) = LIST_NEXT(var, field))
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST(head) = LIST_END(head); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
_Q_INVALIDATE((elm)->field.le_prev); \
|
||||
_Q_INVALIDATE((elm)->field.le_next); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_REPLACE(elm, elm2, field) do { \
|
||||
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
|
||||
(elm2)->field.le_next->field.le_prev = \
|
||||
&(elm2)->field.le_next; \
|
||||
(elm2)->field.le_prev = (elm)->field.le_prev; \
|
||||
*(elm2)->field.le_prev = (elm2); \
|
||||
_Q_INVALIDATE((elm)->field.le_prev); \
|
||||
_Q_INVALIDATE((elm)->field.le_next); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define SIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define SIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define SIMPLEQ_END(head) NULL
|
||||
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
|
||||
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for((var) = SIMPLEQ_FIRST(head); \
|
||||
(var) != SIMPLEQ_END(head); \
|
||||
(var) = SIMPLEQ_NEXT(var, field))
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define SIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* tail queue access methods
|
||||
*/
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_END(head) NULL
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
/* XXX */
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
#define TAILQ_EMPTY(head) \
|
||||
(TAILQ_FIRST(head) == TAILQ_END(head))
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for((var) = TAILQ_FIRST(head); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_NEXT(var, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for((var) = TAILQ_LAST(head, headname); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_PREV(var, headname, field))
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
_Q_INVALIDATE((elm)->field.tqe_prev); \
|
||||
_Q_INVALIDATE((elm)->field.tqe_next); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
|
||||
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
|
||||
(elm2)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm2)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm2)->field.tqe_next; \
|
||||
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
|
||||
*(elm2)->field.tqe_prev = (elm2); \
|
||||
_Q_INVALIDATE((elm)->field.tqe_prev); \
|
||||
_Q_INVALIDATE((elm)->field.tqe_next); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Circular queue definitions.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue access methods
|
||||
*/
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
#define CIRCLEQ_END(head) ((void *)(head))
|
||||
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
||||
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
||||
#define CIRCLEQ_EMPTY(head) \
|
||||
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for((var) = CIRCLEQ_FIRST(head); \
|
||||
(var) != CIRCLEQ_END(head); \
|
||||
(var) = CIRCLEQ_NEXT(var, field))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for((var) = CIRCLEQ_LAST(head); \
|
||||
(var) != CIRCLEQ_END(head); \
|
||||
(var) = CIRCLEQ_PREV(var, field))
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
(head)->cqh_first = CIRCLEQ_END(head); \
|
||||
(head)->cqh_last = CIRCLEQ_END(head); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||
(elm)->field.cqe_prev = (listelm); \
|
||||
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||
(listelm)->field.cqe_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm); \
|
||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||
(listelm)->field.cqe_prev = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
|
||||
if ((head)->cqh_last == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||
(head)->cqh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = CIRCLEQ_END(head); \
|
||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||
if ((head)->cqh_first == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(head)->cqh_last->field.cqe_next = (elm); \
|
||||
(head)->cqh_last = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||
else \
|
||||
(elm)->field.cqe_next->field.cqe_prev = \
|
||||
(elm)->field.cqe_prev; \
|
||||
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||
else \
|
||||
(elm)->field.cqe_prev->field.cqe_next = \
|
||||
(elm)->field.cqe_next; \
|
||||
_Q_INVALIDATE((elm)->field.cqe_prev); \
|
||||
_Q_INVALIDATE((elm)->field.cqe_next); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
|
||||
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
|
||||
CIRCLEQ_END(head)) \
|
||||
(head).cqh_last = (elm2); \
|
||||
else \
|
||||
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
|
||||
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
|
||||
CIRCLEQ_END(head)) \
|
||||
(head).cqh_first = (elm2); \
|
||||
else \
|
||||
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
|
||||
_Q_INVALIDATE((elm)->field.cqe_prev); \
|
||||
_Q_INVALIDATE((elm)->field.cqe_next); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2011 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#ifndef CODELENGTH_H_INCLUDED
|
||||
#define CODELENGTH_H_INCLUDED
|
||||
|
||||
/* Encode length by using 7bit per Byte :
|
||||
* Most significant bit of each byte specifies that the
|
||||
* following byte is part of the code */
|
||||
#define DECODELENGTH(n, p) n = 0; \
|
||||
do { n = (n << 7) | (*p & 0x7f); } \
|
||||
while((*(p++)&0x80) && (n<(1<<25)));
|
||||
|
||||
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
|
||||
n = 0; \
|
||||
do { \
|
||||
if((p) >= (p_limit)) break; \
|
||||
n = (n << 7) | (*(p) & 0x7f); \
|
||||
} while((*((p)++)&0x80) && (n<(1<<25)));
|
||||
|
||||
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
|
||||
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
|
||||
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
|
||||
if(n>=128) *(p++) = (n >> 7) | 0x80; \
|
||||
*(p++) = n & 0x7f;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2010-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
/* use getaddrinfo() or gethostbyname()
|
||||
* uncomment the following line in order to use gethostbyname() */
|
||||
#ifdef NO_GETADDRINFO
|
||||
#define USE_GETHOSTBYNAME
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#define herror
|
||||
#define socklen_t int
|
||||
#else /* #ifdef _WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#define closesocket close
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
|
||||
* during the connect() call */
|
||||
#define MINIUPNPC_IGNORE_EINTR
|
||||
#ifndef USE_GETHOSTBYNAME
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#endif /* #ifndef USE_GETHOSTBYNAME */
|
||||
#endif /* #else _WIN32 */
|
||||
|
||||
/* definition of PRINT_SOCKET_ERROR */
|
||||
#ifdef _WIN32
|
||||
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
|
||||
#else
|
||||
#define PRINT_SOCKET_ERROR(x) perror(x)
|
||||
#endif
|
||||
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#define herror(A) printf("%s\n", A)
|
||||
#endif
|
||||
|
||||
#include "connecthostport.h"
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/* connecthostport()
|
||||
* return a socket connected (TCP) to the host and port
|
||||
* or -1 in case of error */
|
||||
int connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id)
|
||||
{
|
||||
int s, n;
|
||||
#ifdef USE_GETHOSTBYNAME
|
||||
struct sockaddr_in dest;
|
||||
struct hostent *hp;
|
||||
#else /* #ifdef USE_GETHOSTBYNAME */
|
||||
char tmp_host[MAXHOSTNAMELEN+1];
|
||||
char port_str[8];
|
||||
struct addrinfo *ai, *p;
|
||||
struct addrinfo hints;
|
||||
#endif /* #ifdef USE_GETHOSTBYNAME */
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
struct timeval timeout;
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
|
||||
#ifdef USE_GETHOSTBYNAME
|
||||
hp = gethostbyname(host);
|
||||
if(hp == NULL)
|
||||
{
|
||||
herror(host);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
|
||||
memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("socket");
|
||||
return -1;
|
||||
}
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
/* setting a 3 seconds timeout for the connect() call */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(port);
|
||||
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
/* EINTR The system call was interrupted by a signal that was caught
|
||||
* EINPROGRESS The socket is nonblocking and the connection cannot
|
||||
* be completed immediately. */
|
||||
while(n < 0 && (errno == EINTR || errno = EINPROGRESS))
|
||||
{
|
||||
socklen_t len;
|
||||
fd_set wset;
|
||||
int err;
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(s, &wset);
|
||||
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
/*len = 0;*/
|
||||
/*n = getpeername(s, NULL, &len);*/
|
||||
len = sizeof(err);
|
||||
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
|
||||
PRINT_SOCKET_ERROR("getsockopt");
|
||||
closesocket(s);
|
||||
return -1;
|
||||
}
|
||||
if(err != 0) {
|
||||
errno = err;
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
|
||||
if(n<0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("connect");
|
||||
closesocket(s);
|
||||
return -1;
|
||||
}
|
||||
#else /* #ifdef USE_GETHOSTBYNAME */
|
||||
/* use getaddrinfo() instead of gethostbyname() */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
/* hints.ai_flags = AI_ADDRCONFIG; */
|
||||
#ifdef AI_NUMERICSERV
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
#endif
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
|
||||
/* hints.ai_protocol = IPPROTO_TCP; */
|
||||
snprintf(port_str, sizeof(port_str), "%hu", port);
|
||||
if(host[0] == '[')
|
||||
{
|
||||
/* literal ip v6 address */
|
||||
int i, j;
|
||||
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
|
||||
{
|
||||
tmp_host[i] = host[j];
|
||||
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
|
||||
j+=2; /* skip "25" */
|
||||
}
|
||||
tmp_host[i] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(tmp_host, host, MAXHOSTNAMELEN);
|
||||
}
|
||||
tmp_host[MAXHOSTNAMELEN] = '\0';
|
||||
n = getaddrinfo(tmp_host, port_str, &hints, &ai);
|
||||
if(n != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "getaddrinfo() error : %d\n", n);
|
||||
#else
|
||||
fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
s = -1;
|
||||
for(p = ai; p; p = p->ai_next)
|
||||
{
|
||||
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if(s < 0)
|
||||
continue;
|
||||
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
|
||||
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||
addr6->sin6_scope_id = scope_id;
|
||||
}
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
/* setting a 3 seconds timeout for the connect() call */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
n = connect(s, p->ai_addr, p->ai_addrlen);
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
/* EINTR The system call was interrupted by a signal that was caught
|
||||
* EINPROGRESS The socket is nonblocking and the connection cannot
|
||||
* be completed immediately. */
|
||||
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
|
||||
{
|
||||
socklen_t len;
|
||||
fd_set wset;
|
||||
int err;
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(s, &wset);
|
||||
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
/*len = 0;*/
|
||||
/*n = getpeername(s, NULL, &len);*/
|
||||
len = sizeof(err);
|
||||
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
|
||||
PRINT_SOCKET_ERROR("getsockopt");
|
||||
closesocket(s);
|
||||
freeaddrinfo(ai);
|
||||
return -1;
|
||||
}
|
||||
if(err != 0) {
|
||||
errno = err;
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
|
||||
if(n < 0)
|
||||
{
|
||||
closesocket(s);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
if(s < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("socket");
|
||||
return -1;
|
||||
}
|
||||
if(n < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("connect");
|
||||
return -1;
|
||||
}
|
||||
#endif /* #ifdef USE_GETHOSTBYNAME */
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2010-2012 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef CONNECTHOSTPORT_H_INCLUDED
|
||||
#define CONNECTHOSTPORT_H_INCLUDED
|
||||
|
||||
/* connecthostport()
|
||||
* return a socket connected (TCP) to the host and port
|
||||
* or -1 in case of error */
|
||||
int connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef DECLSPEC_H_INCLUDED
|
||||
#define DECLSPEC_H_INCLUDED
|
||||
|
||||
#if defined(_WIN32) && !defined(STATICLIB)
|
||||
/* for windows dll */
|
||||
#ifdef MINIUPNP_EXPORTS
|
||||
#define LIBSPEC __declspec(dllexport)
|
||||
#else
|
||||
#define LIBSPEC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
|
||||
#define LIBSPEC __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define LIBSPEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $
|
||||
# (c) 2010 Reuben Hawkins
|
||||
upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g'
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2010 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include "igd_desc_parse.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Start element handler :
|
||||
* update nesting level counter and copy element name */
|
||||
void IGDstartelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
memcpy( datas->cureltname, name, l);
|
||||
datas->cureltname[l] = '\0';
|
||||
datas->level++;
|
||||
if( (l==7) && !memcmp(name, "service", l) ) {
|
||||
datas->tmp.controlurl[0] = '\0';
|
||||
datas->tmp.eventsuburl[0] = '\0';
|
||||
datas->tmp.scpdurl[0] = '\0';
|
||||
datas->tmp.servicetype[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* End element handler :
|
||||
* update nesting level counter and update parser state if
|
||||
* service element is parsed */
|
||||
void IGDendelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
datas->level--;
|
||||
/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
|
||||
if( (l==7) && !memcmp(name, "service", l) )
|
||||
{
|
||||
/*
|
||||
if( datas->state < 1
|
||||
&& !strcmp(datas->servicetype,
|
||||
// "urn:schemas-upnp-org:service:WANIPConnection:1") )
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
|
||||
datas->state ++;
|
||||
*/
|
||||
if(0==strcmp(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) {
|
||||
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else if(0==strcmp(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) {
|
||||
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else if(0==strcmp(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANIPConnection:1")
|
||||
|| 0==strcmp(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANPPPConnection:1") ) {
|
||||
if(datas->first.servicetype[0] == '\0') {
|
||||
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else {
|
||||
memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Data handler :
|
||||
* copy data depending on the current element name and state */
|
||||
void IGDdata(void * d, const char * data, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
char * dstmember = 0;
|
||||
/*printf("%2d %s : %.*s\n",
|
||||
datas->level, datas->cureltname, l, data); */
|
||||
if( !strcmp(datas->cureltname, "URLBase") )
|
||||
dstmember = datas->urlbase;
|
||||
else if( !strcmp(datas->cureltname, "presentationURL") )
|
||||
dstmember = datas->presentationurl;
|
||||
else if( !strcmp(datas->cureltname, "serviceType") )
|
||||
dstmember = datas->tmp.servicetype;
|
||||
else if( !strcmp(datas->cureltname, "controlURL") )
|
||||
dstmember = datas->tmp.controlurl;
|
||||
else if( !strcmp(datas->cureltname, "eventSubURL") )
|
||||
dstmember = datas->tmp.eventsuburl;
|
||||
else if( !strcmp(datas->cureltname, "SCPDURL") )
|
||||
dstmember = datas->tmp.scpdurl;
|
||||
/* else if( !strcmp(datas->cureltname, "deviceType") )
|
||||
dstmember = datas->devicetype_tmp;*/
|
||||
if(dstmember)
|
||||
{
|
||||
if(l>=MINIUPNPC_URL_MAXSIZE)
|
||||
l = MINIUPNPC_URL_MAXSIZE-1;
|
||||
memcpy(dstmember, data, l);
|
||||
dstmember[l] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void printIGD(struct IGDdatas * d)
|
||||
{
|
||||
printf("urlbase = '%s'\n", d->urlbase);
|
||||
printf("WAN Device (Common interface config) :\n");
|
||||
/*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/
|
||||
printf(" serviceType = '%s'\n", d->CIF.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->CIF.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->CIF.scpdurl);
|
||||
printf("primary WAN Connection Device (IP or PPP Connection):\n");
|
||||
/*printf(" deviceType = '%s'\n", d->first.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->first.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->first.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->first.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->first.scpdurl);
|
||||
printf("secondary WAN Connection Device (IP or PPP Connection):\n");
|
||||
/*printf(" deviceType = '%s'\n", d->second.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->second.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->second.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
|
||||
printf("WAN IPv6 Firewall Control :\n");
|
||||
/*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->IPv6FC.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->IPv6FC.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2010 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef IGD_DESC_PARSE_H_INCLUDED
|
||||
#define IGD_DESC_PARSE_H_INCLUDED
|
||||
|
||||
/* Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices */
|
||||
#define MINIUPNPC_URL_MAXSIZE (128)
|
||||
struct IGDdatas_service {
|
||||
char controlurl[MINIUPNPC_URL_MAXSIZE];
|
||||
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
|
||||
char scpdurl[MINIUPNPC_URL_MAXSIZE];
|
||||
char servicetype[MINIUPNPC_URL_MAXSIZE];
|
||||
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
|
||||
};
|
||||
|
||||
struct IGDdatas {
|
||||
char cureltname[MINIUPNPC_URL_MAXSIZE];
|
||||
char urlbase[MINIUPNPC_URL_MAXSIZE];
|
||||
char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
int level;
|
||||
/*int state;*/
|
||||
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
|
||||
struct IGDdatas_service CIF;
|
||||
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service first;
|
||||
/* if both WANIPConnection and WANPPPConnection are present */
|
||||
struct IGDdatas_service second;
|
||||
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
|
||||
struct IGDdatas_service IPv6FC;
|
||||
/* tmp */
|
||||
struct IGDdatas_service tmp;
|
||||
};
|
||||
|
||||
void IGDstartelt(void *, const char *, int);
|
||||
void IGDendelt(void *, const char *, int);
|
||||
void IGDdata(void *, const char *, int);
|
||||
void printIGD(struct IGDdatas *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import fr.free.miniupnp.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author syuu
|
||||
*/
|
||||
public class JavaBridgeTest {
|
||||
public static void main(String[] args) {
|
||||
int UPNP_DELAY = 2000;
|
||||
MiniupnpcLibrary miniupnpc = MiniupnpcLibrary.INSTANCE;
|
||||
UPNPDev devlist = null;
|
||||
UPNPUrls urls = new UPNPUrls();
|
||||
IGDdatas data = new IGDdatas();
|
||||
ByteBuffer lanaddr = ByteBuffer.allocate(16);
|
||||
ByteBuffer intClient = ByteBuffer.allocate(16);
|
||||
ByteBuffer intPort = ByteBuffer.allocate(6);
|
||||
ByteBuffer desc = ByteBuffer.allocate(80);
|
||||
ByteBuffer enabled = ByteBuffer.allocate(4);
|
||||
ByteBuffer leaseDuration = ByteBuffer.allocate(16);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if(args.length < 2) {
|
||||
System.err.println("Usage : java [...] JavaBridgeTest port protocol");
|
||||
System.out.println(" port is numeric, protocol is TCP or UDP");
|
||||
return;
|
||||
}
|
||||
|
||||
devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, IntBuffer.allocate(1));
|
||||
if (devlist != null) {
|
||||
System.out.println("List of UPNP devices found on the network :");
|
||||
for (UPNPDev device = devlist; device != null; device = device.pNext) {
|
||||
System.out.println("desc: " + device.descURL.getString(0) + " st: " + device.st.getString(0));
|
||||
}
|
||||
if ((i = miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16)) != 0) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
System.out.println("Found valid IGD : " + urls.controlURL.getString(0));
|
||||
break;
|
||||
case 2:
|
||||
System.out.println("Found a (not connected?) IGD : " + urls.controlURL.getString(0));
|
||||
System.out.println("Trying to continue anyway");
|
||||
break;
|
||||
case 3:
|
||||
System.out.println("UPnP device found. Is it an IGD ? : " + urls.controlURL.getString(0));
|
||||
System.out.println("Trying to continue anyway");
|
||||
break;
|
||||
default:
|
||||
System.out.println("Found device (igd ?) : " + urls.controlURL.getString(0));
|
||||
System.out.println("Trying to continue anyway");
|
||||
|
||||
}
|
||||
System.out.println("Local LAN ip address : " + new String(lanaddr.array()));
|
||||
ByteBuffer externalAddress = ByteBuffer.allocate(16);
|
||||
miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0),
|
||||
new String(data.first.servicetype), externalAddress);
|
||||
System.out.println("ExternalIPAddress = " + new String(externalAddress.array()));
|
||||
ret = miniupnpc.UPNP_AddPortMapping(
|
||||
urls.controlURL.getString(0), // controlURL
|
||||
new String(data.first.servicetype), // servicetype
|
||||
args[0], // external Port
|
||||
args[0], // internal Port
|
||||
new String(lanaddr.array()), // internal client
|
||||
"added via miniupnpc/JAVA !", // description
|
||||
args[1], // protocol UDP or TCP
|
||||
null, // remote host (useless)
|
||||
"0"); // leaseDuration
|
||||
if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
|
||||
System.out.println("AddPortMapping() failed with code " + ret);
|
||||
ret = miniupnpc.UPNP_GetSpecificPortMappingEntry(
|
||||
urls.controlURL.getString(0), new String(data.first.servicetype),
|
||||
args[0], args[1], null, intClient, intPort,
|
||||
desc, enabled, leaseDuration);
|
||||
if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
|
||||
System.out.println("GetSpecificPortMappingEntry() failed with code " + ret);
|
||||
System.out.println("InternalIP:Port = " +
|
||||
new String(intClient.array()) + ":" + new String(intPort.array()) +
|
||||
" (" + new String(desc.array()) + ")");
|
||||
ret = miniupnpc.UPNP_DeletePortMapping(
|
||||
urls.controlURL.getString(0),
|
||||
new String(data.first.servicetype),
|
||||
args[0], args[1], null);
|
||||
if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
|
||||
System.out.println("DelPortMapping() failed with code " + ret);
|
||||
miniupnpc.FreeUPNPUrls(urls);
|
||||
} else {
|
||||
System.out.println("No valid UPNP Internet Gateway Device found.");
|
||||
}
|
||||
miniupnpc.freeUPNPDevlist(devlist);
|
||||
} else {
|
||||
System.out.println("No IGD UPnP Device found on the network !\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
@echo off
|
||||
set JAVA=java
|
||||
set JAVAC=javac
|
||||
REM notice the semicolon for Windows. Write once, run ... oh nevermind
|
||||
set CP=miniupnpc_win32.jar;.
|
||||
|
||||
%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1
|
||||
%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
JAVA=java
|
||||
JAVAC=javac
|
||||
CP=$(for i in *.jar; do echo -n $i:; done).
|
||||
|
||||
$JAVAC -cp $CP JavaBridgeTest.java || exit 1
|
||||
$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
.TH MINIUPNPC 3
|
||||
.SH NAME
|
||||
miniupnpc \- UPnP client library
|
||||
.SH SYNOPSIS
|
||||
.SH DESCRIPTION
|
||||
The miniupnpc library implement the UPnP protocol defined
|
||||
to dialog with Internet Gateway Devices. It also has
|
||||
the ability to use data gathered by minissdpd(1) about
|
||||
UPnP devices up on the network in order to skip the
|
||||
long UPnP device discovery process.
|
||||
.PP
|
||||
At first, upnpDiscover(3) has to be used to discover UPnP IGD present
|
||||
on the network. Then UPNP_GetValidIGD(3) to select the right one.
|
||||
Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery
|
||||
process if the root description url of the device to use is known.
|
||||
Then all the UPNP_* functions can be used, such as
|
||||
UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc...
|
||||
.SH "HEADER FILES"
|
||||
.IP miniupnpc.h
|
||||
That's the main header file for the miniupnpc library API.
|
||||
It contains all the functions and structures related to device discovery.
|
||||
.IP upnpcommands.h
|
||||
This header file contain the UPnP IGD methods that are accessible
|
||||
through the miniupnpc API. The name of the C functions are matching
|
||||
the UPnP methods names. ie: GetGenericPortMappingEntry is
|
||||
UPNP_GetGenericPortMappingEntry.
|
||||
.SH "API FUNCTIONS"
|
||||
.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int sameport, int ipv6, int * error);"
|
||||
execute the discovery process.
|
||||
delay (in millisecond) is the maximum time for waiting any device response.
|
||||
If available, device list will be obtained from MiniSSDPd.
|
||||
Default path for minissdpd socket will be used if minissdpdsock argument is NULL.
|
||||
If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets.
|
||||
If sameport is not null, SSDP packets will be sent from the source port 1900 (same as destination port) otherwise system assign a source port.
|
||||
If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process.
|
||||
.IP "void freeUPNPDevlist(struct UPNPDev * devlist);"
|
||||
free the list returned by upnpDiscover().
|
||||
.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
|
||||
browse the list of device returned by upnpDiscover(), find
|
||||
a live UPnP internet gateway device and fill structures passed as arguments
|
||||
with data used for UPNP methods invokation.
|
||||
.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
|
||||
permit to bypass the upnpDiscover() call if the xml root description
|
||||
URL of the UPnP IGD is known.
|
||||
Fill structures passed as arguments
|
||||
with data used for UPNP methods invokation.
|
||||
.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);"
|
||||
.IP "void FreeUPNPUrls(struct UPNPUrls *);"
|
||||
|
||||
.SH "SEE ALSO"
|
||||
minissdpd(1)
|
||||
.SH BUGS
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
@mingw32-make -f Makefile.mingw %1
|
||||
@if errorlevel 1 goto end
|
||||
@if not exist upnpc-static.exe goto end
|
||||
@strip upnpc-static.exe
|
||||
@upx --best upnpc-static.exe
|
||||
@strip upnpc-shared.exe
|
||||
@upx --best upnpc-shared.exe
|
||||
:end
|
||||
|
|
@ -1,486 +0,0 @@
|
|||
/* $Id: minihttptestserver.c,v 1.13 2012/05/29 13:03:07 nanard Exp $ */
|
||||
/* Project : miniUPnP
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define CRAP_LENGTH (2048)
|
||||
|
||||
volatile sig_atomic_t quit = 0;
|
||||
volatile sig_atomic_t child_to_wait_for = 0;
|
||||
|
||||
/**
|
||||
* signal handler for SIGCHLD (child status has changed)
|
||||
*/
|
||||
void handle_signal_chld(int sig)
|
||||
{
|
||||
printf("handle_signal_chld(%d)\n", sig);
|
||||
++child_to_wait_for;
|
||||
}
|
||||
|
||||
/**
|
||||
* signal handler for SIGINT (CRTL C)
|
||||
*/
|
||||
#if 0
|
||||
void handle_signal_int(int sig)
|
||||
{
|
||||
printf("handle_signal_int(%d)\n", sig);
|
||||
quit = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* build a text/plain content of the specified length
|
||||
*/
|
||||
void build_content(char * p, int n)
|
||||
{
|
||||
char line_buffer[80];
|
||||
int k;
|
||||
int i = 0;
|
||||
|
||||
while(n > 0) {
|
||||
k = snprintf(line_buffer, sizeof(line_buffer),
|
||||
"%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n",
|
||||
i, i);
|
||||
if(k != 64) {
|
||||
fprintf(stderr, "snprintf() returned %d in build_content()\n", k);
|
||||
}
|
||||
++i;
|
||||
if(n >= 64) {
|
||||
memcpy(p, line_buffer, 64);
|
||||
p += 64;
|
||||
n -= 64;
|
||||
} else {
|
||||
memcpy(p, line_buffer, n);
|
||||
p += n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build crappy content
|
||||
*/
|
||||
void build_crap(char * p, int n)
|
||||
{
|
||||
static const char crap[] = "_CRAP_\r\n";
|
||||
int i;
|
||||
|
||||
while(n > 0) {
|
||||
i = sizeof(crap) - 1;
|
||||
if(i > n)
|
||||
i = n;
|
||||
memcpy(p, crap, i);
|
||||
p += i;
|
||||
n -= i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build chunked response.
|
||||
* return a malloc'ed buffer
|
||||
*/
|
||||
char * build_chunked_response(int content_length, int * response_len) {
|
||||
char * response_buffer;
|
||||
char * content_buffer;
|
||||
int buffer_length;
|
||||
int i, n;
|
||||
|
||||
/* allocate to have some margin */
|
||||
buffer_length = 256 + content_length + (content_length >> 4);
|
||||
response_buffer = malloc(buffer_length);
|
||||
*response_len = snprintf(response_buffer, buffer_length,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n");
|
||||
|
||||
/* build the content */
|
||||
content_buffer = malloc(content_length);
|
||||
build_content(content_buffer, content_length);
|
||||
|
||||
/* chunk it */
|
||||
i = 0;
|
||||
while(i < content_length) {
|
||||
n = (rand() % 199) + 1;
|
||||
if(i + n > content_length) {
|
||||
n = content_length - i;
|
||||
}
|
||||
/* TODO : check buffer size ! */
|
||||
*response_len += snprintf(response_buffer + *response_len,
|
||||
buffer_length - *response_len,
|
||||
"%x\r\n", n);
|
||||
memcpy(response_buffer + *response_len, content_buffer + i, n);
|
||||
*response_len += n;
|
||||
i += n;
|
||||
response_buffer[(*response_len)++] = '\r';
|
||||
response_buffer[(*response_len)++] = '\n';
|
||||
}
|
||||
/* the last chunk : "0\r\n" a empty body and then
|
||||
* the final "\r\n" */
|
||||
memcpy(response_buffer + *response_len, "0\r\n\r\n", 5);
|
||||
*response_len += 5;
|
||||
free(content_buffer);
|
||||
|
||||
printf("resp_length=%d buffer_length=%d content_length=%d\n",
|
||||
*response_len, buffer_length, content_length);
|
||||
return response_buffer;
|
||||
}
|
||||
|
||||
enum modes { MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL };
|
||||
const struct {
|
||||
const enum modes mode;
|
||||
const char * text;
|
||||
} modes_array[] = {
|
||||
{MODE_CHUNKED, "chunked"},
|
||||
{MODE_ADDCRAP, "addcrap"},
|
||||
{MODE_NORMAL, "normal"},
|
||||
{MODE_INVALID, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* write the response with random behaviour !
|
||||
*/
|
||||
void send_response(int c, const char * buffer, int len)
|
||||
{
|
||||
int n;
|
||||
while(len > 0) {
|
||||
n = (rand() % 99) + 1;
|
||||
if(n > len)
|
||||
n = len;
|
||||
n = write(c, buffer, n);
|
||||
if(n < 0) {
|
||||
if(errno != EINTR) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
/* if errno == EINTR, try again */
|
||||
} else {
|
||||
len -= n;
|
||||
buffer += n;
|
||||
}
|
||||
usleep(10000); /* 10ms */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the HTTP connection
|
||||
*/
|
||||
void handle_http_connection(int c)
|
||||
{
|
||||
char request_buffer[2048];
|
||||
int request_len = 0;
|
||||
int headers_found = 0;
|
||||
int n, i;
|
||||
char request_method[16];
|
||||
char request_uri[256];
|
||||
char http_version[16];
|
||||
char * p;
|
||||
char * response_buffer;
|
||||
int response_len;
|
||||
enum modes mode;
|
||||
int content_length = 16*1024;
|
||||
|
||||
/* read the request */
|
||||
while(request_len < (int)sizeof(request_buffer) && !headers_found) {
|
||||
n = read(c,
|
||||
request_buffer + request_len,
|
||||
sizeof(request_buffer) - request_len);
|
||||
if(n < 0) {
|
||||
perror("read");
|
||||
return;
|
||||
} else if(n==0) {
|
||||
/* remote host closed the connection */
|
||||
break;
|
||||
} else {
|
||||
request_len += n;
|
||||
for(i = 0; i < request_len - 3; i++) {
|
||||
if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) {
|
||||
/* found the end of headers */
|
||||
headers_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!headers_found) {
|
||||
/* error */
|
||||
return;
|
||||
}
|
||||
printf("headers :\n%.*s", request_len, request_buffer);
|
||||
/* the request have been received, now parse the request line */
|
||||
p = request_buffer;
|
||||
for(i = 0; i < (int)sizeof(request_method) - 1; i++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
request_method[i] = *p;
|
||||
++p;
|
||||
}
|
||||
request_method[i] = '\0';
|
||||
while(*p == ' ')
|
||||
p++;
|
||||
for(i = 0; i < (int)sizeof(request_uri) - 1; i++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
request_uri[i] = *p;
|
||||
++p;
|
||||
}
|
||||
request_uri[i] = '\0';
|
||||
while(*p == ' ')
|
||||
p++;
|
||||
for(i = 0; i < (int)sizeof(http_version) - 1; i++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
http_version[i] = *p;
|
||||
++p;
|
||||
}
|
||||
http_version[i] = '\0';
|
||||
printf("Method = %s, URI = %s, %s\n",
|
||||
request_method, request_uri, http_version);
|
||||
/* check if the request method is allowed */
|
||||
if(0 != strcmp(request_method, "GET")) {
|
||||
const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n"
|
||||
"Allow: GET\r\n\r\n";
|
||||
const char * pc;
|
||||
/* 405 Method Not Allowed */
|
||||
/* The response MUST include an Allow header containing a list
|
||||
* of valid methods for the requested resource. */
|
||||
n = sizeof(response405) - 1;
|
||||
pc = response405;
|
||||
while(n > 0) {
|
||||
i = write(c, pc, n);
|
||||
if(i<0) {
|
||||
if(errno != EINTR) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
n -= i;
|
||||
pc += i;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mode = MODE_INVALID;
|
||||
/* use the request URI to know what to do */
|
||||
for(i = 0; modes_array[i].mode != MODE_INVALID; i++) {
|
||||
if(strstr(request_uri, modes_array[i].text)) {
|
||||
mode = modes_array[i].mode; /* found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case MODE_CHUNKED:
|
||||
response_buffer = build_chunked_response(content_length, &response_len);
|
||||
break;
|
||||
case MODE_ADDCRAP:
|
||||
response_len = content_length+256;
|
||||
response_buffer = malloc(response_len);
|
||||
n = snprintf(response_buffer, response_len,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: minihttptestserver\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n", content_length);
|
||||
response_len = content_length+n+CRAP_LENGTH;
|
||||
response_buffer = realloc(response_buffer, response_len);
|
||||
build_content(response_buffer + n, content_length);
|
||||
build_crap(response_buffer + n + content_length, CRAP_LENGTH);
|
||||
break;
|
||||
default:
|
||||
response_len = content_length+256;
|
||||
response_buffer = malloc(response_len);
|
||||
n = snprintf(response_buffer, response_len,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: minihttptestserver\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n");
|
||||
response_len = content_length+n;
|
||||
response_buffer = realloc(response_buffer, response_len);
|
||||
build_content(response_buffer + n, response_len - n);
|
||||
}
|
||||
|
||||
if(response_buffer) {
|
||||
send_response(c, response_buffer, response_len);
|
||||
free(response_buffer);
|
||||
} else {
|
||||
/* Error 500 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
int main(int argc, char * * argv) {
|
||||
int ipv6 = 0;
|
||||
int s, c, i;
|
||||
unsigned short port = 0;
|
||||
struct sockaddr_storage server_addr;
|
||||
socklen_t server_addrlen;
|
||||
struct sockaddr_storage client_addr;
|
||||
socklen_t client_addrlen;
|
||||
pid_t pid;
|
||||
int child = 0;
|
||||
int status;
|
||||
const char * expected_file_name = NULL;
|
||||
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(argv[i][0] == '-') {
|
||||
switch(argv[i][1]) {
|
||||
case '6':
|
||||
ipv6 = 1;
|
||||
break;
|
||||
case 'e':
|
||||
/* write expected file ! */
|
||||
expected_file_name = argv[++i];
|
||||
break;
|
||||
case 'p':
|
||||
/* port */
|
||||
if(++i < argc) {
|
||||
port = (unsigned short)atoi(argv[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown command line switch '%s'\n", argv[i]);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "unkown command line argument '%s'\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
signal(SIGCHLD, handle_signal_chld);
|
||||
#if 0
|
||||
signal(SIGINT, handle_signal_int);
|
||||
#endif
|
||||
|
||||
s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
|
||||
if(s < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
memset(&server_addr, 0, sizeof(struct sockaddr_storage));
|
||||
memset(&client_addr, 0, sizeof(struct sockaddr_storage));
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
|
||||
addr->sin6_family = AF_INET6;
|
||||
addr->sin6_port = htons(port);
|
||||
addr->sin6_addr = in6addr_loopback;
|
||||
} else {
|
||||
struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = htons(port);
|
||||
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
}
|
||||
if(bind(s, (struct sockaddr *)&server_addr,
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
if(listen(s, 5) < 0) {
|
||||
perror("listen");
|
||||
}
|
||||
if(port == 0) {
|
||||
server_addrlen = sizeof(struct sockaddr_storage);
|
||||
if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) {
|
||||
perror("getsockname");
|
||||
return 1;
|
||||
}
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
|
||||
port = ntohs(addr->sin6_port);
|
||||
} else {
|
||||
struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
|
||||
port = ntohs(addr->sin_port);
|
||||
}
|
||||
printf("Listening on port %hu\n", port);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* write expected file */
|
||||
if(expected_file_name) {
|
||||
FILE * f;
|
||||
f = fopen(expected_file_name, "wb");
|
||||
if(f) {
|
||||
char * buffer;
|
||||
buffer = malloc(16*1024);
|
||||
build_content(buffer, 16*1024);
|
||||
i = fwrite(buffer, 1, 16*1024, f);
|
||||
if(i != 16*1024) {
|
||||
fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024);
|
||||
}
|
||||
free(buffer);
|
||||
fclose(f);
|
||||
} else {
|
||||
fprintf(stderr, "error opening file %s for writing\n", expected_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* fork() loop */
|
||||
while(!child && !quit) {
|
||||
while(child_to_wait_for > 0) {
|
||||
pid = wait(&status);
|
||||
if(pid < 0) {
|
||||
perror("wait");
|
||||
} else {
|
||||
printf("child(%d) terminated with status %d\n", pid, status);
|
||||
}
|
||||
--child_to_wait_for;
|
||||
}
|
||||
/* TODO : add a select() call in order to handle the case
|
||||
* when a signal is caught */
|
||||
client_addrlen = sizeof(struct sockaddr_storage);
|
||||
c = accept(s, (struct sockaddr *)&client_addr,
|
||||
&client_addrlen);
|
||||
if(c < 0) {
|
||||
perror("accept");
|
||||
return 1;
|
||||
}
|
||||
printf("accept...\n");
|
||||
pid = fork();
|
||||
if(pid < 0) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
} else if(pid == 0) {
|
||||
/* child */
|
||||
child = 1;
|
||||
close(s);
|
||||
s = -1;
|
||||
handle_http_connection(c);
|
||||
}
|
||||
close(c);
|
||||
}
|
||||
if(s >= 0) {
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
if(!child) {
|
||||
while(child_to_wait_for > 0) {
|
||||
pid = wait(&status);
|
||||
if(pid < 0) {
|
||||
perror("wait");
|
||||
} else {
|
||||
printf("child(%d) terminated with status %d\n", pid, status);
|
||||
}
|
||||
--child_to_wait_for;
|
||||
}
|
||||
printf("Bye...\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
*
|
||||
* Minimal SOAP implementation for UPnP protocol.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include "minisoap.h"
|
||||
#include "miniupnpcstrings.h"
|
||||
|
||||
/* only for malloc */
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
|
||||
#else
|
||||
#define PRINT_SOCKET_ERROR(x) perror(x)
|
||||
#endif
|
||||
|
||||
/* httpWrite sends the headers and the body to the socket
|
||||
* and returns the number of bytes sent */
|
||||
static int
|
||||
httpWrite(int fd, const char * body, int bodysize,
|
||||
const char * headers, int headerssize)
|
||||
{
|
||||
int n = 0;
|
||||
/*n = write(fd, headers, headerssize);*/
|
||||
/*if(bodysize>0)
|
||||
n += write(fd, body, bodysize);*/
|
||||
/* Note : my old linksys router only took into account
|
||||
* soap request that are sent into only one packet */
|
||||
char * p;
|
||||
/* TODO: AVOID MALLOC */
|
||||
p = malloc(headerssize+bodysize);
|
||||
if(!p)
|
||||
return 0;
|
||||
memcpy(p, headers, headerssize);
|
||||
memcpy(p+headerssize, body, bodysize);
|
||||
/*n = write(fd, p, headerssize+bodysize);*/
|
||||
n = send(fd, p, headerssize+bodysize, 0);
|
||||
if(n<0) {
|
||||
PRINT_SOCKET_ERROR("send");
|
||||
}
|
||||
/* disable send on the socket */
|
||||
/* draytek routers dont seems to like that... */
|
||||
#if 0
|
||||
#ifdef _WIN32
|
||||
if(shutdown(fd, SD_SEND)<0) {
|
||||
#else
|
||||
if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/
|
||||
#endif
|
||||
PRINT_SOCKET_ERROR("shutdown");
|
||||
}
|
||||
#endif
|
||||
free(p);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* self explanatory */
|
||||
int soapPostSubmit(int fd,
|
||||
const char * url,
|
||||
const char * host,
|
||||
unsigned short port,
|
||||
const char * action,
|
||||
const char * body,
|
||||
const char * httpversion)
|
||||
{
|
||||
int bodysize;
|
||||
char headerbuf[512];
|
||||
int headerssize;
|
||||
char portstr[8];
|
||||
bodysize = (int)strlen(body);
|
||||
/* We are not using keep-alive HTTP connections.
|
||||
* HTTP/1.1 needs the header Connection: close to do that.
|
||||
* This is the default with HTTP/1.0
|
||||
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
|
||||
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
|
||||
* transfer encoding. */
|
||||
/* Connection: Close is normally there only in HTTP/1.1 but who knows */
|
||||
portstr[0] = '\0';
|
||||
if(port != 80)
|
||||
snprintf(portstr, sizeof(portstr), ":%hu", port);
|
||||
headerssize = snprintf(headerbuf, sizeof(headerbuf),
|
||||
"POST %s HTTP/%s\r\n"
|
||||
"Host: %s%s\r\n"
|
||||
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: text/xml\r\n"
|
||||
"SOAPAction: \"%s\"\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"Cache-Control: no-cache\r\n" /* ??? */
|
||||
"Pragma: no-cache\r\n"
|
||||
"\r\n",
|
||||
url, httpversion, host, portstr, bodysize, action);
|
||||
#ifdef DEBUG
|
||||
/*printf("SOAP request : headersize=%d bodysize=%d\n",
|
||||
headerssize, bodysize);
|
||||
*/
|
||||
printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n",
|
||||
url, httpversion, host, portstr);
|
||||
printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize);
|
||||
printf("Headers :\n%s", headerbuf);
|
||||
printf("Body :\n%s\n", body);
|
||||
#endif
|
||||
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
#ifndef MINISOAP_H_INCLUDED
|
||||
#define MINISOAP_H_INCLUDED
|
||||
|
||||
/*int httpWrite(int, const char *, int, const char *);*/
|
||||
int soapPostSubmit(int, const char *, const char *, unsigned short,
|
||||
const char *, const char *, const char *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2012 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
/*#include <syslog.h>*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <winsock.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#if defined(__amigaos__)
|
||||
#define uint16_t unsigned short
|
||||
#endif
|
||||
/* Hack */
|
||||
#define UNIX_PATH_LEN 108
|
||||
struct sockaddr_un {
|
||||
uint16_t sun_family;
|
||||
char sun_path[UNIX_PATH_LEN];
|
||||
};
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#include "minissdpc.h"
|
||||
#include "miniupnpc.h"
|
||||
|
||||
#include "codelength.h"
|
||||
|
||||
struct UPNPDev *
|
||||
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
|
||||
{
|
||||
struct UPNPDev * tmp;
|
||||
struct UPNPDev * devlist = NULL;
|
||||
unsigned char buffer[2048];
|
||||
ssize_t n;
|
||||
unsigned char * p;
|
||||
unsigned char * url;
|
||||
unsigned int i;
|
||||
unsigned int urlsize, stsize, usnsize, l;
|
||||
int s;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
/*syslog(LOG_ERR, "socket(unix): %m");*/
|
||||
perror("socket(unix)");
|
||||
return NULL;
|
||||
}
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
|
||||
/* TODO : check if we need to handle the EINTR */
|
||||
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||
{
|
||||
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
stsize = strlen(devtype);
|
||||
buffer[0] = 1; /* request type 1 : request devices/services by type */
|
||||
p = buffer + 1;
|
||||
l = stsize; CODELENGTH(l, p);
|
||||
if(p + stsize > buffer + sizeof(buffer))
|
||||
{
|
||||
/* devtype is too long ! */
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(p, devtype, stsize);
|
||||
p += stsize;
|
||||
if(write(s, buffer, p - buffer) < 0)
|
||||
{
|
||||
/*syslog(LOG_ERR, "write(): %m");*/
|
||||
perror("minissdpc.c: write()");
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
n = read(s, buffer, sizeof(buffer));
|
||||
if(n<=0)
|
||||
{
|
||||
perror("minissdpc.c: read()");
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
p = buffer + 1;
|
||||
for(i = 0; i < buffer[0]; i++)
|
||||
{
|
||||
if(p+2>=buffer+sizeof(buffer))
|
||||
break;
|
||||
DECODELENGTH(urlsize, p);
|
||||
if(p+urlsize+2>=buffer+sizeof(buffer))
|
||||
break;
|
||||
url = p;
|
||||
p += urlsize;
|
||||
DECODELENGTH(stsize, p);
|
||||
if(p+stsize+2>=buffer+sizeof(buffer))
|
||||
break;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
memcpy(tmp->buffer, url, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->buffer + urlsize + 1, p, stsize);
|
||||
p += stsize;
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
devlist = tmp;
|
||||
/* added for compatibility with recent versions of MiniSSDPd
|
||||
* >= 2007/12/19 */
|
||||
DECODELENGTH(usnsize, p);
|
||||
p += usnsize;
|
||||
if(p>buffer + sizeof(buffer))
|
||||
break;
|
||||
}
|
||||
close(s);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2007 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINISSDPC_H_INCLUDED
|
||||
#define MINISSDPC_H_INCLUDED
|
||||
|
||||
struct UPNPDev *
|
||||
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,43 +0,0 @@
|
|||
LIBRARY
|
||||
; miniupnpc library
|
||||
miniupnpc
|
||||
|
||||
EXPORTS
|
||||
; miniupnpc
|
||||
upnpDiscover
|
||||
freeUPNPDevlist
|
||||
parserootdesc
|
||||
UPNP_GetValidIGD
|
||||
UPNP_GetIGDFromUrl
|
||||
GetUPNPUrls
|
||||
FreeUPNPUrls
|
||||
; miniwget
|
||||
miniwget
|
||||
miniwget_getaddr
|
||||
; upnpcommands
|
||||
UPNP_GetTotalBytesSent
|
||||
UPNP_GetTotalBytesReceived
|
||||
UPNP_GetTotalPacketsSent
|
||||
UPNP_GetTotalPacketsReceived
|
||||
UPNP_GetStatusInfo
|
||||
UPNP_GetConnectionTypeInfo
|
||||
UPNP_GetExternalIPAddress
|
||||
UPNP_GetLinkLayerMaxBitRates
|
||||
UPNP_AddPortMapping
|
||||
UPNP_DeletePortMapping
|
||||
UPNP_GetPortMappingNumberOfEntries
|
||||
UPNP_GetSpecificPortMappingEntry
|
||||
UPNP_GetGenericPortMappingEntry
|
||||
UPNP_GetListOfPortMappings
|
||||
UPNP_AddPinhole
|
||||
UPNP_CheckPinholeWorking
|
||||
UPNP_UpdatePinhole
|
||||
UPNP_GetPinholePackets
|
||||
UPNP_DeletePinhole
|
||||
UPNP_GetFirewallStatus
|
||||
UPNP_GetOutboundPinholeTimeout
|
||||
; upnperrors
|
||||
strupnperror
|
||||
; portlistingparse
|
||||
ParsePortListing
|
||||
FreePortListing
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/* $Id: miniupnpc.h,v 1.35 2014/01/31 13:26:34 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2012 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPC_H_INCLUDED
|
||||
#define MINIUPNPC_H_INCLUDED
|
||||
|
||||
#include "declspec.h"
|
||||
#include "igd_desc_parse.h"
|
||||
|
||||
/* error codes : */
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
|
||||
/* versions : */
|
||||
#define MINIUPNPC_VERSION "1.9.20140401"
|
||||
#define MINIUPNPC_API_VERSION 10
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structures definitions : */
|
||||
struct UPNParg { const char * elt; const char * val; };
|
||||
|
||||
char *
|
||||
simpleUPnPcommand(int, const char *, const char *,
|
||||
const char *, struct UPNParg *,
|
||||
int *);
|
||||
|
||||
struct UPNPDev {
|
||||
struct UPNPDev * pNext;
|
||||
char * descURL;
|
||||
char * st;
|
||||
unsigned int scope_id;
|
||||
char buffer[2];
|
||||
};
|
||||
|
||||
/* upnpDiscover()
|
||||
* discover UPnP devices on the network.
|
||||
* The discovered devices are returned as a chained list.
|
||||
* It is up to the caller to free the list with freeUPNPDevlist().
|
||||
* delay (in millisecond) is the maximum time for waiting any device
|
||||
* response.
|
||||
* If available, device list will be obtained from MiniSSDPd.
|
||||
* Default path for minissdpd socket will be used if minissdpdsock argument
|
||||
* is NULL.
|
||||
* If multicastif is not NULL, it will be used instead of the default
|
||||
* multicast interface for sending SSDP discover packets.
|
||||
* If sameport is not null, SSDP packets will be sent from the source port
|
||||
* 1900 (same as destination port) otherwise system assign a source port. */
|
||||
LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
int ipv6,
|
||||
int * error);
|
||||
/* freeUPNPDevlist()
|
||||
* free list returned by upnpDiscover() */
|
||||
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
|
||||
|
||||
/* parserootdesc() :
|
||||
* parse root XML description of a UPnP device and fill the IGDdatas
|
||||
* structure. */
|
||||
LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
|
||||
|
||||
/* structure used to get fast access to urls
|
||||
* controlURL: controlURL of the WANIPConnection
|
||||
* ipcondescURL: url of the description of the WANIPConnection
|
||||
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
|
||||
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
|
||||
*/
|
||||
struct UPNPUrls {
|
||||
char * controlURL;
|
||||
char * ipcondescURL;
|
||||
char * controlURL_CIF;
|
||||
char * controlURL_6FC;
|
||||
char * rootdescURL;
|
||||
};
|
||||
|
||||
/* UPNP_GetValidIGD() :
|
||||
* return values :
|
||||
* 0 = NO IGD found
|
||||
* 1 = A valid connected IGD has been found
|
||||
* 2 = A valid IGD has been found but it reported as
|
||||
* not connected
|
||||
* 3 = an UPnP device has been found but was not recognized as an IGD
|
||||
*
|
||||
* In any non zero return case, the urls and data structures
|
||||
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
|
||||
* free allocated memory.
|
||||
*/
|
||||
LIBSPEC int
|
||||
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
/* UPNP_GetIGDFromUrl()
|
||||
* Used when skipping the discovery process.
|
||||
* return value :
|
||||
* 0 - Not ok
|
||||
* 1 - OK */
|
||||
LIBSPEC int
|
||||
UPNP_GetIGDFromUrl(const char * rootdescurl,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
LIBSPEC void
|
||||
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
|
||||
const char *, unsigned int);
|
||||
|
||||
LIBSPEC void
|
||||
FreeUPNPUrls(struct UPNPUrls *);
|
||||
|
||||
/* return 0 or 1 */
|
||||
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,545 +0,0 @@
|
|||
/* $Id: miniupnpcmodule.c,v 1.22 2014/01/31 13:18:25 nanard Exp $*/
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* website : http://miniupnp.tuxfamily.org/
|
||||
* copyright (c) 2007-2014 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <Python.h>
|
||||
#define STATICLIB
|
||||
#include "structmember.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "upnperrors.h"
|
||||
|
||||
/* for compatibility with Python < 2.4 */
|
||||
#ifndef Py_RETURN_NONE
|
||||
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
|
||||
#endif
|
||||
|
||||
#ifndef Py_RETURN_TRUE
|
||||
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
|
||||
#endif
|
||||
|
||||
#ifndef Py_RETURN_FALSE
|
||||
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
|
||||
#endif
|
||||
|
||||
/* for compatibility with Python < 3.0 */
|
||||
#ifndef PyVarObject_HEAD_INIT
|
||||
#define PyVarObject_HEAD_INIT(type, size) \
|
||||
PyObject_HEAD_INIT(type) size,
|
||||
#endif
|
||||
|
||||
#ifndef Py_TYPE
|
||||
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
/* Type-specific fields go here. */
|
||||
struct UPNPDev * devlist;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
unsigned int discoverdelay; /* value passed to upnpDiscover() */
|
||||
char lanaddr[40]; /* our ip address on the LAN */
|
||||
char * multicastif;
|
||||
char * minissdpdsocket;
|
||||
} UPnPObject;
|
||||
|
||||
static PyMemberDef UPnP_members[] = {
|
||||
{"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
|
||||
READONLY, "ip address on the LAN"
|
||||
},
|
||||
{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
|
||||
0/*READWRITE*/, "value in ms used to wait for SSDP responses"
|
||||
},
|
||||
/* T_STRING is allways readonly :( */
|
||||
{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
|
||||
0, "IP of the network interface to be used for multicast operations"
|
||||
},
|
||||
{"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
|
||||
0, "path of the MiniSSDPd unix socket"
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
UPnPObject_dealloc(UPnPObject *self)
|
||||
{
|
||||
freeUPNPDevlist(self->devlist);
|
||||
FreeUPNPUrls(&self->urls);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_discover(UPnPObject *self)
|
||||
{
|
||||
struct UPNPDev * dev;
|
||||
int i;
|
||||
PyObject *res = NULL;
|
||||
if(self->devlist)
|
||||
{
|
||||
freeUPNPDevlist(self->devlist);
|
||||
self->devlist = 0;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
|
||||
0/* multicast if*/,
|
||||
0/*minissdpd socket*/,
|
||||
0/*sameport flag*/,
|
||||
0/*ip v6*/,
|
||||
0/*error */);
|
||||
Py_END_ALLOW_THREADS
|
||||
/* Py_RETURN_NONE ??? */
|
||||
for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
|
||||
i++;
|
||||
res = Py_BuildValue("i", i);
|
||||
return res;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_selectigd(UPnPObject *self)
|
||||
{
|
||||
int r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
|
||||
self->lanaddr, sizeof(self->lanaddr));
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r)
|
||||
{
|
||||
return Py_BuildValue("s", self->urls.controlURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalbytesent(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
return Py_BuildValue("I", i);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalbytereceived(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
return Py_BuildValue("I", i);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalpacketsent(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
return Py_BuildValue("I", i);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalpacketreceived(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
return Py_BuildValue("I", i);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_statusinfo(UPnPObject *self)
|
||||
{
|
||||
char status[64];
|
||||
char lastconnerror[64];
|
||||
unsigned int uptime = 0;
|
||||
int r;
|
||||
status[0] = '\0';
|
||||
lastconnerror[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
|
||||
status, &uptime, lastconnerror);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_connectiontype(UPnPObject *self)
|
||||
{
|
||||
char connectionType[64];
|
||||
int r;
|
||||
connectionType[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
connectionType);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("s", connectionType);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_externalipaddress(UPnPObject *self)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
int r;
|
||||
externalIPAddress[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetExternalIPAddress(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
externalIPAddress);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("s", externalIPAddress);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
|
||||
* remoteHost)
|
||||
* protocol is 'UDP' or 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_addportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
char inPort[6];
|
||||
unsigned short iPort;
|
||||
const char * proto;
|
||||
const char * host;
|
||||
const char * desc;
|
||||
const char * remoteHost;
|
||||
const char * leaseDuration = "0";
|
||||
int r;
|
||||
if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
|
||||
&host, &iPort, &desc, &remoteHost))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
sprintf(inPort, "%hu", iPort);
|
||||
r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPort, inPort, host, desc, proto,
|
||||
remoteHost, leaseDuration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: RAISE an Exception. See upnpcommands.h for errors codes.
|
||||
// upnperrors.c
|
||||
//Py_RETURN_FALSE;
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* DeletePortMapping(extPort, proto, removeHost='')
|
||||
* proto = 'UDP', 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
const char * proto;
|
||||
const char * remoteHost = "";
|
||||
int r;
|
||||
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPort, proto, remoteHost);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_getportmappingnumberofentries(UPnPObject *self)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
int r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
&n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("I", n);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* GetSpecificPortMapping(ePort, proto, remoteHost='')
|
||||
* proto = 'UDP' or 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
const char * proto;
|
||||
const char * remoteHost = "";
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
unsigned short iPort;
|
||||
char desc[80];
|
||||
char enabled[4];
|
||||
char leaseDuration[16];
|
||||
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
|
||||
return NULL;
|
||||
extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
|
||||
desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
extPort, proto, remoteHost,
|
||||
intClient, intPort,
|
||||
desc, enabled, leaseDuration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(intClient[0])
|
||||
{
|
||||
iPort = (unsigned short)atoi(intPort);
|
||||
return Py_BuildValue("(s,H,s,O,i)",
|
||||
intClient, iPort, desc,
|
||||
PyBool_FromLong(atoi(enabled)),
|
||||
atoi(leaseDuration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* GetGenericPortMapping(index) */
|
||||
static PyObject *
|
||||
UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
int i, r;
|
||||
char index[8];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
unsigned short iPort;
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
char protocol[4];
|
||||
char desc[80];
|
||||
char enabled[6];
|
||||
char rHost[64];
|
||||
char duration[16]; /* lease duration */
|
||||
unsigned int dur;
|
||||
if(!PyArg_ParseTuple(args, "i", &i))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
snprintf(index, sizeof(index), "%d", i);
|
||||
rHost[0] = '\0'; enabled[0] = '\0';
|
||||
duration[0] = '\0'; desc[0] = '\0';
|
||||
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
|
||||
r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
index,
|
||||
extPort, intClient, intPort,
|
||||
protocol, desc, enabled, rHost,
|
||||
duration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
ePort = (unsigned short)atoi(extPort);
|
||||
iPort = (unsigned short)atoi(intPort);
|
||||
dur = (unsigned int)strtoul(duration, 0, 0);
|
||||
return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
|
||||
ePort, protocol, intClient, iPort,
|
||||
desc, enabled, rHost, dur);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* miniupnpc.UPnP object Method Table */
|
||||
static PyMethodDef UPnP_methods[] = {
|
||||
{"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
|
||||
"discover UPnP IGD devices on the network"
|
||||
},
|
||||
{"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
|
||||
"select a valid UPnP IGD among discovered devices"
|
||||
},
|
||||
{"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
|
||||
"return the total number of bytes sent by UPnP IGD"
|
||||
},
|
||||
{"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
|
||||
"return the total number of bytes received by UPnP IGD"
|
||||
},
|
||||
{"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
|
||||
"return the total number of packets sent by UPnP IGD"
|
||||
},
|
||||
{"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
|
||||
"return the total number of packets received by UPnP IGD"
|
||||
},
|
||||
{"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
|
||||
"return status and uptime"
|
||||
},
|
||||
{"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
|
||||
"return IGD WAN connection type"
|
||||
},
|
||||
{"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
|
||||
"return external IP address"
|
||||
},
|
||||
{"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
|
||||
"add a port mapping"
|
||||
},
|
||||
{"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
|
||||
"delete a port mapping"
|
||||
},
|
||||
{"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
|
||||
"-- non standard --"
|
||||
},
|
||||
{"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
|
||||
"get details about a specific port mapping entry"
|
||||
},
|
||||
{"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
|
||||
"get all details about the port mapping at index"
|
||||
},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject UPnPType = {
|
||||
PyVarObject_HEAD_INIT(NULL,
|
||||
0) /*ob_size*/
|
||||
"miniupnpc.UPnP", /*tp_name*/
|
||||
sizeof(UPnPObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
(destructor)UPnPObject_dealloc,/*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
"UPnP objects", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
UPnP_methods, /* tp_methods */
|
||||
UPnP_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0,/*(initproc)UPnP_init,*/ /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
#ifndef _WIN32
|
||||
PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* module methods */
|
||||
static PyMethodDef miniupnpc_methods[] = {
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"miniupnpc", /* m_name */
|
||||
"miniupnpc module.", /* m_doc */
|
||||
-1, /* m_size */
|
||||
miniupnpc_methods, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
||||
#define PyMODINIT_FUNC void
|
||||
#endif
|
||||
|
||||
PyMODINIT_FUNC
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyInit_miniupnpc(void)
|
||||
#else
|
||||
initminiupnpc(void)
|
||||
#endif
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
#ifdef _WIN32
|
||||
UPnPType.tp_new = PyType_GenericNew;
|
||||
#endif
|
||||
if (PyType_Ready(&UPnPType) < 0)
|
||||
return;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
m = PyModule_Create(&moduledef);
|
||||
#else
|
||||
m = Py_InitModule3("miniupnpc", miniupnpc_methods,
|
||||
"miniupnpc module.");
|
||||
#endif
|
||||
|
||||
Py_INCREF(&UPnPType);
|
||||
PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return m;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
|
||||
#define MINIUPNPCSTRINGS_H_INCLUDED
|
||||
|
||||
#define OS_STRING "${CMAKE_SYSTEM_NAME}"
|
||||
#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
/* $Id: miniupnpcstrings.h.in,v 1.5 2012/10/16 16:48:26 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2011 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
|
||||
#define MINIUPNPCSTRINGS_H_INCLUDED
|
||||
|
||||
#define OS_STRING "OS/version"
|
||||
#define MINIUPNPC_VERSION_STRING "version"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCTYPES_H_INCLUDED
|
||||
#define MINIUPNPCTYPES_H_INCLUDED
|
||||
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
|
||||
#define UNSIGNED_INTEGER unsigned long long
|
||||
#define STRTOUI strtoull
|
||||
#else
|
||||
#define UNSIGNED_INTEGER unsigned int
|
||||
#define STRTOUI strtoul
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,575 +0,0 @@
|
|||
/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
#define snprintf _snprintf
|
||||
#define socklen_t int
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define strncasecmp _memicmp
|
||||
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#else /* #ifdef _WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
#define socklen_t int
|
||||
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/select.h>
|
||||
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#define closesocket close
|
||||
#endif /* #else _WIN32 */
|
||||
#if defined(__sun) || defined(sun)
|
||||
#define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#include "miniupnpcstrings.h"
|
||||
#include "miniwget.h"
|
||||
#include "connecthostport.h"
|
||||
#include "receivedata.h"
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read a HTTP response from a socket.
|
||||
* Process Content-Length and Transfer-encoding headers.
|
||||
* return a pointer to the content buffer, which length is saved
|
||||
* to the length parameter.
|
||||
*/
|
||||
void *
|
||||
getHTTPResponse(int s, int * size)
|
||||
{
|
||||
char buf[2048];
|
||||
int n;
|
||||
int endofheaders = 0;
|
||||
int chunked = 0;
|
||||
int content_length = -1;
|
||||
unsigned int chunksize = 0;
|
||||
unsigned int bytestocopy = 0;
|
||||
/* buffers : */
|
||||
char * header_buf;
|
||||
unsigned int header_buf_len = 2048;
|
||||
unsigned int header_buf_used = 0;
|
||||
char * content_buf;
|
||||
unsigned int content_buf_len = 2048;
|
||||
unsigned int content_buf_used = 0;
|
||||
char chunksize_buf[32];
|
||||
unsigned int chunksize_buf_index;
|
||||
|
||||
header_buf = malloc(header_buf_len);
|
||||
content_buf = malloc(content_buf_len);
|
||||
chunksize_buf[0] = '\0';
|
||||
chunksize_buf_index = 0;
|
||||
|
||||
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
|
||||
{
|
||||
if(endofheaders == 0)
|
||||
{
|
||||
int i;
|
||||
int linestart=0;
|
||||
int colon=0;
|
||||
int valuestart=0;
|
||||
if(header_buf_used + n > header_buf_len) {
|
||||
header_buf = realloc(header_buf, header_buf_used + n);
|
||||
header_buf_len = header_buf_used + n;
|
||||
}
|
||||
memcpy(header_buf + header_buf_used, buf, n);
|
||||
header_buf_used += n;
|
||||
/* search for CR LF CR LF (end of headers)
|
||||
* recognize also LF LF */
|
||||
i = 0;
|
||||
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
|
||||
if(header_buf[i] == '\r') {
|
||||
i++;
|
||||
if(header_buf[i] == '\n') {
|
||||
i++;
|
||||
if(i < (int)header_buf_used && header_buf[i] == '\r') {
|
||||
i++;
|
||||
if(i < (int)header_buf_used && header_buf[i] == '\n') {
|
||||
endofheaders = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(header_buf[i] == '\n') {
|
||||
i++;
|
||||
if(header_buf[i] == '\n') {
|
||||
endofheaders = i+1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(endofheaders == 0)
|
||||
continue;
|
||||
/* parse header lines */
|
||||
for(i = 0; i < endofheaders - 1; i++) {
|
||||
if(colon <= linestart && header_buf[i]==':')
|
||||
{
|
||||
colon = i;
|
||||
while(i < (endofheaders-1)
|
||||
&& (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
|
||||
i++;
|
||||
valuestart = i + 1;
|
||||
}
|
||||
/* detecting end of line */
|
||||
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
|
||||
{
|
||||
if(colon > linestart && valuestart > colon)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("header='%.*s', value='%.*s'\n",
|
||||
colon-linestart, header_buf+linestart,
|
||||
i-valuestart, header_buf+valuestart);
|
||||
#endif
|
||||
if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
|
||||
{
|
||||
content_length = atoi(header_buf+valuestart);
|
||||
#ifdef DEBUG
|
||||
printf("Content-Length: %d\n", content_length);
|
||||
#endif
|
||||
}
|
||||
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
|
||||
&& 0==strncasecmp(header_buf+valuestart, "chunked", 7))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("chunked transfer-encoding!\n");
|
||||
#endif
|
||||
chunked = 1;
|
||||
}
|
||||
}
|
||||
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
|
||||
i++;
|
||||
linestart = i;
|
||||
colon = linestart;
|
||||
valuestart = 0;
|
||||
}
|
||||
}
|
||||
/* copy the remaining of the received data back to buf */
|
||||
n = header_buf_used - endofheaders;
|
||||
memcpy(buf, header_buf + endofheaders, n);
|
||||
/* if(headers) */
|
||||
}
|
||||
if(endofheaders)
|
||||
{
|
||||
/* content */
|
||||
if(chunked)
|
||||
{
|
||||
int i = 0;
|
||||
while(i < n)
|
||||
{
|
||||
if(chunksize == 0)
|
||||
{
|
||||
/* reading chunk size */
|
||||
if(chunksize_buf_index == 0) {
|
||||
/* skipping any leading CR LF */
|
||||
if(i<n && buf[i] == '\r') i++;
|
||||
if(i<n && buf[i] == '\n') i++;
|
||||
}
|
||||
while(i<n && isxdigit(buf[i])
|
||||
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
|
||||
{
|
||||
chunksize_buf[chunksize_buf_index++] = buf[i];
|
||||
chunksize_buf[chunksize_buf_index] = '\0';
|
||||
i++;
|
||||
}
|
||||
while(i<n && buf[i] != '\r' && buf[i] != '\n')
|
||||
i++; /* discarding chunk-extension */
|
||||
if(i<n && buf[i] == '\r') i++;
|
||||
if(i<n && buf[i] == '\n') {
|
||||
unsigned int j;
|
||||
for(j = 0; j < chunksize_buf_index; j++) {
|
||||
if(chunksize_buf[j] >= '0'
|
||||
&& chunksize_buf[j] <= '9')
|
||||
chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
|
||||
else
|
||||
chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
|
||||
}
|
||||
chunksize_buf[0] = '\0';
|
||||
chunksize_buf_index = 0;
|
||||
i++;
|
||||
} else {
|
||||
/* not finished to get chunksize */
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("chunksize = %u (%x)\n", chunksize, chunksize);
|
||||
#endif
|
||||
if(chunksize == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("end of HTTP content - %d %d\n", i, n);
|
||||
/*printf("'%.*s'\n", n-i, buf+i);*/
|
||||
#endif
|
||||
goto end_of_stream;
|
||||
}
|
||||
}
|
||||
bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
|
||||
if((content_buf_used + bytestocopy) > content_buf_len)
|
||||
{
|
||||
if(content_length >= (int)(content_buf_used + bytestocopy)) {
|
||||
content_buf_len = content_length;
|
||||
} else {
|
||||
content_buf_len = content_buf_used + bytestocopy;
|
||||
}
|
||||
content_buf = (char *)realloc((void *)content_buf,
|
||||
content_buf_len);
|
||||
}
|
||||
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
|
||||
content_buf_used += bytestocopy;
|
||||
i += bytestocopy;
|
||||
chunksize -= bytestocopy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not chunked */
|
||||
if(content_length > 0
|
||||
&& (int)(content_buf_used + n) > content_length) {
|
||||
/* skipping additional bytes */
|
||||
n = content_length - content_buf_used;
|
||||
}
|
||||
if(content_buf_used + n > content_buf_len)
|
||||
{
|
||||
if(content_length >= (int)(content_buf_used + n)) {
|
||||
content_buf_len = content_length;
|
||||
} else {
|
||||
content_buf_len = content_buf_used + n;
|
||||
}
|
||||
content_buf = (char *)realloc((void *)content_buf,
|
||||
content_buf_len);
|
||||
}
|
||||
memcpy(content_buf + content_buf_used, buf, n);
|
||||
content_buf_used += n;
|
||||
}
|
||||
}
|
||||
/* use the Content-Length header value if available */
|
||||
if(content_length > 0 && (int)content_buf_used >= content_length)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("End of HTTP content\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
end_of_stream:
|
||||
free(header_buf); header_buf = NULL;
|
||||
*size = content_buf_used;
|
||||
if(content_buf_used == 0)
|
||||
{
|
||||
free(content_buf);
|
||||
content_buf = NULL;
|
||||
}
|
||||
return content_buf;
|
||||
}
|
||||
|
||||
/* miniwget3() :
|
||||
* do all the work.
|
||||
* Return NULL if something failed. */
|
||||
static void *
|
||||
miniwget3(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
const char * httpversion, unsigned int scope_id)
|
||||
{
|
||||
char buf[2048];
|
||||
int s;
|
||||
int n;
|
||||
int len;
|
||||
int sent;
|
||||
void * content;
|
||||
|
||||
*size = 0;
|
||||
s = connecthostport(host, port, scope_id);
|
||||
if(s < 0)
|
||||
return NULL;
|
||||
|
||||
/* get address for caller ! */
|
||||
if(addr_str)
|
||||
{
|
||||
struct sockaddr_storage saddr;
|
||||
socklen_t saddrlen;
|
||||
|
||||
saddrlen = sizeof(saddr);
|
||||
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
|
||||
{
|
||||
perror("getsockname");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
|
||||
* But his function make a string with the port : nn.nn.nn.nn:port */
|
||||
/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
|
||||
NULL, addr_str, (DWORD *)&addr_str_len))
|
||||
{
|
||||
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
|
||||
}*/
|
||||
/* the following code is only compatible with ip v4 addresses */
|
||||
strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
|
||||
#else
|
||||
#if 0
|
||||
if(saddr.sa_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
&(((struct sockaddr_in6 *)&saddr)->sin6_addr),
|
||||
addr_str, addr_str_len);
|
||||
} else {
|
||||
inet_ntop(AF_INET,
|
||||
&(((struct sockaddr_in *)&saddr)->sin_addr),
|
||||
addr_str, addr_str_len);
|
||||
}
|
||||
#endif
|
||||
/* getnameinfo return ip v6 address with the scope identifier
|
||||
* such as : 2a01:e35:8b2b:7330::%4281128194 */
|
||||
n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
|
||||
addr_str, addr_str_len,
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if(n != 0) {
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "getnameinfo() failed : %d\n", n);
|
||||
#else
|
||||
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("address miniwget : %s\n", addr_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"GET %s HTTP/%s\r\n"
|
||||
"Host: %s:%d\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
|
||||
"\r\n",
|
||||
path, httpversion, host, port);
|
||||
sent = 0;
|
||||
/* sending the HTTP request */
|
||||
while(sent < len)
|
||||
{
|
||||
n = send(s, buf+sent, len-sent, 0);
|
||||
if(n < 0)
|
||||
{
|
||||
perror("send");
|
||||
closesocket(s);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent += n;
|
||||
}
|
||||
}
|
||||
content = getHTTPResponse(s, size);
|
||||
closesocket(s);
|
||||
return content;
|
||||
}
|
||||
|
||||
/* miniwget2() :
|
||||
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
|
||||
static void *
|
||||
miniwget2(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
unsigned int scope_id)
|
||||
{
|
||||
char * respbuffer;
|
||||
|
||||
#if 1
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1", scope_id);
|
||||
#else
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.0", scope_id);
|
||||
if (*size == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Retrying with HTTP/1.1\n");
|
||||
#endif
|
||||
free(respbuffer);
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1", scope_id);
|
||||
}
|
||||
#endif
|
||||
return respbuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* parseURL()
|
||||
* arguments :
|
||||
* url : source string not modified
|
||||
* hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
|
||||
* port : port (destination)
|
||||
* path : pointer to the path part of the URL
|
||||
*
|
||||
* Return values :
|
||||
* 0 - Failure
|
||||
* 1 - Success */
|
||||
int
|
||||
parseURL(const char * url,
|
||||
char * hostname, unsigned short * port,
|
||||
char * * path, unsigned int * scope_id)
|
||||
{
|
||||
char * p1, *p2, *p3;
|
||||
if(!url)
|
||||
return 0;
|
||||
p1 = strstr(url, "://");
|
||||
if(!p1)
|
||||
return 0;
|
||||
p1 += 3;
|
||||
if( (url[0]!='h') || (url[1]!='t')
|
||||
||(url[2]!='t') || (url[3]!='p'))
|
||||
return 0;
|
||||
memset(hostname, 0, MAXHOSTNAMELEN + 1);
|
||||
if(*p1 == '[')
|
||||
{
|
||||
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
|
||||
char * scope;
|
||||
scope = strchr(p1, '%');
|
||||
p2 = strchr(p1, ']');
|
||||
if(p2 && scope && scope < p2 && scope_id) {
|
||||
/* parse scope */
|
||||
#ifdef IF_NAMESIZE
|
||||
char tmp[IF_NAMESIZE];
|
||||
int l;
|
||||
scope++;
|
||||
/* "%25" is just '%' in URL encoding */
|
||||
if(scope[0] == '2' && scope[1] == '5')
|
||||
scope += 2; /* skip "25" */
|
||||
l = p2 - scope;
|
||||
if(l >= IF_NAMESIZE)
|
||||
l = IF_NAMESIZE - 1;
|
||||
memcpy(tmp, scope, l);
|
||||
tmp[l] = '\0';
|
||||
*scope_id = if_nametoindex(tmp);
|
||||
if(*scope_id == 0) {
|
||||
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
|
||||
}
|
||||
#else
|
||||
/* under windows, scope is numerical */
|
||||
char tmp[8];
|
||||
int l;
|
||||
scope++;
|
||||
/* "%25" is just '%' in URL encoding */
|
||||
if(scope[0] == '2' && scope[1] == '5')
|
||||
scope += 2; /* skip "25" */
|
||||
l = p2 - scope;
|
||||
if(l >= sizeof(tmp))
|
||||
l = sizeof(tmp) - 1;
|
||||
memcpy(tmp, scope, l);
|
||||
tmp[l] = '\0';
|
||||
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
|
||||
#endif
|
||||
}
|
||||
p3 = strchr(p1, '/');
|
||||
if(p2 && p3)
|
||||
{
|
||||
p2++;
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
|
||||
if(*p2 == ':')
|
||||
{
|
||||
*port = 0;
|
||||
p2++;
|
||||
while( (*p2 >= '0') && (*p2 <= '9'))
|
||||
{
|
||||
*port *= 10;
|
||||
*port += (unsigned short)(*p2 - '0');
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*port = 80;
|
||||
}
|
||||
*path = p3;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p2 = strchr(p1, ':');
|
||||
p3 = strchr(p1, '/');
|
||||
if(!p3)
|
||||
return 0;
|
||||
if(!p2 || (p2>p3))
|
||||
{
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
|
||||
*port = 80;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
|
||||
*port = 0;
|
||||
p2++;
|
||||
while( (*p2 >= '0') && (*p2 <= '9'))
|
||||
{
|
||||
*port *= 10;
|
||||
*port += (unsigned short)(*p2 - '0');
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
*path = p3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
miniwget(const char * url, int * size, unsigned int scope_id)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
/* protocol://host:port/chemin */
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
*size = 0;
|
||||
if(!parseURL(url, hostname, &port, &path, &scope_id))
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
|
||||
}
|
||||
|
||||
void *
|
||||
miniwget_getaddr(const char * url, int * size,
|
||||
char * addr, int addrlen, unsigned int scope_id)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
/* protocol://host:port/path */
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
*size = 0;
|
||||
if(addr)
|
||||
addr[0] = '\0';
|
||||
if(!parseURL(url, hostname, &port, &path, &scope_id))
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
|
||||
}
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef MINIWGET_H_INCLUDED
|
||||
#define MINIWGET_H_INCLUDED
|
||||
|
||||
#include "declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
LIBSPEC void * getHTTPResponse(int s, int * size);
|
||||
|
||||
LIBSPEC void * miniwget(const char *, int *, unsigned int);
|
||||
|
||||
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
|
||||
|
||||
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */
|
||||
/* minixml.c : the minimum size a xml parser can be ! */
|
||||
/* Project : miniupnp
|
||||
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
|
||||
Copyright (c) 2005-2014, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
* The name of the author may not 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.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "minixml.h"
|
||||
|
||||
/* parseatt : used to parse the argument list
|
||||
* return 0 (false) in case of success and -1 (true) if the end
|
||||
* of the xmlbuffer is reached. */
|
||||
static int parseatt(struct xmlparser * p)
|
||||
{
|
||||
const char * attname;
|
||||
int attnamelen;
|
||||
const char * attvalue;
|
||||
int attvaluelen;
|
||||
while(p->xml < p->xmlend)
|
||||
{
|
||||
if(*p->xml=='/' || *p->xml=='>')
|
||||
return 0;
|
||||
if( !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
char sep;
|
||||
attname = p->xml;
|
||||
attnamelen = 0;
|
||||
while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
attnamelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(*(p->xml++) != '=')
|
||||
{
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(IS_WHITE_SPACE(*p->xml))
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
sep = *p->xml;
|
||||
if(sep=='\'' || sep=='\"')
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while(*p->xml != sep)
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& *p->xml != '>' && *p->xml != '/')
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*printf("%.*s='%.*s'\n",
|
||||
attnamelen, attname, attvaluelen, attvalue);*/
|
||||
if(p->attfunc)
|
||||
p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
|
||||
}
|
||||
p->xml++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parseelt parse the xml stream and
|
||||
* call the callback functions when needed... */
|
||||
static void parseelt(struct xmlparser * p)
|
||||
{
|
||||
int i;
|
||||
const char * elementname;
|
||||
while(p->xml < (p->xmlend - 1))
|
||||
{
|
||||
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
|
||||
{
|
||||
p->xml += 3;
|
||||
/* ignore comments */
|
||||
do
|
||||
{
|
||||
p->xml++;
|
||||
if ((p->xml + 3) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
while(memcmp(p->xml, "-->", 3) != 0);
|
||||
p->xml += 3;
|
||||
}
|
||||
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& (*p->xml!='>') && (*p->xml!='/')
|
||||
)
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
/* to ignore namespace : */
|
||||
if(*p->xml==':')
|
||||
{
|
||||
i = 0;
|
||||
elementname = ++p->xml;
|
||||
}
|
||||
}
|
||||
if(i>0)
|
||||
{
|
||||
if(p->starteltfunc)
|
||||
p->starteltfunc(p->data, elementname, i);
|
||||
if(parseatt(p))
|
||||
return;
|
||||
if(*p->xml!='/')
|
||||
{
|
||||
const char * data;
|
||||
i = 0; data = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while( IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(memcmp(p->xml, "<![CDATA[", 9) == 0)
|
||||
{
|
||||
/* CDATA handling */
|
||||
p->xml += 9;
|
||||
data = p->xml;
|
||||
i = 0;
|
||||
while(memcmp(p->xml, "]]>", 3) != 0)
|
||||
{
|
||||
i++; p->xml++;
|
||||
if ((p->xml + 3) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(i>0 && p->datafunc)
|
||||
p->datafunc(p->data, data, i);
|
||||
while(*p->xml!='<')
|
||||
{
|
||||
p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*p->xml!='<')
|
||||
{
|
||||
i++; p->xml++;
|
||||
if ((p->xml + 1) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(i>0 && p->datafunc && *(p->xml + 1) == '/')
|
||||
p->datafunc(p->data, data, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(*p->xml == '/')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while((*p->xml != '>'))
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(p->endeltfunc)
|
||||
p->endeltfunc(p->data, elementname, i);
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the parser must be initialized before calling this function */
|
||||
void parsexml(struct xmlparser * parser)
|
||||
{
|
||||
parser->xml = parser->xmlstart;
|
||||
parser->xmlend = parser->xmlstart + parser->xmlsize;
|
||||
parseelt(parser);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* minimal xml parser
|
||||
*
|
||||
* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef MINIXML_H_INCLUDED
|
||||
#define MINIXML_H_INCLUDED
|
||||
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
|
||||
|
||||
/* if a callback function pointer is set to NULL,
|
||||
* the function is not called */
|
||||
struct xmlparser {
|
||||
const char *xmlstart;
|
||||
const char *xmlend;
|
||||
const char *xml; /* pointer to current character */
|
||||
int xmlsize;
|
||||
void * data;
|
||||
void (*starteltfunc) (void *, const char *, int);
|
||||
void (*endeltfunc) (void *, const char *, int);
|
||||
void (*datafunc) (void *, const char *, int);
|
||||
void (*attfunc) (void *, const char *, int, const char *, int);
|
||||
};
|
||||
|
||||
/* parsexml()
|
||||
* the xmlparser structure must be initialized before the call
|
||||
* the following structure members have to be initialized :
|
||||
* xmlstart, xmlsize, data, *func
|
||||
* xml is for internal usage, xmlend is computed automatically */
|
||||
void parsexml(struct xmlparser *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/* $Id: minixmlvalid.c,v 1.6 2012/05/01 16:24:07 nanard Exp $ */
|
||||
/* MiniUPnP Project
|
||||
* http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
|
||||
* minixmlvalid.c :
|
||||
* validation program for the minixml parser
|
||||
*
|
||||
* (c) 2006-2011 Thomas Bernard */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "minixml.h"
|
||||
|
||||
/* xml event structure */
|
||||
struct event {
|
||||
enum { ELTSTART, ELTEND, ATT, CHARDATA } type;
|
||||
const char * data;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct eventlist {
|
||||
int n;
|
||||
struct event * events;
|
||||
};
|
||||
|
||||
/* compare 2 xml event lists
|
||||
* return 0 if the two lists are equals */
|
||||
int evtlistcmp(struct eventlist * a, struct eventlist * b)
|
||||
{
|
||||
int i;
|
||||
struct event * ae, * be;
|
||||
if(a->n != b->n)
|
||||
{
|
||||
printf("event number not matching : %d != %d\n", a->n, b->n);
|
||||
/*return 1;*/
|
||||
}
|
||||
for(i=0; i<a->n; i++)
|
||||
{
|
||||
ae = a->events + i;
|
||||
be = b->events + i;
|
||||
if( (ae->type != be->type)
|
||||
||(ae->len != be->len)
|
||||
||memcmp(ae->data, be->data, ae->len))
|
||||
{
|
||||
printf("Found a difference : %d '%.*s' != %d '%.*s'\n",
|
||||
ae->type, ae->len, ae->data,
|
||||
be->type, be->len, be->data);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test data */
|
||||
static const char xmldata[] =
|
||||
"<xmlroot>\n"
|
||||
" <elt1 att1=\"attvalue1\" att2=\"attvalue2\">"
|
||||
"character data"
|
||||
"</elt1> \n \t"
|
||||
"<elt1b/>"
|
||||
"<elt1>\n<![CDATA[ <html>stuff !\n ]]> \n</elt1>\n"
|
||||
"<elt2a> \t<elt2b>chardata1</elt2b><elt2b> chardata2 </elt2b></elt2a>"
|
||||
"</xmlroot>";
|
||||
|
||||
static const struct event evtref[] =
|
||||
{
|
||||
{ELTSTART, "xmlroot", 7},
|
||||
{ELTSTART, "elt1", 4},
|
||||
/* attributes */
|
||||
{CHARDATA, "character data", 14},
|
||||
{ELTEND, "elt1", 4},
|
||||
{ELTSTART, "elt1b", 5},
|
||||
{ELTSTART, "elt1", 4},
|
||||
{CHARDATA, " <html>stuff !\n ", 16},
|
||||
{ELTEND, "elt1", 4},
|
||||
{ELTSTART, "elt2a", 5},
|
||||
{ELTSTART, "elt2b", 5},
|
||||
{CHARDATA, "chardata1", 9},
|
||||
{ELTEND, "elt2b", 5},
|
||||
{ELTSTART, "elt2b", 5},
|
||||
{CHARDATA, " chardata2 ", 11},
|
||||
{ELTEND, "elt2b", 5},
|
||||
{ELTEND, "elt2a", 5},
|
||||
{ELTEND, "xmlroot", 7}
|
||||
};
|
||||
|
||||
void startelt(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("startelt : %.*s\n", l, p);*/
|
||||
evt->type = ELTSTART;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
void endelt(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("endelt : %.*s\n", l, p);*/
|
||||
evt->type = ELTEND;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
void chardata(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("chardata : '%.*s'\n", l, p);*/
|
||||
evt->type = CHARDATA;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
int testxmlparser(const char * xml, int size)
|
||||
{
|
||||
int r;
|
||||
struct eventlist evtlist;
|
||||
struct eventlist evtlistref;
|
||||
struct xmlparser parser;
|
||||
evtlist.n = 0;
|
||||
evtlist.events = malloc(sizeof(struct event)*100);
|
||||
memset(&parser, 0, sizeof(parser));
|
||||
parser.xmlstart = xml;
|
||||
parser.xmlsize = size;
|
||||
parser.data = &evtlist;
|
||||
parser.starteltfunc = startelt;
|
||||
parser.endeltfunc = endelt;
|
||||
parser.datafunc = chardata;
|
||||
parsexml(&parser);
|
||||
printf("%d events\n", evtlist.n);
|
||||
/* compare */
|
||||
evtlistref.n = sizeof(evtref)/sizeof(struct event);
|
||||
evtlistref.events = (struct event *)evtref;
|
||||
r = evtlistcmp(&evtlistref, &evtlist);
|
||||
free(evtlist.events);
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
int r;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
r = testxmlparser(xmldata, sizeof(xmldata)-1);
|
||||
if(r)
|
||||
printf("minixml validation test failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32
|
||||
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="miniupnpc"
|
||||
ProjectGUID="{D28CE435-CB33-4BAE-8A52-C6EF915956F5}"
|
||||
RootNamespace="miniupnpc"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;STATICLIB;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;STATICLIB"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Fichiers sources"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\connecthostport.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\igd_desc_parse.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\minisoap.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniupnpc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniwget.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\minixml.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\portlistingparse.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\receivedata.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnpcommands.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnperrors.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnpreplyparse.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Fichiers d'en-tête"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\bsdqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\connecthostport.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\declspec.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\igd_desc_parse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\minisoap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniupnpc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniupnpcstrings.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniupnpctypes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\miniwget.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\minixml.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\portlistingparse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\receivedata.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnpcommands.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnperrors.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\upnpreplyparse.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Fichiers de ressources"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="upnpc-static"
|
||||
ProjectGUID="{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}"
|
||||
RootNamespace="upnpcstatic"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="ws2_32.lib IPHlpApi.Lib Debug\miniupnpc.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;STATICLIB"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="ws2_32.lib IPHlpApi.Lib Release\miniupnpc.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Fichiers sources"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\upnpc.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Fichiers d'en-tête"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Fichiers de ressources"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "portlistingparse.h"
|
||||
#include "minixml.h"
|
||||
|
||||
/* list of the elements */
|
||||
static const struct {
|
||||
const portMappingElt code;
|
||||
const char * const str;
|
||||
} elements[] = {
|
||||
{ PortMappingEntry, "PortMappingEntry"},
|
||||
{ NewRemoteHost, "NewRemoteHost"},
|
||||
{ NewExternalPort, "NewExternalPort"},
|
||||
{ NewProtocol, "NewProtocol"},
|
||||
{ NewInternalPort, "NewInternalPort"},
|
||||
{ NewInternalClient, "NewInternalClient"},
|
||||
{ NewEnabled, "NewEnabled"},
|
||||
{ NewDescription, "NewDescription"},
|
||||
{ NewLeaseTime, "NewLeaseTime"},
|
||||
{ PortMappingEltNone, NULL}
|
||||
};
|
||||
|
||||
/* Helper function */
|
||||
static UNSIGNED_INTEGER
|
||||
atoui(const char * p, int l)
|
||||
{
|
||||
UNSIGNED_INTEGER r = 0;
|
||||
while(l > 0 && *p)
|
||||
{
|
||||
if(*p >= '0' && *p <= '9')
|
||||
r = r*10 + (*p - '0');
|
||||
else
|
||||
break;
|
||||
p++;
|
||||
l--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Start element handler */
|
||||
static void
|
||||
startelt(void * d, const char * name, int l)
|
||||
{
|
||||
int i;
|
||||
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
|
||||
pdata->curelt = PortMappingEltNone;
|
||||
for(i = 0; elements[i].str; i++)
|
||||
{
|
||||
if(memcmp(name, elements[i].str, l) == 0)
|
||||
{
|
||||
pdata->curelt = elements[i].code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pdata->curelt == PortMappingEntry)
|
||||
{
|
||||
struct PortMapping * pm;
|
||||
pm = calloc(1, sizeof(struct PortMapping));
|
||||
LIST_INSERT_HEAD( &(pdata->head), pm, entries);
|
||||
}
|
||||
}
|
||||
|
||||
/* End element handler */
|
||||
static void
|
||||
endelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
|
||||
(void)name;
|
||||
(void)l;
|
||||
pdata->curelt = PortMappingEltNone;
|
||||
}
|
||||
|
||||
/* Data handler */
|
||||
static void
|
||||
data(void * d, const char * data, int l)
|
||||
{
|
||||
struct PortMapping * pm;
|
||||
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
|
||||
pm = pdata->head.lh_first;
|
||||
if(!pm)
|
||||
return;
|
||||
if(l > 63)
|
||||
l = 63;
|
||||
switch(pdata->curelt)
|
||||
{
|
||||
case NewRemoteHost:
|
||||
memcpy(pm->remoteHost, data, l);
|
||||
pm->remoteHost[l] = '\0';
|
||||
break;
|
||||
case NewExternalPort:
|
||||
pm->externalPort = (unsigned short)atoui(data, l);
|
||||
break;
|
||||
case NewProtocol:
|
||||
if(l > 3)
|
||||
l = 3;
|
||||
memcpy(pm->protocol, data, l);
|
||||
pm->protocol[l] = '\0';
|
||||
break;
|
||||
case NewInternalPort:
|
||||
pm->internalPort = (unsigned short)atoui(data, l);
|
||||
break;
|
||||
case NewInternalClient:
|
||||
memcpy(pm->internalClient, data, l);
|
||||
pm->internalClient[l] = '\0';
|
||||
break;
|
||||
case NewEnabled:
|
||||
pm->enabled = (unsigned char)atoui(data, l);
|
||||
break;
|
||||
case NewDescription:
|
||||
memcpy(pm->description, data, l);
|
||||
pm->description[l] = '\0';
|
||||
break;
|
||||
case NewLeaseTime:
|
||||
pm->leaseTime = atoui(data, l);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Parse the PortMappingList XML document for IGD version 2
|
||||
*/
|
||||
void
|
||||
ParsePortListing(const char * buffer, int bufsize,
|
||||
struct PortMappingParserData * pdata)
|
||||
{
|
||||
struct xmlparser parser;
|
||||
|
||||
memset(pdata, 0, sizeof(struct PortMappingParserData));
|
||||
LIST_INIT(&(pdata->head));
|
||||
/* init xmlparser */
|
||||
parser.xmlstart = buffer;
|
||||
parser.xmlsize = bufsize;
|
||||
parser.data = pdata;
|
||||
parser.starteltfunc = startelt;
|
||||
parser.endeltfunc = endelt;
|
||||
parser.datafunc = data;
|
||||
parser.attfunc = 0;
|
||||
parsexml(&parser);
|
||||
}
|
||||
|
||||
void
|
||||
FreePortListing(struct PortMappingParserData * pdata)
|
||||
{
|
||||
struct PortMapping * pm;
|
||||
while((pm = pdata->head.lh_first) != NULL)
|
||||
{
|
||||
LIST_REMOVE(pm, entries);
|
||||
free(pm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#ifndef PORTLISTINGPARSE_H_INCLUDED
|
||||
#define PORTLISTINGPARSE_H_INCLUDED
|
||||
|
||||
#include "declspec.h"
|
||||
/* for the definition of UNSIGNED_INTEGER */
|
||||
#include "miniupnpctypes.h"
|
||||
|
||||
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
|
||||
#include "bsdqueue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sample of PortMappingEntry :
|
||||
<p:PortMappingEntry>
|
||||
<p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
|
||||
<p:NewExternalPort>2345</p:NewExternalPort>
|
||||
<p:NewProtocol>TCP</p:NewProtocol>
|
||||
<p:NewInternalPort>2345</p:NewInternalPort>
|
||||
<p:NewInternalClient>192.168.1.137</p:NewInternalClient>
|
||||
<p:NewEnabled>1</p:NewEnabled>
|
||||
<p:NewDescription>dooom</p:NewDescription>
|
||||
<p:NewLeaseTime>345</p:NewLeaseTime>
|
||||
</p:PortMappingEntry>
|
||||
*/
|
||||
typedef enum { PortMappingEltNone,
|
||||
PortMappingEntry, NewRemoteHost,
|
||||
NewExternalPort, NewProtocol,
|
||||
NewInternalPort, NewInternalClient,
|
||||
NewEnabled, NewDescription,
|
||||
NewLeaseTime } portMappingElt;
|
||||
|
||||
struct PortMapping {
|
||||
LIST_ENTRY(PortMapping) entries;
|
||||
UNSIGNED_INTEGER leaseTime;
|
||||
unsigned short externalPort;
|
||||
unsigned short internalPort;
|
||||
char remoteHost[64];
|
||||
char internalClient[64];
|
||||
char description[64];
|
||||
char protocol[4];
|
||||
unsigned char enabled;
|
||||
};
|
||||
|
||||
struct PortMappingParserData {
|
||||
LIST_HEAD(portmappinglisthead, PortMapping) head;
|
||||
portMappingElt curelt;
|
||||
};
|
||||
|
||||
LIBSPEC void
|
||||
ParsePortListing(const char * buffer, int bufsize,
|
||||
struct PortMappingParserData * pdata);
|
||||
|
||||
LIBSPEC void
|
||||
FreePortListing(struct PortMappingParserData * pdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#! /usr/bin/python
|
||||
# MiniUPnP project
|
||||
# Author : Thomas Bernard
|
||||
# This Sample code is public domain.
|
||||
# website : http://miniupnp.tuxfamily.org/
|
||||
|
||||
# import the python miniupnpc module
|
||||
import miniupnpc
|
||||
import sys
|
||||
|
||||
# create the object
|
||||
u = miniupnpc.UPnP()
|
||||
print 'inital(default) values :'
|
||||
print ' discoverdelay', u.discoverdelay
|
||||
print ' lanaddr', u.lanaddr
|
||||
print ' multicastif', u.multicastif
|
||||
print ' minissdpdsocket', u.minissdpdsocket
|
||||
u.discoverdelay = 200;
|
||||
#u.minissdpdsocket = '../minissdpd/minissdpd.sock'
|
||||
# discovery process, it usualy takes several seconds (2 seconds or more)
|
||||
print 'Discovering... delay=%ums' % u.discoverdelay
|
||||
print u.discover(), 'device(s) detected'
|
||||
# select an igd
|
||||
try:
|
||||
u.selectigd()
|
||||
except Exception, e:
|
||||
print 'Exception :', e
|
||||
sys.exit(1)
|
||||
# display information about the IGD and the internet connection
|
||||
print 'local ip address :', u.lanaddr
|
||||
print 'external ip address :', u.externalipaddress()
|
||||
print u.statusinfo(), u.connectiontype()
|
||||
|
||||
#print u.addportmapping(64000, 'TCP',
|
||||
# '192.168.1.166', 63000, 'port mapping test', '')
|
||||
#print u.deleteportmapping(64000, 'TCP')
|
||||
|
||||
port = 0
|
||||
proto = 'UDP'
|
||||
# list the redirections :
|
||||
i = 0
|
||||
while True:
|
||||
p = u.getgenericportmapping(i)
|
||||
if p==None:
|
||||
break
|
||||
print i, p
|
||||
(port, proto, (ihost,iport), desc, c, d, e) = p
|
||||
#print port, desc
|
||||
i = i + 1
|
||||
|
||||
print u.getspecificportmapping(port, proto)
|
||||
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
#define socklen_t int
|
||||
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/select.h>
|
||||
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#if !defined(__amigaos__) && !defined(__amigaos4__)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#define MINIUPNPC_IGNORE_EINTR
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
|
||||
#else
|
||||
#define PRINT_SOCKET_ERROR(x) perror(x)
|
||||
#endif
|
||||
|
||||
#include "receivedata.h"
|
||||
|
||||
int
|
||||
receivedata(int socket,
|
||||
char * data, int length,
|
||||
int timeout, unsigned int * scope_id)
|
||||
{
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
#ifdef DEBUG
|
||||
/* to shut up valgrind about uninit value */
|
||||
struct sockaddr_storage src_addr = {0};
|
||||
#else
|
||||
struct sockaddr_storage src_addr;
|
||||
#endif
|
||||
socklen_t src_addr_len = sizeof(src_addr);
|
||||
#endif
|
||||
int n;
|
||||
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
|
||||
/* using poll */
|
||||
struct pollfd fds[1]; /* for the poll */
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
do {
|
||||
#endif
|
||||
fds[0].fd = socket;
|
||||
fds[0].events = POLLIN;
|
||||
n = poll(fds, 1, timeout);
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
} while(n < 0 && errno == EINTR);
|
||||
#endif
|
||||
if(n < 0) {
|
||||
PRINT_SOCKET_ERROR("poll");
|
||||
return -1;
|
||||
} else if(n == 0) {
|
||||
/* timeout */
|
||||
return 0;
|
||||
}
|
||||
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
/* using select under _WIN32 and amigaos */
|
||||
fd_set socketSet;
|
||||
TIMEVAL timeval;
|
||||
FD_ZERO(&socketSet);
|
||||
FD_SET(socket, &socketSet);
|
||||
timeval.tv_sec = timeout / 1000;
|
||||
timeval.tv_usec = (timeout % 1000) * 1000;
|
||||
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
|
||||
if(n < 0) {
|
||||
PRINT_SOCKET_ERROR("select");
|
||||
return -1;
|
||||
} else if(n == 0) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
n = recvfrom(socket, data, length, 0,
|
||||
(struct sockaddr *)&src_addr, &src_addr_len);
|
||||
#else
|
||||
n = recv(socket, data, length, 0);
|
||||
#endif
|
||||
if(n<0) {
|
||||
PRINT_SOCKET_ERROR("recv");
|
||||
}
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
if (src_addr.ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
|
||||
#ifdef DEBUG
|
||||
printf("scope_id=%u\n", src_addr6->sin6_scope_id);
|
||||
#endif
|
||||
if(scope_id)
|
||||
*scope_id = src_addr6->sin6_scope_id;
|
||||
}
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2011-2012 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef RECEIVEDATA_H_INCLUDED
|
||||
#define RECEIVEDATA_H_INCLUDED
|
||||
|
||||
/* Reads data from the specified socket.
|
||||
* Returns the number of bytes read if successful, zero if no bytes were
|
||||
* read or if we timed out. Returns negative if there was an error. */
|
||||
int receivedata(int socket,
|
||||
char * data, int length,
|
||||
int timeout, unsigned int * scope_id);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#! /usr/bin/python
|
||||
# $Id: setup.py,v 1.9 2012/05/23 08:50:10 nanard Exp $
|
||||
# the MiniUPnP Project (c) 2007-2012 Thomas Bernard
|
||||
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
|
||||
#
|
||||
# python script to build the miniupnpc module under unix
|
||||
#
|
||||
# replace libminiupnpc.a by libminiupnpc.so for shared library usage
|
||||
from distutils.core import setup, Extension
|
||||
from distutils import sysconfig
|
||||
sysconfig.get_config_vars()["OPT"] = ''
|
||||
sysconfig.get_config_vars()["CFLAGS"] = ''
|
||||
setup(name="miniupnpc", version="1.7",
|
||||
ext_modules=[
|
||||
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
|
||||
extra_objects=["libminiupnpc.a"])
|
||||
])
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#! /usr/bin/python
|
||||
# $Id: setupmingw32.py,v 1.8 2012/05/23 08:50:10 nanard Exp $
|
||||
# the MiniUPnP Project (c) 2007-2012 Thomas Bernard
|
||||
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
|
||||
#
|
||||
# python script to build the miniupnpc module under windows (using mingw32)
|
||||
#
|
||||
from distutils.core import setup, Extension
|
||||
from distutils import sysconfig
|
||||
sysconfig.get_config_vars()["OPT"] = ''
|
||||
sysconfig.get_config_vars()["CFLAGS"] = ''
|
||||
setup(name="miniupnpc", version="1.7",
|
||||
ext_modules=[
|
||||
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
|
||||
libraries=["ws2_32", "iphlpapi"],
|
||||
extra_objects=["libminiupnpc.a"])
|
||||
])
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue