merged RC_1_1 into master
This commit is contained in:
commit
60b74d2616
110
Jamfile
110
Jamfile
|
@ -45,59 +45,6 @@ else
|
|||
|
||||
VERSION = 1.2.0 ;
|
||||
|
||||
# rule for linking the correct libraries depending
|
||||
# on features and target-os
|
||||
rule link-openssl ( properties * )
|
||||
{
|
||||
local result ;
|
||||
|
||||
# openssl libraries, if enabled
|
||||
# exclude gcc from a regular windows build to make mingw
|
||||
# link against the regular unix library name
|
||||
if <openssl-version>pre1.1 in $(properties)
|
||||
&& <target-os>windows in $(properties)
|
||||
&& ! <toolset>gcc in $(properties)
|
||||
{
|
||||
result += <library>ssleay32 <library>libeay32 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# on windows the library names were changed to be in line with other
|
||||
# system starting with OpenSSL 1.1
|
||||
result += <library>crypto <library>ssl ;
|
||||
}
|
||||
|
||||
if <crypto>libcrypto in $(properties)
|
||||
{
|
||||
# exclude gcc from a regular windows build to make mingw
|
||||
# link against the regular unix library name
|
||||
if <openssl-version>pre1.1 in $(properties)
|
||||
&& <target-os>windows in $(properties)
|
||||
&& ! <toolset>gcc in $(properties)
|
||||
{
|
||||
# it should be possible to cleanup this list, but this is safe for now
|
||||
result += <library>libeay32 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += <library>crypto ;
|
||||
}
|
||||
}
|
||||
|
||||
# windows needs some more libraries when using openSSL
|
||||
if <target-os>windows in $(properties)
|
||||
&& ! <toolset>gcc in $(properties)
|
||||
{
|
||||
result += <library>advapi32
|
||||
<library>user32
|
||||
<library>shell32
|
||||
<library>gdi32
|
||||
;
|
||||
}
|
||||
echo "link openssl = " $(result) ;
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
rule linking ( properties * )
|
||||
{
|
||||
local result ;
|
||||
|
@ -419,7 +366,6 @@ rule openssl-lib-path ( properties * )
|
|||
|
||||
local result ;
|
||||
result += <search>$(OPENSSL_LIB) ;
|
||||
echo "openssl-lib-path = " $(result) ;
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
|
@ -454,7 +400,6 @@ rule openssl-include-path ( properties * )
|
|||
|
||||
local result ;
|
||||
result += <include>$(OPENSSL_INCLUDE) ;
|
||||
echo "openssl-include-path = " $(result) ;
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
|
@ -588,16 +533,51 @@ variant test_arm : debug
|
|||
<export-extra>on <asserts>on
|
||||
;
|
||||
|
||||
lib crypto : : <name>crypto <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
lib ssl : : <name>ssl <use>crypto <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
|
||||
# required for openssl on windows
|
||||
lib ssleay32 : : <name>ssleay32 <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
lib libeay32 : : <name>libeay32 <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
lib advapi32 : : <name>advapi32 ;
|
||||
lib user32 : : <name>user32 ;
|
||||
lib shell32 : : <name>shell32 ;
|
||||
lib gdi32 : : <name>gdi32 ;
|
||||
lib z : : <link>shared <name>z ;
|
||||
|
||||
# windows variants for libssl and libcrypto (they have different names and some
|
||||
# additional dependencies)
|
||||
lib crypto
|
||||
: # sources
|
||||
: # requirements
|
||||
<target-os>windows
|
||||
<openssl-version>pre1.1
|
||||
<name>libeay32
|
||||
<conditional>@openssl-lib-path
|
||||
: # default-build
|
||||
: # usage-requirements
|
||||
<conditional>@openssl-include-path
|
||||
<library>advapi32
|
||||
<library>user32
|
||||
<library>shell32
|
||||
<library>gdi32
|
||||
;
|
||||
|
||||
lib ssl
|
||||
: # sources
|
||||
: # requirements
|
||||
<target-os>windows
|
||||
<openssl-version>pre1.1
|
||||
<name>ssleay32
|
||||
<use>crypto
|
||||
<conditional>@openssl-lib-path
|
||||
: # default-build
|
||||
: # usage-requirments
|
||||
<conditional>@openssl-include-path
|
||||
<library>advapi32
|
||||
<library>user32
|
||||
<library>shell32
|
||||
<library>gdi32
|
||||
;
|
||||
|
||||
|
||||
lib crypto : : <name>crypto <use>z <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
lib ssl : : <name>ssl <use>crypto <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
|
||||
|
||||
lib dbghelp : : <name>dbghelp ;
|
||||
|
||||
# required for networking on beos
|
||||
|
@ -609,8 +589,7 @@ lib libiconv : : <name>iconv <link>shared <search>/usr/local/lib ;
|
|||
|
||||
# openssl on linux/bsd etc.
|
||||
lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ;
|
||||
|
||||
alias openssl-libraries : : : : <conditional>@link-openssl ;
|
||||
lib dl : : <link>shared <name>dl ;
|
||||
|
||||
lib libsocket : : <use>libnsl <name>socket <link>shared <search>/usr/sfw/lib <link>shared ;
|
||||
lib libnsl : : <name>nsl <link>shared <search>/usr/sfw/lib <link>shared ;
|
||||
|
@ -825,8 +804,9 @@ lib torrent
|
|||
<link>shared:<define>TORRENT_BUILDING_SHARED
|
||||
<define>BOOST_NO_DEPRECATED
|
||||
<link>shared:<define>BOOST_SYSTEM_SOURCE
|
||||
<crypto>openssl:<library>openssl-libraries
|
||||
<crypto>libcrypto:<library>openssl-libraries
|
||||
<crypto>openssl:<library>ssl
|
||||
<crypto>openssl:<library>crypto
|
||||
<crypto>libcrypto:<library>crypto
|
||||
|
||||
<dht>on:<source>src/kademlia/$(KADEMLIA_SOURCES).cpp
|
||||
<dht>on:<source>ed25519/src/$(ED25519_SOURCES).cpp
|
||||
|
|
|
@ -152,6 +152,8 @@ my-python-extension libtorrent
|
|||
<toolset>darwin:<cxxflags>-Wno-deprecated-declarations
|
||||
<toolset>darwin:<cxxflags>-Wno-unused-command-line-argument
|
||||
<conditional>@libtorrent_linking
|
||||
<crypto>openssl:<library>/torrent//ssl
|
||||
<crypto>openssl:<library>/torrent//crypto
|
||||
: # default-build
|
||||
<warnings>all
|
||||
: # usage-requirements
|
||||
|
|
|
@ -49,7 +49,10 @@ namespace boost
|
|||
|
||||
#include <boost/asio/error.hpp>
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/error.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
#if TORRENT_USE_I2P
|
||||
#include <libtorrent/i2p_stream.hpp>
|
||||
#endif
|
||||
|
||||
using namespace boost::python;
|
||||
|
|
|
@ -49,9 +49,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <memory>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
// there is no forward declaration header for asio
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
class context;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
|
|
|
@ -39,7 +39,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/optional.hpp>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
// there is no forward declaration header for asio
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
struct context;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
|
|
@ -73,6 +73,18 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/aux_/vector.hpp"
|
||||
#include "libtorrent/aux_/deferred_handler.hpp"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
// there is no forward declaration header for asio
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
class context;
|
||||
class verify_context;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TORRENT_COMPLETE_TYPES_REQUIRED
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#endif
|
||||
|
|
|
@ -46,9 +46,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <unordered_map>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
// there is no forward declaration header for asio
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
class context;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
|
|
@ -36,11 +36,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/error_code.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
#include "libtorrent/http_connection.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
#include "libtorrent/resolver.hpp"
|
||||
#include "libtorrent/debug.hpp"
|
||||
#include "libtorrent/string_util.hpp"
|
||||
#include "libtorrent/aux_/portmap.hpp"
|
||||
#include "libtorrent/aux_/vector.hpp"
|
||||
|
||||
|
@ -49,6 +49,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <set>
|
||||
|
||||
namespace libtorrent {
|
||||
struct http_connection;
|
||||
class http_parser;
|
||||
|
||||
namespace upnp_errors
|
||||
{
|
||||
|
@ -256,16 +258,12 @@ private:
|
|||
|
||||
struct rootdevice
|
||||
{
|
||||
#if TORRENT_USE_ASSERTS
|
||||
rootdevice() {}
|
||||
~rootdevice()
|
||||
{
|
||||
TORRENT_ASSERT(magic == 1337);
|
||||
magic = 0;
|
||||
}
|
||||
rootdevice(rootdevice const&) = default;
|
||||
rootdevice& operator=(rootdevice const&) = default;
|
||||
#endif
|
||||
rootdevice();
|
||||
~rootdevice();
|
||||
rootdevice(rootdevice const&);
|
||||
rootdevice& operator=(rootdevice const&);
|
||||
rootdevice(rootdevice&&);
|
||||
rootdevice& operator=(rootdevice&&);
|
||||
|
||||
// the interface url, through which the list of
|
||||
// supported interfaces are fetched
|
||||
|
@ -310,13 +308,7 @@ private:
|
|||
#if TORRENT_USE_ASSERTS
|
||||
int magic = 1337;
|
||||
#endif
|
||||
void close() const
|
||||
{
|
||||
TORRENT_ASSERT(magic == 1337);
|
||||
if (!upnp_connection) return;
|
||||
upnp_connection->close();
|
||||
upnp_connection.reset();
|
||||
}
|
||||
void close() const;
|
||||
|
||||
bool operator<(rootdevice const& rhs) const
|
||||
{ return url < rhs.url; }
|
||||
|
|
|
@ -1185,7 +1185,20 @@ void block_cache::clear(tailqueue<disk_io_job>& jobs)
|
|||
for (int i = 0; i < cached_piece_entry::num_lrus; ++i)
|
||||
m_lru[i].get_all();
|
||||
|
||||
m_pieces.clear();
|
||||
// it's not ok to erase pieces with a refcount > 0
|
||||
// since we're cancelling all jobs though, it shouldn't be too bad
|
||||
// to let the jobs already running complete.
|
||||
for (cache_t::iterator i = m_pieces.begin(); i != m_pieces.end();)
|
||||
{
|
||||
if (i->refcount == 0 && i->piece_refcount == 0)
|
||||
{
|
||||
i = m_pieces.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void block_cache::move_to_ghost(cached_piece_entry* pe)
|
||||
|
|
|
@ -49,6 +49,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#endif
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace libtorrent {
|
||||
|
|
|
@ -40,6 +40,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/performance_counters.hpp"
|
||||
#include "libtorrent/socket_io.hpp"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#endif
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace libtorrent {
|
||||
|
|
26
src/upnp.cpp
26
src/upnp.cpp
|
@ -40,7 +40,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/random.hpp"
|
||||
#include "libtorrent/aux_/time.hpp" // for aux::time_now()
|
||||
#include "libtorrent/aux_/escape_string.hpp" // for convert_from_native
|
||||
#include "libtorrent/http_connection.hpp"
|
||||
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
#include "libtorrent/debug.hpp"
|
||||
#endif
|
||||
#include "libtorrent/aux_/numeric_cast.hpp"
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
@ -70,6 +74,28 @@ namespace upnp_errors
|
|||
|
||||
static error_code ignore_error;
|
||||
|
||||
upnp::rootdevice::rootdevice() {}
|
||||
upnp::rootdevice::~rootdevice()
|
||||
{
|
||||
TORRENT_ASSERT(magic == 1337);
|
||||
#if TORRENT_USE_ASSERTS
|
||||
magic = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
upnp::rootdevice::rootdevice(rootdevice const&) = default;
|
||||
upnp::rootdevice& upnp::rootdevice::operator=(rootdevice const&) = default;
|
||||
upnp::rootdevice::rootdevice(rootdevice&&) = default;
|
||||
upnp::rootdevice& upnp::rootdevice::operator=(rootdevice&&) = default;
|
||||
|
||||
void upnp::rootdevice::close() const
|
||||
{
|
||||
TORRENT_ASSERT(magic == 1337);
|
||||
if (!upnp_connection) return;
|
||||
upnp_connection->close();
|
||||
upnp_connection.reset();
|
||||
}
|
||||
|
||||
// TODO: 3 bind the broadcast socket. it would probably have to be changed to a vector of interfaces to
|
||||
// bind to, since the broadcast socket opens one socket per local
|
||||
// interface by default
|
||||
|
|
20
test/Jamfile
20
test/Jamfile
|
@ -143,17 +143,23 @@ test-suite libtorrent :
|
|||
test_enum_net.cpp
|
||||
test_linked_list.cpp
|
||||
test_stack_allocator.cpp
|
||||
test_listen_socket.cpp
|
||||
test_file_progress.cpp
|
||||
test_alloca.cpp ]
|
||||
|
||||
[ run test_listen_socket.cpp
|
||||
: : : <crypto>openssl:<library>/torrent//ssl
|
||||
<crypto>openssl:<library>/torrent//crypto
|
||||
]
|
||||
|
||||
[ run test_piece_picker.cpp ]
|
||||
|
||||
[ run test_dht.cpp
|
||||
test_dht_storage.cpp
|
||||
test_direct_dht.cpp
|
||||
test_hasher512.cpp
|
||||
]
|
||||
: : : <crypto>openssl:<library>/torrent//ssl
|
||||
<crypto>openssl:<library>/torrent//crypto
|
||||
]
|
||||
|
||||
[ run test_string.cpp
|
||||
test_utf8.cpp
|
||||
|
@ -183,7 +189,10 @@ test-suite libtorrent :
|
|||
[ run test_recheck.cpp ]
|
||||
[ run test_read_resume.cpp ]
|
||||
[ run test_resume.cpp ]
|
||||
[ run test_ssl.cpp ]
|
||||
[ run test_ssl.cpp : :
|
||||
: <crypto>openssl:<library>/torrent//ssl
|
||||
<crypto>openssl:<library>/torrent//crypto
|
||||
]
|
||||
[ run test_tracker.cpp ]
|
||||
[ run test_checking.cpp ]
|
||||
[ run test_url_seed.cpp ]
|
||||
|
@ -202,7 +211,10 @@ test-suite libtorrent :
|
|||
[ run test_remap_files.cpp ]
|
||||
[ run test_utp.cpp ]
|
||||
[ run test_auto_unchoke.cpp ]
|
||||
[ run test_http_connection.cpp ]
|
||||
[ run test_http_connection.cpp : :
|
||||
: <crypto>openssl:<library>/torrent//ssl
|
||||
<crypto>openssl:<library>/torrent//crypto
|
||||
]
|
||||
[ run test_torrent.cpp ]
|
||||
[ run test_transfer.cpp ]
|
||||
[ run test_time_critical.cpp ]
|
||||
|
|
|
@ -43,7 +43,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/create_torrent.hpp"
|
||||
#include "libtorrent/socket_io.hpp" // print_endpoint
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/session_stats.hpp"
|
||||
#include "libtorrent/random.hpp"
|
||||
|
@ -57,11 +56,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "test_utils.hpp"
|
||||
#include "setup_transfer.hpp"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <spawn.h>
|
||||
#include <csignal>
|
||||
|
|
|
@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/random.hpp"
|
||||
#include "libtorrent/socket_io.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/aux_/session_interface.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6()
|
||||
#include "setup_transfer.hpp" // for rand_v4
|
||||
|
||||
|
@ -165,8 +165,8 @@ TORRENT_TEST(ip_voter_1)
|
|||
TEST_CHECK(!ec);
|
||||
for (int i = 0; i < 50; ++i)
|
||||
{
|
||||
ipv1.cast_vote(real_external, aux::session_impl::source_dht, rand_v4());
|
||||
ipv1.cast_vote(rand_v4(), aux::session_impl::source_dht, malicious);
|
||||
ipv1.cast_vote(real_external, aux::session_interface::source_dht, rand_v4());
|
||||
ipv1.cast_vote(rand_v4(), aux::session_interface::source_dht, malicious);
|
||||
}
|
||||
TEST_CHECK(ipv1.external_address() == real_external);
|
||||
}
|
||||
|
@ -205,13 +205,13 @@ TORRENT_TEST(ip_voter_2)
|
|||
|
||||
for (int i = 0; i < 50; ++i)
|
||||
{
|
||||
ipv2.cast_vote(real_external1, aux::session_impl::source_dht, rand_v4());
|
||||
ipv2.cast_vote(malicious_external, aux::session_impl::source_dht, malicious);
|
||||
ipv2.cast_vote(real_external1, aux::session_interface::source_dht, rand_v4());
|
||||
ipv2.cast_vote(malicious_external, aux::session_interface::source_dht, malicious);
|
||||
#if TORRENT_USE_IPV6
|
||||
if (supports_ipv6())
|
||||
{
|
||||
ipv6.cast_vote(real_external2, aux::session_impl::source_dht, rand_v6());
|
||||
ipv6.cast_vote(malicious_external2, aux::session_impl::source_dht, malicious2);
|
||||
ipv6.cast_vote(real_external2, aux::session_interface::source_dht, rand_v6());
|
||||
ipv6.cast_vote(malicious_external2, aux::session_interface::source_dht, malicious2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/create_torrent.hpp"
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
#include "libtorrent/read_resume_data.hpp"
|
||||
|
@ -48,6 +47,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/aux_/path.hpp"
|
||||
#include "libtorrent/aux_/storage_utils.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <functional> // for bind
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/upnp.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/socket_io.hpp" // print_endpoint
|
||||
#include "libtorrent/http_parser.hpp"
|
||||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp"
|
||||
#include "libtorrent/aux_/path.hpp"
|
||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/upnp.hpp"
|
||||
#include "test.hpp"
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
char upnp_xml[] =
|
||||
"<root>"
|
||||
|
|
Loading…
Reference in New Issue