Struct bluer::rfcomm::Socket

source ·
pub struct Socket { /* private fields */ }
Available on crate feature rfcomm only.
Expand description

An RFCOMM socket that has not yet been converted to a Listener or Stream.

The primary use of this is to configure the socket before connecting or listening.

Implementations§

source§

impl Socket

source

pub fn new() -> Result<Self>

Creates a new socket of stream type.

source

pub fn listen(self, backlog: u32) -> Result<Listener>

Convert the socket into a Listener.

backlog defines the maximum number of pending connections are queued by the operating system at any given time.

This will not register an SDP record for this channel. Register a Bluetooth RFCOMM profile instead, if you need a service record.

source

pub async fn connect(self, sa: SocketAddr) -> Result<Stream>

Establish a stream connection with a peer at the specified socket address.

This requires knowledge of the channel number. Register a Bluetooth RFCOMM profile, if you need to discover the channel number using a service record.

source

pub fn bind(&self, sa: SocketAddr) -> Result<()>

Bind the socket to the given address.

source

pub fn local_addr(&self) -> Result<SocketAddr>

Get the local address of this socket.

Examples found in repository?
examples/rfcomm_server.rs (line 22)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;
    adapter.set_discoverable(true).await?;
    let adapter_addr = adapter.address().await?;

    let local_sa = SocketAddr::new(adapter_addr, CHANNEL);
    let listener = Listener::bind(local_sa).await?;

    println!(
        "Listening on {} channel {}. Press enter to quit.",
        listener.as_ref().local_addr()?.addr,
        listener.as_ref().local_addr()?.channel
    );
    let stdin = BufReader::new(tokio::io::stdin());
    let mut lines = stdin.lines();

    loop {
        println!("\nWaiting for connection...");

        let (mut stream, sa) = tokio::select! {
            l = listener.accept() => {
                match l {
                    Ok(v) => v,
                    Err(err) => {
                        println!("Accepting connection failed: {}", &err);
                        continue;
                    }}
            },
            _ = lines.next_line() => break,
        };

        println!("Accepted connection from {:?}", &sa);

        println!("Sending hello");
        if let Err(err) = stream.write_all(HELLO_MSG).await {
            println!("Write failed: {}", &err);
            continue;
        }

        loop {
            let buf_size = 1024;
            let mut buf = vec![0; buf_size as _];

            let n = match stream.read(&mut buf).await {
                Ok(0) => {
                    println!("Stream ended");
                    break;
                }
                Ok(n) => n,
                Err(err) => {
                    println!("Read failed: {}", &err);
                    break;
                }
            };
            let buf = &buf[..n];

            println!("Echoing {} bytes", buf.len());
            if let Err(err) = stream.write_all(buf).await {
                println!("Write failed: {}", &err);
                continue;
            }
        }
    }

    Ok(())
}
More examples
Hide additional examples
examples/rfcomm_client.rs (line 31)
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;

    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Specify target Bluetooth address as argument");
        exit(1);
    }

    let target_addr: Address = args[1].parse().expect("invalid address");
    let target_sa = SocketAddr::new(target_addr, CHANNEL);

    println!("Connecting to {:?}", &target_sa);
    let mut stream = Stream::connect(target_sa).await.expect("connection failed");
    println!("Local address: {:?}", stream.as_ref().local_addr()?);
    println!("Remote address: {:?}", stream.peer_addr()?);
    println!("Security: {:?}", stream.as_ref().security()?);

    println!("\nReceiving hello");
    let mut hello_buf = [0u8; HELLO_MSG.len()];
    stream.read_exact(&mut hello_buf).await.expect("read failed");
    println!("Received: {}", String::from_utf8_lossy(&hello_buf));
    if hello_buf != HELLO_MSG {
        panic!("Wrong hello message");
    }

    let (mut rh, mut wh) = stream.into_split();
    let mut rng = rand::thread_rng();
    for i in 0..15 {
        let len = rng.gen_range(0..50000);
        let data: Vec<u8> = (0..len).map(|_| rng.gen()).collect();

        println!("\nTest iteration {i} with data size {len}");

        // We must read back the data while sending, otherwise the connection
        // buffer will overrun and we will lose data.
        let read_task = tokio::spawn(async move {
            let mut echo_buf = vec![0u8; len];
            let res = match rh.read_exact(&mut echo_buf).await {
                Ok(_) => Ok(echo_buf),
                Err(err) => Err(err),
            };
            (rh, res)
        });

        // Note that write_all will automatically split the buffer into
        // multiple writes of MTU size.
        wh.write_all(&data).await.expect("write failed");

        println!("Waiting for echo");
        let (rh_back, res) = read_task.await.unwrap();
        rh = rh_back;
        let echo_buf = res.expect("read failed");

        if echo_buf != data {
            panic!("Echoed data does not match sent data");
        }
        println!("Data matches");
    }

    println!("Done");
    Ok(())
}
source

pub fn security(&self) -> Result<Security>

Get socket security.

This corresponds to the BT_SECURITY socket option.

Examples found in repository?
examples/rfcomm_client.rs (line 33)
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;

    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Specify target Bluetooth address as argument");
        exit(1);
    }

    let target_addr: Address = args[1].parse().expect("invalid address");
    let target_sa = SocketAddr::new(target_addr, CHANNEL);

    println!("Connecting to {:?}", &target_sa);
    let mut stream = Stream::connect(target_sa).await.expect("connection failed");
    println!("Local address: {:?}", stream.as_ref().local_addr()?);
    println!("Remote address: {:?}", stream.peer_addr()?);
    println!("Security: {:?}", stream.as_ref().security()?);

    println!("\nReceiving hello");
    let mut hello_buf = [0u8; HELLO_MSG.len()];
    stream.read_exact(&mut hello_buf).await.expect("read failed");
    println!("Received: {}", String::from_utf8_lossy(&hello_buf));
    if hello_buf != HELLO_MSG {
        panic!("Wrong hello message");
    }

    let (mut rh, mut wh) = stream.into_split();
    let mut rng = rand::thread_rng();
    for i in 0..15 {
        let len = rng.gen_range(0..50000);
        let data: Vec<u8> = (0..len).map(|_| rng.gen()).collect();

        println!("\nTest iteration {i} with data size {len}");

        // We must read back the data while sending, otherwise the connection
        // buffer will overrun and we will lose data.
        let read_task = tokio::spawn(async move {
            let mut echo_buf = vec![0u8; len];
            let res = match rh.read_exact(&mut echo_buf).await {
                Ok(_) => Ok(echo_buf),
                Err(err) => Err(err),
            };
            (rh, res)
        });

        // Note that write_all will automatically split the buffer into
        // multiple writes of MTU size.
        wh.write_all(&data).await.expect("write failed");

        println!("Waiting for echo");
        let (rh_back, res) = read_task.await.unwrap();
        rh = rh_back;
        let echo_buf = res.expect("read failed");

        if echo_buf != data {
            panic!("Echoed data does not match sent data");
        }
        println!("Data matches");
    }

    println!("Done");
    Ok(())
}
source

pub fn set_security(&self, security: Security) -> Result<()>

Set socket security.

This corresponds to the BT_SECURITY socket option.

source

pub fn recv_buffer(&self) -> Result<i32>

Gets the maximum socket receive buffer in bytes.

This corresponds to the SO_RCVBUF socket option.

source

pub fn set_recv_buffer(&self, recv_buffer: i32) -> Result<()>

Sets the maximum socket receive buffer in bytes.

This corresponds to the SO_RCVBUF socket option.

source

pub fn conn_info(&self) -> Result<ConnInfo>

Gets the RFCOMM socket connection information.

This corresponds to the RFCOMM_CONNINFO socket option.

source

pub fn is_master(&self) -> Result<bool>

Gets whether the RFCOMM socket is the master.

This corresponds to the RFCOMM_LM socket option and option bit RFCOMM_LM_MASTER.

source

pub fn set_master(&self, master: bool) -> Result<()>

sets whether the RFCOMM socket is the master.

This corresponds to the RFCOMM_LM socket option and option bit RFCOMM_LM_MASTER.

source

pub fn input_buffer(&self) -> Result<u32>

Get the number of bytes in the input buffer.

This corresponds to the TIOCINQ IOCTL.

source

pub fn output_buffer(&self) -> Result<u32>

Get the number of bytes in the output buffer.

This corresponds to the TIOCOUTQ IOCTL.

source

pub fn create_tty(&self, dev_id: i16) -> Result<i16>

Creates a TTY (virtual serial port) for this RFCOMM connection.

Set dev_id to -1 to automatically allocate an id. Returns the allocated device id.

This corresponds to the RFCOMMCREATEDEV IOCTL.

source

pub fn release_tty(dev_id: i16) -> Result<()>

Releases a TTY (virtual serial port) for this RFCOMM connection.

This corresponds to the RFCOMMRELEASEDEV IOCTL.

source

pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self>

Constructs a new Socket from the given raw file descriptor.

The file descriptor must have been set to non-blocking mode.

This function consumes ownership of the specified file descriptor. The returned object will take responsibility for closing it when the object goes out of scope.

§Safety

If the passed file descriptor is invalid, undefined behavior may occur.

Trait Implementations§

source§

impl AsRawFd for Socket

source§

fn as_raw_fd(&self) -> RawFd

Extracts the raw file descriptor. Read more
source§

impl AsRef<Socket> for Listener

source§

fn as_ref(&self) -> &Socket

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl AsRef<Socket> for Stream

source§

fn as_ref(&self) -> &Socket

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl Debug for Socket

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl FromRawFd for Socket

source§

unsafe fn from_raw_fd(fd: RawFd) -> Self

Constructs a new instance of Self from the given raw file descriptor.

The file descriptor must have been set to non-blocking mode.

§Panics

Panics when the conversion fails. Use Socket::from_raw_fd for a non-panicking variant.

source§

impl IntoRawFd for Socket

source§

fn into_raw_fd(self) -> RawFd

Consumes this object, returning the raw underlying file descriptor. Read more

Auto Trait Implementations§

§

impl Freeze for Socket

§

impl !RefUnwindSafe for Socket

§

impl Send for Socket

§

impl Sync for Socket

§

impl Unpin for Socket

§

impl !UnwindSafe for Socket

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.