Do implicit bind in socket.sendto

This commit is contained in:
Aviv Palivoda committed 2019-03-03 18:15:14 +02:00
1 parent 9b5ba068af
commit f09f75ac8d
2 files changed
+47 -14

No files matched your search

+21 -7
View File
@@ -44,18 +44,32 @@ sock1.bind(("127.0.0.1", 0))
sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock2.sendto(MESSAGE_A, sock1.getsockname())
(recv_a, addr) = sock1.recvfrom(len(MESSAGE_A))
(recv_a, addr1) = sock1.recvfrom(len(MESSAGE_A))
assert recv_a == MESSAGE_A
sock2.bind(("127.0.0.1", 0))
sock1.connect(("127.0.0.1", sock2.getsockname()[1]))
sock2.connect(("127.0.0.1", sock1.getsockname()[1]))
sock2.sendto(MESSAGE_B, sock1.getsockname())
(recv_b, addr2) = sock1.recvfrom(len(MESSAGE_B))
assert recv_b == MESSAGE_B
assert addr1[0] == addr2[0]
assert addr1[1] == addr2[1]
sock2.close()
sock3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock3.bind(("127.0.0.1", 0))
sock3.sendto(MESSAGE_A, sock1.getsockname())
(recv_a, addr) = sock1.recvfrom(len(MESSAGE_A))
assert recv_a == MESSAGE_A
assert addr == sock3.getsockname()
sock1.connect(("127.0.0.1", sock3.getsockname()[1]))
sock3.connect(("127.0.0.1", sock1.getsockname()[1]))
sock1.send(MESSAGE_A)
sock2.send(MESSAGE_B)
recv_a = sock2.recv(len(MESSAGE_A))
sock3.send(MESSAGE_B)
recv_a = sock3.recv(len(MESSAGE_A))
recv_b = sock1.recv(len(MESSAGE_B))
assert recv_a == MESSAGE_A
assert recv_b == MESSAGE_B
sock1.close()
sock2.close()
sock3.close()
+26 -7
View File
@@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::io;
use std::io::Read;
use std::io::Write;
use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket};
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket};
use std::ops::DerefMut;
use crate::obj::objbytes;
@@ -78,6 +78,13 @@ impl Connection {
_ => Err(io::Error::new(io::ErrorKind::Other, "oh no!")),
}
}
fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
match self {
Connection::UdpSocket(con) => con.send_to(buf, addr),
_ => Err(io::Error::new(io::ErrorKind::Other, "oh no!")),
}
}
}
impl Read for Connection {
@@ -360,17 +367,29 @@ fn socket_sendto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
);
let address_string = get_address_string(vm, address)?;
let socket = get_socket(zelf);
let mut socket = get_socket(zelf);
match socket.socket_kind {
SocketKind::Dgram => {
// We can't do sendto without bind in std::net::UdpSocket
if let Ok(dgram) = UdpSocket::bind("0.0.0.0:0") {
if let Ok(_) = dgram.send_to(&objbytes::get_value(&bytes), address_string) {
return Ok(vm.get_none());
match socket.con {
Some(ref mut v) => {
if let Ok(_) = v.send_to(&objbytes::get_value(&bytes), address_string) {
Ok(vm.get_none())
} else {
Err(vm.new_type_error("socket failed".to_string()))
}
}
None => {
// Doing implicit bind
if let Ok(dgram) = UdpSocket::bind("0.0.0.0:0") {
if let Ok(_) = dgram.send_to(&objbytes::get_value(&bytes), address_string) {
socket.con = Some(Connection::UdpSocket(dgram));
return Ok(vm.get_none());
}
}
Err(vm.new_type_error("socket failed".to_string()))
}
}
Err(vm.new_type_error("socket failed".to_string()))
}
_ => Err(vm.new_not_implemented_error("".to_string())),
}