Created
November 16, 2016 21:00
-
-
Save nathansizemore/82d02f1a30dfe46c834fc98839237649 to your computer and use it in GitHub Desktop.
Rust wrapper for a raw Linux socket
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2016 Nathan Sizemore <[email protected]> | |
// | |
// This Source Code Form is subject to the terms of the | |
// Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed | |
// with this file, you can obtain one at http://mozilla.org/MPL/2.0/. | |
use std::io::{self, Error, ErrorKind, Read, Write}; | |
use std::os::unix::io::{AsRawFd, RawFd}; | |
use libc; | |
#[derive(Debug, Clone, Copy)] | |
pub struct Socket { | |
fd: RawFd | |
} | |
impl Socket { | |
pub fn new(fd: RawFd) -> Socket { Socket { fd: fd } } | |
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { | |
let l = buf.len(); | |
let b = buf.as_mut_ptr() as *mut libc::c_void; | |
let r = unsafe { libc::recv(self.fd, b, l, 0) }; | |
// These calls return the number of bytes received, or -1 if an error | |
// occurred. In the event of an error, errno is set to indicate the | |
// error. | |
if r == -1 { | |
Err(Error::last_os_error()) | |
} else if r == 0 { | |
// When a stream socket peer has performed an orderly shutdown, the | |
// return value will be 0 (the traditional "end-of-file" return). | |
// | |
// The value 0 may also be returned if the requested number of bytes | |
// to receive from a stream socket was 0. | |
if buf.len() == 0 { Ok(0) } | |
else { Err(Error::new(ErrorKind::UnexpectedEof, "EOF")) } | |
} else { | |
Ok(r as usize) | |
} | |
} | |
pub fn send(&self, buf: &[u8]) -> io::Result<usize> { | |
let l = buf.len(); | |
let b = buf.as_ptr() as *const libc::c_void; | |
let r = unsafe { libc::send(self.fd, b, l, 0) }; | |
// On success, these calls return the number of bytes sent. | |
// On error, -1 is returned, and errno is set appropriately. | |
if r == -1 { | |
Err(Error::last_os_error()) | |
} else if r == 0 { | |
if buf.len() == 0 { Ok(0) } | |
else { Err(Error::new(ErrorKind::WriteZero, "WriteZero")) } | |
} else { | |
Ok(r as usize) | |
} | |
} | |
} | |
impl AsRawFd for Socket { fn as_raw_fd(&self) -> RawFd { self.fd } } | |
impl Read for Socket { | |
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.recv(buf) } | |
} | |
impl Write for Socket { | |
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.send(buf) } | |
fn flush(&mut self) -> io::Result<()> { Ok(()) } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment