Client NAT traversal 0.1

UPnP is now used to request a port on the NAT be forwarded to the local machine.
This obviously only works for NATs that support UPnP, and thus is not a panacea
for all NAT-related connectivity issues.

Notable hacks in this patch include a transmit/receive UDP socket pair to work
around current protocol limitations whereby the full node assumes its peer can
receive on the same UDP port it transmitted from.
This commit is contained in:
Michael Vines
2018-06-29 14:12:26 -07:00
committed by Grimes
parent 4ffb5d157a
commit 0b56d603c2
10 changed files with 138 additions and 85 deletions

View File

@ -15,7 +15,8 @@ use transaction::Transaction;
/// An object for querying and sending transactions to the network.
pub struct ThinClient {
requests_addr: SocketAddr,
requests_socket: UdpSocket,
requests_sender: UdpSocket,
requests_receiver: UdpSocket,
transactions_addr: SocketAddr,
transactions_socket: UdpSocket,
last_id: Option<Hash>,
@ -30,13 +31,15 @@ impl ThinClient {
/// to a public address before invoking ThinClient methods.
pub fn new(
requests_addr: SocketAddr,
requests_socket: UdpSocket,
requests_sender: UdpSocket,
requests_receiver: UdpSocket,
transactions_addr: SocketAddr,
transactions_socket: UdpSocket,
) -> Self {
let client = ThinClient {
requests_addr,
requests_socket,
requests_sender,
requests_receiver,
transactions_addr,
transactions_socket,
last_id: None,
@ -50,7 +53,7 @@ impl ThinClient {
pub fn recv_response(&self) -> io::Result<Response> {
let mut buf = vec![0u8; 1024];
trace!("start recv_from");
self.requests_socket.recv_from(&mut buf)?;
self.requests_receiver.recv_from(&mut buf)?;
trace!("end recv_from");
let resp = deserialize(&buf).expect("deserialize balance in thin_client");
Ok(resp)
@ -112,7 +115,7 @@ impl ThinClient {
trace!("get_balance");
let req = Request::GetBalance { key: *pubkey };
let data = serialize(&req).expect("serialize GetBalance in pub fn get_balance");
self.requests_socket
self.requests_sender
.send_to(&data, &self.requests_addr)
.expect("buffer error in pub fn get_balance");
let mut done = false;
@ -136,7 +139,7 @@ impl ThinClient {
serialize(&req).expect("serialize GetTransactionCount in pub fn transaction_count");
let mut done = false;
while !done {
self.requests_socket
self.requests_sender
.send_to(&data, &self.requests_addr)
.expect("buffer error in pub fn transaction_count");
@ -159,7 +162,8 @@ impl ThinClient {
let data = serialize(&req).expect("serialize GetLastId in pub fn get_last_id");
let mut done = false;
while !done {
self.requests_socket
eprintln!("get_last_id send_to {}", &self.requests_addr);
self.requests_sender
.send_to(&data, &self.requests_addr)
.expect("buffer error in pub fn get_last_id");
@ -201,7 +205,7 @@ impl ThinClient {
let data = serialize(&req).expect("serialize GetSignature in pub fn check_signature");
let mut done = false;
while !done {
self.requests_socket
self.requests_sender
.send_to(&data, &self.requests_addr)
.expect("buffer error in pub fn get_last_id");
@ -263,6 +267,7 @@ mod tests {
let mut client = ThinClient::new(
leader.data.requests_addr,
requests_socket.try_clone().unwrap(),
requests_socket,
leader.data.transactions_addr,
transactions_socket,
@ -310,6 +315,7 @@ mod tests {
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut client = ThinClient::new(
leader.data.requests_addr,
requests_socket.try_clone().unwrap(),
requests_socket,
leader.data.transactions_addr,
transactions_socket,
@ -368,6 +374,7 @@ mod tests {
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut client = ThinClient::new(
leader.data.requests_addr,
requests_socket.try_clone().unwrap(),
requests_socket,
leader.data.transactions_addr,
transactions_socket,