diff options
Diffstat (limited to 'src/libutp/utp_internal.h')
| -rw-r--r-- | src/libutp/utp_internal.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/libutp/utp_internal.h b/src/libutp/utp_internal.h new file mode 100644 index 00000000..1edb1aa2 --- /dev/null +++ b/src/libutp/utp_internal.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2010-2013 BitTorrent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __UTP_INTERNAL_H__ +#define __UTP_INTERNAL_H__ + +#include <stdarg.h> +#include <string.h> +#include <stdio.h> + +#include <algorithm> +#include <functional> +#include <memory> +#include <unordered_map> +#include <vector> + +#include "utp.h" +#include "utp_callbacks.h" +#include "utp_templates.h" +#include "utp_packedsockaddr.h" + +/* These originally lived in utp_config.h */ +#define CCONTROL_TARGET (100 * 1000) // us + +enum bandwidth_type_t { + payload_bandwidth, connect_overhead, + close_overhead, ack_overhead, + header_overhead, retransmit_overhead +}; + +#ifdef WIN32 + #ifdef _MSC_VER + #include "libutp_inet_ntop.h" + #endif + + // newer versions of MSVC define these in errno.h + #ifndef ECONNRESET + #define ECONNRESET WSAECONNRESET + #define EMSGSIZE WSAEMSGSIZE + #define ECONNREFUSED WSAECONNREFUSED + #define ETIMEDOUT WSAETIMEDOUT + #endif +#endif + +struct PACKED_ATTRIBUTE RST_Info { + RST_Info() = default; + + RST_Info(PackedSockAddr _addr, uint32 _connid, uint16 _ack_nr, uint64 _timestamp) + : addr{ _addr } + , connid{ _connid } + , ack_nr{ _ack_nr } + , timestamp{ _timestamp } + { + } + + PackedSockAddr addr; + uint32 connid; + uint16 ack_nr; + uint64 timestamp; +}; + +struct UTPSocketKey { + PackedSockAddr addr; + uint32 recv_id; // "conn_seed", "conn_id" + + UTPSocketKey(const PackedSockAddr& _addr, uint32 _recv_id) { + addr = _addr; + recv_id = _recv_id; + } + + bool operator == (const UTPSocketKey &other) const { + return recv_id == other.recv_id && addr == other.addr; + } + + uint32 compute_hash() const { + return recv_id ^ addr.compute_hash(); + } +}; + +template<> +struct std::hash<UTPSocketKey> +{ + // It's really important that we don't have duplicate keys in the hash table. + // If we do, we'll eventually crash. if we try to remove the second instance + // of the key, we'll accidentally remove the first instead. then later, + // checkTimeouts will try to access the second one's already freed memory. + std::size_t operator()(const UTPSocketKey& key) const { + return key.compute_hash(); + } +}; + +extern void utp_socket_delete(UTPSocket*); + +// Container that owns a set of UTPSockets. +// The sockets are destroyed when removed from the container. +class UTPSocketHT { + + // UTPSocket is an opaque type, so we can't use it for V. + // Instead, use a unique_ptr<> which deletes via `utp_socket_delete()`. + struct SocketDeleter { + void operator()(UTPSocket* conn) const noexcept { + utp_socket_delete(conn); + } + }; + +public: + using Key = UTPSocketKey; + using Value = UTPSocket; + using V = std::unique_ptr<Value, SocketDeleter>; + using Map = std::unordered_map<Key, V>; + + [[nodiscard]] auto contains(Key const& key)->bool const { + return map_.count(key) != 0U; + } + + [[nodiscard]] auto size()->size_t const { + return map_.size(); + } + + [[nodiscard]] Value* lookup(Key const& key) const { + const auto iter = map_.find(key); + return iter != map_.end() ? iter->second.get() : nullptr; + } + + void add(Key const& key, Value* value) { + map_[key].reset(value); + } + + void erase_if(std::function<bool(Map::iterator const&)> pred) { + for (auto it = map_.begin(); it != map_.end(); ) { + if (pred(it)) { + it = map_.erase(it); + } else { + ++it; + } + } + } + +private: + Map map_; +}; + +struct struct_utp_context { + void *userdata; + utp_callback_t* callbacks[UTP_ARRAY_SIZE]; + + uint64 current_ms; + utp_context_stats context_stats; + UTPSocket *last_utp_socket; + std::vector<UTPSocket*> ack_sockets; + std::vector<RST_Info> rst_info; + UTPSocketHT utp_sockets; + size_t target_delay; + size_t opt_sndbuf; + size_t opt_rcvbuf; + uint64 last_check; + + struct_utp_context(); + + void log(int level, utp_socket *socket, char const *fmt, ...); + void log_unchecked(utp_socket *socket, char const *fmt, ...); + bool would_log(int level); + + bool log_normal:1; // log normal events? + bool log_mtu:1; // log MTU related events? + bool log_debug:1; // log debugging events? (Must also compile with UTP_DEBUG_LOGGING defined) +}; + +#endif //__UTP_INTERNAL_H__ |
