remove udt and make websocketpp includes public
This commit is contained in:
parent
2f202e017c
commit
b07f429556
34 changed files with 3 additions and 15077 deletions
|
|
@ -226,7 +226,6 @@ set( fc_sources
|
|||
src/crypto/rand.cpp
|
||||
src/network/tcp_socket.cpp
|
||||
src/network/udp_socket.cpp
|
||||
src/network/udt_socket.cpp
|
||||
src/network/http/http_connection.cpp
|
||||
src/network/http/http_server.cpp
|
||||
src/network/http/websocket.cpp
|
||||
|
|
@ -253,7 +252,6 @@ list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp")
|
|||
list(APPEND sources ${fc_headers})
|
||||
|
||||
add_subdirectory( vendor/websocketpp )
|
||||
add_subdirectory( vendor/udt4 )
|
||||
add_subdirectory( vendor/equihash )
|
||||
|
||||
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC DONT_INSTALL_LIBRARY )
|
||||
|
|
@ -348,22 +346,21 @@ target_include_directories(fc
|
|||
${Boost_INCLUDE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
"vendor/diff-match-patch-cpp-stl"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||
"${readline_includes}"
|
||||
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/cyoencode-1.0.2/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/equihash
|
||||
)
|
||||
|
||||
#target_link_libraries( fc PUBLIC udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
|
||||
#target_link_libraries( fc PUBLIC ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
|
||||
IF(NOT WIN32)
|
||||
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
|
||||
ENDIF()
|
||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} udt equihash ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} equihash ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
#include <fc/io/iostream.hpp>
|
||||
#include <fc/time.hpp>
|
||||
#include <fc/noncopyable.hpp>
|
||||
|
||||
namespace fc {
|
||||
namespace ip { class endpoint; }
|
||||
|
||||
class udt_socket : public virtual iostream, public noncopyable
|
||||
{
|
||||
public:
|
||||
udt_socket();
|
||||
~udt_socket();
|
||||
|
||||
void bind( const fc::ip::endpoint& local_endpoint );
|
||||
void connect_to( const fc::ip::endpoint& remote_endpoint );
|
||||
|
||||
fc::ip::endpoint remote_endpoint() const;
|
||||
fc::ip::endpoint local_endpoint() const;
|
||||
|
||||
using istream::get;
|
||||
void get( char& c )
|
||||
{
|
||||
read( &c, 1 );
|
||||
}
|
||||
|
||||
|
||||
/// istream interface
|
||||
/// @{
|
||||
virtual size_t readsome( char* buffer, size_t max );
|
||||
virtual size_t readsome( const std::shared_ptr<char>& buf, size_t len, size_t offset );
|
||||
virtual bool eof()const;
|
||||
/// @}
|
||||
|
||||
/// ostream interface
|
||||
/// @{
|
||||
virtual size_t writesome( const char* buffer, size_t len );
|
||||
virtual size_t writesome( const std::shared_ptr<const char>& buf, size_t len, size_t offset );
|
||||
virtual void flush();
|
||||
virtual void close();
|
||||
/// @}
|
||||
|
||||
void open();
|
||||
bool is_open()const;
|
||||
|
||||
private:
|
||||
friend class udt_server;
|
||||
int _udt_socket_id;
|
||||
};
|
||||
typedef std::shared_ptr<udt_socket> udt_socket_ptr;
|
||||
|
||||
class udt_server : public noncopyable
|
||||
{
|
||||
public:
|
||||
udt_server();
|
||||
~udt_server();
|
||||
|
||||
void close();
|
||||
void accept( udt_socket& s );
|
||||
|
||||
void listen( const fc::ip::endpoint& ep );
|
||||
fc::ip::endpoint local_endpoint() const;
|
||||
|
||||
private:
|
||||
int _udt_socket_id;
|
||||
};
|
||||
|
||||
} // fc
|
||||
|
|
@ -1,405 +0,0 @@
|
|||
#include <fc/network/udt_socket.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/thread/mutex.hpp>
|
||||
#include <fc/thread/unique_lock.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <udt.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
||||
void check_udt_errors()
|
||||
{
|
||||
UDT::ERRORINFO& error_info = UDT::getlasterror();
|
||||
if( error_info.getErrorCode() )
|
||||
{
|
||||
std::string error_message = error_info.getErrorMessage();
|
||||
error_info.clear();
|
||||
FC_CAPTURE_AND_THROW( udt_exception, (error_message) );
|
||||
}
|
||||
}
|
||||
|
||||
class udt_epoll_service
|
||||
{
|
||||
public:
|
||||
udt_epoll_service()
|
||||
:_epoll_thread("udt_epoll")
|
||||
{
|
||||
UDT::startup();
|
||||
check_udt_errors();
|
||||
_epoll_id = UDT::epoll_create();
|
||||
_epoll_loop = _epoll_thread.async( [=](){ poll_loop(); }, "udt_poll_loop" );
|
||||
}
|
||||
|
||||
~udt_epoll_service()
|
||||
{
|
||||
_epoll_loop.cancel("udt_epoll_service is destructing");
|
||||
_epoll_loop.wait();
|
||||
UDT::cleanup();
|
||||
}
|
||||
|
||||
void poll_loop()
|
||||
{
|
||||
std::set<UDTSOCKET> read_ready;
|
||||
std::set<UDTSOCKET> write_ready;
|
||||
while( !_epoll_loop.canceled() )
|
||||
{
|
||||
UDT::epoll_wait( _epoll_id,
|
||||
&read_ready,
|
||||
&write_ready, 100000000 );
|
||||
|
||||
{ synchronized(_read_promises_mutex)
|
||||
for( auto sock : read_ready )
|
||||
{
|
||||
auto itr = _read_promises.find( sock );
|
||||
if( itr != _read_promises.end() )
|
||||
{
|
||||
itr->second->set_value();
|
||||
_read_promises.erase(itr);
|
||||
}
|
||||
}
|
||||
} // synchronized read promise mutex
|
||||
|
||||
{ synchronized(_write_promises_mutex)
|
||||
for( auto sock : write_ready )
|
||||
{
|
||||
auto itr = _write_promises.find( sock );
|
||||
if( itr != _write_promises.end() )
|
||||
{
|
||||
itr->second->set_value();
|
||||
_write_promises.erase(itr);
|
||||
}
|
||||
}
|
||||
} // synchronized write promise mutex
|
||||
} // while not canceled
|
||||
} // poll_loop
|
||||
|
||||
|
||||
void notify_read( int udt_socket_id,
|
||||
const promise<void>::ptr& p )
|
||||
{
|
||||
int events = UDT_EPOLL_IN | UDT_EPOLL_ERR;
|
||||
if( 0 != UDT::epoll_add_usock( _epoll_id,
|
||||
udt_socket_id,
|
||||
&events ) )
|
||||
{
|
||||
check_udt_errors();
|
||||
}
|
||||
{ synchronized(_read_promises_mutex)
|
||||
|
||||
_read_promises[udt_socket_id] = p;
|
||||
}
|
||||
}
|
||||
|
||||
void notify_write( int udt_socket_id,
|
||||
const promise<void>::ptr& p )
|
||||
{
|
||||
int events = UDT_EPOLL_OUT | UDT_EPOLL_ERR;
|
||||
if( 0 != UDT::epoll_add_usock( _epoll_id,
|
||||
udt_socket_id,
|
||||
&events ) )
|
||||
{
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
{ synchronized(_write_promises_mutex)
|
||||
_write_promises[udt_socket_id] = p;
|
||||
}
|
||||
}
|
||||
void remove( int udt_socket_id )
|
||||
{
|
||||
{ synchronized(_read_promises_mutex)
|
||||
auto read_itr = _read_promises.find( udt_socket_id );
|
||||
if( read_itr != _read_promises.end() )
|
||||
{
|
||||
read_itr->second->set_exception( fc::copy_exception( fc::exception() ) );
|
||||
_read_promises.erase(read_itr);
|
||||
}
|
||||
}
|
||||
{ synchronized(_write_promises_mutex)
|
||||
auto write_itr = _write_promises.find( udt_socket_id );
|
||||
if( write_itr != _write_promises.end() )
|
||||
{
|
||||
write_itr->second->set_exception( fc::copy_exception( fc::exception() ) );
|
||||
_write_promises.erase(write_itr);
|
||||
}
|
||||
}
|
||||
UDT::epoll_remove_usock( _epoll_id, udt_socket_id );
|
||||
}
|
||||
|
||||
private:
|
||||
fc::mutex _read_promises_mutex;
|
||||
fc::mutex _write_promises_mutex;
|
||||
std::unordered_map<int, promise<void>::ptr > _read_promises;
|
||||
std::unordered_map<int, promise<void>::ptr > _write_promises;
|
||||
|
||||
fc::future<void> _epoll_loop;
|
||||
fc::thread _epoll_thread;
|
||||
int _epoll_id;
|
||||
};
|
||||
|
||||
|
||||
udt_epoll_service& default_epool_service()
|
||||
{
|
||||
static udt_epoll_service* default_service = new udt_epoll_service();
|
||||
return *default_service;
|
||||
}
|
||||
|
||||
|
||||
|
||||
udt_socket::udt_socket()
|
||||
:_udt_socket_id( UDT::INVALID_SOCK )
|
||||
{
|
||||
}
|
||||
|
||||
udt_socket::~udt_socket()
|
||||
{
|
||||
try {
|
||||
close();
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
wlog( "${e}", ("e", e.to_detail_string() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void udt_socket::bind( const fc::ip::endpoint& local_endpoint )
|
||||
{ try {
|
||||
if( !is_open() )
|
||||
open();
|
||||
|
||||
sockaddr_in local_addr;
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons(local_endpoint.port());
|
||||
local_addr.sin_addr.s_addr = htonl(local_endpoint.get_address());
|
||||
|
||||
if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&local_addr, sizeof(local_addr)) )
|
||||
check_udt_errors();
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_socket::connect_to( const ip::endpoint& remote_endpoint )
|
||||
{ try {
|
||||
if( !is_open() )
|
||||
open();
|
||||
|
||||
sockaddr_in serv_addr;
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(remote_endpoint.port());
|
||||
serv_addr.sin_addr.s_addr = htonl(remote_endpoint.get_address());
|
||||
|
||||
// UDT doesn't allow now blocking connects...
|
||||
fc::thread connect_thread("connect_thread");
|
||||
connect_thread.async( [&](){
|
||||
if( UDT::ERROR == UDT::connect(_udt_socket_id, (sockaddr*)&serv_addr, sizeof(serv_addr)) )
|
||||
check_udt_errors();
|
||||
}, "udt_socket::connect_to").wait();
|
||||
|
||||
bool block = false;
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (remote_endpoint) ) }
|
||||
|
||||
ip::endpoint udt_socket::remote_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in peer_addr;
|
||||
int peer_addr_size = sizeof(peer_addr);
|
||||
int error_code = UDT::getpeername( _udt_socket_id, (struct sockaddr*)&peer_addr, &peer_addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( peer_addr.sin_addr.s_addr ) ), htons(peer_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
ip::endpoint udt_socket::local_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in sock_addr;
|
||||
int addr_size = sizeof(sock_addr);
|
||||
int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
|
||||
/// @{
|
||||
size_t udt_socket::readsome( char* buffer, size_t max )
|
||||
{ try {
|
||||
auto bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 );
|
||||
while( bytes_read == UDT::ERROR )
|
||||
{
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_socket::readsome"));
|
||||
default_epool_service().notify_read( _udt_socket_id, p );
|
||||
p->wait();
|
||||
bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 );
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
return bytes_read;
|
||||
} FC_CAPTURE_AND_RETHROW( (max) ) }
|
||||
|
||||
size_t udt_socket::readsome( const std::shared_ptr<char>& buf, size_t len, size_t offset )
|
||||
{
|
||||
return readsome(buf.get() + offset, len);
|
||||
}
|
||||
|
||||
bool udt_socket::eof()const
|
||||
{
|
||||
// TODO...
|
||||
return false;
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// ostream interface
|
||||
/// @{
|
||||
size_t udt_socket::writesome( const char* buffer, size_t len )
|
||||
{ try {
|
||||
auto bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0);
|
||||
|
||||
while( UDT::ERROR == bytes_sent )
|
||||
{
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCSND )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_socket::writesome"));
|
||||
default_epool_service().notify_write( _udt_socket_id, p );
|
||||
p->wait();
|
||||
bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
return bytes_sent;
|
||||
} FC_CAPTURE_AND_RETHROW( (len) ) }
|
||||
|
||||
size_t udt_socket::writesome( const std::shared_ptr<const char>& buf, size_t len, size_t offset )
|
||||
{
|
||||
return writesome(buf.get() + offset, len);
|
||||
}
|
||||
|
||||
void udt_socket::flush(){}
|
||||
|
||||
void udt_socket::close()
|
||||
{ try {
|
||||
if( is_open() )
|
||||
{
|
||||
default_epool_service().remove( _udt_socket_id );
|
||||
UDT::close( _udt_socket_id );
|
||||
check_udt_errors();
|
||||
_udt_socket_id = UDT::INVALID_SOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog( "already closed" );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
/// @}
|
||||
|
||||
void udt_socket::open()
|
||||
{
|
||||
_udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( _udt_socket_id == UDT::INVALID_SOCK )
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
bool udt_socket::is_open()const
|
||||
{
|
||||
return _udt_socket_id != UDT::INVALID_SOCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
udt_server::udt_server()
|
||||
:_udt_socket_id( UDT::INVALID_SOCK )
|
||||
{
|
||||
_udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( _udt_socket_id == UDT::INVALID_SOCK )
|
||||
check_udt_errors();
|
||||
|
||||
bool block = false;
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
udt_server::~udt_server()
|
||||
{
|
||||
try {
|
||||
close();
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
wlog( "${e}", ("e", e.to_detail_string() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void udt_server::close()
|
||||
{ try {
|
||||
if( _udt_socket_id != UDT::INVALID_SOCK )
|
||||
{
|
||||
UDT::close( _udt_socket_id );
|
||||
check_udt_errors();
|
||||
default_epool_service().remove( _udt_socket_id );
|
||||
_udt_socket_id = UDT::INVALID_SOCK;
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_server::accept( udt_socket& s )
|
||||
{ try {
|
||||
FC_ASSERT( !s.is_open() );
|
||||
int namelen;
|
||||
sockaddr_in their_addr;
|
||||
|
||||
|
||||
while( s._udt_socket_id == UDT::INVALID_SOCK )
|
||||
{
|
||||
s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen );
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_server::accept"));
|
||||
default_epool_service().notify_read( _udt_socket_id, p );
|
||||
p->wait();
|
||||
s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen );
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_server::listen( const ip::endpoint& ep )
|
||||
{ try {
|
||||
sockaddr_in my_addr;
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(ep.port());
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(my_addr.sin_zero), '\0', 8);
|
||||
|
||||
if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&my_addr, sizeof(my_addr)) )
|
||||
check_udt_errors();
|
||||
|
||||
UDT::listen(_udt_socket_id, 10);
|
||||
check_udt_errors();
|
||||
} FC_CAPTURE_AND_RETHROW( (ep) ) }
|
||||
|
||||
fc::ip::endpoint udt_server::local_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in sock_addr;
|
||||
int addr_size = sizeof(sock_addr);
|
||||
int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
}
|
||||
|
|
@ -29,13 +29,6 @@ target_link_libraries( hmac_test fc )
|
|||
add_executable( blinding_test blinding_test.cpp )
|
||||
target_link_libraries( blinding_test fc )
|
||||
|
||||
|
||||
add_executable( udt_server udts.cpp )
|
||||
target_link_libraries( udt_server fc udt )
|
||||
|
||||
add_executable( udt_client udtc.cpp )
|
||||
target_link_libraries( udt_client fc udt )
|
||||
|
||||
add_executable( ecc_test crypto/ecc_test.cpp )
|
||||
target_link_libraries( ecc_test fc )
|
||||
|
||||
|
|
|
|||
26
vendor/udt4/CMakeLists.txt
vendored
26
vendor/udt4/CMakeLists.txt
vendored
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
IF( APPLE )
|
||||
add_definitions( -DOSX )
|
||||
ELSEIF( WIN32 )
|
||||
add_definitions( -DWIN32 )
|
||||
ELSE()
|
||||
add_definitions( -DLINUX )
|
||||
ENDIF()
|
||||
|
||||
set( udt_sources
|
||||
src/api.cpp
|
||||
src/buffer.cpp
|
||||
src/cache.cpp
|
||||
src/ccc.cpp
|
||||
src/channel.cpp
|
||||
src/common.cpp
|
||||
src/core.cpp
|
||||
src/epoll.cpp
|
||||
src/list.cpp
|
||||
src/md5.cpp
|
||||
src/packet.cpp
|
||||
src/queue.cpp
|
||||
src/window.cpp
|
||||
)
|
||||
|
||||
add_library( udt ${udt_sources} )
|
||||
32
vendor/udt4/LICENSE.txt
vendored
32
vendor/udt4/LICENSE.txt
vendored
|
|
@ -1,32 +0,0 @@
|
|||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
43
vendor/udt4/README.txt
vendored
43
vendor/udt4/README.txt
vendored
|
|
@ -1,43 +0,0 @@
|
|||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
All Rights Reserved.
|
||||
Copyright (c) 2011 - 2012, Google, Inc. All Rights Reserved.
|
||||
|
||||
UDP-based Data Transfer (UDT) Library - version 4
|
||||
Author: Yunhong Gu [yunhong.gu @ gmail.com]
|
||||
|
||||
UDT version 4 is free software under BSD License. See ./LICENSE.txt.
|
||||
|
||||
============================================================================
|
||||
|
||||
UDT Website:
|
||||
http://udt.sf.net
|
||||
http://sf.net/projects/udt/
|
||||
|
||||
|
||||
CONTENT:
|
||||
./src: UDT source code
|
||||
./app: Example programs
|
||||
./doc: UDT documentation (HTML)
|
||||
./win: Visual C++ project files for the Windows version of UDT
|
||||
|
||||
|
||||
To make:
|
||||
make -e os=XXX arch=YYY
|
||||
|
||||
XXX: [LINUX(default), BSD, OSX]
|
||||
YYY: [IA32(default), POWERPC, IA64, AMD64]
|
||||
|
||||
For example, on OS X, you may need to do "make -e os=OSX arch=POWERPC";
|
||||
on 32-bit i386 Linux system, simply use "make".
|
||||
|
||||
On Windows systems, use the Visual C++ project files in ./win directory.
|
||||
|
||||
Note for BSD users, please use GNU Make.
|
||||
|
||||
To use UDT in your application:
|
||||
Read index.htm in ./doc. The documentation is in HTML format and requires your
|
||||
browser to support JavaScript.
|
||||
|
||||
|
||||
Questions? please post to the UDT project forum:
|
||||
https://sourceforge.net/projects/udt/forums
|
||||
2392
vendor/udt4/src/api.cpp
vendored
2392
vendor/udt4/src/api.cpp
vendored
File diff suppressed because it is too large
Load diff
268
vendor/udt4/src/api.h
vendored
268
vendor/udt4/src/api.h
vendored
|
|
@ -1,268 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 09/28/2010
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_API_H__
|
||||
#define __UDT_API_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "udt.h"
|
||||
#include "packet.h"
|
||||
#include "queue.h"
|
||||
#include "cache.h"
|
||||
#include "epoll.h"
|
||||
|
||||
class CUDT;
|
||||
|
||||
class CUDTSocket
|
||||
{
|
||||
public:
|
||||
CUDTSocket();
|
||||
~CUDTSocket();
|
||||
|
||||
UDTSTATUS m_Status; // current socket state
|
||||
|
||||
uint64_t m_TimeStamp; // time when the socket is closed
|
||||
|
||||
int m_iIPversion; // IP version
|
||||
sockaddr* m_pSelfAddr; // pointer to the local address of the socket
|
||||
sockaddr* m_pPeerAddr; // pointer to the peer address of the socket
|
||||
|
||||
UDTSOCKET m_SocketID; // socket ID
|
||||
UDTSOCKET m_ListenSocket; // ID of the listener socket; 0 means this is an independent socket
|
||||
|
||||
UDTSOCKET m_PeerID; // peer socket ID
|
||||
int32_t m_iISN; // initial sequence number, used to tell different connection from same IP:port
|
||||
|
||||
CUDT* m_pUDT; // pointer to the UDT entity
|
||||
|
||||
std::set<UDTSOCKET>* m_pQueuedSockets; // set of connections waiting for accept()
|
||||
std::set<UDTSOCKET>* m_pAcceptSockets; // set of accept()ed connections
|
||||
|
||||
pthread_cond_t m_AcceptCond; // used to block "accept" call
|
||||
pthread_mutex_t m_AcceptLock; // mutex associated to m_AcceptCond
|
||||
|
||||
unsigned int m_uiBackLog; // maximum number of connections in queue
|
||||
|
||||
int m_iMuxID; // multiplexer ID
|
||||
|
||||
pthread_mutex_t m_ControlLock; // lock this socket exclusively for control APIs: bind/listen/connect
|
||||
|
||||
private:
|
||||
CUDTSocket(const CUDTSocket&);
|
||||
CUDTSocket& operator=(const CUDTSocket&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CUDTUnited
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CRendezvousQueue;
|
||||
|
||||
public:
|
||||
CUDTUnited();
|
||||
~CUDTUnited();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// initialize the UDT library.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise -1 is returned.
|
||||
|
||||
int startup();
|
||||
|
||||
// Functionality:
|
||||
// release the UDT library.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise -1 is returned.
|
||||
|
||||
int cleanup();
|
||||
|
||||
// Functionality:
|
||||
// Create a new UDT socket.
|
||||
// Parameters:
|
||||
// 0) [in] af: IP version, IPv4 (AF_INET) or IPv6 (AF_INET6).
|
||||
// 1) [in] type: socket type, SOCK_STREAM or SOCK_DGRAM
|
||||
// Returned value:
|
||||
// The new UDT socket ID, or INVALID_SOCK.
|
||||
|
||||
UDTSOCKET newSocket(int af, int type);
|
||||
|
||||
// Functionality:
|
||||
// Create a new UDT connection.
|
||||
// Parameters:
|
||||
// 0) [in] listen: the listening UDT socket;
|
||||
// 1) [in] peer: peer address.
|
||||
// 2) [in/out] hs: handshake information from peer side (in), negotiated value (out);
|
||||
// Returned value:
|
||||
// If the new connection is successfully created: 1 success, 0 already exist, -1 error.
|
||||
|
||||
int newConnection(const UDTSOCKET listen, const sockaddr* peer, CHandShake* hs);
|
||||
|
||||
// Functionality:
|
||||
// look up the UDT entity according to its ID.
|
||||
// Parameters:
|
||||
// 0) [in] u: the UDT socket ID.
|
||||
// Returned value:
|
||||
// Pointer to the UDT entity.
|
||||
|
||||
CUDT* lookup(const UDTSOCKET u);
|
||||
|
||||
// Functionality:
|
||||
// Check the status of the UDT socket.
|
||||
// Parameters:
|
||||
// 0) [in] u: the UDT socket ID.
|
||||
// Returned value:
|
||||
// UDT socket status, or NONEXIST if not found.
|
||||
|
||||
UDTSTATUS getStatus(const UDTSOCKET u);
|
||||
|
||||
// socket APIs
|
||||
|
||||
int bind(const UDTSOCKET u, const sockaddr* name, int namelen);
|
||||
int bind(const UDTSOCKET u, UDPSOCKET udpsock);
|
||||
int listen(const UDTSOCKET u, int backlog);
|
||||
UDTSOCKET accept(const UDTSOCKET listen, sockaddr* addr, int* addrlen);
|
||||
int connect(const UDTSOCKET u, const sockaddr* name, int namelen);
|
||||
int close(const UDTSOCKET u);
|
||||
int getpeername(const UDTSOCKET u, sockaddr* name, int* namelen);
|
||||
int getsockname(const UDTSOCKET u, sockaddr* name, int* namelen);
|
||||
int select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout);
|
||||
int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds, std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
|
||||
int epoll_create();
|
||||
int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
|
||||
int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
int epoll_remove_usock(const int eid, const UDTSOCKET u);
|
||||
int epoll_remove_ssock(const int eid, const SYSSOCKET s);
|
||||
int epoll_wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* lwfds = NULL);
|
||||
int epoll_release(const int eid);
|
||||
|
||||
// Functionality:
|
||||
// record the UDT exception.
|
||||
// Parameters:
|
||||
// 0) [in] e: pointer to a UDT exception instance.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setError(CUDTException* e);
|
||||
|
||||
// Functionality:
|
||||
// look up the most recent UDT exception.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// pointer to a UDT exception instance.
|
||||
|
||||
CUDTException* getError();
|
||||
|
||||
private:
|
||||
// void init();
|
||||
|
||||
private:
|
||||
std::map<UDTSOCKET, CUDTSocket*> m_Sockets; // stores all the socket structures
|
||||
|
||||
pthread_mutex_t m_ControlLock; // used to synchronize UDT API
|
||||
|
||||
pthread_mutex_t m_IDLock; // used to synchronize ID generation
|
||||
UDTSOCKET m_SocketID; // seed to generate a new unique socket ID
|
||||
|
||||
std::map<int64_t, std::set<UDTSOCKET> > m_PeerRec;// record sockets from peers to avoid repeated connection request, int64_t = (socker_id << 30) + isn
|
||||
|
||||
private:
|
||||
pthread_key_t m_TLSError; // thread local error record (last error)
|
||||
#ifndef WIN32
|
||||
static void TLSDestroy(void* e) {if (NULL != e) delete (CUDTException*)e;}
|
||||
#else
|
||||
std::map<DWORD, CUDTException*> m_mTLSRecord;
|
||||
void checkTLSValue();
|
||||
pthread_mutex_t m_TLSLock;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void connect_complete(const UDTSOCKET u);
|
||||
CUDTSocket* locate(const UDTSOCKET u);
|
||||
CUDTSocket* locate(const sockaddr* peer, const UDTSOCKET id, int32_t isn);
|
||||
void updateMux(CUDTSocket* s, const sockaddr* addr = NULL, const UDPSOCKET* = NULL);
|
||||
void updateMux(CUDTSocket* s, const CUDTSocket* ls);
|
||||
|
||||
private:
|
||||
std::map<int, CMultiplexer> m_mMultiplexer; // UDP multiplexer
|
||||
pthread_mutex_t m_MultiplexerLock;
|
||||
|
||||
private:
|
||||
CCache<CInfoBlock>* m_pCache; // UDT network information cache
|
||||
|
||||
private:
|
||||
volatile bool m_bClosing;
|
||||
pthread_mutex_t m_GCStopLock;
|
||||
pthread_cond_t m_GCStopCond;
|
||||
|
||||
pthread_mutex_t m_InitLock;
|
||||
int m_iInstanceCount; // number of startup() called by application
|
||||
bool m_bGCStatus; // if the GC thread is working (true)
|
||||
|
||||
pthread_t m_GCThread;
|
||||
#ifndef WIN32
|
||||
static void* garbageCollect(void*);
|
||||
#else
|
||||
static DWORD WINAPI garbageCollect(LPVOID);
|
||||
#endif
|
||||
|
||||
std::map<UDTSOCKET, CUDTSocket*> m_ClosedSockets; // temporarily store closed sockets
|
||||
|
||||
void checkBrokenSockets();
|
||||
void removeSocket(const UDTSOCKET u);
|
||||
|
||||
private:
|
||||
CEPoll m_EPoll; // handling epoll data structures and events
|
||||
|
||||
private:
|
||||
CUDTUnited(const CUDTUnited&);
|
||||
CUDTUnited& operator=(const CUDTUnited&);
|
||||
};
|
||||
|
||||
#endif
|
||||
652
vendor/udt4/src/buffer.cpp
vendored
652
vendor/udt4/src/buffer.cpp
vendored
|
|
@ -1,652 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 03/12/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "buffer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CSndBuffer::CSndBuffer(int size, int mss):
|
||||
m_BufLock(),
|
||||
m_pBlock(NULL),
|
||||
m_pFirstBlock(NULL),
|
||||
m_pCurrBlock(NULL),
|
||||
m_pLastBlock(NULL),
|
||||
m_pBuffer(NULL),
|
||||
m_iNextMsgNo(1),
|
||||
m_iSize(size),
|
||||
m_iMSS(mss),
|
||||
m_iCount(0)
|
||||
{
|
||||
// initial physical buffer of "size"
|
||||
m_pBuffer = new Buffer;
|
||||
m_pBuffer->m_pcData = new char [m_iSize * m_iMSS];
|
||||
m_pBuffer->m_iSize = m_iSize;
|
||||
m_pBuffer->m_pNext = NULL;
|
||||
|
||||
// circular linked list for out bound packets
|
||||
m_pBlock = new Block;
|
||||
Block* pb = m_pBlock;
|
||||
for (int i = 1; i < m_iSize; ++ i)
|
||||
{
|
||||
pb->m_pNext = new Block;
|
||||
pb->m_iMsgNo = 0;
|
||||
pb = pb->m_pNext;
|
||||
}
|
||||
pb->m_pNext = m_pBlock;
|
||||
|
||||
pb = m_pBlock;
|
||||
char* pc = m_pBuffer->m_pcData;
|
||||
for (int i = 0; i < m_iSize; ++ i)
|
||||
{
|
||||
pb->m_pcData = pc;
|
||||
pb = pb->m_pNext;
|
||||
pc += m_iMSS;
|
||||
}
|
||||
|
||||
m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock;
|
||||
|
||||
#ifndef WIN32
|
||||
pthread_mutex_init(&m_BufLock, NULL);
|
||||
#else
|
||||
m_BufLock = CreateMutex(NULL, false, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
CSndBuffer::~CSndBuffer()
|
||||
{
|
||||
Block* pb = m_pBlock->m_pNext;
|
||||
while (pb != m_pBlock)
|
||||
{
|
||||
Block* temp = pb;
|
||||
pb = pb->m_pNext;
|
||||
delete temp;
|
||||
}
|
||||
delete m_pBlock;
|
||||
|
||||
while (m_pBuffer != NULL)
|
||||
{
|
||||
Buffer* temp = m_pBuffer;
|
||||
m_pBuffer = m_pBuffer->m_pNext;
|
||||
delete [] temp->m_pcData;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
pthread_mutex_destroy(&m_BufLock);
|
||||
#else
|
||||
CloseHandle(m_BufLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order)
|
||||
{
|
||||
int size = len / m_iMSS;
|
||||
if ((len % m_iMSS) != 0)
|
||||
size ++;
|
||||
|
||||
// dynamically increase sender buffer
|
||||
while (size + m_iCount >= m_iSize)
|
||||
increase();
|
||||
|
||||
uint64_t time = CTimer::getTime();
|
||||
int32_t inorder = order;
|
||||
inorder <<= 29;
|
||||
|
||||
Block* s = m_pLastBlock;
|
||||
for (int i = 0; i < size; ++ i)
|
||||
{
|
||||
int pktlen = len - i * m_iMSS;
|
||||
if (pktlen > m_iMSS)
|
||||
pktlen = m_iMSS;
|
||||
|
||||
memcpy(s->m_pcData, data + i * m_iMSS, pktlen);
|
||||
s->m_iLength = pktlen;
|
||||
|
||||
s->m_iMsgNo = m_iNextMsgNo | inorder;
|
||||
if (i == 0)
|
||||
s->m_iMsgNo |= 0x80000000;
|
||||
if (i == size - 1)
|
||||
s->m_iMsgNo |= 0x40000000;
|
||||
|
||||
s->m_OriginTime = time;
|
||||
s->m_iTTL = ttl;
|
||||
|
||||
s = s->m_pNext;
|
||||
}
|
||||
m_pLastBlock = s;
|
||||
|
||||
CGuard::enterCS(m_BufLock);
|
||||
m_iCount += size;
|
||||
CGuard::leaveCS(m_BufLock);
|
||||
|
||||
m_iNextMsgNo ++;
|
||||
if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo)
|
||||
m_iNextMsgNo = 1;
|
||||
}
|
||||
|
||||
int CSndBuffer::addBufferFromFile(fstream& ifs, int len)
|
||||
{
|
||||
int size = len / m_iMSS;
|
||||
if ((len % m_iMSS) != 0)
|
||||
size ++;
|
||||
|
||||
// dynamically increase sender buffer
|
||||
while (size + m_iCount >= m_iSize)
|
||||
increase();
|
||||
|
||||
Block* s = m_pLastBlock;
|
||||
int total = 0;
|
||||
for (int i = 0; i < size; ++ i)
|
||||
{
|
||||
if (ifs.bad() || ifs.fail() || ifs.eof())
|
||||
break;
|
||||
|
||||
int pktlen = len - i * m_iMSS;
|
||||
if (pktlen > m_iMSS)
|
||||
pktlen = m_iMSS;
|
||||
|
||||
ifs.read(s->m_pcData, pktlen);
|
||||
if ((pktlen = ifs.gcount()) <= 0)
|
||||
break;
|
||||
|
||||
// currently file transfer is only available in streaming mode, message is always in order, ttl = infinite
|
||||
s->m_iMsgNo = m_iNextMsgNo | 0x20000000;
|
||||
if (i == 0)
|
||||
s->m_iMsgNo |= 0x80000000;
|
||||
if (i == size - 1)
|
||||
s->m_iMsgNo |= 0x40000000;
|
||||
|
||||
s->m_iLength = pktlen;
|
||||
s->m_iTTL = -1;
|
||||
s = s->m_pNext;
|
||||
|
||||
total += pktlen;
|
||||
}
|
||||
m_pLastBlock = s;
|
||||
|
||||
CGuard::enterCS(m_BufLock);
|
||||
m_iCount += size;
|
||||
CGuard::leaveCS(m_BufLock);
|
||||
|
||||
m_iNextMsgNo ++;
|
||||
if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo)
|
||||
m_iNextMsgNo = 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int CSndBuffer::readData(char** data, int32_t& msgno)
|
||||
{
|
||||
// No data to read
|
||||
if (m_pCurrBlock == m_pLastBlock)
|
||||
return 0;
|
||||
|
||||
*data = m_pCurrBlock->m_pcData;
|
||||
int readlen = m_pCurrBlock->m_iLength;
|
||||
msgno = m_pCurrBlock->m_iMsgNo;
|
||||
|
||||
m_pCurrBlock = m_pCurrBlock->m_pNext;
|
||||
|
||||
return readlen;
|
||||
}
|
||||
|
||||
int CSndBuffer::readData(char** data, const int offset, int32_t& msgno, int& msglen)
|
||||
{
|
||||
CGuard bufferguard(m_BufLock);
|
||||
|
||||
Block* p = m_pFirstBlock;
|
||||
|
||||
for (int i = 0; i < offset; ++ i)
|
||||
p = p->m_pNext;
|
||||
|
||||
if ((p->m_iTTL >= 0) && ((CTimer::getTime() - p->m_OriginTime) / 1000 > (uint64_t)p->m_iTTL))
|
||||
{
|
||||
msgno = p->m_iMsgNo & 0x1FFFFFFF;
|
||||
|
||||
msglen = 1;
|
||||
p = p->m_pNext;
|
||||
bool move = false;
|
||||
while (msgno == (p->m_iMsgNo & 0x1FFFFFFF))
|
||||
{
|
||||
if (p == m_pCurrBlock)
|
||||
move = true;
|
||||
p = p->m_pNext;
|
||||
if (move)
|
||||
m_pCurrBlock = p;
|
||||
msglen ++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
*data = p->m_pcData;
|
||||
int readlen = p->m_iLength;
|
||||
msgno = p->m_iMsgNo;
|
||||
|
||||
return readlen;
|
||||
}
|
||||
|
||||
void CSndBuffer::ackData(int offset)
|
||||
{
|
||||
CGuard bufferguard(m_BufLock);
|
||||
|
||||
for (int i = 0; i < offset; ++ i)
|
||||
m_pFirstBlock = m_pFirstBlock->m_pNext;
|
||||
|
||||
m_iCount -= offset;
|
||||
|
||||
CTimer::triggerEvent();
|
||||
}
|
||||
|
||||
int CSndBuffer::getCurrBufSize() const
|
||||
{
|
||||
return m_iCount;
|
||||
}
|
||||
|
||||
void CSndBuffer::increase()
|
||||
{
|
||||
int unitsize = m_pBuffer->m_iSize;
|
||||
|
||||
// new physical buffer
|
||||
Buffer* nbuf = NULL;
|
||||
try
|
||||
{
|
||||
nbuf = new Buffer;
|
||||
nbuf->m_pcData = new char [unitsize * m_iMSS];
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete nbuf;
|
||||
throw CUDTException(3, 2, 0);
|
||||
}
|
||||
nbuf->m_iSize = unitsize;
|
||||
nbuf->m_pNext = NULL;
|
||||
|
||||
// insert the buffer at the end of the buffer list
|
||||
Buffer* p = m_pBuffer;
|
||||
while (NULL != p->m_pNext)
|
||||
p = p->m_pNext;
|
||||
p->m_pNext = nbuf;
|
||||
|
||||
// new packet blocks
|
||||
Block* nblk = NULL;
|
||||
try
|
||||
{
|
||||
nblk = new Block;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete nblk;
|
||||
throw CUDTException(3, 2, 0);
|
||||
}
|
||||
Block* pb = nblk;
|
||||
for (int i = 1; i < unitsize; ++ i)
|
||||
{
|
||||
pb->m_pNext = new Block;
|
||||
pb = pb->m_pNext;
|
||||
}
|
||||
|
||||
// insert the new blocks onto the existing one
|
||||
pb->m_pNext = m_pLastBlock->m_pNext;
|
||||
m_pLastBlock->m_pNext = nblk;
|
||||
|
||||
pb = nblk;
|
||||
char* pc = nbuf->m_pcData;
|
||||
for (int i = 0; i < unitsize; ++ i)
|
||||
{
|
||||
pb->m_pcData = pc;
|
||||
pb = pb->m_pNext;
|
||||
pc += m_iMSS;
|
||||
}
|
||||
|
||||
m_iSize += unitsize;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CRcvBuffer::CRcvBuffer(CUnitQueue* queue, int bufsize):
|
||||
m_pUnit(NULL),
|
||||
m_iSize(bufsize),
|
||||
m_pUnitQueue(queue),
|
||||
m_iStartPos(0),
|
||||
m_iLastAckPos(0),
|
||||
m_iMaxPos(0),
|
||||
m_iNotch(0)
|
||||
{
|
||||
m_pUnit = new CUnit* [m_iSize];
|
||||
for (int i = 0; i < m_iSize; ++ i)
|
||||
m_pUnit[i] = NULL;
|
||||
}
|
||||
|
||||
CRcvBuffer::~CRcvBuffer()
|
||||
{
|
||||
for (int i = 0; i < m_iSize; ++ i)
|
||||
{
|
||||
if (NULL != m_pUnit[i])
|
||||
{
|
||||
m_pUnit[i]->m_iFlag = 0;
|
||||
-- m_pUnitQueue->m_iCount;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] m_pUnit;
|
||||
}
|
||||
|
||||
int CRcvBuffer::addData(CUnit* unit, int offset)
|
||||
{
|
||||
int pos = (m_iLastAckPos + offset) % m_iSize;
|
||||
if (offset > m_iMaxPos)
|
||||
m_iMaxPos = offset;
|
||||
|
||||
if (NULL != m_pUnit[pos])
|
||||
return -1;
|
||||
|
||||
m_pUnit[pos] = unit;
|
||||
|
||||
unit->m_iFlag = 1;
|
||||
++ m_pUnitQueue->m_iCount;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CRcvBuffer::readBuffer(char* data, int len)
|
||||
{
|
||||
int p = m_iStartPos;
|
||||
int lastack = m_iLastAckPos;
|
||||
int rs = len;
|
||||
|
||||
while ((p != lastack) && (rs > 0))
|
||||
{
|
||||
int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch;
|
||||
if (unitsize > rs)
|
||||
unitsize = rs;
|
||||
|
||||
memcpy(data, m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize);
|
||||
data += unitsize;
|
||||
|
||||
if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch))
|
||||
{
|
||||
CUnit* tmp = m_pUnit[p];
|
||||
m_pUnit[p] = NULL;
|
||||
tmp->m_iFlag = 0;
|
||||
-- m_pUnitQueue->m_iCount;
|
||||
|
||||
if (++ p == m_iSize)
|
||||
p = 0;
|
||||
|
||||
m_iNotch = 0;
|
||||
}
|
||||
else
|
||||
m_iNotch += rs;
|
||||
|
||||
rs -= unitsize;
|
||||
}
|
||||
|
||||
m_iStartPos = p;
|
||||
return len - rs;
|
||||
}
|
||||
|
||||
int CRcvBuffer::readBufferToFile(fstream& ofs, int len)
|
||||
{
|
||||
int p = m_iStartPos;
|
||||
int lastack = m_iLastAckPos;
|
||||
int rs = len;
|
||||
|
||||
while ((p != lastack) && (rs > 0))
|
||||
{
|
||||
int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch;
|
||||
if (unitsize > rs)
|
||||
unitsize = rs;
|
||||
|
||||
ofs.write(m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize);
|
||||
if (ofs.fail())
|
||||
break;
|
||||
|
||||
if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch))
|
||||
{
|
||||
CUnit* tmp = m_pUnit[p];
|
||||
m_pUnit[p] = NULL;
|
||||
tmp->m_iFlag = 0;
|
||||
-- m_pUnitQueue->m_iCount;
|
||||
|
||||
if (++ p == m_iSize)
|
||||
p = 0;
|
||||
|
||||
m_iNotch = 0;
|
||||
}
|
||||
else
|
||||
m_iNotch += rs;
|
||||
|
||||
rs -= unitsize;
|
||||
}
|
||||
|
||||
m_iStartPos = p;
|
||||
|
||||
return len - rs;
|
||||
}
|
||||
|
||||
void CRcvBuffer::ackData(int len)
|
||||
{
|
||||
m_iLastAckPos = (m_iLastAckPos + len) % m_iSize;
|
||||
m_iMaxPos -= len;
|
||||
if (m_iMaxPos < 0)
|
||||
m_iMaxPos = 0;
|
||||
|
||||
CTimer::triggerEvent();
|
||||
}
|
||||
|
||||
int CRcvBuffer::getAvailBufSize() const
|
||||
{
|
||||
// One slot must be empty in order to tell the difference between "empty buffer" and "full buffer"
|
||||
return m_iSize - getRcvDataSize() - 1;
|
||||
}
|
||||
|
||||
int CRcvBuffer::getRcvDataSize() const
|
||||
{
|
||||
if (m_iLastAckPos >= m_iStartPos)
|
||||
return m_iLastAckPos - m_iStartPos;
|
||||
|
||||
return m_iSize + m_iLastAckPos - m_iStartPos;
|
||||
}
|
||||
|
||||
void CRcvBuffer::dropMsg(int32_t msgno)
|
||||
{
|
||||
for (int i = m_iStartPos, n = (m_iLastAckPos + m_iMaxPos) % m_iSize; i != n; i = (i + 1) % m_iSize)
|
||||
if ((NULL != m_pUnit[i]) && (msgno == m_pUnit[i]->m_Packet.m_iMsgNo))
|
||||
m_pUnit[i]->m_iFlag = 3;
|
||||
}
|
||||
|
||||
int CRcvBuffer::readMsg(char* data, int len)
|
||||
{
|
||||
int p, q;
|
||||
bool passack;
|
||||
if (!scanMsg(p, q, passack))
|
||||
return 0;
|
||||
|
||||
int rs = len;
|
||||
while (p != (q + 1) % m_iSize)
|
||||
{
|
||||
int unitsize = m_pUnit[p]->m_Packet.getLength();
|
||||
if ((rs >= 0) && (unitsize > rs))
|
||||
unitsize = rs;
|
||||
|
||||
if (unitsize > 0)
|
||||
{
|
||||
memcpy(data, m_pUnit[p]->m_Packet.m_pcData, unitsize);
|
||||
data += unitsize;
|
||||
rs -= unitsize;
|
||||
}
|
||||
|
||||
if (!passack)
|
||||
{
|
||||
CUnit* tmp = m_pUnit[p];
|
||||
m_pUnit[p] = NULL;
|
||||
tmp->m_iFlag = 0;
|
||||
-- m_pUnitQueue->m_iCount;
|
||||
}
|
||||
else
|
||||
m_pUnit[p]->m_iFlag = 2;
|
||||
|
||||
if (++ p == m_iSize)
|
||||
p = 0;
|
||||
}
|
||||
|
||||
if (!passack)
|
||||
m_iStartPos = (q + 1) % m_iSize;
|
||||
|
||||
return len - rs;
|
||||
}
|
||||
|
||||
int CRcvBuffer::getRcvMsgNum()
|
||||
{
|
||||
int p, q;
|
||||
bool passack;
|
||||
return scanMsg(p, q, passack) ? 1 : 0;
|
||||
}
|
||||
|
||||
bool CRcvBuffer::scanMsg(int& p, int& q, bool& passack)
|
||||
{
|
||||
// empty buffer
|
||||
if ((m_iStartPos == m_iLastAckPos) && (m_iMaxPos <= 0))
|
||||
return false;
|
||||
|
||||
//skip all bad msgs at the beginning
|
||||
while (m_iStartPos != m_iLastAckPos)
|
||||
{
|
||||
if (NULL == m_pUnit[m_iStartPos])
|
||||
{
|
||||
if (++ m_iStartPos == m_iSize)
|
||||
m_iStartPos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((1 == m_pUnit[m_iStartPos]->m_iFlag) && (m_pUnit[m_iStartPos]->m_Packet.getMsgBoundary() > 1))
|
||||
{
|
||||
bool good = true;
|
||||
|
||||
// look ahead for the whole message
|
||||
for (int i = m_iStartPos; i != m_iLastAckPos;)
|
||||
{
|
||||
if ((NULL == m_pUnit[i]) || (1 != m_pUnit[i]->m_iFlag))
|
||||
{
|
||||
good = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((m_pUnit[i]->m_Packet.getMsgBoundary() == 1) || (m_pUnit[i]->m_Packet.getMsgBoundary() == 3))
|
||||
break;
|
||||
|
||||
if (++ i == m_iSize)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (good)
|
||||
break;
|
||||
}
|
||||
|
||||
CUnit* tmp = m_pUnit[m_iStartPos];
|
||||
m_pUnit[m_iStartPos] = NULL;
|
||||
tmp->m_iFlag = 0;
|
||||
-- m_pUnitQueue->m_iCount;
|
||||
|
||||
if (++ m_iStartPos == m_iSize)
|
||||
m_iStartPos = 0;
|
||||
}
|
||||
|
||||
p = -1; // message head
|
||||
q = m_iStartPos; // message tail
|
||||
passack = m_iStartPos == m_iLastAckPos;
|
||||
bool found = false;
|
||||
|
||||
// looking for the first message
|
||||
for (int i = 0, n = m_iMaxPos + getRcvDataSize(); i <= n; ++ i)
|
||||
{
|
||||
if ((NULL != m_pUnit[q]) && (1 == m_pUnit[q]->m_iFlag))
|
||||
{
|
||||
switch (m_pUnit[q]->m_Packet.getMsgBoundary())
|
||||
{
|
||||
case 3: // 11
|
||||
p = q;
|
||||
found = true;
|
||||
break;
|
||||
|
||||
case 2: // 10
|
||||
p = q;
|
||||
break;
|
||||
|
||||
case 1: // 01
|
||||
if (p != -1)
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// a hole in this message, not valid, restart search
|
||||
p = -1;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
// the msg has to be ack'ed or it is allowed to read out of order, and was not read before
|
||||
if (!passack || !m_pUnit[q]->m_Packet.getMsgOrderFlag())
|
||||
break;
|
||||
|
||||
found = false;
|
||||
}
|
||||
|
||||
if (++ q == m_iSize)
|
||||
q = 0;
|
||||
|
||||
if (q == m_iLastAckPos)
|
||||
passack = true;
|
||||
}
|
||||
|
||||
// no msg found
|
||||
if (!found)
|
||||
{
|
||||
// if the message is larger than the receiver buffer, return part of the message
|
||||
if ((p != -1) && ((q + 1) % m_iSize == p))
|
||||
found = true;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
275
vendor/udt4/src/buffer.h
vendored
275
vendor/udt4/src/buffer.h
vendored
|
|
@ -1,275 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 05/05/2009
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_BUFFER_H__
|
||||
#define __UDT_BUFFER_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "list.h"
|
||||
#include "queue.h"
|
||||
#include <fstream>
|
||||
|
||||
class CSndBuffer
|
||||
{
|
||||
public:
|
||||
CSndBuffer(int size = 32, int mss = 1500);
|
||||
~CSndBuffer();
|
||||
|
||||
// Functionality:
|
||||
// Insert a user buffer into the sending list.
|
||||
// Parameters:
|
||||
// 0) [in] data: pointer to the user data block.
|
||||
// 1) [in] len: size of the block.
|
||||
// 2) [in] ttl: time to live in milliseconds
|
||||
// 3) [in] order: if the block should be delivered in order, for DGRAM only
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void addBuffer(const char* data, int len, int ttl = -1, bool order = false);
|
||||
|
||||
// Functionality:
|
||||
// Read a block of data from file and insert it into the sending list.
|
||||
// Parameters:
|
||||
// 0) [in] ifs: input file stream.
|
||||
// 1) [in] len: size of the block.
|
||||
// Returned value:
|
||||
// actual size of data added from the file.
|
||||
|
||||
int addBufferFromFile(std::fstream& ifs, int len);
|
||||
|
||||
// Functionality:
|
||||
// Find data position to pack a DATA packet from the furthest reading point.
|
||||
// Parameters:
|
||||
// 0) [out] data: the pointer to the data position.
|
||||
// 1) [out] msgno: message number of the packet.
|
||||
// Returned value:
|
||||
// Actual length of data read.
|
||||
|
||||
int readData(char** data, int32_t& msgno);
|
||||
|
||||
// Functionality:
|
||||
// Find data position to pack a DATA packet for a retransmission.
|
||||
// Parameters:
|
||||
// 0) [out] data: the pointer to the data position.
|
||||
// 1) [in] offset: offset from the last ACK point.
|
||||
// 2) [out] msgno: message number of the packet.
|
||||
// 3) [out] msglen: length of the message
|
||||
// Returned value:
|
||||
// Actual length of data read.
|
||||
|
||||
int readData(char** data, const int offset, int32_t& msgno, int& msglen);
|
||||
|
||||
// Functionality:
|
||||
// Update the ACK point and may release/unmap/return the user data according to the flag.
|
||||
// Parameters:
|
||||
// 0) [in] offset: number of packets acknowledged.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void ackData(int offset);
|
||||
|
||||
// Functionality:
|
||||
// Read size of data still in the sending list.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Current size of the data in the sending list.
|
||||
|
||||
int getCurrBufSize() const;
|
||||
|
||||
private:
|
||||
void increase();
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_BufLock; // used to synchronize buffer operation
|
||||
|
||||
struct Block
|
||||
{
|
||||
char* m_pcData; // pointer to the data block
|
||||
int m_iLength; // length of the block
|
||||
|
||||
int32_t m_iMsgNo; // message number
|
||||
uint64_t m_OriginTime; // original request time
|
||||
int m_iTTL; // time to live (milliseconds)
|
||||
|
||||
Block* m_pNext; // next block
|
||||
} *m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock;
|
||||
|
||||
// m_pBlock: The head pointer
|
||||
// m_pFirstBlock: The first block
|
||||
// m_pCurrBlock: The current block
|
||||
// m_pLastBlock: The last block (if first == last, buffer is empty)
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
char* m_pcData; // buffer
|
||||
int m_iSize; // size
|
||||
Buffer* m_pNext; // next buffer
|
||||
} *m_pBuffer; // physical buffer
|
||||
|
||||
int32_t m_iNextMsgNo; // next message number
|
||||
|
||||
int m_iSize; // buffer size (number of packets)
|
||||
int m_iMSS; // maximum seqment/packet size
|
||||
|
||||
int m_iCount; // number of used blocks
|
||||
|
||||
private:
|
||||
CSndBuffer(const CSndBuffer&);
|
||||
CSndBuffer& operator=(const CSndBuffer&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CRcvBuffer
|
||||
{
|
||||
public:
|
||||
CRcvBuffer(CUnitQueue* queue, int bufsize = 65536);
|
||||
~CRcvBuffer();
|
||||
|
||||
// Functionality:
|
||||
// Write data into the buffer.
|
||||
// Parameters:
|
||||
// 0) [in] unit: pointer to a data unit containing new packet
|
||||
// 1) [in] offset: offset from last ACK point.
|
||||
// Returned value:
|
||||
// 0 is success, -1 if data is repeated.
|
||||
|
||||
int addData(CUnit* unit, int offset);
|
||||
|
||||
// Functionality:
|
||||
// Read data into a user buffer.
|
||||
// Parameters:
|
||||
// 0) [in] data: pointer to user buffer.
|
||||
// 1) [in] len: length of user buffer.
|
||||
// Returned value:
|
||||
// size of data read.
|
||||
|
||||
int readBuffer(char* data, int len);
|
||||
|
||||
// Functionality:
|
||||
// Read data directly into file.
|
||||
// Parameters:
|
||||
// 0) [in] file: C++ file stream.
|
||||
// 1) [in] len: expected length of data to write into the file.
|
||||
// Returned value:
|
||||
// size of data read.
|
||||
|
||||
int readBufferToFile(std::fstream& ofs, int len);
|
||||
|
||||
// Functionality:
|
||||
// Update the ACK point of the buffer.
|
||||
// Parameters:
|
||||
// 0) [in] len: size of data to be acknowledged.
|
||||
// Returned value:
|
||||
// 1 if a user buffer is fulfilled, otherwise 0.
|
||||
|
||||
void ackData(int len);
|
||||
|
||||
// Functionality:
|
||||
// Query how many buffer space left for data receiving.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// size of available buffer space (including user buffer) for data receiving.
|
||||
|
||||
int getAvailBufSize() const;
|
||||
|
||||
// Functionality:
|
||||
// Query how many data has been continuously received (for reading).
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// size of valid (continous) data for reading.
|
||||
|
||||
int getRcvDataSize() const;
|
||||
|
||||
// Functionality:
|
||||
// mark the message to be dropped from the message list.
|
||||
// Parameters:
|
||||
// 0) [in] msgno: message nuumer.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void dropMsg(int32_t msgno);
|
||||
|
||||
// Functionality:
|
||||
// read a message.
|
||||
// Parameters:
|
||||
// 0) [out] data: buffer to write the message into.
|
||||
// 1) [in] len: size of the buffer.
|
||||
// Returned value:
|
||||
// actuall size of data read.
|
||||
|
||||
int readMsg(char* data, int len);
|
||||
|
||||
// Functionality:
|
||||
// Query how many messages are available now.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// number of messages available for recvmsg.
|
||||
|
||||
int getRcvMsgNum();
|
||||
|
||||
private:
|
||||
bool scanMsg(int& start, int& end, bool& passack);
|
||||
|
||||
private:
|
||||
CUnit** m_pUnit; // pointer to the protocol buffer
|
||||
int m_iSize; // size of the protocol buffer
|
||||
CUnitQueue* m_pUnitQueue; // the shared unit queue
|
||||
|
||||
int m_iStartPos; // the head position for I/O (inclusive)
|
||||
int m_iLastAckPos; // the last ACKed position (exclusive)
|
||||
// EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1
|
||||
int m_iMaxPos; // the furthest data position
|
||||
|
||||
int m_iNotch; // the starting read point of the first unit
|
||||
|
||||
private:
|
||||
CRcvBuffer();
|
||||
CRcvBuffer(const CRcvBuffer&);
|
||||
CRcvBuffer& operator=(const CRcvBuffer&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
123
vendor/udt4/src/cache.cpp
vendored
123
vendor/udt4/src/cache.cpp
vendored
|
|
@ -1,123 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 05/05/2009
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#ifdef LEGACY_WIN32
|
||||
#include <wspiapi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include "cache.h"
|
||||
#include "core.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj)
|
||||
{
|
||||
std::copy(obj.m_piIP, obj.m_piIP + 3, m_piIP);
|
||||
m_iIPversion = obj.m_iIPversion;
|
||||
m_ullTimeStamp = obj.m_ullTimeStamp;
|
||||
m_iRTT = obj.m_iRTT;
|
||||
m_iBandwidth = obj.m_iBandwidth;
|
||||
m_iLossRate = obj.m_iLossRate;
|
||||
m_iReorderDistance = obj.m_iReorderDistance;
|
||||
m_dInterval = obj.m_dInterval;
|
||||
m_dCWnd = obj.m_dCWnd;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CInfoBlock::operator==(const CInfoBlock& obj)
|
||||
{
|
||||
if (m_iIPversion != obj.m_iIPversion)
|
||||
return false;
|
||||
|
||||
else if (m_iIPversion == AF_INET)
|
||||
return (m_piIP[0] == obj.m_piIP[0]);
|
||||
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
{
|
||||
if (m_piIP[i] != obj.m_piIP[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CInfoBlock* CInfoBlock::clone()
|
||||
{
|
||||
CInfoBlock* obj = new CInfoBlock;
|
||||
|
||||
std::copy(m_piIP, m_piIP + 3, obj->m_piIP);
|
||||
obj->m_iIPversion = m_iIPversion;
|
||||
obj->m_ullTimeStamp = m_ullTimeStamp;
|
||||
obj->m_iRTT = m_iRTT;
|
||||
obj->m_iBandwidth = m_iBandwidth;
|
||||
obj->m_iLossRate = m_iLossRate;
|
||||
obj->m_iReorderDistance = m_iReorderDistance;
|
||||
obj->m_dInterval = m_dInterval;
|
||||
obj->m_dCWnd = m_dCWnd;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
int CInfoBlock::getKey()
|
||||
{
|
||||
if (m_iIPversion == AF_INET)
|
||||
return m_piIP[0];
|
||||
|
||||
return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3];
|
||||
}
|
||||
|
||||
void CInfoBlock::convert(const sockaddr* addr, int ver, uint32_t ip[])
|
||||
{
|
||||
if (ver == AF_INET)
|
||||
{
|
||||
ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr;
|
||||
ip[1] = ip[2] = ip[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16);
|
||||
}
|
||||
}
|
||||
293
vendor/udt4/src/cache.h
vendored
293
vendor/udt4/src/cache.h
vendored
|
|
@ -1,293 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/27/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_CACHE_H__
|
||||
#define __UDT_CACHE_H__
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
#include "udt.h"
|
||||
|
||||
class CCacheItem
|
||||
{
|
||||
public:
|
||||
virtual ~CCacheItem() {}
|
||||
|
||||
public:
|
||||
virtual CCacheItem& operator=(const CCacheItem&) = 0;
|
||||
|
||||
// The "==" operator SHOULD only compare key values.
|
||||
virtual bool operator==(const CCacheItem&) = 0;
|
||||
|
||||
// Functionality:
|
||||
// get a deep copy clone of the current item
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Pointer to the new item, or NULL if failed.
|
||||
|
||||
virtual CCacheItem* clone() = 0;
|
||||
|
||||
// Functionality:
|
||||
// get a random key value between 0 and MAX_INT to be used for the hash in cache
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// A random hash key.
|
||||
|
||||
virtual int getKey() = 0;
|
||||
|
||||
// If there is any shared resources between the cache item and its clone,
|
||||
// the shared resource should be released by this function.
|
||||
virtual void release() {}
|
||||
};
|
||||
|
||||
template<typename T> class CCache
|
||||
{
|
||||
public:
|
||||
CCache(int size = 1024):
|
||||
m_iMaxSize(size),
|
||||
m_iHashSize(size * 3),
|
||||
m_iCurrSize(0)
|
||||
{
|
||||
m_vHashPtr.resize(m_iHashSize);
|
||||
CGuard::createMutex(m_Lock);
|
||||
}
|
||||
|
||||
~CCache()
|
||||
{
|
||||
clear();
|
||||
CGuard::releaseMutex(m_Lock);
|
||||
}
|
||||
|
||||
public:
|
||||
// Functionality:
|
||||
// find the matching item in the cache.
|
||||
// Parameters:
|
||||
// 0) [in/out] data: storage for the retrieved item; initially it must carry the key information
|
||||
// Returned value:
|
||||
// 0 if found a match, otherwise -1.
|
||||
|
||||
int lookup(T* data)
|
||||
{
|
||||
CGuard cacheguard(m_Lock);
|
||||
|
||||
int key = data->getKey();
|
||||
if (key < 0)
|
||||
return -1;
|
||||
if (key >= m_iMaxSize)
|
||||
key %= m_iHashSize;
|
||||
|
||||
const ItemPtrList& item_list = m_vHashPtr[key];
|
||||
for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i)
|
||||
{
|
||||
if (*data == ***i)
|
||||
{
|
||||
// copy the cached info
|
||||
*data = ***i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Functionality:
|
||||
// update an item in the cache, or insert one if it doesn't exist; oldest item may be removed
|
||||
// Parameters:
|
||||
// 0) [in] data: the new item to updated/inserted to the cache
|
||||
// Returned value:
|
||||
// 0 if success, otherwise -1.
|
||||
|
||||
int update(T* data)
|
||||
{
|
||||
CGuard cacheguard(m_Lock);
|
||||
|
||||
int key = data->getKey();
|
||||
if (key < 0)
|
||||
return -1;
|
||||
if (key >= m_iMaxSize)
|
||||
key %= m_iHashSize;
|
||||
|
||||
T* curr = NULL;
|
||||
|
||||
ItemPtrList& item_list = m_vHashPtr[key];
|
||||
for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
|
||||
{
|
||||
if (*data == ***i)
|
||||
{
|
||||
// update the existing entry with the new value
|
||||
***i = *data;
|
||||
curr = **i;
|
||||
|
||||
// remove the current entry
|
||||
m_StorageList.erase(*i);
|
||||
item_list.erase(i);
|
||||
|
||||
// re-insert to the front
|
||||
m_StorageList.push_front(curr);
|
||||
item_list.push_front(m_StorageList.begin());
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// create new entry and insert to front
|
||||
curr = data->clone();
|
||||
m_StorageList.push_front(curr);
|
||||
item_list.push_front(m_StorageList.begin());
|
||||
|
||||
++ m_iCurrSize;
|
||||
if (m_iCurrSize >= m_iMaxSize)
|
||||
{
|
||||
// Cache overflow, remove oldest entry.
|
||||
T* last_data = m_StorageList.back();
|
||||
int last_key = last_data->getKey() % m_iHashSize;
|
||||
|
||||
item_list = m_vHashPtr[last_key];
|
||||
for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
|
||||
{
|
||||
if (*last_data == ***i)
|
||||
{
|
||||
item_list.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last_data->release();
|
||||
delete last_data;
|
||||
m_StorageList.pop_back();
|
||||
-- m_iCurrSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Functionality:
|
||||
// Specify the cache size (i.e., max number of items).
|
||||
// Parameters:
|
||||
// 0) [in] size: max cache size.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setSizeLimit(int size)
|
||||
{
|
||||
m_iMaxSize = size;
|
||||
m_iHashSize = size * 3;
|
||||
m_vHashPtr.resize(m_iHashSize);
|
||||
}
|
||||
|
||||
// Functionality:
|
||||
// Clear all entries in the cache, restore to initialization state.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (typename std::list<T*>::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i)
|
||||
{
|
||||
(*i)->release();
|
||||
delete *i;
|
||||
}
|
||||
m_StorageList.clear();
|
||||
for (typename std::vector<ItemPtrList>::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i)
|
||||
i->clear();
|
||||
m_iCurrSize = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<T*> m_StorageList;
|
||||
typedef typename std::list<T*>::iterator ItemPtr;
|
||||
typedef std::list<ItemPtr> ItemPtrList;
|
||||
std::vector<ItemPtrList> m_vHashPtr;
|
||||
|
||||
int m_iMaxSize;
|
||||
int m_iHashSize;
|
||||
int m_iCurrSize;
|
||||
|
||||
pthread_mutex_t m_Lock;
|
||||
|
||||
private:
|
||||
CCache(const CCache&);
|
||||
CCache& operator=(const CCache&);
|
||||
};
|
||||
|
||||
|
||||
class CInfoBlock
|
||||
{
|
||||
public:
|
||||
uint32_t m_piIP[4]; // IP address, machine read only, not human readable format
|
||||
int m_iIPversion; // IP version
|
||||
uint64_t m_ullTimeStamp; // last update time
|
||||
int m_iRTT; // RTT
|
||||
int m_iBandwidth; // estimated bandwidth
|
||||
int m_iLossRate; // average loss rate
|
||||
int m_iReorderDistance; // packet reordering distance
|
||||
double m_dInterval; // inter-packet time, congestion control
|
||||
double m_dCWnd; // congestion window size, congestion control
|
||||
|
||||
public:
|
||||
virtual ~CInfoBlock() {}
|
||||
virtual CInfoBlock& operator=(const CInfoBlock& obj);
|
||||
virtual bool operator==(const CInfoBlock& obj);
|
||||
virtual CInfoBlock* clone();
|
||||
virtual int getKey();
|
||||
virtual void release() {}
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// convert sockaddr structure to an integer array
|
||||
// Parameters:
|
||||
// 0) [in] addr: network address
|
||||
// 1) [in] ver: IP version
|
||||
// 2) [out] ip: the result machine readable IP address in integer array
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
static void convert(const sockaddr* addr, int ver, uint32_t ip[]);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
314
vendor/udt4/src/ccc.cpp
vendored
314
vendor/udt4/src/ccc.cpp
vendored
|
|
@ -1,314 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 02/21/2013
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "core.h"
|
||||
#include "ccc.h"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
CCC::CCC():
|
||||
m_iSYNInterval(CUDT::m_iSYNInterval),
|
||||
m_dPktSndPeriod(1.0),
|
||||
m_dCWndSize(16.0),
|
||||
m_iBandwidth(),
|
||||
m_dMaxCWndSize(),
|
||||
m_iMSS(),
|
||||
m_iSndCurrSeqNo(),
|
||||
m_iRcvRate(),
|
||||
m_iRTT(),
|
||||
m_pcParam(NULL),
|
||||
m_iPSize(0),
|
||||
m_UDT(),
|
||||
m_iACKPeriod(0),
|
||||
m_iACKInterval(0),
|
||||
m_bUserDefinedRTO(false),
|
||||
m_iRTO(-1),
|
||||
m_PerfInfo()
|
||||
{
|
||||
}
|
||||
|
||||
CCC::~CCC()
|
||||
{
|
||||
delete [] m_pcParam;
|
||||
}
|
||||
|
||||
void CCC::setACKTimer(int msINT)
|
||||
{
|
||||
m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT;
|
||||
}
|
||||
|
||||
void CCC::setACKInterval(int pktINT)
|
||||
{
|
||||
m_iACKInterval = pktINT;
|
||||
}
|
||||
|
||||
void CCC::setRTO(int usRTO)
|
||||
{
|
||||
m_bUserDefinedRTO = true;
|
||||
m_iRTO = usRTO;
|
||||
}
|
||||
|
||||
void CCC::sendCustomMsg(CPacket& pkt) const
|
||||
{
|
||||
CUDT* u = CUDT::getUDTHandle(m_UDT);
|
||||
|
||||
if (NULL != u)
|
||||
{
|
||||
pkt.m_iID = u->m_PeerID;
|
||||
u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
const CPerfMon* CCC::getPerfInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
CUDT* u = CUDT::getUDTHandle(m_UDT);
|
||||
if (NULL != u)
|
||||
u->sample(&m_PerfInfo, false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &m_PerfInfo;
|
||||
}
|
||||
|
||||
void CCC::setMSS(int mss)
|
||||
{
|
||||
m_iMSS = mss;
|
||||
}
|
||||
|
||||
void CCC::setBandwidth(int bw)
|
||||
{
|
||||
m_iBandwidth = bw;
|
||||
}
|
||||
|
||||
void CCC::setSndCurrSeqNo(int32_t seqno)
|
||||
{
|
||||
m_iSndCurrSeqNo = seqno;
|
||||
}
|
||||
|
||||
void CCC::setRcvRate(int rcvrate)
|
||||
{
|
||||
m_iRcvRate = rcvrate;
|
||||
}
|
||||
|
||||
void CCC::setMaxCWndSize(int cwnd)
|
||||
{
|
||||
m_dMaxCWndSize = cwnd;
|
||||
}
|
||||
|
||||
void CCC::setRTT(int rtt)
|
||||
{
|
||||
m_iRTT = rtt;
|
||||
}
|
||||
|
||||
void CCC::setUserParam(const char* param, int size)
|
||||
{
|
||||
delete [] m_pcParam;
|
||||
m_pcParam = new char[size];
|
||||
memcpy(m_pcParam, param, size);
|
||||
m_iPSize = size;
|
||||
}
|
||||
|
||||
//
|
||||
CUDTCC::CUDTCC():
|
||||
m_iRCInterval(),
|
||||
m_LastRCTime(),
|
||||
m_bSlowStart(),
|
||||
m_iLastAck(),
|
||||
m_bLoss(),
|
||||
m_iLastDecSeq(),
|
||||
m_dLastDecPeriod(),
|
||||
m_iNAKCount(),
|
||||
m_iDecRandom(),
|
||||
m_iAvgNAKNum(),
|
||||
m_iDecCount()
|
||||
{
|
||||
}
|
||||
|
||||
void CUDTCC::init()
|
||||
{
|
||||
m_iRCInterval = m_iSYNInterval;
|
||||
m_LastRCTime = CTimer::getTime();
|
||||
setACKTimer(m_iRCInterval);
|
||||
|
||||
m_bSlowStart = true;
|
||||
m_iLastAck = m_iSndCurrSeqNo;
|
||||
m_bLoss = false;
|
||||
m_iLastDecSeq = CSeqNo::decseq(m_iLastAck);
|
||||
m_dLastDecPeriod = 1;
|
||||
m_iAvgNAKNum = 0;
|
||||
m_iNAKCount = 0;
|
||||
m_iDecRandom = 1;
|
||||
|
||||
m_dCWndSize = 16;
|
||||
m_dPktSndPeriod = 1;
|
||||
}
|
||||
|
||||
void CUDTCC::onACK(int32_t ack)
|
||||
{
|
||||
int64_t B = 0;
|
||||
double inc = 0;
|
||||
// Note: 1/24/2012
|
||||
// The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01
|
||||
// because the original was too small and caused sending rate to stay at low level
|
||||
// for long time.
|
||||
const double min_inc = 0.01;
|
||||
|
||||
uint64_t currtime = CTimer::getTime();
|
||||
if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval)
|
||||
return;
|
||||
|
||||
m_LastRCTime = currtime;
|
||||
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack);
|
||||
m_iLastAck = ack;
|
||||
|
||||
if (m_dCWndSize > m_dMaxCWndSize)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
else
|
||||
m_dPktSndPeriod = (m_iRTT + m_iRCInterval) / m_dCWndSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16;
|
||||
|
||||
// During Slow Start, no rate increase
|
||||
if (m_bSlowStart)
|
||||
return;
|
||||
|
||||
if (m_bLoss)
|
||||
{
|
||||
m_bLoss = false;
|
||||
return;
|
||||
}
|
||||
|
||||
B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod);
|
||||
if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B))
|
||||
B = m_iBandwidth / 9;
|
||||
if (B <= 0)
|
||||
inc = min_inc;
|
||||
else
|
||||
{
|
||||
// inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS)
|
||||
// Beta = 1.5 * 10^(-6)
|
||||
|
||||
inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS;
|
||||
|
||||
if (inc < min_inc)
|
||||
inc = min_inc;
|
||||
}
|
||||
|
||||
m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval);
|
||||
}
|
||||
|
||||
void CUDTCC::onLoss(const int32_t* losslist, int)
|
||||
{
|
||||
//Slow Start stopped, if it hasn't yet
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
{
|
||||
// Set the sending rate to the receiving rate.
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
return;
|
||||
}
|
||||
// If no receiving rate is observed, we have to compute the sending
|
||||
// rate according to the current window size, and decrease it
|
||||
// using the method below.
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
|
||||
}
|
||||
|
||||
m_bLoss = true;
|
||||
|
||||
if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0)
|
||||
{
|
||||
m_dLastDecPeriod = m_dPktSndPeriod;
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
|
||||
|
||||
m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125);
|
||||
m_iNAKCount = 1;
|
||||
m_iDecCount = 1;
|
||||
|
||||
m_iLastDecSeq = m_iSndCurrSeqNo;
|
||||
|
||||
// remove global synchronization using randomization
|
||||
srand(m_iLastDecSeq);
|
||||
m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
|
||||
if (m_iDecRandom < 1)
|
||||
m_iDecRandom = 1;
|
||||
}
|
||||
else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom)))
|
||||
{
|
||||
// 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
|
||||
m_iLastDecSeq = m_iSndCurrSeqNo;
|
||||
}
|
||||
}
|
||||
|
||||
void CUDTCC::onTimeout()
|
||||
{
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
else
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
m_dLastDecPeriod = m_dPktSndPeriod;
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2);
|
||||
m_iLastDecSeq = m_iLastAck;
|
||||
*/
|
||||
}
|
||||
}
|
||||
278
vendor/udt4/src/ccc.h
vendored
278
vendor/udt4/src/ccc.h
vendored
|
|
@ -1,278 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 02/28/2012
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __UDT_CCC_H__
|
||||
#define __UDT_CCC_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
class UDT_API CCC
|
||||
{
|
||||
friend class CUDT;
|
||||
|
||||
public:
|
||||
CCC();
|
||||
virtual ~CCC();
|
||||
|
||||
private:
|
||||
CCC(const CCC&);
|
||||
CCC& operator=(const CCC&) {return *this;}
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called (only) at the start of a UDT connection.
|
||||
// note that this is different from CCC(), which is always called.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void init() {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when a UDT connection is closed.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void close() {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when an ACK packet is received.
|
||||
// Parameters:
|
||||
// 0) [in] ackno: the data sequence number acknowledged by this ACK.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void onACK(int32_t) {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when a loss report is received.
|
||||
// Parameters:
|
||||
// 0) [in] losslist: list of sequence number of packets, in the format describled in packet.cpp.
|
||||
// 1) [in] size: length of the loss list.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void onLoss(const int32_t*, int) {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when a timeout event occurs.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void onTimeout() {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when a data is sent.
|
||||
// Parameters:
|
||||
// 0) [in] seqno: the data sequence number.
|
||||
// 1) [in] size: the payload size.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void onPktSent(const CPacket*) {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to be called when a data is received.
|
||||
// Parameters:
|
||||
// 0) [in] seqno: the data sequence number.
|
||||
// 1) [in] size: the payload size.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void onPktReceived(const CPacket*) {}
|
||||
|
||||
// Functionality:
|
||||
// Callback function to Process a user defined packet.
|
||||
// Parameters:
|
||||
// 0) [in] pkt: the user defined packet.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void processCustomMsg(const CPacket*) {}
|
||||
|
||||
protected:
|
||||
|
||||
// Functionality:
|
||||
// Set periodical acknowldging and the ACK period.
|
||||
// Parameters:
|
||||
// 0) [in] msINT: the period to send an ACK.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setACKTimer(int msINT);
|
||||
|
||||
// Functionality:
|
||||
// Set packet-based acknowldging and the number of packets to send an ACK.
|
||||
// Parameters:
|
||||
// 0) [in] pktINT: the number of packets to send an ACK.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setACKInterval(int pktINT);
|
||||
|
||||
// Functionality:
|
||||
// Set RTO value.
|
||||
// Parameters:
|
||||
// 0) [in] msRTO: RTO in macroseconds.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setRTO(int usRTO);
|
||||
|
||||
// Functionality:
|
||||
// Send a user defined control packet.
|
||||
// Parameters:
|
||||
// 0) [in] pkt: user defined packet.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void sendCustomMsg(CPacket& pkt) const;
|
||||
|
||||
// Functionality:
|
||||
// retrieve performance information.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Pointer to a performance info structure.
|
||||
|
||||
const CPerfMon* getPerfInfo();
|
||||
|
||||
// Functionality:
|
||||
// Set user defined parameters.
|
||||
// Parameters:
|
||||
// 0) [in] param: the paramters in one buffer.
|
||||
// 1) [in] size: the size of the buffer.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setUserParam(const char* param, int size);
|
||||
|
||||
private:
|
||||
void setMSS(int mss);
|
||||
void setMaxCWndSize(int cwnd);
|
||||
void setBandwidth(int bw);
|
||||
void setSndCurrSeqNo(int32_t seqno);
|
||||
void setRcvRate(int rcvrate);
|
||||
void setRTT(int rtt);
|
||||
|
||||
protected:
|
||||
const int32_t& m_iSYNInterval; // UDT constant parameter, SYN
|
||||
|
||||
double m_dPktSndPeriod; // Packet sending period, in microseconds
|
||||
double m_dCWndSize; // Congestion window size, in packets
|
||||
|
||||
int m_iBandwidth; // estimated bandwidth, packets per second
|
||||
double m_dMaxCWndSize; // maximum cwnd size, in packets
|
||||
|
||||
int m_iMSS; // Maximum Packet Size, including all packet headers
|
||||
int32_t m_iSndCurrSeqNo; // current maximum seq no sent out
|
||||
int m_iRcvRate; // packet arrive rate at receiver side, packets per second
|
||||
int m_iRTT; // current estimated RTT, microsecond
|
||||
|
||||
char* m_pcParam; // user defined parameter
|
||||
int m_iPSize; // size of m_pcParam
|
||||
|
||||
private:
|
||||
UDTSOCKET m_UDT; // The UDT entity that this congestion control algorithm is bound to
|
||||
|
||||
int m_iACKPeriod; // Periodical timer to send an ACK, in milliseconds
|
||||
int m_iACKInterval; // How many packets to send one ACK, in packets
|
||||
|
||||
bool m_bUserDefinedRTO; // if the RTO value is defined by users
|
||||
int m_iRTO; // RTO value, microseconds
|
||||
|
||||
CPerfMon m_PerfInfo; // protocol statistics information
|
||||
};
|
||||
|
||||
class CCCVirtualFactory
|
||||
{
|
||||
public:
|
||||
virtual ~CCCVirtualFactory() {}
|
||||
|
||||
virtual CCC* create() = 0;
|
||||
virtual CCCVirtualFactory* clone() = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CCCFactory: public CCCVirtualFactory
|
||||
{
|
||||
public:
|
||||
virtual ~CCCFactory() {}
|
||||
|
||||
virtual CCC* create() {return new T;}
|
||||
virtual CCCVirtualFactory* clone() {return new CCCFactory<T>;}
|
||||
};
|
||||
|
||||
class CUDTCC: public CCC
|
||||
{
|
||||
public:
|
||||
CUDTCC();
|
||||
|
||||
public:
|
||||
virtual void init();
|
||||
virtual void onACK(int32_t);
|
||||
virtual void onLoss(const int32_t*, int);
|
||||
virtual void onTimeout();
|
||||
|
||||
private:
|
||||
int m_iRCInterval; // UDT Rate control interval
|
||||
uint64_t m_LastRCTime; // last rate increase time
|
||||
bool m_bSlowStart; // if in slow start phase
|
||||
int32_t m_iLastAck; // last ACKed seq no
|
||||
bool m_bLoss; // if loss happened since last rate increase
|
||||
int32_t m_iLastDecSeq; // max pkt seq no sent out when last decrease happened
|
||||
double m_dLastDecPeriod; // value of pktsndperiod when last decrease happened
|
||||
int m_iNAKCount; // NAK counter
|
||||
int m_iDecRandom; // random threshold on decrease by number of loss events
|
||||
int m_iAvgNAKNum; // average number of NAKs per congestion
|
||||
int m_iDecCount; // number of decreases in a congestion epoch
|
||||
};
|
||||
|
||||
#endif
|
||||
340
vendor/udt4/src/channel.cpp
vendored
340
vendor/udt4/src/channel.cpp
vendored
|
|
@ -1,340 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/27/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#ifdef LEGACY_WIN32
|
||||
#include <wspiapi.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "channel.h"
|
||||
#include "packet.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define socklen_t int
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#define NET_ERROR errno
|
||||
#else
|
||||
#define NET_ERROR WSAGetLastError()
|
||||
#endif
|
||||
|
||||
|
||||
CChannel::CChannel():
|
||||
m_iIPversion(AF_INET),
|
||||
m_iSockAddrSize(sizeof(sockaddr_in)),
|
||||
m_iSocket(),
|
||||
m_iSndBufSize(65536),
|
||||
m_iRcvBufSize(65536)
|
||||
{
|
||||
}
|
||||
|
||||
CChannel::CChannel(int version):
|
||||
m_iIPversion(version),
|
||||
m_iSocket(),
|
||||
m_iSndBufSize(65536),
|
||||
m_iRcvBufSize(65536)
|
||||
{
|
||||
m_iSockAddrSize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
|
||||
}
|
||||
|
||||
CChannel::~CChannel()
|
||||
{
|
||||
}
|
||||
|
||||
void CChannel::open(const sockaddr* addr)
|
||||
{
|
||||
// construct an socket
|
||||
m_iSocket = ::socket(m_iIPversion, SOCK_DGRAM, 0);
|
||||
|
||||
#ifdef WIN32
|
||||
if (INVALID_SOCKET == m_iSocket)
|
||||
#else
|
||||
if (m_iSocket < 0)
|
||||
#endif
|
||||
throw CUDTException(1, 0, NET_ERROR);
|
||||
|
||||
if (NULL != addr)
|
||||
{
|
||||
socklen_t namelen = m_iSockAddrSize;
|
||||
|
||||
if (0 != ::bind(m_iSocket, addr, namelen))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sendto or WSASendTo will also automatically bind the socket
|
||||
addrinfo hints;
|
||||
addrinfo* res;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = m_iIPversion;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
|
||||
if (0 != ::getaddrinfo(NULL, "0", &hints, &res))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
|
||||
if (0 != ::bind(m_iSocket, res->ai_addr, res->ai_addrlen))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
|
||||
::freeaddrinfo(res);
|
||||
}
|
||||
|
||||
setUDPSockOpt();
|
||||
}
|
||||
|
||||
void CChannel::open(UDPSOCKET udpsock)
|
||||
{
|
||||
m_iSocket = udpsock;
|
||||
setUDPSockOpt();
|
||||
}
|
||||
|
||||
void CChannel::setUDPSockOpt()
|
||||
{
|
||||
#if defined(BSD) || defined(OSX)
|
||||
// BSD system will fail setsockopt if the requested buffer size exceeds system maximum value
|
||||
int maxsize = 64000;
|
||||
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int)))
|
||||
::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&maxsize, sizeof(int));
|
||||
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int)))
|
||||
::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&maxsize, sizeof(int));
|
||||
#else
|
||||
// for other systems, if requested is greated than maximum, the maximum value will be automactally used
|
||||
if ((0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) ||
|
||||
(0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int))))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
#endif
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
#if defined (BSD) || defined (OSX)
|
||||
// Known BSD bug as the day I wrote this code.
|
||||
// A small time out value will cause the socket to block forever.
|
||||
tv.tv_usec = 10000;
|
||||
#else
|
||||
tv.tv_usec = 100;
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
// Set non-blocking I/O
|
||||
// UNIX does not support SO_RCVTIMEO
|
||||
int opts = ::fcntl(m_iSocket, F_GETFL);
|
||||
if (-1 == ::fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
#elif WIN32
|
||||
DWORD ot = 1; //milliseconds
|
||||
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD)))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
#else
|
||||
// Set receiving time-out value
|
||||
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval)))
|
||||
throw CUDTException(1, 3, NET_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CChannel::close() const
|
||||
{
|
||||
#ifndef WIN32
|
||||
::close(m_iSocket);
|
||||
#else
|
||||
::closesocket(m_iSocket);
|
||||
#endif
|
||||
}
|
||||
|
||||
int CChannel::getSndBufSize()
|
||||
{
|
||||
socklen_t size = sizeof(socklen_t);
|
||||
::getsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&m_iSndBufSize, &size);
|
||||
return m_iSndBufSize;
|
||||
}
|
||||
|
||||
int CChannel::getRcvBufSize()
|
||||
{
|
||||
socklen_t size = sizeof(socklen_t);
|
||||
::getsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char *)&m_iRcvBufSize, &size);
|
||||
return m_iRcvBufSize;
|
||||
}
|
||||
|
||||
void CChannel::setSndBufSize(int size)
|
||||
{
|
||||
m_iSndBufSize = size;
|
||||
}
|
||||
|
||||
void CChannel::setRcvBufSize(int size)
|
||||
{
|
||||
m_iRcvBufSize = size;
|
||||
}
|
||||
|
||||
void CChannel::getSockAddr(sockaddr* addr) const
|
||||
{
|
||||
socklen_t namelen = m_iSockAddrSize;
|
||||
::getsockname(m_iSocket, addr, &namelen);
|
||||
}
|
||||
|
||||
void CChannel::getPeerAddr(sockaddr* addr) const
|
||||
{
|
||||
socklen_t namelen = m_iSockAddrSize;
|
||||
::getpeername(m_iSocket, addr, &namelen);
|
||||
}
|
||||
|
||||
int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
|
||||
{
|
||||
// convert control information into network order
|
||||
if (packet.getFlag())
|
||||
for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
|
||||
*((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i));
|
||||
|
||||
// convert packet header into network order
|
||||
//for (int j = 0; j < 4; ++ j)
|
||||
// packet.m_nHeader[j] = htonl(packet.m_nHeader[j]);
|
||||
uint32_t* p = packet.m_nHeader;
|
||||
for (int j = 0; j < 4; ++ j)
|
||||
{
|
||||
*p = htonl(*p);
|
||||
++ p;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
msghdr mh;
|
||||
mh.msg_name = (sockaddr*)addr;
|
||||
mh.msg_namelen = m_iSockAddrSize;
|
||||
mh.msg_iov = (iovec*)packet.m_PacketVector;
|
||||
mh.msg_iovlen = 2;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
mh.msg_flags = 0;
|
||||
|
||||
int res = ::sendmsg(m_iSocket, &mh, 0);
|
||||
#else
|
||||
DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
|
||||
int addrsize = m_iSockAddrSize;
|
||||
int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr, addrsize, NULL, NULL);
|
||||
res = (0 == res) ? size : -1;
|
||||
#endif
|
||||
|
||||
// convert back into local host order
|
||||
//for (int k = 0; k < 4; ++ k)
|
||||
// packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]);
|
||||
p = packet.m_nHeader;
|
||||
for (int k = 0; k < 4; ++ k)
|
||||
{
|
||||
*p = ntohl(*p);
|
||||
++ p;
|
||||
}
|
||||
|
||||
if (packet.getFlag())
|
||||
{
|
||||
for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
|
||||
*((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int CChannel::recvfrom(sockaddr* addr, CPacket& packet) const
|
||||
{
|
||||
#ifndef WIN32
|
||||
msghdr mh;
|
||||
mh.msg_name = addr;
|
||||
mh.msg_namelen = m_iSockAddrSize;
|
||||
mh.msg_iov = packet.m_PacketVector;
|
||||
mh.msg_iovlen = 2;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
mh.msg_flags = 0;
|
||||
|
||||
#ifdef UNIX
|
||||
fd_set set;
|
||||
timeval tv;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(m_iSocket, &set);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
::select(m_iSocket+1, &set, NULL, &set, &tv);
|
||||
#endif
|
||||
|
||||
int res = ::recvmsg(m_iSocket, &mh, 0);
|
||||
#else
|
||||
DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
|
||||
DWORD flag = 0;
|
||||
int addrsize = m_iSockAddrSize;
|
||||
|
||||
int res = ::WSARecvFrom(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, &flag, addr, &addrsize, NULL, NULL);
|
||||
res = (0 == res) ? size : -1;
|
||||
#endif
|
||||
|
||||
if (res <= 0)
|
||||
{
|
||||
packet.setLength(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
packet.setLength(res - CPacket::m_iPktHdrSize);
|
||||
|
||||
// convert back into local host order
|
||||
//for (int i = 0; i < 4; ++ i)
|
||||
// packet.m_nHeader[i] = ntohl(packet.m_nHeader[i]);
|
||||
uint32_t* p = packet.m_nHeader;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
{
|
||||
*p = ntohl(*p);
|
||||
++ p;
|
||||
}
|
||||
|
||||
if (packet.getFlag())
|
||||
{
|
||||
for (int j = 0, n = packet.getLength() / 4; j < n; ++ j)
|
||||
*((uint32_t *)packet.m_pcData + j) = ntohl(*((uint32_t *)packet.m_pcData + j));
|
||||
}
|
||||
|
||||
return packet.getLength();
|
||||
}
|
||||
171
vendor/udt4/src/channel.h
vendored
171
vendor/udt4/src/channel.h
vendored
|
|
@ -1,171 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/27/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_CHANNEL_H__
|
||||
#define __UDT_CHANNEL_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
class CChannel
|
||||
{
|
||||
public:
|
||||
CChannel();
|
||||
CChannel(int version);
|
||||
~CChannel();
|
||||
|
||||
// Functionality:
|
||||
// Open a UDP channel.
|
||||
// Parameters:
|
||||
// 0) [in] addr: The local address that UDP will use.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void open(const sockaddr* addr = NULL);
|
||||
|
||||
// Functionality:
|
||||
// Open a UDP channel based on an existing UDP socket.
|
||||
// Parameters:
|
||||
// 0) [in] udpsock: UDP socket descriptor.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void open(UDPSOCKET udpsock);
|
||||
|
||||
// Functionality:
|
||||
// Disconnect and close the UDP entity.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void close() const;
|
||||
|
||||
// Functionality:
|
||||
// Get the UDP sending buffer size.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Current UDP sending buffer size.
|
||||
|
||||
int getSndBufSize();
|
||||
|
||||
// Functionality:
|
||||
// Get the UDP receiving buffer size.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Current UDP receiving buffer size.
|
||||
|
||||
int getRcvBufSize();
|
||||
|
||||
// Functionality:
|
||||
// Set the UDP sending buffer size.
|
||||
// Parameters:
|
||||
// 0) [in] size: expected UDP sending buffer size.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setSndBufSize(int size);
|
||||
|
||||
// Functionality:
|
||||
// Set the UDP receiving buffer size.
|
||||
// Parameters:
|
||||
// 0) [in] size: expected UDP receiving buffer size.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setRcvBufSize(int size);
|
||||
|
||||
// Functionality:
|
||||
// Query the socket address that the channel is using.
|
||||
// Parameters:
|
||||
// 0) [out] addr: pointer to store the returned socket address.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void getSockAddr(sockaddr* addr) const;
|
||||
|
||||
// Functionality:
|
||||
// Query the peer side socket address that the channel is connect to.
|
||||
// Parameters:
|
||||
// 0) [out] addr: pointer to store the returned socket address.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void getPeerAddr(sockaddr* addr) const;
|
||||
|
||||
// Functionality:
|
||||
// Send a packet to the given address.
|
||||
// Parameters:
|
||||
// 0) [in] addr: pointer to the destination address.
|
||||
// 1) [in] packet: reference to a CPacket entity.
|
||||
// Returned value:
|
||||
// Actual size of data sent.
|
||||
|
||||
int sendto(const sockaddr* addr, CPacket& packet) const;
|
||||
|
||||
// Functionality:
|
||||
// Receive a packet from the channel and record the source address.
|
||||
// Parameters:
|
||||
// 0) [in] addr: pointer to the source address.
|
||||
// 1) [in] packet: reference to a CPacket entity.
|
||||
// Returned value:
|
||||
// Actual size of data received.
|
||||
|
||||
int recvfrom(sockaddr* addr, CPacket& packet) const;
|
||||
|
||||
private:
|
||||
void setUDPSockOpt();
|
||||
|
||||
private:
|
||||
int m_iIPversion; // IP version
|
||||
int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test)
|
||||
|
||||
UDPSOCKET m_iSocket; // socket descriptor
|
||||
|
||||
int m_iSndBufSize; // UDP sending buffer size
|
||||
int m_iRcvBufSize; // UDP receiving buffer size
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
765
vendor/udt4/src/common.cpp
vendored
765
vendor/udt4/src/common.cpp
vendored
|
|
@ -1,765 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 07/25/2010
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <unistd.h>
|
||||
#ifdef OSX
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#ifdef LEGACY_WIN32
|
||||
#include <wspiapi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include "md5.h"
|
||||
#include "common.h"
|
||||
|
||||
bool CTimer::m_bUseMicroSecond = false;
|
||||
uint64_t CTimer::s_ullCPUFrequency = CTimer::readCPUFrequency();
|
||||
#ifndef WIN32
|
||||
pthread_mutex_t CTimer::m_EventLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t CTimer::m_EventCond = PTHREAD_COND_INITIALIZER;
|
||||
#else
|
||||
pthread_mutex_t CTimer::m_EventLock = CreateMutex(NULL, false, NULL);
|
||||
pthread_cond_t CTimer::m_EventCond = CreateEvent(NULL, false, false, NULL);
|
||||
#endif
|
||||
|
||||
CTimer::CTimer():
|
||||
m_ullSchedTime(),
|
||||
m_TickCond(),
|
||||
m_TickLock()
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_init(&m_TickLock, NULL);
|
||||
pthread_cond_init(&m_TickCond, NULL);
|
||||
#else
|
||||
m_TickLock = CreateMutex(NULL, false, NULL);
|
||||
m_TickCond = CreateEvent(NULL, false, false, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
CTimer::~CTimer()
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_destroy(&m_TickLock);
|
||||
pthread_cond_destroy(&m_TickCond);
|
||||
#else
|
||||
CloseHandle(m_TickLock);
|
||||
CloseHandle(m_TickCond);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTimer::rdtsc(uint64_t &x)
|
||||
{
|
||||
if (m_bUseMicroSecond)
|
||||
{
|
||||
x = getTime();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef IA32
|
||||
uint32_t lval, hval;
|
||||
//asm volatile ("push %eax; push %ebx; push %ecx; push %edx");
|
||||
//asm volatile ("xor %eax, %eax; cpuid");
|
||||
asm volatile ("rdtsc" : "=a" (lval), "=d" (hval));
|
||||
//asm volatile ("pop %edx; pop %ecx; pop %ebx; pop %eax");
|
||||
x = hval;
|
||||
x = (x << 32) | lval;
|
||||
#elif defined(IA64)
|
||||
asm ("mov %0=ar.itc" : "=r"(x) :: "memory");
|
||||
#elif defined(AMD64)
|
||||
uint32_t lval, hval;
|
||||
asm ("rdtsc" : "=a" (lval), "=d" (hval));
|
||||
x = hval;
|
||||
x = (x << 32) | lval;
|
||||
#elif defined(WIN32)
|
||||
//HANDLE hCurThread = ::GetCurrentThread();
|
||||
//DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
|
||||
BOOL ret = QueryPerformanceCounter((LARGE_INTEGER *)&x);
|
||||
//SetThreadAffinityMask(hCurThread, dwOldMask);
|
||||
if (!ret)
|
||||
x = getTime() * s_ullCPUFrequency;
|
||||
#elif defined(OSX)
|
||||
x = mach_absolute_time();
|
||||
#else
|
||||
// use system call to read time clock for other archs
|
||||
x = getTime();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t CTimer::readCPUFrequency()
|
||||
{
|
||||
uint64_t frequency = 1; // 1 tick per microsecond.
|
||||
|
||||
#if defined(IA32) || defined(IA64) || defined(AMD64)
|
||||
uint64_t t1, t2;
|
||||
|
||||
rdtsc(t1);
|
||||
timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 100000000;
|
||||
nanosleep(&ts, NULL);
|
||||
rdtsc(t2);
|
||||
|
||||
// CPU clocks per microsecond
|
||||
frequency = (t2 - t1) / 100000;
|
||||
#elif defined(WIN32)
|
||||
int64_t ccf;
|
||||
if (QueryPerformanceFrequency((LARGE_INTEGER *)&ccf))
|
||||
frequency = ccf / 1000000;
|
||||
#elif defined(OSX)
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info(&info);
|
||||
frequency = info.denom * 1000ULL / info.numer;
|
||||
#endif
|
||||
|
||||
// Fall back to microsecond if the resolution is not high enough.
|
||||
if (frequency < 10)
|
||||
{
|
||||
frequency = 1;
|
||||
m_bUseMicroSecond = true;
|
||||
}
|
||||
return frequency;
|
||||
}
|
||||
|
||||
uint64_t CTimer::getCPUFrequency()
|
||||
{
|
||||
return s_ullCPUFrequency;
|
||||
}
|
||||
|
||||
void CTimer::sleep(uint64_t interval)
|
||||
{
|
||||
uint64_t t;
|
||||
rdtsc(t);
|
||||
|
||||
// sleep next "interval" time
|
||||
sleepto(t + interval);
|
||||
}
|
||||
|
||||
void CTimer::sleepto(uint64_t nexttime)
|
||||
{
|
||||
// Use class member such that the method can be interrupted by others
|
||||
m_ullSchedTime = nexttime;
|
||||
|
||||
uint64_t t;
|
||||
rdtsc(t);
|
||||
|
||||
while (t < m_ullSchedTime)
|
||||
{
|
||||
#ifndef NO_BUSY_WAITING
|
||||
#ifdef IA32
|
||||
__asm__ volatile ("pause; rep; nop; nop; nop; nop; nop;");
|
||||
#elif IA64
|
||||
__asm__ volatile ("nop 0; nop 0; nop 0; nop 0; nop 0;");
|
||||
#elif AMD64
|
||||
__asm__ volatile ("nop; nop; nop; nop; nop;");
|
||||
#endif
|
||||
#else
|
||||
#ifndef WIN32
|
||||
timeval now;
|
||||
timespec timeout;
|
||||
gettimeofday(&now, 0);
|
||||
if (now.tv_usec < 990000)
|
||||
{
|
||||
timeout.tv_sec = now.tv_sec;
|
||||
timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout.tv_sec = now.tv_sec + 1;
|
||||
timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
|
||||
}
|
||||
pthread_mutex_lock(&m_TickLock);
|
||||
pthread_cond_timedwait(&m_TickCond, &m_TickLock, &timeout);
|
||||
pthread_mutex_unlock(&m_TickLock);
|
||||
#else
|
||||
WaitForSingleObject(m_TickCond, 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
rdtsc(t);
|
||||
}
|
||||
}
|
||||
|
||||
void CTimer::interrupt()
|
||||
{
|
||||
// schedule the sleepto time to the current CCs, so that it will stop
|
||||
rdtsc(m_ullSchedTime);
|
||||
tick();
|
||||
}
|
||||
|
||||
void CTimer::tick()
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_cond_signal(&m_TickCond);
|
||||
#else
|
||||
SetEvent(m_TickCond);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t CTimer::getTime()
|
||||
{
|
||||
//For Cygwin and other systems without microsecond level resolution, uncomment the following three lines
|
||||
//uint64_t x;
|
||||
//rdtsc(x);
|
||||
//return x / s_ullCPUFrequency;
|
||||
//Specific fix may be necessary if rdtsc is not available either.
|
||||
|
||||
#ifndef WIN32
|
||||
timeval t;
|
||||
gettimeofday(&t, 0);
|
||||
return t.tv_sec * 1000000ULL + t.tv_usec;
|
||||
#else
|
||||
LARGE_INTEGER ccf;
|
||||
HANDLE hCurThread = ::GetCurrentThread();
|
||||
DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
|
||||
if (QueryPerformanceFrequency(&ccf))
|
||||
{
|
||||
LARGE_INTEGER cc;
|
||||
if (QueryPerformanceCounter(&cc))
|
||||
{
|
||||
SetThreadAffinityMask(hCurThread, dwOldMask);
|
||||
return (cc.QuadPart * 1000000ULL / ccf.QuadPart);
|
||||
}
|
||||
}
|
||||
|
||||
SetThreadAffinityMask(hCurThread, dwOldMask);
|
||||
return GetTickCount() * 1000ULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTimer::triggerEvent()
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_cond_signal(&m_EventCond);
|
||||
#else
|
||||
SetEvent(m_EventCond);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTimer::waitForEvent()
|
||||
{
|
||||
#ifndef WIN32
|
||||
timeval now;
|
||||
timespec timeout;
|
||||
gettimeofday(&now, 0);
|
||||
if (now.tv_usec < 990000)
|
||||
{
|
||||
timeout.tv_sec = now.tv_sec;
|
||||
timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout.tv_sec = now.tv_sec + 1;
|
||||
timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
|
||||
}
|
||||
pthread_mutex_lock(&m_EventLock);
|
||||
pthread_cond_timedwait(&m_EventCond, &m_EventLock, &timeout);
|
||||
pthread_mutex_unlock(&m_EventLock);
|
||||
#else
|
||||
WaitForSingleObject(m_EventCond, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTimer::sleep()
|
||||
{
|
||||
#ifndef WIN32
|
||||
usleep(10);
|
||||
#else
|
||||
Sleep(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Automatically lock in constructor
|
||||
CGuard::CGuard(pthread_mutex_t& lock):
|
||||
m_Mutex(lock),
|
||||
m_iLocked()
|
||||
{
|
||||
#ifndef WIN32
|
||||
m_iLocked = pthread_mutex_lock(&m_Mutex);
|
||||
#else
|
||||
m_iLocked = WaitForSingleObject(m_Mutex, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Automatically unlock in destructor
|
||||
CGuard::~CGuard()
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (0 == m_iLocked)
|
||||
pthread_mutex_unlock(&m_Mutex);
|
||||
#else
|
||||
if (WAIT_FAILED != m_iLocked)
|
||||
ReleaseMutex(m_Mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::enterCS(pthread_mutex_t& lock)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_lock(&lock);
|
||||
#else
|
||||
WaitForSingleObject(lock, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::leaveCS(pthread_mutex_t& lock)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_unlock(&lock);
|
||||
#else
|
||||
ReleaseMutex(lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::createMutex(pthread_mutex_t& lock)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
#else
|
||||
lock = CreateMutex(NULL, false, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::releaseMutex(pthread_mutex_t& lock)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_mutex_destroy(&lock);
|
||||
#else
|
||||
CloseHandle(lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::createCond(pthread_cond_t& cond)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_cond_init(&cond, NULL);
|
||||
#else
|
||||
cond = CreateEvent(NULL, false, false, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGuard::releaseCond(pthread_cond_t& cond)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pthread_cond_destroy(&cond);
|
||||
#else
|
||||
CloseHandle(cond);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
CUDTException::CUDTException(int major, int minor, int err):
|
||||
m_iMajor(major),
|
||||
m_iMinor(minor)
|
||||
{
|
||||
if (-1 == err)
|
||||
#ifndef WIN32
|
||||
m_iErrno = errno;
|
||||
#else
|
||||
m_iErrno = GetLastError();
|
||||
#endif
|
||||
else
|
||||
m_iErrno = err;
|
||||
}
|
||||
|
||||
CUDTException::CUDTException(const CUDTException& e):
|
||||
m_iMajor(e.m_iMajor),
|
||||
m_iMinor(e.m_iMinor),
|
||||
m_iErrno(e.m_iErrno),
|
||||
m_strMsg()
|
||||
{
|
||||
}
|
||||
|
||||
CUDTException::~CUDTException()
|
||||
{
|
||||
}
|
||||
|
||||
const char* CUDTException::getErrorMessage()
|
||||
{
|
||||
// translate "Major:Minor" code into text message.
|
||||
|
||||
switch (m_iMajor)
|
||||
{
|
||||
case 0:
|
||||
m_strMsg = "Success";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_strMsg = "Connection setup failure";
|
||||
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg += ": connection time out";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg += ": connection rejected";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_strMsg += ": unable to create/configure UDP socket";
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_strMsg += ": abort for security reasons";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg = "Connection was broken";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg = "Connection does not exist";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_strMsg = "System resource failure";
|
||||
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg += ": unable to create new threads";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg += ": unable to allocate buffers";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_strMsg = "File system failure";
|
||||
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg += ": cannot seek read position";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg += ": failure in read";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_strMsg += ": cannot seek write position";
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_strMsg += ": failure in write";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_strMsg = "Operation not supported";
|
||||
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg += ": Cannot do this operation on a BOUND socket";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg += ": Cannot do this operation on a CONNECTED socket";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_strMsg += ": Bad parameters";
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_strMsg += ": Invalid socket ID";
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_strMsg += ": Cannot do this operation on an UNBOUND socket";
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_strMsg += ": Socket is not in listening state";
|
||||
break;
|
||||
|
||||
case 7:
|
||||
m_strMsg += ": Listen/accept is not supported in rendezous connection setup";
|
||||
break;
|
||||
|
||||
case 8:
|
||||
m_strMsg += ": Cannot call connect on UNBOUND socket in rendezvous connection setup";
|
||||
break;
|
||||
|
||||
case 9:
|
||||
m_strMsg += ": This operation is not supported in SOCK_STREAM mode";
|
||||
break;
|
||||
|
||||
case 10:
|
||||
m_strMsg += ": This operation is not supported in SOCK_DGRAM mode";
|
||||
break;
|
||||
|
||||
case 11:
|
||||
m_strMsg += ": Another socket is already listening on the same port";
|
||||
break;
|
||||
|
||||
case 12:
|
||||
m_strMsg += ": Message is too large to send (it must be less than the UDT send buffer size)";
|
||||
break;
|
||||
|
||||
case 13:
|
||||
m_strMsg += ": Invalid epoll ID";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_strMsg = "Non-blocking call failure";
|
||||
|
||||
switch (m_iMinor)
|
||||
{
|
||||
case 1:
|
||||
m_strMsg += ": no buffer available for sending";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_strMsg += ": no data available for reading";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
m_strMsg = "The peer side has signalled an error";
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
m_strMsg = "Unknown error";
|
||||
}
|
||||
|
||||
// Adding "errno" information
|
||||
if ((0 != m_iMajor) && (0 < m_iErrno))
|
||||
{
|
||||
m_strMsg += ": ";
|
||||
#ifndef WIN32
|
||||
char errmsg[1024];
|
||||
if (strerror_r(m_iErrno, errmsg, 1024) == 0)
|
||||
m_strMsg += errmsg;
|
||||
#else
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_iErrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
m_strMsg += (char*)lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
// period
|
||||
#ifndef WIN32
|
||||
m_strMsg += ".";
|
||||
#endif
|
||||
|
||||
return m_strMsg.c_str();
|
||||
}
|
||||
|
||||
int CUDTException::getErrorCode() const
|
||||
{
|
||||
return m_iMajor * 1000 + m_iMinor;
|
||||
}
|
||||
|
||||
void CUDTException::clear()
|
||||
{
|
||||
m_iMajor = 0;
|
||||
m_iMinor = 0;
|
||||
m_iErrno = 0;
|
||||
}
|
||||
|
||||
const int CUDTException::SUCCESS = 0;
|
||||
const int CUDTException::ECONNSETUP = 1000;
|
||||
const int CUDTException::ENOSERVER = 1001;
|
||||
const int CUDTException::ECONNREJ = 1002;
|
||||
const int CUDTException::ESOCKFAIL = 1003;
|
||||
const int CUDTException::ESECFAIL = 1004;
|
||||
const int CUDTException::ECONNFAIL = 2000;
|
||||
const int CUDTException::ECONNLOST = 2001;
|
||||
const int CUDTException::ENOCONN = 2002;
|
||||
const int CUDTException::ERESOURCE = 3000;
|
||||
const int CUDTException::ETHREAD = 3001;
|
||||
const int CUDTException::ENOBUF = 3002;
|
||||
const int CUDTException::EFILE = 4000;
|
||||
const int CUDTException::EINVRDOFF = 4001;
|
||||
const int CUDTException::ERDPERM = 4002;
|
||||
const int CUDTException::EINVWROFF = 4003;
|
||||
const int CUDTException::EWRPERM = 4004;
|
||||
const int CUDTException::EINVOP = 5000;
|
||||
const int CUDTException::EBOUNDSOCK = 5001;
|
||||
const int CUDTException::ECONNSOCK = 5002;
|
||||
const int CUDTException::EINVPARAM = 5003;
|
||||
const int CUDTException::EINVSOCK = 5004;
|
||||
const int CUDTException::EUNBOUNDSOCK = 5005;
|
||||
const int CUDTException::ENOLISTEN = 5006;
|
||||
const int CUDTException::ERDVNOSERV = 5007;
|
||||
const int CUDTException::ERDVUNBOUND = 5008;
|
||||
const int CUDTException::ESTREAMILL = 5009;
|
||||
const int CUDTException::EDGRAMILL = 5010;
|
||||
const int CUDTException::EDUPLISTEN = 5011;
|
||||
const int CUDTException::ELARGEMSG = 5012;
|
||||
const int CUDTException::EINVPOLLID = 5013;
|
||||
const int CUDTException::EASYNCFAIL = 6000;
|
||||
const int CUDTException::EASYNCSND = 6001;
|
||||
const int CUDTException::EASYNCRCV = 6002;
|
||||
const int CUDTException::ETIMEOUT = 6003;
|
||||
const int CUDTException::EPEERERR = 7000;
|
||||
const int CUDTException::EUNKNOWN = -1;
|
||||
|
||||
|
||||
//
|
||||
bool CIPAddress::ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver)
|
||||
{
|
||||
if (AF_INET == ver)
|
||||
{
|
||||
sockaddr_in* a1 = (sockaddr_in*)addr1;
|
||||
sockaddr_in* a2 = (sockaddr_in*)addr2;
|
||||
|
||||
if ((a1->sin_port == a2->sin_port) && (a1->sin_addr.s_addr == a2->sin_addr.s_addr))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sockaddr_in6* a1 = (sockaddr_in6*)addr1;
|
||||
sockaddr_in6* a2 = (sockaddr_in6*)addr2;
|
||||
|
||||
if (a1->sin6_port == a2->sin6_port)
|
||||
{
|
||||
for (int i = 0; i < 16; ++ i)
|
||||
if (*((char*)&(a1->sin6_addr) + i) != *((char*)&(a2->sin6_addr) + i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CIPAddress::ntop(const sockaddr* addr, uint32_t ip[4], int ver)
|
||||
{
|
||||
if (AF_INET == ver)
|
||||
{
|
||||
sockaddr_in* a = (sockaddr_in*)addr;
|
||||
ip[0] = a->sin_addr.s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
sockaddr_in6* a = (sockaddr_in6*)addr;
|
||||
ip[3] = (a->sin6_addr.s6_addr[15] << 24) + (a->sin6_addr.s6_addr[14] << 16) + (a->sin6_addr.s6_addr[13] << 8) + a->sin6_addr.s6_addr[12];
|
||||
ip[2] = (a->sin6_addr.s6_addr[11] << 24) + (a->sin6_addr.s6_addr[10] << 16) + (a->sin6_addr.s6_addr[9] << 8) + a->sin6_addr.s6_addr[8];
|
||||
ip[1] = (a->sin6_addr.s6_addr[7] << 24) + (a->sin6_addr.s6_addr[6] << 16) + (a->sin6_addr.s6_addr[5] << 8) + a->sin6_addr.s6_addr[4];
|
||||
ip[0] = (a->sin6_addr.s6_addr[3] << 24) + (a->sin6_addr.s6_addr[2] << 16) + (a->sin6_addr.s6_addr[1] << 8) + a->sin6_addr.s6_addr[0];
|
||||
}
|
||||
}
|
||||
|
||||
void CIPAddress::pton(sockaddr* addr, const uint32_t ip[4], int ver)
|
||||
{
|
||||
if (AF_INET == ver)
|
||||
{
|
||||
sockaddr_in* a = (sockaddr_in*)addr;
|
||||
a->sin_addr.s_addr = ip[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
sockaddr_in6* a = (sockaddr_in6*)addr;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
{
|
||||
a->sin6_addr.s6_addr[i * 4] = ip[i] & 0xFF;
|
||||
a->sin6_addr.s6_addr[i * 4 + 1] = (unsigned char)((ip[i] & 0xFF00) >> 8);
|
||||
a->sin6_addr.s6_addr[i * 4 + 2] = (unsigned char)((ip[i] & 0xFF0000) >> 16);
|
||||
a->sin6_addr.s6_addr[i * 4 + 3] = (unsigned char)((ip[i] & 0xFF000000) >> 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void CMD5::compute(const char* input, unsigned char result[16])
|
||||
{
|
||||
md5_state_t state;
|
||||
|
||||
md5_init(&state);
|
||||
md5_append(&state, (const md5_byte_t *)input, strlen(input));
|
||||
md5_finish(&state, result);
|
||||
}
|
||||
321
vendor/udt4/src/common.h
vendored
321
vendor/udt4/src/common.h
vendored
|
|
@ -1,321 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 08/01/2009
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_COMMON_H__
|
||||
#define __UDT_COMMON_H__
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
#include <stdint.h>
|
||||
#include "udt.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// Windows compability
|
||||
typedef HANDLE pthread_t;
|
||||
typedef HANDLE pthread_mutex_t;
|
||||
typedef HANDLE pthread_cond_t;
|
||||
typedef DWORD pthread_key_t;
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
~CTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Sleep for "interval" CCs.
|
||||
// Parameters:
|
||||
// 0) [in] interval: CCs to sleep.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void sleep(uint64_t interval);
|
||||
|
||||
// Functionality:
|
||||
// Seelp until CC "nexttime".
|
||||
// Parameters:
|
||||
// 0) [in] nexttime: next time the caller is waken up.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void sleepto(uint64_t nexttime);
|
||||
|
||||
// Functionality:
|
||||
// Stop the sleep() or sleepto() methods.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void interrupt();
|
||||
|
||||
// Functionality:
|
||||
// trigger the clock for a tick, for better granuality in no_busy_waiting timer.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void tick();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Read the CPU clock cycle into x.
|
||||
// Parameters:
|
||||
// 0) [out] x: to record cpu clock cycles.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
static void rdtsc(uint64_t &x);
|
||||
|
||||
// Functionality:
|
||||
// return the CPU frequency.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// CPU frequency.
|
||||
|
||||
static uint64_t getCPUFrequency();
|
||||
|
||||
// Functionality:
|
||||
// check the current time, 64bit, in microseconds.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// current time in microseconds.
|
||||
|
||||
static uint64_t getTime();
|
||||
|
||||
// Functionality:
|
||||
// trigger an event such as new connection, close, new data, etc. for "select" call.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
static void triggerEvent();
|
||||
|
||||
// Functionality:
|
||||
// wait for an event to br triggered by "triggerEvent".
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
static void waitForEvent();
|
||||
|
||||
// Functionality:
|
||||
// sleep for a short interval. exact sleep time does not matter
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
static void sleep();
|
||||
|
||||
private:
|
||||
uint64_t getTimeInMicroSec();
|
||||
|
||||
private:
|
||||
uint64_t m_ullSchedTime; // next schedulled time
|
||||
|
||||
pthread_cond_t m_TickCond;
|
||||
pthread_mutex_t m_TickLock;
|
||||
|
||||
static pthread_cond_t m_EventCond;
|
||||
static pthread_mutex_t m_EventLock;
|
||||
|
||||
private:
|
||||
static uint64_t s_ullCPUFrequency; // CPU frequency : clock cycles per microsecond
|
||||
static uint64_t readCPUFrequency();
|
||||
static bool m_bUseMicroSecond; // No higher resolution timer available, use gettimeofday().
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CGuard
|
||||
{
|
||||
public:
|
||||
CGuard(pthread_mutex_t& lock);
|
||||
~CGuard();
|
||||
|
||||
public:
|
||||
static void enterCS(pthread_mutex_t& lock);
|
||||
static void leaveCS(pthread_mutex_t& lock);
|
||||
|
||||
static void createMutex(pthread_mutex_t& lock);
|
||||
static void releaseMutex(pthread_mutex_t& lock);
|
||||
|
||||
static void createCond(pthread_cond_t& cond);
|
||||
static void releaseCond(pthread_cond_t& cond);
|
||||
|
||||
private:
|
||||
pthread_mutex_t& m_Mutex; // Alias name of the mutex to be protected
|
||||
int m_iLocked; // Locking status
|
||||
|
||||
CGuard& operator=(const CGuard&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// UDT Sequence Number 0 - (2^31 - 1)
|
||||
|
||||
// seqcmp: compare two seq#, considering the wraping
|
||||
// seqlen: length from the 1st to the 2nd seq#, including both
|
||||
// seqoff: offset from the 2nd to the 1st seq#
|
||||
// incseq: increase the seq# by 1
|
||||
// decseq: decrease the seq# by 1
|
||||
// incseq: increase the seq# by a given offset
|
||||
|
||||
class CSeqNo
|
||||
{
|
||||
public:
|
||||
inline static int seqcmp(int32_t seq1, int32_t seq2)
|
||||
{return (abs(seq1 - seq2) < m_iSeqNoTH) ? (seq1 - seq2) : (seq2 - seq1);}
|
||||
|
||||
inline static int seqlen(int32_t seq1, int32_t seq2)
|
||||
{return (seq1 <= seq2) ? (seq2 - seq1 + 1) : (seq2 - seq1 + m_iMaxSeqNo + 2);}
|
||||
|
||||
inline static int seqoff(int32_t seq1, int32_t seq2)
|
||||
{
|
||||
if (abs(seq1 - seq2) < m_iSeqNoTH)
|
||||
return seq2 - seq1;
|
||||
|
||||
if (seq1 < seq2)
|
||||
return seq2 - seq1 - m_iMaxSeqNo - 1;
|
||||
|
||||
return seq2 - seq1 + m_iMaxSeqNo + 1;
|
||||
}
|
||||
|
||||
inline static int32_t incseq(int32_t seq)
|
||||
{return (seq == m_iMaxSeqNo) ? 0 : seq + 1;}
|
||||
|
||||
inline static int32_t decseq(int32_t seq)
|
||||
{return (seq == 0) ? m_iMaxSeqNo : seq - 1;}
|
||||
|
||||
inline static int32_t incseq(int32_t seq, int32_t inc)
|
||||
{return (m_iMaxSeqNo - seq >= inc) ? seq + inc : seq - m_iMaxSeqNo + inc - 1;}
|
||||
|
||||
public:
|
||||
static const int32_t m_iSeqNoTH; // threshold for comparing seq. no.
|
||||
static const int32_t m_iMaxSeqNo; // maximum sequence number used in UDT
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// UDT ACK Sub-sequence Number: 0 - (2^31 - 1)
|
||||
|
||||
class CAckNo
|
||||
{
|
||||
public:
|
||||
inline static int32_t incack(int32_t ackno)
|
||||
{return (ackno == m_iMaxAckSeqNo) ? 0 : ackno + 1;}
|
||||
|
||||
public:
|
||||
static const int32_t m_iMaxAckSeqNo; // maximum ACK sub-sequence number used in UDT
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// UDT Message Number: 0 - (2^29 - 1)
|
||||
|
||||
class CMsgNo
|
||||
{
|
||||
public:
|
||||
inline static int msgcmp(int32_t msgno1, int32_t msgno2)
|
||||
{return (abs(msgno1 - msgno2) < m_iMsgNoTH) ? (msgno1 - msgno2) : (msgno2 - msgno1);}
|
||||
|
||||
inline static int msglen(int32_t msgno1, int32_t msgno2)
|
||||
{return (msgno1 <= msgno2) ? (msgno2 - msgno1 + 1) : (msgno2 - msgno1 + m_iMaxMsgNo + 2);}
|
||||
|
||||
inline static int msgoff(int32_t msgno1, int32_t msgno2)
|
||||
{
|
||||
if (abs(msgno1 - msgno2) < m_iMsgNoTH)
|
||||
return msgno2 - msgno1;
|
||||
|
||||
if (msgno1 < msgno2)
|
||||
return msgno2 - msgno1 - m_iMaxMsgNo - 1;
|
||||
|
||||
return msgno2 - msgno1 + m_iMaxMsgNo + 1;
|
||||
}
|
||||
|
||||
inline static int32_t incmsg(int32_t msgno)
|
||||
{return (msgno == m_iMaxMsgNo) ? 0 : msgno + 1;}
|
||||
|
||||
public:
|
||||
static const int32_t m_iMsgNoTH; // threshold for comparing msg. no.
|
||||
static const int32_t m_iMaxMsgNo; // maximum message number used in UDT
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CIPAddress
|
||||
{
|
||||
static bool ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver = AF_INET);
|
||||
static void ntop(const sockaddr* addr, uint32_t ip[4], int ver = AF_INET);
|
||||
static void pton(sockaddr* addr, const uint32_t ip[4], int ver = AF_INET);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CMD5
|
||||
{
|
||||
static void compute(const char* input, unsigned char result[16]);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
2675
vendor/udt4/src/core.cpp
vendored
2675
vendor/udt4/src/core.cpp
vendored
File diff suppressed because it is too large
Load diff
458
vendor/udt4/src/core.h
vendored
458
vendor/udt4/src/core.h
vendored
|
|
@ -1,458 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 02/28/2012
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_CORE_H__
|
||||
#define __UDT_CORE_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "common.h"
|
||||
#include "list.h"
|
||||
#include "buffer.h"
|
||||
#include "window.h"
|
||||
#include "packet.h"
|
||||
#include "channel.h"
|
||||
#include "api.h"
|
||||
#include "ccc.h"
|
||||
#include "cache.h"
|
||||
#include "queue.h"
|
||||
|
||||
enum UDTSockType {UDT_STREAM = 1, UDT_DGRAM};
|
||||
|
||||
class CUDT
|
||||
{
|
||||
friend class CUDTSocket;
|
||||
friend class CUDTUnited;
|
||||
friend class CCC;
|
||||
friend struct CUDTComp;
|
||||
friend class CCache<CInfoBlock>;
|
||||
friend class CRendezvousQueue;
|
||||
friend class CSndQueue;
|
||||
friend class CRcvQueue;
|
||||
friend class CSndUList;
|
||||
friend class CRcvUList;
|
||||
|
||||
private: // constructor and desctructor
|
||||
CUDT();
|
||||
CUDT(const CUDT& ancestor);
|
||||
const CUDT& operator=(const CUDT&) {return *this;}
|
||||
~CUDT();
|
||||
|
||||
public: //API
|
||||
static int startup();
|
||||
static int cleanup();
|
||||
static UDTSOCKET socket(int af, int type = SOCK_STREAM, int protocol = 0);
|
||||
static int bind(UDTSOCKET u, const sockaddr* name, int namelen);
|
||||
static int bind(UDTSOCKET u, UDPSOCKET udpsock);
|
||||
static int listen(UDTSOCKET u, int backlog);
|
||||
static UDTSOCKET accept(UDTSOCKET u, sockaddr* addr, int* addrlen);
|
||||
static int connect(UDTSOCKET u, const sockaddr* name, int namelen);
|
||||
static int close(UDTSOCKET u);
|
||||
static int getpeername(UDTSOCKET u, sockaddr* name, int* namelen);
|
||||
static int getsockname(UDTSOCKET u, sockaddr* name, int* namelen);
|
||||
static int getsockopt(UDTSOCKET u, int level, UDTOpt optname, void* optval, int* optlen);
|
||||
static int setsockopt(UDTSOCKET u, int level, UDTOpt optname, const void* optval, int optlen);
|
||||
static int send(UDTSOCKET u, const char* buf, int len, int flags);
|
||||
static int recv(UDTSOCKET u, char* buf, int len, int flags);
|
||||
static int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false);
|
||||
static int recvmsg(UDTSOCKET u, char* buf, int len);
|
||||
static int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000);
|
||||
static int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000);
|
||||
static int select(int nfds, ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout);
|
||||
static int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds, std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
|
||||
static int epoll_create();
|
||||
static int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
|
||||
static int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
static int epoll_remove_usock(const int eid, const UDTSOCKET u);
|
||||
static int epoll_remove_ssock(const int eid, const SYSSOCKET s);
|
||||
static int epoll_wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* wrfds = NULL);
|
||||
static int epoll_release(const int eid);
|
||||
static CUDTException& getlasterror();
|
||||
static int perfmon(UDTSOCKET u, CPerfMon* perf, bool clear = true);
|
||||
static UDTSTATUS getsockstate(UDTSOCKET u);
|
||||
|
||||
public: // internal API
|
||||
static CUDT* getUDTHandle(UDTSOCKET u);
|
||||
|
||||
private:
|
||||
// Functionality:
|
||||
// initialize a UDT entity and bind to a local address.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void open();
|
||||
|
||||
// Functionality:
|
||||
// Start listening to any connection request.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void listen();
|
||||
|
||||
// Functionality:
|
||||
// Connect to a UDT entity listening at address "peer".
|
||||
// Parameters:
|
||||
// 0) [in] peer: The address of the listening UDT entity.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void connect(const sockaddr* peer);
|
||||
|
||||
// Functionality:
|
||||
// Process the response handshake packet.
|
||||
// Parameters:
|
||||
// 0) [in] pkt: handshake packet.
|
||||
// Returned value:
|
||||
// Return 0 if connected, positive value if connection is in progress, otherwise error code.
|
||||
|
||||
int connect(const CPacket& pkt) throw ();
|
||||
|
||||
// Functionality:
|
||||
// Connect to a UDT entity listening at address "peer", which has sent "hs" request.
|
||||
// Parameters:
|
||||
// 0) [in] peer: The address of the listening UDT entity.
|
||||
// 1) [in/out] hs: The handshake information sent by the peer side (in), negotiated value (out).
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void connect(const sockaddr* peer, CHandShake* hs);
|
||||
|
||||
// Functionality:
|
||||
// Close the opened UDT entity.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void close();
|
||||
|
||||
// Functionality:
|
||||
// Request UDT to send out a data block "data" with size of "len".
|
||||
// Parameters:
|
||||
// 0) [in] data: The address of the application data to be sent.
|
||||
// 1) [in] len: The size of the data block.
|
||||
// Returned value:
|
||||
// Actual size of data sent.
|
||||
|
||||
int send(const char* data, int len);
|
||||
|
||||
// Functionality:
|
||||
// Request UDT to receive data to a memory block "data" with size of "len".
|
||||
// Parameters:
|
||||
// 0) [out] data: data received.
|
||||
// 1) [in] len: The desired size of data to be received.
|
||||
// Returned value:
|
||||
// Actual size of data received.
|
||||
|
||||
int recv(char* data, int len);
|
||||
|
||||
// Functionality:
|
||||
// send a message of a memory block "data" with size of "len".
|
||||
// Parameters:
|
||||
// 0) [out] data: data received.
|
||||
// 1) [in] len: The desired size of data to be received.
|
||||
// 2) [in] ttl: the time-to-live of the message.
|
||||
// 3) [in] inorder: if the message should be delivered in order.
|
||||
// Returned value:
|
||||
// Actual size of data sent.
|
||||
|
||||
int sendmsg(const char* data, int len, int ttl, bool inorder);
|
||||
|
||||
// Functionality:
|
||||
// Receive a message to buffer "data".
|
||||
// Parameters:
|
||||
// 0) [out] data: data received.
|
||||
// 1) [in] len: size of the buffer.
|
||||
// Returned value:
|
||||
// Actual size of data received.
|
||||
|
||||
int recvmsg(char* data, int len);
|
||||
|
||||
// Functionality:
|
||||
// Request UDT to send out a file described as "fd", starting from "offset", with size of "size".
|
||||
// Parameters:
|
||||
// 0) [in] ifs: The input file stream.
|
||||
// 1) [in, out] offset: From where to read and send data; output is the new offset when the call returns.
|
||||
// 2) [in] size: How many data to be sent.
|
||||
// 3) [in] block: size of block per read from disk
|
||||
// Returned value:
|
||||
// Actual size of data sent.
|
||||
|
||||
int64_t sendfile(std::fstream& ifs, int64_t& offset, int64_t size, int block = 366000);
|
||||
|
||||
// Functionality:
|
||||
// Request UDT to receive data into a file described as "fd", starting from "offset", with expected size of "size".
|
||||
// Parameters:
|
||||
// 0) [out] ofs: The output file stream.
|
||||
// 1) [in, out] offset: From where to write data; output is the new offset when the call returns.
|
||||
// 2) [in] size: How many data to be received.
|
||||
// 3) [in] block: size of block per write to disk
|
||||
// Returned value:
|
||||
// Actual size of data received.
|
||||
|
||||
int64_t recvfile(std::fstream& ofs, int64_t& offset, int64_t size, int block = 7320000);
|
||||
|
||||
// Functionality:
|
||||
// Configure UDT options.
|
||||
// Parameters:
|
||||
// 0) [in] optName: The enum name of a UDT option.
|
||||
// 1) [in] optval: The value to be set.
|
||||
// 2) [in] optlen: size of "optval".
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setOpt(UDTOpt optName, const void* optval, int optlen);
|
||||
|
||||
// Functionality:
|
||||
// Read UDT options.
|
||||
// Parameters:
|
||||
// 0) [in] optName: The enum name of a UDT option.
|
||||
// 1) [in] optval: The value to be returned.
|
||||
// 2) [out] optlen: size of "optval".
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void getOpt(UDTOpt optName, void* optval, int& optlen);
|
||||
|
||||
// Functionality:
|
||||
// read the performance data since last sample() call.
|
||||
// Parameters:
|
||||
// 0) [in, out] perf: pointer to a CPerfMon structure to record the performance data.
|
||||
// 1) [in] clear: flag to decide if the local performance trace should be cleared.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void sample(CPerfMon* perf, bool clear = true);
|
||||
|
||||
private:
|
||||
static CUDTUnited s_UDTUnited; // UDT global management base
|
||||
|
||||
public:
|
||||
static const UDTSOCKET INVALID_SOCK; // invalid socket descriptor
|
||||
static const int ERROR; // socket api error returned value
|
||||
|
||||
private: // Identification
|
||||
UDTSOCKET m_SocketID; // UDT socket number
|
||||
UDTSockType m_iSockType; // Type of the UDT connection (SOCK_STREAM or SOCK_DGRAM)
|
||||
UDTSOCKET m_PeerID; // peer id, for multiplexer
|
||||
static const int m_iVersion; // UDT version, for compatibility use
|
||||
|
||||
private: // Packet sizes
|
||||
int m_iPktSize; // Maximum/regular packet size, in bytes
|
||||
int m_iPayloadSize; // Maximum/regular payload size, in bytes
|
||||
|
||||
private: // Options
|
||||
int m_iMSS; // Maximum Segment Size, in bytes
|
||||
bool m_bSynSending; // Sending syncronization mode
|
||||
bool m_bSynRecving; // Receiving syncronization mode
|
||||
int m_iFlightFlagSize; // Maximum number of packets in flight from the peer side
|
||||
int m_iSndBufSize; // Maximum UDT sender buffer size
|
||||
int m_iRcvBufSize; // Maximum UDT receiver buffer size
|
||||
linger m_Linger; // Linger information on close
|
||||
int m_iUDPSndBufSize; // UDP sending buffer size
|
||||
int m_iUDPRcvBufSize; // UDP receiving buffer size
|
||||
int m_iIPversion; // IP version
|
||||
bool m_bRendezvous; // Rendezvous connection mode
|
||||
int m_iSndTimeOut; // sending timeout in milliseconds
|
||||
int m_iRcvTimeOut; // receiving timeout in milliseconds
|
||||
bool m_bReuseAddr; // reuse an exiting port or not, for UDP multiplexer
|
||||
int64_t m_llMaxBW; // maximum data transfer rate (threshold)
|
||||
|
||||
private: // congestion control
|
||||
CCCVirtualFactory* m_pCCFactory; // Factory class to create a specific CC instance
|
||||
CCC* m_pCC; // congestion control class
|
||||
CCache<CInfoBlock>* m_pCache; // network information cache
|
||||
|
||||
private: // Status
|
||||
volatile bool m_bListening; // If the UDT entit is listening to connection
|
||||
volatile bool m_bConnecting; // The short phase when connect() is called but not yet completed
|
||||
volatile bool m_bConnected; // Whether the connection is on or off
|
||||
volatile bool m_bClosing; // If the UDT entity is closing
|
||||
volatile bool m_bShutdown; // If the peer side has shutdown the connection
|
||||
volatile bool m_bBroken; // If the connection has been broken
|
||||
volatile bool m_bPeerHealth; // If the peer status is normal
|
||||
bool m_bOpened; // If the UDT entity has been opened
|
||||
int m_iBrokenCounter; // a counter (number of GC checks) to let the GC tag this socket as disconnected
|
||||
|
||||
int m_iEXPCount; // Expiration counter
|
||||
int m_iBandwidth; // Estimated bandwidth, number of packets per second
|
||||
int m_iRTT; // RTT, in microseconds
|
||||
int m_iRTTVar; // RTT variance
|
||||
int m_iDeliveryRate; // Packet arrival rate at the receiver side
|
||||
|
||||
uint64_t m_ullLingerExpiration; // Linger expiration time (for GC to close a socket with data in sending buffer)
|
||||
|
||||
CHandShake m_ConnReq; // connection request
|
||||
CHandShake m_ConnRes; // connection response
|
||||
int64_t m_llLastReqTime; // last time when a connection request is sent
|
||||
|
||||
private: // Sending related data
|
||||
CSndBuffer* m_pSndBuffer; // Sender buffer
|
||||
CSndLossList* m_pSndLossList; // Sender loss list
|
||||
CPktTimeWindow* m_pSndTimeWindow; // Packet sending time window
|
||||
|
||||
volatile uint64_t m_ullInterval; // Inter-packet time, in CPU clock cycles
|
||||
uint64_t m_ullTimeDiff; // aggregate difference in inter-packet time
|
||||
|
||||
volatile int m_iFlowWindowSize; // Flow control window size
|
||||
volatile double m_dCongestionWindow; // congestion window size
|
||||
|
||||
volatile int32_t m_iSndLastAck; // Last ACK received
|
||||
volatile int32_t m_iSndLastDataAck; // The real last ACK that updates the sender buffer and loss list
|
||||
volatile int32_t m_iSndCurrSeqNo; // The largest sequence number that has been sent
|
||||
int32_t m_iLastDecSeq; // Sequence number sent last decrease occurs
|
||||
int32_t m_iSndLastAck2; // Last ACK2 sent back
|
||||
uint64_t m_ullSndLastAck2Time; // The time when last ACK2 was sent back
|
||||
|
||||
int32_t m_iISN; // Initial Sequence Number
|
||||
|
||||
void CCUpdate();
|
||||
|
||||
private: // Receiving related data
|
||||
CRcvBuffer* m_pRcvBuffer; // Receiver buffer
|
||||
CRcvLossList* m_pRcvLossList; // Receiver loss list
|
||||
CACKWindow* m_pACKWindow; // ACK history window
|
||||
CPktTimeWindow* m_pRcvTimeWindow; // Packet arrival time window
|
||||
|
||||
int32_t m_iRcvLastAck; // Last sent ACK
|
||||
uint64_t m_ullLastAckTime; // Timestamp of last ACK
|
||||
int32_t m_iRcvLastAckAck; // Last sent ACK that has been acknowledged
|
||||
int32_t m_iAckSeqNo; // Last ACK sequence number
|
||||
int32_t m_iRcvCurrSeqNo; // Largest received sequence number
|
||||
|
||||
uint64_t m_ullLastWarningTime; // Last time that a warning message is sent
|
||||
|
||||
int32_t m_iPeerISN; // Initial Sequence Number of the peer side
|
||||
|
||||
private: // synchronization: mutexes and conditions
|
||||
pthread_mutex_t m_ConnectionLock; // used to synchronize connection operation
|
||||
|
||||
pthread_cond_t m_SendBlockCond; // used to block "send" call
|
||||
pthread_mutex_t m_SendBlockLock; // lock associated to m_SendBlockCond
|
||||
|
||||
pthread_mutex_t m_AckLock; // used to protected sender's loss list when processing ACK
|
||||
|
||||
pthread_cond_t m_RecvDataCond; // used to block "recv" when there is no data
|
||||
pthread_mutex_t m_RecvDataLock; // lock associated to m_RecvDataCond
|
||||
|
||||
pthread_mutex_t m_SendLock; // used to synchronize "send" call
|
||||
pthread_mutex_t m_RecvLock; // used to synchronize "recv" call
|
||||
|
||||
void initSynch();
|
||||
void destroySynch();
|
||||
void releaseSynch();
|
||||
|
||||
private: // Generation and processing of packets
|
||||
void sendCtrl(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0);
|
||||
void processCtrl(CPacket& ctrlpkt);
|
||||
int packData(CPacket& packet, uint64_t& ts);
|
||||
int processData(CUnit* unit);
|
||||
int listen(sockaddr* addr, CPacket& packet);
|
||||
|
||||
private: // Trace
|
||||
uint64_t m_StartTime; // timestamp when the UDT entity is started
|
||||
int64_t m_llSentTotal; // total number of sent data packets, including retransmissions
|
||||
int64_t m_llRecvTotal; // total number of received packets
|
||||
int m_iSndLossTotal; // total number of lost packets (sender side)
|
||||
int m_iRcvLossTotal; // total number of lost packets (receiver side)
|
||||
int m_iRetransTotal; // total number of retransmitted packets
|
||||
int m_iSentACKTotal; // total number of sent ACK packets
|
||||
int m_iRecvACKTotal; // total number of received ACK packets
|
||||
int m_iSentNAKTotal; // total number of sent NAK packets
|
||||
int m_iRecvNAKTotal; // total number of received NAK packets
|
||||
int64_t m_llSndDurationTotal; // total real time for sending
|
||||
|
||||
uint64_t m_LastSampleTime; // last performance sample time
|
||||
int64_t m_llTraceSent; // number of pakctes sent in the last trace interval
|
||||
int64_t m_llTraceRecv; // number of pakctes received in the last trace interval
|
||||
int m_iTraceSndLoss; // number of lost packets in the last trace interval (sender side)
|
||||
int m_iTraceRcvLoss; // number of lost packets in the last trace interval (receiver side)
|
||||
int m_iTraceRetrans; // number of retransmitted packets in the last trace interval
|
||||
int m_iSentACK; // number of ACKs sent in the last trace interval
|
||||
int m_iRecvACK; // number of ACKs received in the last trace interval
|
||||
int m_iSentNAK; // number of NAKs sent in the last trace interval
|
||||
int m_iRecvNAK; // number of NAKs received in the last trace interval
|
||||
int64_t m_llSndDuration; // real time for sending
|
||||
int64_t m_llSndDurationCounter; // timers to record the sending duration
|
||||
|
||||
private: // Timers
|
||||
uint64_t m_ullCPUFrequency; // CPU clock frequency, used for Timer, ticks per microsecond
|
||||
|
||||
static const int m_iSYNInterval; // Periodical Rate Control Interval, 10000 microsecond
|
||||
static const int m_iSelfClockInterval; // ACK interval for self-clocking
|
||||
|
||||
uint64_t m_ullNextACKTime; // Next ACK time, in CPU clock cycles, same below
|
||||
uint64_t m_ullNextNAKTime; // Next NAK time
|
||||
|
||||
volatile uint64_t m_ullSYNInt; // SYN interval
|
||||
volatile uint64_t m_ullACKInt; // ACK interval
|
||||
volatile uint64_t m_ullNAKInt; // NAK interval
|
||||
volatile uint64_t m_ullLastRspTime; // time stamp of last response from the peer
|
||||
|
||||
uint64_t m_ullMinNakInt; // NAK timeout lower bound; too small value can cause unnecessary retransmission
|
||||
uint64_t m_ullMinExpInt; // timeout lower bound threshold: too small timeout can cause problem
|
||||
|
||||
int m_iPktCount; // packet counter for ACK
|
||||
int m_iLightACKCount; // light ACK counter
|
||||
|
||||
uint64_t m_ullTargetTime; // scheduled time of next packet sending
|
||||
|
||||
void checkTimers();
|
||||
|
||||
private: // for UDP multiplexer
|
||||
CSndQueue* m_pSndQueue; // packet sending queue
|
||||
CRcvQueue* m_pRcvQueue; // packet receiving queue
|
||||
sockaddr* m_pPeerAddr; // peer address
|
||||
uint32_t m_piSelfIP[4]; // local UDP IP address
|
||||
CSNode* m_pSNode; // node information for UDT list used in snd queue
|
||||
CRNode* m_pRNode; // node information for UDT list used in rcv queue
|
||||
|
||||
private: // for epoll
|
||||
std::set<int> m_sPollID; // set of epoll ID to trigger
|
||||
void addEPoll(const int eid);
|
||||
void removeEPoll(const int eid);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
367
vendor/udt4/src/epoll.cpp
vendored
367
vendor/udt4/src/epoll.cpp
vendored
|
|
@ -1,367 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/01/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef LINUX
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
#include "common.h"
|
||||
#include "epoll.h"
|
||||
#include "udt.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CEPoll::CEPoll():
|
||||
m_iIDSeed(0)
|
||||
{
|
||||
CGuard::createMutex(m_EPollLock);
|
||||
}
|
||||
|
||||
CEPoll::~CEPoll()
|
||||
{
|
||||
CGuard::releaseMutex(m_EPollLock);
|
||||
}
|
||||
|
||||
int CEPoll::create()
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
int localid = 0;
|
||||
|
||||
#ifdef LINUX
|
||||
localid = epoll_create(1024);
|
||||
if (localid < 0)
|
||||
throw CUDTException(-1, 0, errno);
|
||||
#else
|
||||
// on BSD, use kqueue
|
||||
// on Solaris, use /dev/poll
|
||||
// on Windows, select
|
||||
#endif
|
||||
|
||||
if (++ m_iIDSeed >= 0x7FFFFFFF)
|
||||
m_iIDSeed = 0;
|
||||
|
||||
CEPollDesc desc;
|
||||
desc.m_iID = m_iIDSeed;
|
||||
desc.m_iLocalID = localid;
|
||||
m_mPolls[desc.m_iID] = desc;
|
||||
|
||||
return desc.m_iID;
|
||||
}
|
||||
|
||||
int CEPoll::add_usock(const int eid, const UDTSOCKET& u, const int* events)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(5, 13);
|
||||
|
||||
if (!events || (*events & UDT_EPOLL_IN))
|
||||
p->second.m_sUDTSocksIn.insert(u);
|
||||
if (!events || (*events & UDT_EPOLL_OUT))
|
||||
p->second.m_sUDTSocksOut.insert(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(5, 13);
|
||||
|
||||
#ifdef LINUX
|
||||
epoll_event ev;
|
||||
memset(&ev, 0, sizeof(epoll_event));
|
||||
|
||||
if (NULL == events)
|
||||
ev.events = EPOLLIN | EPOLLOUT | EPOLLERR;
|
||||
else
|
||||
{
|
||||
ev.events = 0;
|
||||
if (*events & UDT_EPOLL_IN)
|
||||
ev.events |= EPOLLIN;
|
||||
if (*events & UDT_EPOLL_OUT)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (*events & UDT_EPOLL_ERR)
|
||||
ev.events |= EPOLLERR;
|
||||
}
|
||||
|
||||
ev.data.fd = s;
|
||||
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_ADD, s, &ev) < 0)
|
||||
throw CUDTException();
|
||||
#endif
|
||||
|
||||
p->second.m_sLocals.insert(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::remove_usock(const int eid, const UDTSOCKET& u)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(5, 13);
|
||||
|
||||
p->second.m_sUDTSocksIn.erase(u);
|
||||
p->second.m_sUDTSocksOut.erase(u);
|
||||
p->second.m_sUDTSocksEx.erase(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(5, 13);
|
||||
|
||||
#ifdef LINUX
|
||||
epoll_event ev; // ev is ignored, for compatibility with old Linux kernel only.
|
||||
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_DEL, s, &ev) < 0)
|
||||
throw CUDTException();
|
||||
#endif
|
||||
|
||||
p->second.m_sLocals.erase(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::wait(const int eid, set<UDTSOCKET>* readfds, set<UDTSOCKET>* writefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds)
|
||||
{
|
||||
// if all fields is NULL and waiting time is infinite, then this would be a deadlock
|
||||
if (!readfds && !writefds && !lrfds && lwfds && (msTimeOut < 0))
|
||||
throw CUDTException(5, 3, 0);
|
||||
|
||||
// Clear these sets in case the app forget to do it.
|
||||
if (readfds) readfds->clear();
|
||||
if (writefds) writefds->clear();
|
||||
if (lrfds) lrfds->clear();
|
||||
if (lwfds) lwfds->clear();
|
||||
|
||||
int total = 0;
|
||||
|
||||
int64_t entertime = CTimer::getTime();
|
||||
while (true)
|
||||
{
|
||||
CGuard::enterCS(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
{
|
||||
CGuard::leaveCS(m_EPollLock);
|
||||
throw CUDTException(5, 13);
|
||||
}
|
||||
|
||||
if (p->second.m_sUDTSocksIn.empty() && p->second.m_sUDTSocksOut.empty() && p->second.m_sLocals.empty() && (msTimeOut < 0))
|
||||
{
|
||||
// no socket is being monitored, this may be a deadlock
|
||||
CGuard::leaveCS(m_EPollLock);
|
||||
throw CUDTException(5, 3);
|
||||
}
|
||||
|
||||
// Sockets with exceptions are returned to both read and write sets.
|
||||
if ((NULL != readfds) && (!p->second.m_sUDTReads.empty() || !p->second.m_sUDTExcepts.empty()))
|
||||
{
|
||||
*readfds = p->second.m_sUDTReads;
|
||||
for (set<UDTSOCKET>::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i)
|
||||
readfds->insert(*i);
|
||||
total += p->second.m_sUDTReads.size() + p->second.m_sUDTExcepts.size();
|
||||
}
|
||||
if ((NULL != writefds) && (!p->second.m_sUDTWrites.empty() || !p->second.m_sUDTExcepts.empty()))
|
||||
{
|
||||
*writefds = p->second.m_sUDTWrites;
|
||||
for (set<UDTSOCKET>::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i)
|
||||
writefds->insert(*i);
|
||||
total += p->second.m_sUDTWrites.size() + p->second.m_sUDTExcepts.size();
|
||||
}
|
||||
|
||||
if (lrfds || lwfds)
|
||||
{
|
||||
#ifdef LINUX
|
||||
const int max_events = p->second.m_sLocals.size();
|
||||
epoll_event ev[max_events];
|
||||
int nfds = ::epoll_wait(p->second.m_iLocalID, ev, max_events, 0);
|
||||
|
||||
for (int i = 0; i < nfds; ++ i)
|
||||
{
|
||||
if ((NULL != lrfds) && (ev[i].events & EPOLLIN))
|
||||
{
|
||||
lrfds->insert(ev[i].data.fd);
|
||||
++ total;
|
||||
}
|
||||
if ((NULL != lwfds) && (ev[i].events & EPOLLOUT))
|
||||
{
|
||||
lwfds->insert(ev[i].data.fd);
|
||||
++ total;
|
||||
}
|
||||
}
|
||||
#else
|
||||
//currently "select" is used for all non-Linux platforms.
|
||||
//faster approaches can be applied for specific systems in the future.
|
||||
|
||||
//"select" has a limitation on the number of sockets
|
||||
|
||||
fd_set readfds;
|
||||
fd_set writefds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
|
||||
for (set<SYSSOCKET>::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i)
|
||||
{
|
||||
if (lrfds)
|
||||
FD_SET(*i, &readfds);
|
||||
if (lwfds)
|
||||
FD_SET(*i, &writefds);
|
||||
}
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
if (::select(0, &readfds, &writefds, NULL, &tv) > 0)
|
||||
{
|
||||
for (set<SYSSOCKET>::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i)
|
||||
{
|
||||
if (lrfds && FD_ISSET(*i, &readfds))
|
||||
{
|
||||
lrfds->insert(*i);
|
||||
++ total;
|
||||
}
|
||||
if (lwfds && FD_ISSET(*i, &writefds))
|
||||
{
|
||||
lwfds->insert(*i);
|
||||
++ total;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CGuard::leaveCS(m_EPollLock);
|
||||
|
||||
if (total > 0)
|
||||
return total;
|
||||
|
||||
if ((msTimeOut >= 0) && (int64_t(CTimer::getTime() - entertime) >= msTimeOut * 1000LL))
|
||||
throw CUDTException(6, 3, 0);
|
||||
|
||||
CTimer::waitForEvent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::release(const int eid)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator i = m_mPolls.find(eid);
|
||||
if (i == m_mPolls.end())
|
||||
throw CUDTException(5, 13);
|
||||
|
||||
#ifdef LINUX
|
||||
// release local/system epoll descriptor
|
||||
::close(i->second.m_iLocalID);
|
||||
#endif
|
||||
|
||||
m_mPolls.erase(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void update_epoll_sets(const UDTSOCKET& uid, const set<UDTSOCKET>& watch, set<UDTSOCKET>& result, bool enable)
|
||||
{
|
||||
if (enable && (watch.find(uid) != watch.end()))
|
||||
{
|
||||
result.insert(uid);
|
||||
}
|
||||
else if (!enable)
|
||||
{
|
||||
result.erase(uid);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int CEPoll::update_events(const UDTSOCKET& uid, std::set<int>& eids, int events, bool enable)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p;
|
||||
|
||||
vector<int> lost;
|
||||
for (set<int>::iterator i = eids.begin(); i != eids.end(); ++ i)
|
||||
{
|
||||
p = m_mPolls.find(*i);
|
||||
if (p == m_mPolls.end())
|
||||
{
|
||||
lost.push_back(*i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((events & UDT_EPOLL_IN) != 0)
|
||||
update_epoll_sets(uid, p->second.m_sUDTSocksIn, p->second.m_sUDTReads, enable);
|
||||
if ((events & UDT_EPOLL_OUT) != 0)
|
||||
update_epoll_sets(uid, p->second.m_sUDTSocksOut, p->second.m_sUDTWrites, enable);
|
||||
if ((events & UDT_EPOLL_ERR) != 0)
|
||||
update_epoll_sets(uid, p->second.m_sUDTSocksEx, p->second.m_sUDTExcepts, enable);
|
||||
}
|
||||
}
|
||||
|
||||
for (vector<int>::iterator i = lost.begin(); i != lost.end(); ++ i)
|
||||
eids.erase(*i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
173
vendor/udt4/src/epoll.h
vendored
173
vendor/udt4/src/epoll.h
vendored
|
|
@ -1,173 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 08/20/2010
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_EPOLL_H__
|
||||
#define __UDT_EPOLL_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "udt.h"
|
||||
|
||||
|
||||
struct CEPollDesc
|
||||
{
|
||||
int m_iID; // epoll ID
|
||||
std::set<UDTSOCKET> m_sUDTSocksOut; // set of UDT sockets waiting for write events
|
||||
std::set<UDTSOCKET> m_sUDTSocksIn; // set of UDT sockets waiting for read events
|
||||
std::set<UDTSOCKET> m_sUDTSocksEx; // set of UDT sockets waiting for exceptions
|
||||
|
||||
int m_iLocalID; // local system epoll ID
|
||||
std::set<SYSSOCKET> m_sLocals; // set of local (non-UDT) descriptors
|
||||
|
||||
std::set<UDTSOCKET> m_sUDTWrites; // UDT sockets ready for write
|
||||
std::set<UDTSOCKET> m_sUDTReads; // UDT sockets ready for read
|
||||
std::set<UDTSOCKET> m_sUDTExcepts; // UDT sockets with exceptions (connection broken, etc.)
|
||||
};
|
||||
|
||||
class CEPoll
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CRendezvousQueue;
|
||||
|
||||
public:
|
||||
CEPoll();
|
||||
~CEPoll();
|
||||
|
||||
public: // for CUDTUnited API
|
||||
|
||||
// Functionality:
|
||||
// create a new EPoll.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// new EPoll ID if success, otherwise an error number.
|
||||
|
||||
int create();
|
||||
|
||||
// Functionality:
|
||||
// add a UDT socket to an EPoll.
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// 1) [in] u: UDT Socket ID.
|
||||
// 2) [in] events: events to watch.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number.
|
||||
|
||||
int add_usock(const int eid, const UDTSOCKET& u, const int* events = NULL);
|
||||
|
||||
// Functionality:
|
||||
// add a system socket to an EPoll.
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// 1) [in] s: system Socket ID.
|
||||
// 2) [in] events: events to watch.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number.
|
||||
|
||||
int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
|
||||
|
||||
// Functionality:
|
||||
// remove a UDT socket event from an EPoll; socket will be removed if no events to watch
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// 1) [in] u: UDT socket ID.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number.
|
||||
|
||||
int remove_usock(const int eid, const UDTSOCKET& u);
|
||||
|
||||
// Functionality:
|
||||
// remove a system socket event from an EPoll; socket will be removed if no events to watch
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// 1) [in] s: system socket ID.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number.
|
||||
|
||||
int remove_ssock(const int eid, const SYSSOCKET& s);
|
||||
|
||||
// Functionality:
|
||||
// wait for EPoll events or timeout.
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// 1) [out] readfds: UDT sockets available for reading.
|
||||
// 2) [out] writefds: UDT sockets available for writing.
|
||||
// 3) [in] msTimeOut: timeout threshold, in milliseconds.
|
||||
// 4) [out] lrfds: system file descriptors for reading.
|
||||
// 5) [out] lwfds: system file descriptors for writing.
|
||||
// Returned value:
|
||||
// number of sockets available for IO.
|
||||
|
||||
int wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds, std::set<SYSSOCKET>* lwfds);
|
||||
|
||||
// Functionality:
|
||||
// close and release an EPoll.
|
||||
// Parameters:
|
||||
// 0) [in] eid: EPoll ID.
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number.
|
||||
|
||||
int release(const int eid);
|
||||
|
||||
public: // for CUDT to acknowledge IO status
|
||||
|
||||
// Functionality:
|
||||
// Update events available for a UDT socket.
|
||||
// Parameters:
|
||||
// 0) [in] uid: UDT socket ID.
|
||||
// 1) [in] eids: EPoll IDs to be set
|
||||
// 1) [in] events: Combination of events to update
|
||||
// 1) [in] enable: true -> enable, otherwise disable
|
||||
// Returned value:
|
||||
// 0 if success, otherwise an error number
|
||||
|
||||
int update_events(const UDTSOCKET& uid, std::set<int>& eids, int events, bool enable);
|
||||
|
||||
private:
|
||||
int m_iIDSeed; // seed to generate a new ID
|
||||
pthread_mutex_t m_SeedLock;
|
||||
|
||||
std::map<int, CEPollDesc> m_mPolls; // all epolls
|
||||
pthread_mutex_t m_EPollLock;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
703
vendor/udt4/src/list.cpp
vendored
703
vendor/udt4/src/list.cpp
vendored
|
|
@ -1,703 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/22/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
CSndLossList::CSndLossList(int size):
|
||||
m_piData1(NULL),
|
||||
m_piData2(NULL),
|
||||
m_piNext(NULL),
|
||||
m_iHead(-1),
|
||||
m_iLength(0),
|
||||
m_iSize(size),
|
||||
m_iLastInsertPos(-1),
|
||||
m_ListLock()
|
||||
{
|
||||
m_piData1 = new int32_t [m_iSize];
|
||||
m_piData2 = new int32_t [m_iSize];
|
||||
m_piNext = new int [m_iSize];
|
||||
|
||||
// -1 means there is no data in the node
|
||||
for (int i = 0; i < size; ++ i)
|
||||
{
|
||||
m_piData1[i] = -1;
|
||||
m_piData2[i] = -1;
|
||||
}
|
||||
|
||||
// sender list needs mutex protection
|
||||
#ifndef WIN32
|
||||
pthread_mutex_init(&m_ListLock, 0);
|
||||
#else
|
||||
m_ListLock = CreateMutex(NULL, false, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
CSndLossList::~CSndLossList()
|
||||
{
|
||||
delete [] m_piData1;
|
||||
delete [] m_piData2;
|
||||
delete [] m_piNext;
|
||||
|
||||
#ifndef WIN32
|
||||
pthread_mutex_destroy(&m_ListLock);
|
||||
#else
|
||||
CloseHandle(m_ListLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
int CSndLossList::insert(int32_t seqno1, int32_t seqno2)
|
||||
{
|
||||
CGuard listguard(m_ListLock);
|
||||
|
||||
if (0 == m_iLength)
|
||||
{
|
||||
// insert data into an empty list
|
||||
|
||||
m_iHead = 0;
|
||||
m_piData1[m_iHead] = seqno1;
|
||||
if (seqno2 != seqno1)
|
||||
m_piData2[m_iHead] = seqno2;
|
||||
|
||||
m_piNext[m_iHead] = -1;
|
||||
m_iLastInsertPos = m_iHead;
|
||||
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
|
||||
|
||||
return m_iLength;
|
||||
}
|
||||
|
||||
// otherwise find the position where the data can be inserted
|
||||
int origlen = m_iLength;
|
||||
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1);
|
||||
int loc = (m_iHead + offset + m_iSize) % m_iSize;
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
// Insert data prior to the head pointer
|
||||
|
||||
m_piData1[loc] = seqno1;
|
||||
if (seqno2 != seqno1)
|
||||
m_piData2[loc] = seqno2;
|
||||
|
||||
// new node becomes head
|
||||
m_piNext[loc] = m_iHead;
|
||||
m_iHead = loc;
|
||||
m_iLastInsertPos = loc;
|
||||
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
|
||||
}
|
||||
else if (offset > 0)
|
||||
{
|
||||
if (seqno1 == m_piData1[loc])
|
||||
{
|
||||
m_iLastInsertPos = loc;
|
||||
|
||||
// first seqno is equivlent, compare the second
|
||||
if (-1 == m_piData2[loc])
|
||||
{
|
||||
if (seqno2 != seqno1)
|
||||
{
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1;
|
||||
m_piData2[loc] = seqno2;
|
||||
}
|
||||
}
|
||||
else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0)
|
||||
{
|
||||
// new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7]
|
||||
m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1;
|
||||
m_piData2[loc] = seqno2;
|
||||
}
|
||||
else
|
||||
// Do nothing if it is already there
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// searching the prior node
|
||||
int i;
|
||||
if ((-1 != m_iLastInsertPos) && (CSeqNo::seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0))
|
||||
i = m_iLastInsertPos;
|
||||
else
|
||||
i = m_iHead;
|
||||
|
||||
while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno1) < 0))
|
||||
i = m_piNext[i];
|
||||
|
||||
if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(m_piData2[i], seqno1) < 0))
|
||||
{
|
||||
m_iLastInsertPos = loc;
|
||||
|
||||
// no overlap, create new node
|
||||
m_piData1[loc] = seqno1;
|
||||
if (seqno2 != seqno1)
|
||||
m_piData2[loc] = seqno2;
|
||||
|
||||
m_piNext[loc] = m_piNext[i];
|
||||
m_piNext[i] = loc;
|
||||
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iLastInsertPos = i;
|
||||
|
||||
// overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7]
|
||||
if (CSeqNo::seqcmp(m_piData2[i], seqno2) < 0)
|
||||
{
|
||||
m_iLength += CSeqNo::seqlen(m_piData2[i], seqno2) - 1;
|
||||
m_piData2[i] = seqno2;
|
||||
|
||||
loc = i;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iLastInsertPos = m_iHead;
|
||||
|
||||
// insert to head node
|
||||
if (seqno2 != seqno1)
|
||||
{
|
||||
if (-1 == m_piData2[loc])
|
||||
{
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1;
|
||||
m_piData2[loc] = seqno2;
|
||||
}
|
||||
else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0)
|
||||
{
|
||||
m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1;
|
||||
m_piData2[loc] = seqno2;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9]
|
||||
while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc]))
|
||||
{
|
||||
int i = m_piNext[loc];
|
||||
|
||||
if (CSeqNo::seqcmp(m_piData1[i], CSeqNo::incseq(m_piData2[loc])) <= 0)
|
||||
{
|
||||
// coalesce if there is overlap
|
||||
if (-1 != m_piData2[i])
|
||||
{
|
||||
if (CSeqNo::seqcmp(m_piData2[i], m_piData2[loc]) > 0)
|
||||
{
|
||||
if (CSeqNo::seqcmp(m_piData2[loc], m_piData1[i]) >= 0)
|
||||
m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[loc]);
|
||||
|
||||
m_piData2[loc] = m_piData2[i];
|
||||
}
|
||||
else
|
||||
m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_piData1[i] == CSeqNo::incseq(m_piData2[loc]))
|
||||
m_piData2[loc] = m_piData1[i];
|
||||
else
|
||||
m_iLength --;
|
||||
}
|
||||
|
||||
m_piData1[i] = -1;
|
||||
m_piData2[i] = -1;
|
||||
m_piNext[loc] = m_piNext[i];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return m_iLength - origlen;
|
||||
}
|
||||
|
||||
void CSndLossList::remove(int32_t seqno)
|
||||
{
|
||||
CGuard listguard(m_ListLock);
|
||||
|
||||
if (0 == m_iLength)
|
||||
return;
|
||||
|
||||
// Remove all from the head pointer to a node with a larger seq. no. or the list is empty
|
||||
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno);
|
||||
int loc = (m_iHead + offset + m_iSize) % m_iSize;
|
||||
|
||||
if (0 == offset)
|
||||
{
|
||||
// It is the head. Remove the head and point to the next node
|
||||
loc = (loc + 1) % m_iSize;
|
||||
|
||||
if (-1 == m_piData2[m_iHead])
|
||||
loc = m_piNext[m_iHead];
|
||||
else
|
||||
{
|
||||
m_piData1[loc] = CSeqNo::incseq(seqno);
|
||||
if (CSeqNo::seqcmp(m_piData2[m_iHead], CSeqNo::incseq(seqno)) > 0)
|
||||
m_piData2[loc] = m_piData2[m_iHead];
|
||||
|
||||
m_piData2[m_iHead] = -1;
|
||||
|
||||
m_piNext[loc] = m_piNext[m_iHead];
|
||||
}
|
||||
|
||||
m_piData1[m_iHead] = -1;
|
||||
|
||||
if (m_iLastInsertPos == m_iHead)
|
||||
m_iLastInsertPos = -1;
|
||||
|
||||
m_iHead = loc;
|
||||
|
||||
m_iLength --;
|
||||
}
|
||||
else if (offset > 0)
|
||||
{
|
||||
int h = m_iHead;
|
||||
|
||||
if (seqno == m_piData1[loc])
|
||||
{
|
||||
// target node is not empty, remove part/all of the seqno in the node.
|
||||
int temp = loc;
|
||||
loc = (loc + 1) % m_iSize;
|
||||
|
||||
if (-1 == m_piData2[temp])
|
||||
m_iHead = m_piNext[temp];
|
||||
else
|
||||
{
|
||||
// remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3)
|
||||
m_piData1[loc] = CSeqNo::incseq(seqno);
|
||||
if (CSeqNo::seqcmp(m_piData2[temp], m_piData1[loc]) > 0)
|
||||
m_piData2[loc] = m_piData2[temp];
|
||||
m_iHead = loc;
|
||||
m_piNext[loc] = m_piNext[temp];
|
||||
m_piNext[temp] = loc;
|
||||
m_piData2[temp] = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// target node is empty, check prior node
|
||||
int i = m_iHead;
|
||||
while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno) < 0))
|
||||
i = m_piNext[i];
|
||||
|
||||
loc = (loc + 1) % m_iSize;
|
||||
|
||||
if (-1 == m_piData2[i])
|
||||
m_iHead = m_piNext[i];
|
||||
else if (CSeqNo::seqcmp(m_piData2[i], seqno) > 0)
|
||||
{
|
||||
// remove part/all seqno in the prior node
|
||||
m_piData1[loc] = CSeqNo::incseq(seqno);
|
||||
if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0)
|
||||
m_piData2[loc] = m_piData2[i];
|
||||
|
||||
m_piData2[i] = seqno;
|
||||
|
||||
m_piNext[loc] = m_piNext[i];
|
||||
m_piNext[i] = loc;
|
||||
|
||||
m_iHead = loc;
|
||||
}
|
||||
else
|
||||
m_iHead = m_piNext[i];
|
||||
}
|
||||
|
||||
// Remove all nodes prior to the new head
|
||||
while (h != m_iHead)
|
||||
{
|
||||
if (m_piData2[h] != -1)
|
||||
{
|
||||
m_iLength -= CSeqNo::seqlen(m_piData1[h], m_piData2[h]);
|
||||
m_piData2[h] = -1;
|
||||
}
|
||||
else
|
||||
m_iLength --;
|
||||
|
||||
m_piData1[h] = -1;
|
||||
|
||||
if (m_iLastInsertPos == h)
|
||||
m_iLastInsertPos = -1;
|
||||
|
||||
h = m_piNext[h];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CSndLossList::getLossLength()
|
||||
{
|
||||
CGuard listguard(m_ListLock);
|
||||
|
||||
return m_iLength;
|
||||
}
|
||||
|
||||
int32_t CSndLossList::getLostSeq()
|
||||
{
|
||||
if (0 == m_iLength)
|
||||
return -1;
|
||||
|
||||
CGuard listguard(m_ListLock);
|
||||
|
||||
if (0 == m_iLength)
|
||||
return -1;
|
||||
|
||||
if (m_iLastInsertPos == m_iHead)
|
||||
m_iLastInsertPos = -1;
|
||||
|
||||
// return the first loss seq. no.
|
||||
int32_t seqno = m_piData1[m_iHead];
|
||||
|
||||
// head moves to the next node
|
||||
if (-1 == m_piData2[m_iHead])
|
||||
{
|
||||
//[3, -1] becomes [], and head moves to next node in the list
|
||||
m_piData1[m_iHead] = -1;
|
||||
m_iHead = m_piNext[m_iHead];
|
||||
}
|
||||
else
|
||||
{
|
||||
// shift to next node, e.g., [3, 7] becomes [], [4, 7]
|
||||
int loc = (m_iHead + 1) % m_iSize;
|
||||
|
||||
m_piData1[loc] = CSeqNo::incseq(seqno);
|
||||
if (CSeqNo::seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0)
|
||||
m_piData2[loc] = m_piData2[m_iHead];
|
||||
|
||||
m_piData1[m_iHead] = -1;
|
||||
m_piData2[m_iHead] = -1;
|
||||
|
||||
m_piNext[loc] = m_piNext[m_iHead];
|
||||
m_iHead = loc;
|
||||
}
|
||||
|
||||
m_iLength --;
|
||||
|
||||
return seqno;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CRcvLossList::CRcvLossList(int size):
|
||||
m_piData1(NULL),
|
||||
m_piData2(NULL),
|
||||
m_piNext(NULL),
|
||||
m_piPrior(NULL),
|
||||
m_iHead(-1),
|
||||
m_iTail(-1),
|
||||
m_iLength(0),
|
||||
m_iSize(size)
|
||||
{
|
||||
m_piData1 = new int32_t [m_iSize];
|
||||
m_piData2 = new int32_t [m_iSize];
|
||||
m_piNext = new int [m_iSize];
|
||||
m_piPrior = new int [m_iSize];
|
||||
|
||||
// -1 means there is no data in the node
|
||||
for (int i = 0; i < size; ++ i)
|
||||
{
|
||||
m_piData1[i] = -1;
|
||||
m_piData2[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CRcvLossList::~CRcvLossList()
|
||||
{
|
||||
delete [] m_piData1;
|
||||
delete [] m_piData2;
|
||||
delete [] m_piNext;
|
||||
delete [] m_piPrior;
|
||||
}
|
||||
|
||||
void CRcvLossList::insert(int32_t seqno1, int32_t seqno2)
|
||||
{
|
||||
// Data to be inserted must be larger than all those in the list
|
||||
// guaranteed by the UDT receiver
|
||||
|
||||
if (0 == m_iLength)
|
||||
{
|
||||
// insert data into an empty list
|
||||
m_iHead = 0;
|
||||
m_iTail = 0;
|
||||
m_piData1[m_iHead] = seqno1;
|
||||
if (seqno2 != seqno1)
|
||||
m_piData2[m_iHead] = seqno2;
|
||||
|
||||
m_piNext[m_iHead] = -1;
|
||||
m_piPrior[m_iHead] = -1;
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise searching for the position where the node should be
|
||||
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1);
|
||||
int loc = (m_iHead + offset) % m_iSize;
|
||||
|
||||
if ((-1 != m_piData2[m_iTail]) && (CSeqNo::incseq(m_piData2[m_iTail]) == seqno1))
|
||||
{
|
||||
// coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7]
|
||||
loc = m_iTail;
|
||||
m_piData2[loc] = seqno2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new node
|
||||
m_piData1[loc] = seqno1;
|
||||
|
||||
if (seqno2 != seqno1)
|
||||
m_piData2[loc] = seqno2;
|
||||
|
||||
m_piNext[m_iTail] = loc;
|
||||
m_piPrior[loc] = m_iTail;
|
||||
m_piNext[loc] = -1;
|
||||
m_iTail = loc;
|
||||
}
|
||||
|
||||
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
|
||||
}
|
||||
|
||||
bool CRcvLossList::remove(int32_t seqno)
|
||||
{
|
||||
if (0 == m_iLength)
|
||||
return false;
|
||||
|
||||
// locate the position of "seqno" in the list
|
||||
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno);
|
||||
if (offset < 0)
|
||||
return false;
|
||||
|
||||
int loc = (m_iHead + offset) % m_iSize;
|
||||
|
||||
if (seqno == m_piData1[loc])
|
||||
{
|
||||
// This is a seq. no. that starts the loss sequence
|
||||
|
||||
if (-1 == m_piData2[loc])
|
||||
{
|
||||
// there is only 1 loss in the sequence, delete it from the node
|
||||
if (m_iHead == loc)
|
||||
{
|
||||
m_iHead = m_piNext[m_iHead];
|
||||
if (-1 != m_iHead)
|
||||
m_piPrior[m_iHead] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_piNext[m_piPrior[loc]] = m_piNext[loc];
|
||||
if (-1 != m_piNext[loc])
|
||||
m_piPrior[m_piNext[loc]] = m_piPrior[loc];
|
||||
else
|
||||
m_iTail = m_piPrior[loc];
|
||||
}
|
||||
|
||||
m_piData1[loc] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// there are more than 1 loss in the sequence
|
||||
// move the node to the next and update the starter as the next loss inSeqNo(seqno)
|
||||
|
||||
// find next node
|
||||
int i = (loc + 1) % m_iSize;
|
||||
|
||||
// remove the "seqno" and change the starter as next seq. no.
|
||||
m_piData1[i] = CSeqNo::incseq(m_piData1[loc]);
|
||||
|
||||
// process the sequence end
|
||||
if (CSeqNo::seqcmp(m_piData2[loc], CSeqNo::incseq(m_piData1[loc])) > 0)
|
||||
m_piData2[i] = m_piData2[loc];
|
||||
|
||||
// remove the current node
|
||||
m_piData1[loc] = -1;
|
||||
m_piData2[loc] = -1;
|
||||
|
||||
// update list pointer
|
||||
m_piNext[i] = m_piNext[loc];
|
||||
m_piPrior[i] = m_piPrior[loc];
|
||||
|
||||
if (m_iHead == loc)
|
||||
m_iHead = i;
|
||||
else
|
||||
m_piNext[m_piPrior[i]] = i;
|
||||
|
||||
if (m_iTail == loc)
|
||||
m_iTail = i;
|
||||
else
|
||||
m_piPrior[m_piNext[i]] = i;
|
||||
}
|
||||
|
||||
m_iLength --;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// There is no loss sequence in the current position
|
||||
// the "seqno" may be contained in a previous node
|
||||
|
||||
// searching previous node
|
||||
int i = (loc - 1 + m_iSize) % m_iSize;
|
||||
while (-1 == m_piData1[i])
|
||||
i = (i - 1 + m_iSize) % m_iSize;
|
||||
|
||||
// not contained in this node, return
|
||||
if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(seqno, m_piData2[i]) > 0))
|
||||
return false;
|
||||
|
||||
if (seqno == m_piData2[i])
|
||||
{
|
||||
// it is the sequence end
|
||||
|
||||
if (seqno == CSeqNo::incseq(m_piData1[i]))
|
||||
m_piData2[i] = -1;
|
||||
else
|
||||
m_piData2[i] = CSeqNo::decseq(seqno);
|
||||
}
|
||||
else
|
||||
{
|
||||
// split the sequence
|
||||
|
||||
// construct the second sequence from CSeqNo::incseq(seqno) to the original sequence end
|
||||
// located at "loc + 1"
|
||||
loc = (loc + 1) % m_iSize;
|
||||
|
||||
m_piData1[loc] = CSeqNo::incseq(seqno);
|
||||
if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0)
|
||||
m_piData2[loc] = m_piData2[i];
|
||||
|
||||
// the first (original) sequence is between the original sequence start to CSeqNo::decseq(seqno)
|
||||
if (seqno == CSeqNo::incseq(m_piData1[i]))
|
||||
m_piData2[i] = -1;
|
||||
else
|
||||
m_piData2[i] = CSeqNo::decseq(seqno);
|
||||
|
||||
// update the list pointer
|
||||
m_piNext[loc] = m_piNext[i];
|
||||
m_piNext[i] = loc;
|
||||
m_piPrior[loc] = i;
|
||||
|
||||
if (m_iTail == i)
|
||||
m_iTail = loc;
|
||||
else
|
||||
m_piPrior[m_piNext[loc]] = loc;
|
||||
}
|
||||
|
||||
m_iLength --;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CRcvLossList::remove(int32_t seqno1, int32_t seqno2)
|
||||
{
|
||||
if (seqno1 <= seqno2)
|
||||
{
|
||||
for (int32_t i = seqno1; i <= seqno2; ++ i)
|
||||
remove(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int32_t j = seqno1; j < CSeqNo::m_iMaxSeqNo; ++ j)
|
||||
remove(j);
|
||||
for (int32_t k = 0; k <= seqno2; ++ k)
|
||||
remove(k);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CRcvLossList::find(int32_t seqno1, int32_t seqno2) const
|
||||
{
|
||||
if (0 == m_iLength)
|
||||
return false;
|
||||
|
||||
int p = m_iHead;
|
||||
|
||||
while (-1 != p)
|
||||
{
|
||||
if ((CSeqNo::seqcmp(m_piData1[p], seqno1) == 0) ||
|
||||
((CSeqNo::seqcmp(m_piData1[p], seqno1) > 0) && (CSeqNo::seqcmp(m_piData1[p], seqno2) <= 0)) ||
|
||||
((CSeqNo::seqcmp(m_piData1[p], seqno1) < 0) && (m_piData2[p] != -1) && CSeqNo::seqcmp(m_piData2[p], seqno1) >= 0))
|
||||
return true;
|
||||
|
||||
p = m_piNext[p];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CRcvLossList::getLossLength() const
|
||||
{
|
||||
return m_iLength;
|
||||
}
|
||||
|
||||
int CRcvLossList::getFirstLostSeq() const
|
||||
{
|
||||
if (0 == m_iLength)
|
||||
return -1;
|
||||
|
||||
return m_piData1[m_iHead];
|
||||
}
|
||||
|
||||
void CRcvLossList::getLossArray(int32_t* array, int& len, int limit)
|
||||
{
|
||||
len = 0;
|
||||
|
||||
int i = m_iHead;
|
||||
|
||||
while ((len < limit - 1) && (-1 != i))
|
||||
{
|
||||
array[len] = m_piData1[i];
|
||||
if (-1 != m_piData2[i])
|
||||
{
|
||||
// there are more than 1 loss in the sequence
|
||||
array[len] |= 0x80000000;
|
||||
++ len;
|
||||
array[len] = m_piData2[i];
|
||||
}
|
||||
|
||||
++ len;
|
||||
|
||||
i = m_piNext[i];
|
||||
}
|
||||
}
|
||||
202
vendor/udt4/src/list.h
vendored
202
vendor/udt4/src/list.h
vendored
|
|
@ -1,202 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/22/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_LIST_H__
|
||||
#define __UDT_LIST_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
class CSndLossList
|
||||
{
|
||||
public:
|
||||
CSndLossList(int size = 1024);
|
||||
~CSndLossList();
|
||||
|
||||
// Functionality:
|
||||
// Insert a seq. no. into the sender loss list.
|
||||
// Parameters:
|
||||
// 0) [in] seqno1: sequence number starts.
|
||||
// 1) [in] seqno2: sequence number ends.
|
||||
// Returned value:
|
||||
// number of packets that are not in the list previously.
|
||||
|
||||
int insert(int32_t seqno1, int32_t seqno2);
|
||||
|
||||
// Functionality:
|
||||
// Remove ALL the seq. no. that are not greater than the parameter.
|
||||
// Parameters:
|
||||
// 0) [in] seqno: sequence number.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void remove(int32_t seqno);
|
||||
|
||||
// Functionality:
|
||||
// Read the loss length.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// The length of the list.
|
||||
|
||||
int getLossLength();
|
||||
|
||||
// Functionality:
|
||||
// Read the first (smallest) loss seq. no. in the list and remove it.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// The seq. no. or -1 if the list is empty.
|
||||
|
||||
int32_t getLostSeq();
|
||||
|
||||
private:
|
||||
int32_t* m_piData1; // sequence number starts
|
||||
int32_t* m_piData2; // seqnence number ends
|
||||
int* m_piNext; // next node in the list
|
||||
|
||||
int m_iHead; // first node
|
||||
int m_iLength; // loss length
|
||||
int m_iSize; // size of the static array
|
||||
int m_iLastInsertPos; // position of last insert node
|
||||
|
||||
pthread_mutex_t m_ListLock; // used to synchronize list operation
|
||||
|
||||
private:
|
||||
CSndLossList(const CSndLossList&);
|
||||
CSndLossList& operator=(const CSndLossList&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CRcvLossList
|
||||
{
|
||||
public:
|
||||
CRcvLossList(int size = 1024);
|
||||
~CRcvLossList();
|
||||
|
||||
// Functionality:
|
||||
// Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list.
|
||||
// Parameters:
|
||||
// 0) [in] seqno1: sequence number starts.
|
||||
// 1) [in] seqno2: seqeunce number ends.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void insert(int32_t seqno1, int32_t seqno2);
|
||||
|
||||
// Functionality:
|
||||
// Remove a loss seq. no. from the receiver's loss list.
|
||||
// Parameters:
|
||||
// 0) [in] seqno: sequence number.
|
||||
// Returned value:
|
||||
// if the packet is removed (true) or no such lost packet is found (false).
|
||||
|
||||
bool remove(int32_t seqno);
|
||||
|
||||
// Functionality:
|
||||
// Remove all packets between seqno1 and seqno2.
|
||||
// Parameters:
|
||||
// 0) [in] seqno1: start sequence number.
|
||||
// 1) [in] seqno2: end sequence number.
|
||||
// Returned value:
|
||||
// if the packet is removed (true) or no such lost packet is found (false).
|
||||
|
||||
bool remove(int32_t seqno1, int32_t seqno2);
|
||||
|
||||
// Functionality:
|
||||
// Find if there is any lost packets whose sequence number falling seqno1 and seqno2.
|
||||
// Parameters:
|
||||
// 0) [in] seqno1: start sequence number.
|
||||
// 1) [in] seqno2: end sequence number.
|
||||
// Returned value:
|
||||
// True if found; otherwise false.
|
||||
|
||||
bool find(int32_t seqno1, int32_t seqno2) const;
|
||||
|
||||
// Functionality:
|
||||
// Read the loss length.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// the length of the list.
|
||||
|
||||
int getLossLength() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the first (smallest) seq. no. in the list.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// the sequence number or -1 if the list is empty.
|
||||
|
||||
int getFirstLostSeq() const;
|
||||
|
||||
// Functionality:
|
||||
// Get a encoded loss array for NAK report.
|
||||
// Parameters:
|
||||
// 0) [out] array: the result list of seq. no. to be included in NAK.
|
||||
// 1) [out] physical length of the result array.
|
||||
// 2) [in] limit: maximum length of the array.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void getLossArray(int32_t* array, int& len, int limit);
|
||||
|
||||
private:
|
||||
int32_t* m_piData1; // sequence number starts
|
||||
int32_t* m_piData2; // sequence number ends
|
||||
int* m_piNext; // next node in the list
|
||||
int* m_piPrior; // prior node in the list;
|
||||
|
||||
int m_iHead; // first node in the list
|
||||
int m_iTail; // last node in the list;
|
||||
int m_iLength; // loss length
|
||||
int m_iSize; // size of the static array
|
||||
|
||||
private:
|
||||
CRcvLossList(const CRcvLossList&);
|
||||
CRcvLossList& operator=(const CRcvLossList&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
381
vendor/udt4/src/md5.cpp
vendored
381
vendor/udt4/src/md5.cpp
vendored
|
|
@ -1,381 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.cpp,v 1.3 2008/01/20 22:52:04 lilyco Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
# define BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
#define T_MASK ((md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
md5_word_t xbuf[16];
|
||||
const md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const md5_word_t *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
md5_init(md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||
{
|
||||
static const md5_byte_t pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
91
vendor/udt4/src/md5.h
vendored
91
vendor/udt4/src/md5.h
vendored
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
||||
411
vendor/udt4/src/packet.cpp
vendored
411
vendor/udt4/src/packet.cpp
vendored
|
|
@ -1,411 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 02/12/2011
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Packet Header |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// ~ Data / Control Information Field ~
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |0| Sequence Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |ff |o| Message Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Time Stamp |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Destination Socket ID |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// bit 0:
|
||||
// 0: Data Packet
|
||||
// 1: Control Packet
|
||||
// bit ff:
|
||||
// 11: solo message packet
|
||||
// 10: first packet of a message
|
||||
// 01: last packet of a message
|
||||
// bit o:
|
||||
// 0: in order delivery not required
|
||||
// 1: in order delivery required
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1| Type | Reserved |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Additional Info |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Time Stamp |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Destination Socket ID |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// bit 1-15:
|
||||
// 0: Protocol Connection Handshake
|
||||
// Add. Info: Undefined
|
||||
// Control Info: Handshake information (see CHandShake)
|
||||
// 1: Keep-alive
|
||||
// Add. Info: Undefined
|
||||
// Control Info: None
|
||||
// 2: Acknowledgement (ACK)
|
||||
// Add. Info: The ACK sequence number
|
||||
// Control Info: The sequence number to which (but not include) all the previous packets have beed received
|
||||
// Optional: RTT
|
||||
// RTT Variance
|
||||
// available receiver buffer size (in bytes)
|
||||
// advertised flow window size (number of packets)
|
||||
// estimated bandwidth (number of packets per second)
|
||||
// 3: Negative Acknowledgement (NAK)
|
||||
// Add. Info: Undefined
|
||||
// Control Info: Loss list (see loss list coding below)
|
||||
// 4: Congestion/Delay Warning
|
||||
// Add. Info: Undefined
|
||||
// Control Info: None
|
||||
// 5: Shutdown
|
||||
// Add. Info: Undefined
|
||||
// Control Info: None
|
||||
// 6: Acknowledgement of Acknowledement (ACK-square)
|
||||
// Add. Info: The ACK sequence number
|
||||
// Control Info: None
|
||||
// 7: Message Drop Request
|
||||
// Add. Info: Message ID
|
||||
// Control Info: first sequence number of the message
|
||||
// last seqeunce number of the message
|
||||
// 8: Error Signal from the Peer Side
|
||||
// Add. Info: Error code
|
||||
// Control Info: None
|
||||
// 0x7FFF: Explained by bits 16 - 31
|
||||
//
|
||||
// bit 16 - 31:
|
||||
// This space is used for future expansion or user defined control packets.
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1| Sequence Number a (first) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |0| Sequence Number b (last) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |0| Sequence Number (single) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Loss List Field Coding:
|
||||
// For any consectutive lost seqeunce numbers that the differnece between
|
||||
// the last and first is more than 1, only record the first (a) and the
|
||||
// the last (b) sequence numbers in the loss list field, and modify the
|
||||
// the first bit of a to 1.
|
||||
// For any single loss or consectutive loss less than 2 packets, use
|
||||
// the original sequence numbers in the field.
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
const int CPacket::m_iPktHdrSize = 16;
|
||||
const int CHandShake::m_iContentSize = 48;
|
||||
|
||||
|
||||
// Set up the aliases in the constructure
|
||||
CPacket::CPacket():
|
||||
m_iSeqNo((int32_t&)(m_nHeader[0])),
|
||||
m_iMsgNo((int32_t&)(m_nHeader[1])),
|
||||
m_iTimeStamp((int32_t&)(m_nHeader[2])),
|
||||
m_iID((int32_t&)(m_nHeader[3])),
|
||||
m_pcData((char*&)(m_PacketVector[1].iov_base)),
|
||||
__pad()
|
||||
{
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
m_nHeader[i] = 0;
|
||||
m_PacketVector[0].iov_base = (char *)m_nHeader;
|
||||
m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize;
|
||||
m_PacketVector[1].iov_base = NULL;
|
||||
m_PacketVector[1].iov_len = 0;
|
||||
}
|
||||
|
||||
CPacket::~CPacket()
|
||||
{
|
||||
}
|
||||
|
||||
int CPacket::getLength() const
|
||||
{
|
||||
return m_PacketVector[1].iov_len;
|
||||
}
|
||||
|
||||
void CPacket::setLength(int len)
|
||||
{
|
||||
m_PacketVector[1].iov_len = len;
|
||||
}
|
||||
|
||||
void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
|
||||
{
|
||||
// Set (bit-0 = 1) and (bit-1~15 = type)
|
||||
m_nHeader[0] = 0x80000000 | (pkttype << 16);
|
||||
|
||||
// Set additional information and control information field
|
||||
switch (pkttype)
|
||||
{
|
||||
case 2: //0010 - Acknowledgement (ACK)
|
||||
// ACK packet seq. no.
|
||||
if (NULL != lparam)
|
||||
m_nHeader[1] = *(int32_t *)lparam;
|
||||
|
||||
// data ACK seq. no.
|
||||
// optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second)
|
||||
m_PacketVector[1].iov_base = (char *)rparam;
|
||||
m_PacketVector[1].iov_len = size;
|
||||
|
||||
break;
|
||||
|
||||
case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2)
|
||||
// ACK packet seq. no.
|
||||
m_nHeader[1] = *(int32_t *)lparam;
|
||||
|
||||
// control info field should be none
|
||||
// but "writev" does not allow this
|
||||
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
|
||||
m_PacketVector[1].iov_len = 4; //0;
|
||||
|
||||
break;
|
||||
|
||||
case 3: //0011 - Loss Report (NAK)
|
||||
// loss list
|
||||
m_PacketVector[1].iov_base = (char *)rparam;
|
||||
m_PacketVector[1].iov_len = size;
|
||||
|
||||
break;
|
||||
|
||||
case 4: //0100 - Congestion Warning
|
||||
// control info field should be none
|
||||
// but "writev" does not allow this
|
||||
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
|
||||
m_PacketVector[1].iov_len = 4; //0;
|
||||
|
||||
break;
|
||||
|
||||
case 1: //0001 - Keep-alive
|
||||
// control info field should be none
|
||||
// but "writev" does not allow this
|
||||
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
|
||||
m_PacketVector[1].iov_len = 4; //0;
|
||||
|
||||
break;
|
||||
|
||||
case 0: //0000 - Handshake
|
||||
// control info filed is handshake info
|
||||
m_PacketVector[1].iov_base = (char *)rparam;
|
||||
m_PacketVector[1].iov_len = size; //sizeof(CHandShake);
|
||||
|
||||
break;
|
||||
|
||||
case 5: //0101 - Shutdown
|
||||
// control info field should be none
|
||||
// but "writev" does not allow this
|
||||
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
|
||||
m_PacketVector[1].iov_len = 4; //0;
|
||||
|
||||
break;
|
||||
|
||||
case 7: //0111 - Message Drop Request
|
||||
// msg id
|
||||
m_nHeader[1] = *(int32_t *)lparam;
|
||||
|
||||
//first seq no, last seq no
|
||||
m_PacketVector[1].iov_base = (char *)rparam;
|
||||
m_PacketVector[1].iov_len = size;
|
||||
|
||||
break;
|
||||
|
||||
case 8: //1000 - Error Signal from the Peer Side
|
||||
// Error type
|
||||
m_nHeader[1] = *(int32_t *)lparam;
|
||||
|
||||
// control info field should be none
|
||||
// but "writev" does not allow this
|
||||
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
|
||||
m_PacketVector[1].iov_len = 4; //0;
|
||||
|
||||
break;
|
||||
|
||||
case 32767: //0x7FFF - Reserved for user defined control packets
|
||||
// for extended control packet
|
||||
// "lparam" contains the extended type information for bit 16 - 31
|
||||
// "rparam" is the control information
|
||||
m_nHeader[0] |= *(int32_t *)lparam;
|
||||
|
||||
if (NULL != rparam)
|
||||
{
|
||||
m_PacketVector[1].iov_base = (char *)rparam;
|
||||
m_PacketVector[1].iov_len = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PacketVector[1].iov_base = (char *)&__pad;
|
||||
m_PacketVector[1].iov_len = 4;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iovec* CPacket::getPacketVector()
|
||||
{
|
||||
return m_PacketVector;
|
||||
}
|
||||
|
||||
int CPacket::getFlag() const
|
||||
{
|
||||
// read bit 0
|
||||
return m_nHeader[0] >> 31;
|
||||
}
|
||||
|
||||
int CPacket::getType() const
|
||||
{
|
||||
// read bit 1~15
|
||||
return (m_nHeader[0] >> 16) & 0x00007FFF;
|
||||
}
|
||||
|
||||
int CPacket::getExtendedType() const
|
||||
{
|
||||
// read bit 16~31
|
||||
return m_nHeader[0] & 0x0000FFFF;
|
||||
}
|
||||
|
||||
int32_t CPacket::getAckSeqNo() const
|
||||
{
|
||||
// read additional information field
|
||||
return m_nHeader[1];
|
||||
}
|
||||
|
||||
int CPacket::getMsgBoundary() const
|
||||
{
|
||||
// read [1] bit 0~1
|
||||
return m_nHeader[1] >> 30;
|
||||
}
|
||||
|
||||
bool CPacket::getMsgOrderFlag() const
|
||||
{
|
||||
// read [1] bit 2
|
||||
return (1 == ((m_nHeader[1] >> 29) & 1));
|
||||
}
|
||||
|
||||
int32_t CPacket::getMsgSeq() const
|
||||
{
|
||||
// read [1] bit 3~31
|
||||
return m_nHeader[1] & 0x1FFFFFFF;
|
||||
}
|
||||
|
||||
CPacket* CPacket::clone() const
|
||||
{
|
||||
CPacket* pkt = new CPacket;
|
||||
memcpy(pkt->m_nHeader, m_nHeader, m_iPktHdrSize);
|
||||
pkt->m_pcData = new char[m_PacketVector[1].iov_len];
|
||||
memcpy(pkt->m_pcData, m_pcData, m_PacketVector[1].iov_len);
|
||||
pkt->m_PacketVector[1].iov_len = m_PacketVector[1].iov_len;
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
CHandShake::CHandShake():
|
||||
m_iVersion(0),
|
||||
m_iType(0),
|
||||
m_iISN(0),
|
||||
m_iMSS(0),
|
||||
m_iFlightFlagSize(0),
|
||||
m_iReqType(0),
|
||||
m_iID(0),
|
||||
m_iCookie(0)
|
||||
{
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
m_piPeerIP[i] = 0;
|
||||
}
|
||||
|
||||
int CHandShake::serialize(char* buf, int& size)
|
||||
{
|
||||
if (size < m_iContentSize)
|
||||
return -1;
|
||||
|
||||
int32_t* p = (int32_t*)buf;
|
||||
*p++ = m_iVersion;
|
||||
*p++ = m_iType;
|
||||
*p++ = m_iISN;
|
||||
*p++ = m_iMSS;
|
||||
*p++ = m_iFlightFlagSize;
|
||||
*p++ = m_iReqType;
|
||||
*p++ = m_iID;
|
||||
*p++ = m_iCookie;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
*p++ = m_piPeerIP[i];
|
||||
|
||||
size = m_iContentSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CHandShake::deserialize(const char* buf, int size)
|
||||
{
|
||||
if (size < m_iContentSize)
|
||||
return -1;
|
||||
|
||||
int32_t* p = (int32_t*)buf;
|
||||
m_iVersion = *p++;
|
||||
m_iType = *p++;
|
||||
m_iISN = *p++;
|
||||
m_iMSS = *p++;
|
||||
m_iFlightFlagSize = *p++;
|
||||
m_iReqType = *p++;
|
||||
m_iID = *p++;
|
||||
m_iCookie = *p++;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
m_piPeerIP[i] = *p++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
223
vendor/udt4/src/packet.h
vendored
223
vendor/udt4/src/packet.h
vendored
|
|
@ -1,223 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/02/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_PACKET_H__
|
||||
#define __UDT_PACKET_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
|
||||
#ifdef WIN32
|
||||
struct iovec
|
||||
{
|
||||
int iov_len;
|
||||
char* iov_base;
|
||||
};
|
||||
#endif
|
||||
|
||||
class CChannel;
|
||||
|
||||
class CPacket
|
||||
{
|
||||
friend class CChannel;
|
||||
friend class CSndQueue;
|
||||
friend class CRcvQueue;
|
||||
|
||||
public:
|
||||
int32_t& m_iSeqNo; // alias: sequence number
|
||||
int32_t& m_iMsgNo; // alias: message number
|
||||
int32_t& m_iTimeStamp; // alias: timestamp
|
||||
int32_t& m_iID; // alias: socket ID
|
||||
char*& m_pcData; // alias: data/control information
|
||||
|
||||
static const int m_iPktHdrSize; // packet header size
|
||||
|
||||
public:
|
||||
CPacket();
|
||||
~CPacket();
|
||||
|
||||
// Functionality:
|
||||
// Get the payload or the control information field length.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// the payload or the control information field length.
|
||||
|
||||
int getLength() const;
|
||||
|
||||
// Functionality:
|
||||
// Set the payload or the control information field length.
|
||||
// Parameters:
|
||||
// 0) [in] len: the payload or the control information field length.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void setLength(int len);
|
||||
|
||||
// Functionality:
|
||||
// Pack a Control packet.
|
||||
// Parameters:
|
||||
// 0) [in] pkttype: packet type filed.
|
||||
// 1) [in] lparam: pointer to the first data structure, explained by the packet type.
|
||||
// 2) [in] rparam: pointer to the second data structure, explained by the packet type.
|
||||
// 3) [in] size: size of rparam, in number of bytes;
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void pack(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0);
|
||||
|
||||
// Functionality:
|
||||
// Read the packet vector.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Pointer to the packet vector.
|
||||
|
||||
iovec* getPacketVector();
|
||||
|
||||
// Functionality:
|
||||
// Read the packet flag.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet flag (0 or 1).
|
||||
|
||||
int getFlag() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the packet type.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet type filed (000 ~ 111).
|
||||
|
||||
int getType() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the extended packet type.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// extended packet type filed (0x000 ~ 0xFFF).
|
||||
|
||||
int getExtendedType() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the ACK-2 seq. no.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet header field (bit 16~31).
|
||||
|
||||
int32_t getAckSeqNo() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the message boundary flag bit.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet header field [1] (bit 0~1).
|
||||
|
||||
int getMsgBoundary() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the message inorder delivery flag bit.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet header field [1] (bit 2).
|
||||
|
||||
bool getMsgOrderFlag() const;
|
||||
|
||||
// Functionality:
|
||||
// Read the message sequence number.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// packet header field [1] (bit 3~31).
|
||||
|
||||
int32_t getMsgSeq() const;
|
||||
|
||||
// Functionality:
|
||||
// Clone this packet.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Pointer to the new packet.
|
||||
|
||||
CPacket* clone() const;
|
||||
|
||||
protected:
|
||||
uint32_t m_nHeader[4]; // The 128-bit header field
|
||||
iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data]
|
||||
|
||||
int32_t __pad;
|
||||
|
||||
protected:
|
||||
CPacket& operator=(const CPacket&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CHandShake
|
||||
{
|
||||
public:
|
||||
CHandShake();
|
||||
|
||||
int serialize(char* buf, int& size);
|
||||
int deserialize(const char* buf, int size);
|
||||
|
||||
public:
|
||||
static const int m_iContentSize; // Size of hand shake data
|
||||
|
||||
public:
|
||||
int32_t m_iVersion; // UDT version
|
||||
int32_t m_iType; // UDT socket type
|
||||
int32_t m_iISN; // random initial sequence number
|
||||
int32_t m_iMSS; // maximum segment size
|
||||
int32_t m_iFlightFlagSize; // flow control window size
|
||||
int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response
|
||||
int32_t m_iID; // socket ID
|
||||
int32_t m_iCookie; // cookie
|
||||
uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1253
vendor/udt4/src/queue.cpp
vendored
1253
vendor/udt4/src/queue.cpp
vendored
File diff suppressed because it is too large
Load diff
527
vendor/udt4/src/queue.h
vendored
527
vendor/udt4/src/queue.h
vendored
|
|
@ -1,527 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/12/2011
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __UDT_QUEUE_H__
|
||||
#define __UDT_QUEUE_H__
|
||||
|
||||
#include "channel.h"
|
||||
#include "common.h"
|
||||
#include "packet.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
class CUDT;
|
||||
|
||||
struct CUnit
|
||||
{
|
||||
CPacket m_Packet; // packet
|
||||
int m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped
|
||||
};
|
||||
|
||||
class CUnitQueue
|
||||
{
|
||||
friend class CRcvQueue;
|
||||
friend class CRcvBuffer;
|
||||
|
||||
public:
|
||||
CUnitQueue();
|
||||
~CUnitQueue();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Initialize the unit queue.
|
||||
// Parameters:
|
||||
// 1) [in] size: queue size
|
||||
// 2) [in] mss: maximum segament size
|
||||
// 3) [in] version: IP version
|
||||
// Returned value:
|
||||
// 0: success, -1: failure.
|
||||
|
||||
int init(int size, int mss, int version);
|
||||
|
||||
// Functionality:
|
||||
// Increase (double) the unit queue size.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// 0: success, -1: failure.
|
||||
|
||||
int increase();
|
||||
|
||||
// Functionality:
|
||||
// Decrease (halve) the unit queue size.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// 0: success, -1: failure.
|
||||
|
||||
int shrink();
|
||||
|
||||
// Functionality:
|
||||
// find an available unit for incoming packet.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Pointer to the available unit, NULL if not found.
|
||||
|
||||
CUnit* getNextAvailUnit();
|
||||
|
||||
private:
|
||||
struct CQEntry
|
||||
{
|
||||
CUnit* m_pUnit; // unit queue
|
||||
char* m_pBuffer; // data buffer
|
||||
int m_iSize; // size of each queue
|
||||
|
||||
CQEntry* m_pNext;
|
||||
}
|
||||
*m_pQEntry, // pointer to the first unit queue
|
||||
*m_pCurrQueue, // pointer to the current available queue
|
||||
*m_pLastQueue; // pointer to the last unit queue
|
||||
|
||||
CUnit* m_pAvailUnit; // recent available unit
|
||||
|
||||
int m_iSize; // total size of the unit queue, in number of packets
|
||||
int m_iCount; // total number of valid packets in the queue
|
||||
|
||||
int m_iMSS; // unit buffer size
|
||||
int m_iIPversion; // IP version
|
||||
|
||||
private:
|
||||
CUnitQueue(const CUnitQueue&);
|
||||
CUnitQueue& operator=(const CUnitQueue&);
|
||||
};
|
||||
|
||||
struct CSNode
|
||||
{
|
||||
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
|
||||
uint64_t m_llTimeStamp; // Time Stamp
|
||||
|
||||
int m_iHeapLoc; // location on the heap, -1 means not on the heap
|
||||
};
|
||||
|
||||
class CSndUList
|
||||
{
|
||||
friend class CSndQueue;
|
||||
|
||||
public:
|
||||
CSndUList();
|
||||
~CSndUList();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Insert a new UDT instance into the list.
|
||||
// Parameters:
|
||||
// 1) [in] ts: time stamp: next processing time
|
||||
// 2) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void insert(int64_t ts, const CUDT* u);
|
||||
|
||||
// Functionality:
|
||||
// Update the timestamp of the UDT instance on the list.
|
||||
// Parameters:
|
||||
// 1) [in] u: pointer to the UDT instance
|
||||
// 2) [in] resechedule: if the timestampe shoudl be rescheduled
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void update(const CUDT* u, bool reschedule = true);
|
||||
|
||||
// Functionality:
|
||||
// Retrieve the next packet and peer address from the first entry, and reschedule it in the queue.
|
||||
// Parameters:
|
||||
// 0) [out] addr: destination address of the next packet
|
||||
// 1) [out] pkt: the next packet to be sent
|
||||
// Returned value:
|
||||
// 1 if successfully retrieved, -1 if no packet found.
|
||||
|
||||
int pop(sockaddr*& addr, CPacket& pkt);
|
||||
|
||||
// Functionality:
|
||||
// Remove UDT instance from the list.
|
||||
// Parameters:
|
||||
// 1) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void remove(const CUDT* u);
|
||||
|
||||
// Functionality:
|
||||
// Retrieve the next scheduled processing time.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Scheduled processing time of the first UDT socket in the list.
|
||||
|
||||
uint64_t getNextProcTime();
|
||||
|
||||
private:
|
||||
void insert_(int64_t ts, const CUDT* u);
|
||||
void remove_(const CUDT* u);
|
||||
|
||||
private:
|
||||
CSNode** m_pHeap; // The heap array
|
||||
int m_iArrayLength; // physical length of the array
|
||||
int m_iLastEntry; // position of last entry on the heap array
|
||||
|
||||
pthread_mutex_t m_ListLock;
|
||||
|
||||
pthread_mutex_t* m_pWindowLock;
|
||||
pthread_cond_t* m_pWindowCond;
|
||||
|
||||
CTimer* m_pTimer;
|
||||
|
||||
private:
|
||||
CSndUList(const CSndUList&);
|
||||
CSndUList& operator=(const CSndUList&);
|
||||
};
|
||||
|
||||
struct CRNode
|
||||
{
|
||||
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
|
||||
uint64_t m_llTimeStamp; // Time Stamp
|
||||
|
||||
CRNode* m_pPrev; // previous link
|
||||
CRNode* m_pNext; // next link
|
||||
|
||||
bool m_bOnList; // if the node is already on the list
|
||||
};
|
||||
|
||||
class CRcvUList
|
||||
{
|
||||
public:
|
||||
CRcvUList();
|
||||
~CRcvUList();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Insert a new UDT instance to the list.
|
||||
// Parameters:
|
||||
// 1) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void insert(const CUDT* u);
|
||||
|
||||
// Functionality:
|
||||
// Remove the UDT instance from the list.
|
||||
// Parameters:
|
||||
// 1) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void remove(const CUDT* u);
|
||||
|
||||
// Functionality:
|
||||
// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing.
|
||||
// Parameters:
|
||||
// 1) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void update(const CUDT* u);
|
||||
|
||||
public:
|
||||
CRNode* m_pUList; // the head node
|
||||
|
||||
private:
|
||||
CRNode* m_pLast; // the last node
|
||||
|
||||
private:
|
||||
CRcvUList(const CRcvUList&);
|
||||
CRcvUList& operator=(const CRcvUList&);
|
||||
};
|
||||
|
||||
class CHash
|
||||
{
|
||||
public:
|
||||
CHash();
|
||||
~CHash();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Initialize the hash table.
|
||||
// Parameters:
|
||||
// 1) [in] size: hash table size
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void init(int size);
|
||||
|
||||
// Functionality:
|
||||
// Look for a UDT instance from the hash table.
|
||||
// Parameters:
|
||||
// 1) [in] id: socket ID
|
||||
// Returned value:
|
||||
// Pointer to a UDT instance, or NULL if not found.
|
||||
|
||||
CUDT* lookup(int32_t id);
|
||||
|
||||
// Functionality:
|
||||
// Insert an entry to the hash table.
|
||||
// Parameters:
|
||||
// 1) [in] id: socket ID
|
||||
// 2) [in] u: pointer to the UDT instance
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void insert(int32_t id, CUDT* u);
|
||||
|
||||
// Functionality:
|
||||
// Remove an entry from the hash table.
|
||||
// Parameters:
|
||||
// 1) [in] id: socket ID
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void remove(int32_t id);
|
||||
|
||||
private:
|
||||
struct CBucket
|
||||
{
|
||||
int32_t m_iID; // Socket ID
|
||||
CUDT* m_pUDT; // Socket instance
|
||||
|
||||
CBucket* m_pNext; // next bucket
|
||||
} **m_pBucket; // list of buckets (the hash table)
|
||||
|
||||
int m_iHashSize; // size of hash table
|
||||
|
||||
private:
|
||||
CHash(const CHash&);
|
||||
CHash& operator=(const CHash&);
|
||||
};
|
||||
|
||||
class CRendezvousQueue
|
||||
{
|
||||
public:
|
||||
CRendezvousQueue();
|
||||
~CRendezvousQueue();
|
||||
|
||||
public:
|
||||
void insert(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
|
||||
void remove(const UDTSOCKET& id);
|
||||
CUDT* retrieve(const sockaddr* addr, UDTSOCKET& id);
|
||||
|
||||
void updateConnStatus();
|
||||
|
||||
private:
|
||||
struct CRL
|
||||
{
|
||||
UDTSOCKET m_iID; // UDT socket ID (self)
|
||||
CUDT* m_pUDT; // UDT instance
|
||||
int m_iIPversion; // IP version
|
||||
sockaddr* m_pPeerAddr; // UDT sonnection peer address
|
||||
uint64_t m_ullTTL; // the time that this request expires
|
||||
};
|
||||
std::list<CRL> m_lRendezvousID; // The sockets currently in rendezvous mode
|
||||
|
||||
pthread_mutex_t m_RIDVectorLock;
|
||||
};
|
||||
|
||||
class CSndQueue
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CUDTUnited;
|
||||
|
||||
public:
|
||||
CSndQueue();
|
||||
~CSndQueue();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Initialize the sending queue.
|
||||
// Parameters:
|
||||
// 1) [in] c: UDP channel to be associated to the queue
|
||||
// 2) [in] t: Timer
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void init(CChannel* c, CTimer* t);
|
||||
|
||||
// Functionality:
|
||||
// Send out a packet to a given address.
|
||||
// Parameters:
|
||||
// 1) [in] addr: destination address
|
||||
// 2) [in] packet: packet to be sent out
|
||||
// Returned value:
|
||||
// Size of data sent out.
|
||||
|
||||
int sendto(const sockaddr* addr, CPacket& packet);
|
||||
|
||||
private:
|
||||
#ifndef WIN32
|
||||
static void* worker(void* param);
|
||||
#else
|
||||
static DWORD WINAPI worker(LPVOID param);
|
||||
#endif
|
||||
|
||||
pthread_t m_WorkerThread;
|
||||
|
||||
private:
|
||||
CSndUList* m_pSndUList; // List of UDT instances for data sending
|
||||
CChannel* m_pChannel; // The UDP channel for data sending
|
||||
CTimer* m_pTimer; // Timing facility
|
||||
|
||||
pthread_mutex_t m_WindowLock;
|
||||
pthread_cond_t m_WindowCond;
|
||||
|
||||
volatile bool m_bClosing; // closing the worker
|
||||
pthread_cond_t m_ExitCond;
|
||||
|
||||
private:
|
||||
CSndQueue(const CSndQueue&);
|
||||
CSndQueue& operator=(const CSndQueue&);
|
||||
};
|
||||
|
||||
class CRcvQueue
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CUDTUnited;
|
||||
|
||||
public:
|
||||
CRcvQueue();
|
||||
~CRcvQueue();
|
||||
|
||||
public:
|
||||
|
||||
// Functionality:
|
||||
// Initialize the receiving queue.
|
||||
// Parameters:
|
||||
// 1) [in] size: queue size
|
||||
// 2) [in] mss: maximum packet size
|
||||
// 3) [in] version: IP version
|
||||
// 4) [in] hsize: hash table size
|
||||
// 5) [in] c: UDP channel to be associated to the queue
|
||||
// 6) [in] t: timer
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void init(int size, int payload, int version, int hsize, CChannel* c, CTimer* t);
|
||||
|
||||
// Functionality:
|
||||
// Read a packet for a specific UDT socket id.
|
||||
// Parameters:
|
||||
// 1) [in] id: Socket ID
|
||||
// 2) [out] packet: received packet
|
||||
// Returned value:
|
||||
// Data size of the packet
|
||||
|
||||
int recvfrom(int32_t id, CPacket& packet);
|
||||
|
||||
private:
|
||||
#ifndef WIN32
|
||||
static void* worker(void* param);
|
||||
#else
|
||||
static DWORD WINAPI worker(LPVOID param);
|
||||
#endif
|
||||
|
||||
pthread_t m_WorkerThread;
|
||||
|
||||
private:
|
||||
CUnitQueue m_UnitQueue; // The received packet queue
|
||||
|
||||
CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue
|
||||
CHash* m_pHash; // Hash table for UDT socket looking up
|
||||
CChannel* m_pChannel; // UDP channel for receving packets
|
||||
CTimer* m_pTimer; // shared timer with the snd queue
|
||||
|
||||
int m_iPayloadSize; // packet payload size
|
||||
|
||||
volatile bool m_bClosing; // closing the workder
|
||||
pthread_cond_t m_ExitCond;
|
||||
|
||||
private:
|
||||
int setListener(CUDT* u);
|
||||
void removeListener(const CUDT* u);
|
||||
|
||||
void registerConnector(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
|
||||
void removeConnector(const UDTSOCKET& id);
|
||||
|
||||
void setNewEntry(CUDT* u);
|
||||
bool ifNewEntry();
|
||||
CUDT* getNewEntry();
|
||||
|
||||
void storePkt(int32_t id, CPacket* pkt);
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_LSLock;
|
||||
CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity
|
||||
CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode
|
||||
|
||||
std::vector<CUDT*> m_vNewEntry; // newly added entries, to be inserted
|
||||
pthread_mutex_t m_IDLock;
|
||||
|
||||
std::map<int32_t, std::queue<CPacket*> > m_mBuffer; // temporary buffer for rendezvous connection request
|
||||
pthread_mutex_t m_PassLock;
|
||||
pthread_cond_t m_PassCond;
|
||||
|
||||
private:
|
||||
CRcvQueue(const CRcvQueue&);
|
||||
CRcvQueue& operator=(const CRcvQueue&);
|
||||
};
|
||||
|
||||
struct CMultiplexer
|
||||
{
|
||||
CSndQueue* m_pSndQueue; // The sending queue
|
||||
CRcvQueue* m_pRcvQueue; // The receiving queue
|
||||
CChannel* m_pChannel; // The UDP channel for sending and receiving
|
||||
CTimer* m_pTimer; // The timer
|
||||
|
||||
int m_iPort; // The UDP port number of this multiplexer
|
||||
int m_iIPversion; // IP version
|
||||
int m_iMSS; // Maximum Segment Size
|
||||
int m_iRefCount; // number of UDT instances that are associated with this multiplexer
|
||||
bool m_bReusable; // if this one can be shared with others
|
||||
|
||||
int m_iID; // multiplexer ID
|
||||
};
|
||||
|
||||
#endif
|
||||
359
vendor/udt4/src/udt.h
vendored
359
vendor/udt4/src/udt.h
vendored
|
|
@ -1,359 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/18/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_H__
|
||||
#define __UDT_H__
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#ifdef __MINGW__
|
||||
#include <stdint.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//if compiling on VC6.0 or pre-WindowsXP systems
|
||||
//use -DLEGACY_WIN32
|
||||
|
||||
//if compiling with MinGW, it only works on XP or above
|
||||
//use -D_WIN32_WINNT=0x0501
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#if !defined(__MINGW__) && defined(UDT_IS_DLL)
|
||||
// Explicitly define 32-bit and 64-bit numbers
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#ifndef LEGACY_WIN32
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
// VC 6.0 does not support unsigned __int64: may cause potential problems.
|
||||
typedef __int64 uint64_t;
|
||||
#endif
|
||||
|
||||
#ifdef UDT_EXPORTS
|
||||
#define UDT_API __declspec(dllexport)
|
||||
#else
|
||||
#define UDT_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define UDT_API
|
||||
#endif
|
||||
#else
|
||||
#define UDT_API __attribute__ ((visibility("default")))
|
||||
#endif
|
||||
|
||||
#define NO_BUSY_WAITING
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef __MINGW__
|
||||
typedef SOCKET SYSSOCKET;
|
||||
#else
|
||||
typedef int SYSSOCKET;
|
||||
#endif
|
||||
#else
|
||||
typedef int SYSSOCKET;
|
||||
#endif
|
||||
|
||||
typedef SYSSOCKET UDPSOCKET;
|
||||
typedef int UDTSOCKET;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::set<UDTSOCKET> ud_set;
|
||||
#define UD_CLR(u, uset) ((uset)->erase(u))
|
||||
#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end())
|
||||
#define UD_SET(u, uset) ((uset)->insert(u))
|
||||
#define UD_ZERO(uset) ((uset)->clear())
|
||||
|
||||
enum EPOLLOpt
|
||||
{
|
||||
// this values are defined same as linux epoll.h
|
||||
// so that if system values are used by mistake, they should have the same effect
|
||||
UDT_EPOLL_IN = 0x1,
|
||||
UDT_EPOLL_OUT = 0x4,
|
||||
UDT_EPOLL_ERR = 0x8
|
||||
};
|
||||
|
||||
enum UDTSTATUS {INIT = 1, OPENED, LISTENING, CONNECTING, CONNECTED, BROKEN, CLOSING, CLOSED, NONEXIST};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum UDTOpt
|
||||
{
|
||||
UDT_MSS, // the Maximum Transfer Unit
|
||||
UDT_SNDSYN, // if sending is blocking
|
||||
UDT_RCVSYN, // if receiving is blocking
|
||||
UDT_CC, // custom congestion control algorithm
|
||||
UDT_FC, // Flight flag size (window size)
|
||||
UDT_SNDBUF, // maximum buffer in sending queue
|
||||
UDT_RCVBUF, // UDT receiving buffer size
|
||||
UDT_LINGER, // waiting for unsent data when closing
|
||||
UDP_SNDBUF, // UDP sending buffer size
|
||||
UDP_RCVBUF, // UDP receiving buffer size
|
||||
UDT_MAXMSG, // maximum datagram message size
|
||||
UDT_MSGTTL, // time-to-live of a datagram message
|
||||
UDT_RENDEZVOUS, // rendezvous connection mode
|
||||
UDT_SNDTIMEO, // send() timeout
|
||||
UDT_RCVTIMEO, // recv() timeout
|
||||
UDT_REUSEADDR, // reuse an existing port or create a new one
|
||||
UDT_MAXBW, // maximum bandwidth (bytes per second) that the connection can use
|
||||
UDT_STATE, // current socket state, see UDTSTATUS, read only
|
||||
UDT_EVENT, // current avalable events associated with the socket
|
||||
UDT_SNDDATA, // size of data in the sending buffer
|
||||
UDT_RCVDATA // size of data available for recv
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CPerfMon
|
||||
{
|
||||
// global measurements
|
||||
int64_t msTimeStamp; // time since the UDT entity is started, in milliseconds
|
||||
int64_t pktSentTotal; // total number of sent data packets, including retransmissions
|
||||
int64_t pktRecvTotal; // total number of received packets
|
||||
int pktSndLossTotal; // total number of lost packets (sender side)
|
||||
int pktRcvLossTotal; // total number of lost packets (receiver side)
|
||||
int pktRetransTotal; // total number of retransmitted packets
|
||||
int pktSentACKTotal; // total number of sent ACK packets
|
||||
int pktRecvACKTotal; // total number of received ACK packets
|
||||
int pktSentNAKTotal; // total number of sent NAK packets
|
||||
int pktRecvNAKTotal; // total number of received NAK packets
|
||||
int64_t usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive)
|
||||
|
||||
// local measurements
|
||||
int64_t pktSent; // number of sent data packets, including retransmissions
|
||||
int64_t pktRecv; // number of received packets
|
||||
int pktSndLoss; // number of lost packets (sender side)
|
||||
int pktRcvLoss; // number of lost packets (receiver side)
|
||||
int pktRetrans; // number of retransmitted packets
|
||||
int pktSentACK; // number of sent ACK packets
|
||||
int pktRecvACK; // number of received ACK packets
|
||||
int pktSentNAK; // number of sent NAK packets
|
||||
int pktRecvNAK; // number of received NAK packets
|
||||
double mbpsSendRate; // sending rate in Mb/s
|
||||
double mbpsRecvRate; // receiving rate in Mb/s
|
||||
int64_t usSndDuration; // busy sending time (i.e., idle time exclusive)
|
||||
|
||||
// instant measurements
|
||||
double usPktSndPeriod; // packet sending period, in microseconds
|
||||
int pktFlowWindow; // flow window size, in number of packets
|
||||
int pktCongestionWindow; // congestion window size, in number of packets
|
||||
int pktFlightSize; // number of packets on flight
|
||||
double msRTT; // RTT, in milliseconds
|
||||
double mbpsBandwidth; // estimated bandwidth, in Mb/s
|
||||
int byteAvailSndBuf; // available UDT sender buffer size
|
||||
int byteAvailRcvBuf; // available UDT receiver buffer size
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class UDT_API CUDTException
|
||||
{
|
||||
public:
|
||||
CUDTException(int major = 0, int minor = 0, int err = -1);
|
||||
CUDTException(const CUDTException& e);
|
||||
virtual ~CUDTException();
|
||||
|
||||
// Functionality:
|
||||
// Get the description of the exception.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Text message for the exception description.
|
||||
|
||||
virtual const char* getErrorMessage();
|
||||
|
||||
// Functionality:
|
||||
// Get the system errno for the exception.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// errno.
|
||||
|
||||
virtual int getErrorCode() const;
|
||||
|
||||
// Functionality:
|
||||
// Clear the error code.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
virtual void clear();
|
||||
|
||||
private:
|
||||
int m_iMajor; // major exception categories
|
||||
|
||||
// 0: correct condition
|
||||
// 1: network setup exception
|
||||
// 2: network connection broken
|
||||
// 3: memory exception
|
||||
// 4: file exception
|
||||
// 5: method not supported
|
||||
// 6+: undefined error
|
||||
|
||||
int m_iMinor; // for specific error reasons
|
||||
int m_iErrno; // errno returned by the system if there is any
|
||||
std::string m_strMsg; // text error message
|
||||
|
||||
std::string m_strAPI; // the name of UDT function that returns the error
|
||||
std::string m_strDebug; // debug information, set to the original place that causes the error
|
||||
|
||||
public: // Error Code
|
||||
static const int SUCCESS;
|
||||
static const int ECONNSETUP;
|
||||
static const int ENOSERVER;
|
||||
static const int ECONNREJ;
|
||||
static const int ESOCKFAIL;
|
||||
static const int ESECFAIL;
|
||||
static const int ECONNFAIL;
|
||||
static const int ECONNLOST;
|
||||
static const int ENOCONN;
|
||||
static const int ERESOURCE;
|
||||
static const int ETHREAD;
|
||||
static const int ENOBUF;
|
||||
static const int EFILE;
|
||||
static const int EINVRDOFF;
|
||||
static const int ERDPERM;
|
||||
static const int EINVWROFF;
|
||||
static const int EWRPERM;
|
||||
static const int EINVOP;
|
||||
static const int EBOUNDSOCK;
|
||||
static const int ECONNSOCK;
|
||||
static const int EINVPARAM;
|
||||
static const int EINVSOCK;
|
||||
static const int EUNBOUNDSOCK;
|
||||
static const int ENOLISTEN;
|
||||
static const int ERDVNOSERV;
|
||||
static const int ERDVUNBOUND;
|
||||
static const int ESTREAMILL;
|
||||
static const int EDGRAMILL;
|
||||
static const int EDUPLISTEN;
|
||||
static const int ELARGEMSG;
|
||||
static const int EINVPOLLID;
|
||||
static const int EASYNCFAIL;
|
||||
static const int EASYNCSND;
|
||||
static const int EASYNCRCV;
|
||||
static const int ETIMEOUT;
|
||||
static const int EPEERERR;
|
||||
static const int EUNKNOWN;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// If you need to export these APIs to be used by a different language,
|
||||
// declare extern "C" for them, and add a "udt_" prefix to each API.
|
||||
// The following APIs: sendfile(), recvfile(), epoll_wait(), geterrormsg(),
|
||||
// include C++ specific feature, please use the corresponding sendfile2(), etc.
|
||||
|
||||
namespace UDT
|
||||
{
|
||||
|
||||
typedef CUDTException ERRORINFO;
|
||||
typedef UDTOpt SOCKOPT;
|
||||
typedef CPerfMon TRACEINFO;
|
||||
typedef ud_set UDSET;
|
||||
|
||||
UDT_API extern const UDTSOCKET INVALID_SOCK;
|
||||
#undef ERROR
|
||||
UDT_API extern const int ERROR;
|
||||
|
||||
UDT_API int startup();
|
||||
UDT_API int cleanup();
|
||||
UDT_API UDTSOCKET socket(int af, int type, int protocol);
|
||||
UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen);
|
||||
UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock);
|
||||
UDT_API int listen(UDTSOCKET u, int backlog);
|
||||
UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen);
|
||||
UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen);
|
||||
UDT_API int close(UDTSOCKET u);
|
||||
UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen);
|
||||
UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen);
|
||||
UDT_API int getsockopt(UDTSOCKET u, int level, SOCKOPT optname, void* optval, int* optlen);
|
||||
UDT_API int setsockopt(UDTSOCKET u, int level, SOCKOPT optname, const void* optval, int optlen);
|
||||
UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags);
|
||||
UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags);
|
||||
UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false);
|
||||
UDT_API int recvmsg(UDTSOCKET u, char* buf, int len);
|
||||
UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000);
|
||||
UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000);
|
||||
UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000);
|
||||
UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000);
|
||||
|
||||
// select and selectEX are DEPRECATED; please use epoll.
|
||||
UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout);
|
||||
UDT_API int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds,
|
||||
std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
|
||||
|
||||
UDT_API int epoll_create();
|
||||
UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL);
|
||||
UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL);
|
||||
UDT_API int epoll_remove_usock(int eid, UDTSOCKET u);
|
||||
UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s);
|
||||
UDT_API int epoll_wait(int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut,
|
||||
std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* wrfds = NULL);
|
||||
UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut,
|
||||
SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL);
|
||||
UDT_API int epoll_release(int eid);
|
||||
UDT_API ERRORINFO& getlasterror();
|
||||
UDT_API int getlasterror_code();
|
||||
UDT_API const char* getlasterror_desc();
|
||||
UDT_API int perfmon(UDTSOCKET u, TRACEINFO* perf, bool clear = true);
|
||||
UDT_API UDTSTATUS getsockstate(UDTSOCKET u);
|
||||
|
||||
} // namespace UDT
|
||||
|
||||
#endif
|
||||
286
vendor/udt4/src/window.cpp
vendored
286
vendor/udt4/src/window.cpp
vendored
|
|
@ -1,286 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/22/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#include <cmath>
|
||||
#include "common.h"
|
||||
#include "window.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
CACKWindow::CACKWindow(int size):
|
||||
m_piACKSeqNo(NULL),
|
||||
m_piACK(NULL),
|
||||
m_pTimeStamp(NULL),
|
||||
m_iSize(size),
|
||||
m_iHead(0),
|
||||
m_iTail(0)
|
||||
{
|
||||
m_piACKSeqNo = new int32_t[m_iSize];
|
||||
m_piACK = new int32_t[m_iSize];
|
||||
m_pTimeStamp = new uint64_t[m_iSize];
|
||||
|
||||
m_piACKSeqNo[0] = -1;
|
||||
}
|
||||
|
||||
CACKWindow::~CACKWindow()
|
||||
{
|
||||
delete [] m_piACKSeqNo;
|
||||
delete [] m_piACK;
|
||||
delete [] m_pTimeStamp;
|
||||
}
|
||||
|
||||
void CACKWindow::store(int32_t seq, int32_t ack)
|
||||
{
|
||||
m_piACKSeqNo[m_iHead] = seq;
|
||||
m_piACK[m_iHead] = ack;
|
||||
m_pTimeStamp[m_iHead] = CTimer::getTime();
|
||||
|
||||
m_iHead = (m_iHead + 1) % m_iSize;
|
||||
|
||||
// overwrite the oldest ACK since it is not likely to be acknowledged
|
||||
if (m_iHead == m_iTail)
|
||||
m_iTail = (m_iTail + 1) % m_iSize;
|
||||
}
|
||||
|
||||
int CACKWindow::acknowledge(int32_t seq, int32_t& ack)
|
||||
{
|
||||
if (m_iHead >= m_iTail)
|
||||
{
|
||||
// Head has not exceeded the physical boundary of the window
|
||||
|
||||
for (int i = m_iTail, n = m_iHead; i < n; ++ i)
|
||||
{
|
||||
// looking for indentical ACK Seq. No.
|
||||
if (seq == m_piACKSeqNo[i])
|
||||
{
|
||||
// return the Data ACK it carried
|
||||
ack = m_piACK[i];
|
||||
|
||||
// calculate RTT
|
||||
int rtt = int(CTimer::getTime() - m_pTimeStamp[i]);
|
||||
|
||||
if (i + 1 == m_iHead)
|
||||
{
|
||||
m_iTail = m_iHead = 0;
|
||||
m_piACKSeqNo[0] = -1;
|
||||
}
|
||||
else
|
||||
m_iTail = (i + 1) % m_iSize;
|
||||
|
||||
return rtt;
|
||||
}
|
||||
}
|
||||
|
||||
// Bad input, the ACK node has been overwritten
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Head has exceeded the physical window boundary, so it is behind tail
|
||||
for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j)
|
||||
{
|
||||
// looking for indentical ACK seq. no.
|
||||
if (seq == m_piACKSeqNo[j % m_iSize])
|
||||
{
|
||||
// return Data ACK
|
||||
j %= m_iSize;
|
||||
ack = m_piACK[j];
|
||||
|
||||
// calculate RTT
|
||||
int rtt = int(CTimer::getTime() - m_pTimeStamp[j]);
|
||||
|
||||
if (j == m_iHead)
|
||||
{
|
||||
m_iTail = m_iHead = 0;
|
||||
m_piACKSeqNo[0] = -1;
|
||||
}
|
||||
else
|
||||
m_iTail = (j + 1) % m_iSize;
|
||||
|
||||
return rtt;
|
||||
}
|
||||
}
|
||||
|
||||
// bad input, the ACK node has been overwritten
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPktTimeWindow::CPktTimeWindow(int asize, int psize):
|
||||
m_iAWSize(asize),
|
||||
m_piPktWindow(NULL),
|
||||
m_iPktWindowPtr(0),
|
||||
m_iPWSize(psize),
|
||||
m_piProbeWindow(NULL),
|
||||
m_iProbeWindowPtr(0),
|
||||
m_iLastSentTime(0),
|
||||
m_iMinPktSndInt(1000000),
|
||||
m_LastArrTime(),
|
||||
m_CurrArrTime(),
|
||||
m_ProbeTime()
|
||||
{
|
||||
m_piPktWindow = new int[m_iAWSize];
|
||||
m_piPktReplica = new int[m_iAWSize];
|
||||
m_piProbeWindow = new int[m_iPWSize];
|
||||
m_piProbeReplica = new int[m_iPWSize];
|
||||
|
||||
m_LastArrTime = CTimer::getTime();
|
||||
|
||||
for (int i = 0; i < m_iAWSize; ++ i)
|
||||
m_piPktWindow[i] = 1000000;
|
||||
|
||||
for (int k = 0; k < m_iPWSize; ++ k)
|
||||
m_piProbeWindow[k] = 1000;
|
||||
}
|
||||
|
||||
CPktTimeWindow::~CPktTimeWindow()
|
||||
{
|
||||
delete [] m_piPktWindow;
|
||||
delete [] m_piPktReplica;
|
||||
delete [] m_piProbeWindow;
|
||||
delete [] m_piProbeReplica;
|
||||
}
|
||||
|
||||
int CPktTimeWindow::getMinPktSndInt() const
|
||||
{
|
||||
return m_iMinPktSndInt;
|
||||
}
|
||||
|
||||
int CPktTimeWindow::getPktRcvSpeed() const
|
||||
{
|
||||
// get median value, but cannot change the original value order in the window
|
||||
std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica);
|
||||
std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1);
|
||||
int median = m_piPktReplica[m_iAWSize / 2];
|
||||
|
||||
int count = 0;
|
||||
int sum = 0;
|
||||
int upper = median << 3;
|
||||
int lower = median >> 3;
|
||||
|
||||
// median filtering
|
||||
int* p = m_piPktWindow;
|
||||
for (int i = 0, n = m_iAWSize; i < n; ++ i)
|
||||
{
|
||||
if ((*p < upper) && (*p > lower))
|
||||
{
|
||||
++ count;
|
||||
sum += *p;
|
||||
}
|
||||
++ p;
|
||||
}
|
||||
|
||||
// claculate speed, or return 0 if not enough valid value
|
||||
if (count > (m_iAWSize >> 1))
|
||||
return (int)ceil(1000000.0 / (sum / count));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CPktTimeWindow::getBandwidth() const
|
||||
{
|
||||
// get median value, but cannot change the original value order in the window
|
||||
std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica);
|
||||
std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1);
|
||||
int median = m_piProbeReplica[m_iPWSize / 2];
|
||||
|
||||
int count = 1;
|
||||
int sum = median;
|
||||
int upper = median << 3;
|
||||
int lower = median >> 3;
|
||||
|
||||
// median filtering
|
||||
int* p = m_piProbeWindow;
|
||||
for (int i = 0, n = m_iPWSize; i < n; ++ i)
|
||||
{
|
||||
if ((*p < upper) && (*p > lower))
|
||||
{
|
||||
++ count;
|
||||
sum += *p;
|
||||
}
|
||||
++ p;
|
||||
}
|
||||
|
||||
return (int)ceil(1000000.0 / (double(sum) / double(count)));
|
||||
}
|
||||
|
||||
void CPktTimeWindow::onPktSent(int currtime)
|
||||
{
|
||||
int interval = currtime - m_iLastSentTime;
|
||||
|
||||
if ((interval < m_iMinPktSndInt) && (interval > 0))
|
||||
m_iMinPktSndInt = interval;
|
||||
|
||||
m_iLastSentTime = currtime;
|
||||
}
|
||||
|
||||
void CPktTimeWindow::onPktArrival()
|
||||
{
|
||||
m_CurrArrTime = CTimer::getTime();
|
||||
|
||||
// record the packet interval between the current and the last one
|
||||
*(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime);
|
||||
|
||||
// the window is logically circular
|
||||
++ m_iPktWindowPtr;
|
||||
if (m_iPktWindowPtr == m_iAWSize)
|
||||
m_iPktWindowPtr = 0;
|
||||
|
||||
// remember last packet arrival time
|
||||
m_LastArrTime = m_CurrArrTime;
|
||||
}
|
||||
|
||||
void CPktTimeWindow::probe1Arrival()
|
||||
{
|
||||
m_ProbeTime = CTimer::getTime();
|
||||
}
|
||||
|
||||
void CPktTimeWindow::probe2Arrival()
|
||||
{
|
||||
m_CurrArrTime = CTimer::getTime();
|
||||
|
||||
// record the probing packets interval
|
||||
*(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime);
|
||||
// the window is logically circular
|
||||
++ m_iProbeWindowPtr;
|
||||
if (m_iProbeWindowPtr == m_iPWSize)
|
||||
m_iProbeWindowPtr = 0;
|
||||
}
|
||||
187
vendor/udt4/src/window.h
vendored
187
vendor/udt4/src/window.h
vendored
|
|
@ -1,187 +0,0 @@
|
|||
/*****************************************************************************
|
||||
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
|
||||
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.
|
||||
|
||||
* Neither the name of the University of Illinois
|
||||
nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 01/22/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_WINDOW_H__
|
||||
#define __UDT_WINDOW_H__
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include "udt.h"
|
||||
|
||||
|
||||
class CACKWindow
|
||||
{
|
||||
public:
|
||||
CACKWindow(int size = 1024);
|
||||
~CACKWindow();
|
||||
|
||||
// Functionality:
|
||||
// Write an ACK record into the window.
|
||||
// Parameters:
|
||||
// 0) [in] seq: ACK seq. no.
|
||||
// 1) [in] ack: DATA ACK no.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void store(int32_t seq, int32_t ack);
|
||||
|
||||
// Functionality:
|
||||
// Search the ACK-2 "seq" in the window, find out the DATA "ack" and caluclate RTT .
|
||||
// Parameters:
|
||||
// 0) [in] seq: ACK-2 seq. no.
|
||||
// 1) [out] ack: the DATA ACK no. that matches the ACK-2 no.
|
||||
// Returned value:
|
||||
// RTT.
|
||||
|
||||
int acknowledge(int32_t seq, int32_t& ack);
|
||||
|
||||
private:
|
||||
int32_t* m_piACKSeqNo; // Seq. No. for the ACK packet
|
||||
int32_t* m_piACK; // Data Seq. No. carried by the ACK packet
|
||||
uint64_t* m_pTimeStamp; // The timestamp when the ACK was sent
|
||||
|
||||
int m_iSize; // Size of the ACK history window
|
||||
int m_iHead; // Pointer to the lastest ACK record
|
||||
int m_iTail; // Pointer to the oldest ACK record
|
||||
|
||||
private:
|
||||
CACKWindow(const CACKWindow&);
|
||||
CACKWindow& operator=(const CACKWindow&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CPktTimeWindow
|
||||
{
|
||||
public:
|
||||
CPktTimeWindow(int asize = 16, int psize = 16);
|
||||
~CPktTimeWindow();
|
||||
|
||||
// Functionality:
|
||||
// read the minimum packet sending interval.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// minimum packet sending interval (microseconds).
|
||||
|
||||
int getMinPktSndInt() const;
|
||||
|
||||
// Functionality:
|
||||
// Calculate the packes arrival speed.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Packet arrival speed (packets per second).
|
||||
|
||||
int getPktRcvSpeed() const;
|
||||
|
||||
// Functionality:
|
||||
// Estimate the bandwidth.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// Estimated bandwidth (packets per second).
|
||||
|
||||
int getBandwidth() const;
|
||||
|
||||
// Functionality:
|
||||
// Record time information of a packet sending.
|
||||
// Parameters:
|
||||
// 0) currtime: timestamp of the packet sending.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void onPktSent(int currtime);
|
||||
|
||||
// Functionality:
|
||||
// Record time information of an arrived packet.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void onPktArrival();
|
||||
|
||||
// Functionality:
|
||||
// Record the arrival time of the first probing packet.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void probe1Arrival();
|
||||
|
||||
// Functionality:
|
||||
// Record the arrival time of the second probing packet and the interval between packet pairs.
|
||||
// Parameters:
|
||||
// None.
|
||||
// Returned value:
|
||||
// None.
|
||||
|
||||
void probe2Arrival();
|
||||
|
||||
private:
|
||||
int m_iAWSize; // size of the packet arrival history window
|
||||
int* m_piPktWindow; // packet information window
|
||||
int* m_piPktReplica;
|
||||
int m_iPktWindowPtr; // position pointer of the packet info. window.
|
||||
|
||||
int m_iPWSize; // size of probe history window size
|
||||
int* m_piProbeWindow; // record inter-packet time for probing packet pairs
|
||||
int* m_piProbeReplica;
|
||||
int m_iProbeWindowPtr; // position pointer to the probing window
|
||||
|
||||
int m_iLastSentTime; // last packet sending time
|
||||
int m_iMinPktSndInt; // Minimum packet sending interval
|
||||
|
||||
uint64_t m_LastArrTime; // last packet arrival time
|
||||
uint64_t m_CurrArrTime; // current packet arrival time
|
||||
uint64_t m_ProbeTime; // arrival time of the first probing packet
|
||||
|
||||
private:
|
||||
CPktTimeWindow(const CPktTimeWindow&);
|
||||
CPktTimeWindow &operator=(const CPktTimeWindow&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue