Skip to content

Commit c1ddcbb

Browse files
Merge pull request #632 from palaviv/socket-errors
Socket OSError
2 parents 56bb6d2 + 8df0e46 commit c1ddcbb

File tree

3 files changed

+80
-48
lines changed

3 files changed

+80
-48
lines changed

tests/snippets/stdlib_socket.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,29 @@
2929
with assertRaises(TypeError):
3030
s.connect(("127.0.0.1", 8888, 8888))
3131

32+
with assertRaises(OSError):
33+
# Lets hope nobody is listening on port 1
34+
s.connect(("127.0.0.1", 1))
35+
3236
with assertRaises(TypeError):
3337
s.bind(("127.0.0.1", 8888, 8888))
3438

39+
with assertRaises(OSError):
40+
# Lets hope nobody run this test on machine with ip 1.2.3.4
41+
s.bind(("1.2.3.4", 8888))
42+
3543
with assertRaises(TypeError):
3644
s.bind((888, 8888))
3745

46+
s.close()
47+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48+
s.bind(("127.0.0.1", 0))
49+
with assertRaises(OSError):
50+
s.recv(100)
51+
52+
with assertRaises(OSError):
53+
s.send(MESSAGE_A)
54+
3855
s.close()
3956

4057
# UDP
@@ -73,3 +90,15 @@
7390
assert recv_b == MESSAGE_B
7491
sock1.close()
7592
sock3.close()
93+
94+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
95+
with assertRaises(OSError):
96+
s.bind(("1.2.3.4", 888))
97+
98+
s.close()
99+
### Errors
100+
with assertRaises(OSError):
101+
socket.socket(100, socket.SOCK_STREAM)
102+
103+
with assertRaises(OSError):
104+
socket.socket(socket.AF_INET, 1000)

vm/src/builtins.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
802802
"StopIteration" => ctx.exceptions.stop_iteration.clone(),
803803
"ZeroDivisionError" => ctx.exceptions.zero_division_error.clone(),
804804
"KeyError" => ctx.exceptions.key_error.clone(),
805+
"OSError" => ctx.exceptions.os_error.clone(),
805806
});
806807

807808
#[cfg(not(target_arch = "wasm32"))]

vm/src/stdlib/socket.rs

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ enum AddressFamily {
2424
}
2525

2626
impl AddressFamily {
27-
fn from_i32(value: i32) -> AddressFamily {
27+
fn from_i32(vm: &mut VirtualMachine, value: i32) -> Result<AddressFamily, PyObjectRef> {
2828
match value {
29-
1 => AddressFamily::Unix,
30-
2 => AddressFamily::Inet,
31-
3 => AddressFamily::Inet6,
32-
_ => panic!("Unknown value: {}", value),
29+
1 => Ok(AddressFamily::Unix),
30+
2 => Ok(AddressFamily::Inet),
31+
3 => Ok(AddressFamily::Inet6),
32+
_ => Err(vm.new_os_error(format!("Unknown address family value: {}", value))),
3333
}
3434
}
3535
}
@@ -41,11 +41,11 @@ enum SocketKind {
4141
}
4242

4343
impl SocketKind {
44-
fn from_i32(value: i32) -> SocketKind {
44+
fn from_i32(vm: &mut VirtualMachine, value: i32) -> Result<SocketKind, PyObjectRef> {
4545
match value {
46-
1 => SocketKind::Stream,
47-
2 => SocketKind::Dgram,
48-
_ => panic!("Unknown value: {}", value),
46+
1 => Ok(SocketKind::Stream),
47+
2 => Ok(SocketKind::Dgram),
48+
_ => Err(vm.new_os_error(format!("Unknown socket kind value: {}", value))),
4949
}
5050
}
5151
}
@@ -146,8 +146,9 @@ fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
146146
]
147147
);
148148

149-
let address_family = AddressFamily::from_i32(objint::get_value(family_int).to_i32().unwrap());
150-
let kind = SocketKind::from_i32(objint::get_value(kind_int).to_i32().unwrap());
149+
let address_family =
150+
AddressFamily::from_i32(vm, objint::get_value(family_int).to_i32().unwrap())?;
151+
let kind = SocketKind::from_i32(vm, objint::get_value(kind_int).to_i32().unwrap())?;
151152

152153
let socket = RefCell::new(Socket::new(address_family, kind));
153154

@@ -171,21 +172,18 @@ fn socket_connect(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
171172
let mut socket = get_socket(zelf);
172173

173174
match socket.socket_kind {
174-
SocketKind::Stream => {
175-
if let Ok(stream) = TcpStream::connect(address_string) {
175+
SocketKind::Stream => match TcpStream::connect(address_string) {
176+
Ok(stream) => {
176177
socket.con = Some(Connection::TcpStream(stream));
177178
Ok(vm.get_none())
178-
} else {
179-
// TODO: Socket error
180-
Err(vm.new_type_error("socket failed".to_string()))
181179
}
182-
}
180+
Err(s) => Err(vm.new_os_error(s.to_string())),
181+
},
183182
SocketKind::Dgram => {
184183
if let Some(Connection::UdpSocket(con)) = &socket.con {
185184
match con.connect(address_string) {
186185
Ok(_) => Ok(vm.get_none()),
187-
// TODO: Socket error
188-
Err(_) => Err(vm.new_type_error("socket failed".to_string())),
186+
Err(s) => Err(vm.new_os_error(s.to_string())),
189187
}
190188
} else {
191189
Err(vm.new_type_error("".to_string()))
@@ -206,24 +204,20 @@ fn socket_bind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
206204
let mut socket = get_socket(zelf);
207205

208206
match socket.socket_kind {
209-
SocketKind::Stream => {
210-
if let Ok(stream) = TcpListener::bind(address_string) {
207+
SocketKind::Stream => match TcpListener::bind(address_string) {
208+
Ok(stream) => {
211209
socket.con = Some(Connection::TcpListener(stream));
212210
Ok(vm.get_none())
213-
} else {
214-
// TODO: Socket error
215-
Err(vm.new_type_error("socket failed".to_string()))
216211
}
217-
}
218-
SocketKind::Dgram => {
219-
if let Ok(dgram) = UdpSocket::bind(address_string) {
212+
Err(s) => Err(vm.new_os_error(s.to_string())),
213+
},
214+
SocketKind::Dgram => match UdpSocket::bind(address_string) {
215+
Ok(dgram) => {
220216
socket.con = Some(Connection::UdpSocket(dgram));
221217
Ok(vm.get_none())
222-
} else {
223-
// TODO: Socket error
224-
Err(vm.new_type_error("socket failed".to_string()))
225218
}
226-
}
219+
Err(s) => Err(vm.new_os_error(s.to_string())),
220+
},
227221
}
228222
}
229223

@@ -272,7 +266,7 @@ fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
272266

273267
let (tcp_stream, addr) = match ret {
274268
Ok((socket, addr)) => (socket, addr),
275-
_ => return Err(vm.new_type_error("".to_string())),
269+
Err(s) => return Err(vm.new_os_error(s.to_string())),
276270
};
277271

278272
let socket = RefCell::new(Socket {
@@ -303,7 +297,10 @@ fn socket_recv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
303297

304298
let mut buffer = vec![0u8; objint::get_value(bufsize).to_usize().unwrap()];
305299
match socket.con {
306-
Some(ref mut v) => v.read_exact(&mut buffer).unwrap(),
300+
Some(ref mut v) => match v.read_exact(&mut buffer) {
301+
Ok(_) => (),
302+
Err(s) => return Err(vm.new_os_error(s.to_string())),
303+
},
307304
None => return Err(vm.new_type_error("".to_string())),
308305
};
309306
Ok(vm.ctx.new_bytes(buffer))
@@ -326,7 +323,7 @@ fn socket_recvfrom(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
326323

327324
let addr = match ret {
328325
Ok((_size, addr)) => addr,
329-
_ => return Err(vm.new_type_error("".to_string())),
326+
Err(s) => return Err(vm.new_os_error(s.to_string())),
330327
};
331328

332329
let addr_tuple = get_addr_tuple(vm, addr)?;
@@ -343,7 +340,10 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
343340
let mut socket = get_socket(zelf);
344341

345342
match socket.con {
346-
Some(ref mut v) => v.write(&objbytes::get_value(&bytes)).unwrap(),
343+
Some(ref mut v) => match v.write(&objbytes::get_value(&bytes)) {
344+
Ok(_) => (),
345+
Err(s) => return Err(vm.new_os_error(s.to_string())),
346+
},
347347
None => return Err(vm.new_type_error("".to_string())),
348348
};
349349
Ok(vm.get_none())
@@ -366,22 +366,24 @@ fn socket_sendto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
366366
match socket.socket_kind {
367367
SocketKind::Dgram => {
368368
match socket.con {
369-
Some(ref mut v) => {
370-
if let Ok(_) = v.send_to(&objbytes::get_value(&bytes), address_string) {
371-
Ok(vm.get_none())
372-
} else {
373-
Err(vm.new_type_error("socket failed".to_string()))
374-
}
375-
}
369+
Some(ref mut v) => match v.send_to(&objbytes::get_value(&bytes), address_string) {
370+
Ok(_) => Ok(vm.get_none()),
371+
Err(s) => Err(vm.new_os_error(s.to_string())),
372+
},
376373
None => {
377374
// Doing implicit bind
378-
if let Ok(dgram) = UdpSocket::bind("0.0.0.0:0") {
379-
if let Ok(_) = dgram.send_to(&objbytes::get_value(&bytes), address_string) {
380-
socket.con = Some(Connection::UdpSocket(dgram));
381-
return Ok(vm.get_none());
375+
match UdpSocket::bind("0.0.0.0:0") {
376+
Ok(dgram) => {
377+
match dgram.send_to(&objbytes::get_value(&bytes), address_string) {
378+
Ok(_) => {
379+
socket.con = Some(Connection::UdpSocket(dgram));
380+
Ok(vm.get_none())
381+
}
382+
Err(s) => Err(vm.new_os_error(s.to_string())),
383+
}
382384
}
385+
Err(s) => Err(vm.new_os_error(s.to_string())),
383386
}
384-
Err(vm.new_type_error("socket failed".to_string()))
385387
}
386388
}
387389
}
@@ -408,7 +410,7 @@ fn socket_getsockname(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
408410

409411
match addr {
410412
Ok(addr) => get_addr_tuple(vm, addr),
411-
_ => Err(vm.new_type_error("".to_string())),
413+
Err(s) => Err(vm.new_os_error(s.to_string())),
412414
}
413415
}
414416

0 commit comments

Comments
 (0)