Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to create UDP and TCP sockets #223

Closed
crawford opened this issue May 31, 2018 · 12 comments
Closed

Unable to create UDP and TCP sockets #223

crawford opened this issue May 31, 2018 · 12 comments

Comments

@crawford
Copy link
Contributor

I'm trying to create two listening sockets, one UDP and one TCP, with the following code:

    let mut udp_rx_payload = [0; 128];   
    let mut udp_rx_metadata = [PacketMetadata::EMPTY; 1];
    let mut udp_tx_payload = [0; 128];
    let mut udp_tx_metadata = [PacketMetadata::EMPTY; 1];
    let udp_socket = UdpSocket::new(
        UdpSocketBuffer::new(udp_rx_metadata.as_mut(), udp_rx_payload.as_mut()),
        UdpSocketBuffer::new(udp_tx_metadata.as_mut(), udp_tx_payload.as_mut()),
    );                        

    let mut tcp_rx_payload = [0; 128];                      
    let mut tcp_tx_payload = [0; 128];
    let tcp_socket = TcpSocket::new(
        TcpSocketBuffer::new(tcp_rx_payload.as_mut()),                         
        TcpSocketBuffer::new(tcp_tx_payload.as_mut()),
    );
            
    let mut sockets = [None, None];
    let mut socket_set = SocketSet::new(sockets.as_mut());
    let udp_handle = socket_set.add(udp_socket);
    let tcp_handle = socket_set.add(tcp_socket);

When I try to build this, I get the following error:

error[E0597]: `udp_rx_payload` does not live long enough
   --> src/main.rs:117:56
    |
117 |         UdpSocketBuffer::new(udp_rx_metadata.as_mut(), udp_rx_payload.as_mut()),
    |                                                        ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
167 | }
    | - borrowed value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...

error[E0597]: `udp_tx_payload` does not live long enough
   --> src/main.rs:118:56
    |
118 |         UdpSocketBuffer::new(udp_tx_metadata.as_mut(), udp_tx_payload.as_mut()),
    |                                                        ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
167 | }
    | - borrowed value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...

If I comment out either of the calls to socket_set.add, it builds and runs.

I'm using rustc 1.28.0-nightly (c2d46037f 2018-05-24).

@whitequark
Copy link
Contributor

The lifetimes of all sockets unify with each other, so you need to group them like this:

    let mut udp_rx_payload = [0; 128];   
    let mut udp_tx_payload = [0; 128];
    let mut tcp_rx_payload = [0; 128];                      
    let mut tcp_tx_payload = [0; 128];
    let mut udp_tx_metadata = [PacketMetadata::EMPTY; 1];
    let mut udp_rx_metadata = [PacketMetadata::EMPTY; 1];
    let udp_socket = UdpSocket::new(
        UdpSocketBuffer::new(udp_rx_metadata.as_mut(), udp_rx_payload.as_mut()),
        UdpSocketBuffer::new(udp_tx_metadata.as_mut(), udp_tx_payload.as_mut()),
    );                        
    let tcp_socket = TcpSocket::new(
        TcpSocketBuffer::new(tcp_rx_payload.as_mut()),                         
        TcpSocketBuffer::new(tcp_tx_payload.as_mut()),
    );
            
    let mut sockets = [None, None];
    let mut socket_set = SocketSet::new(sockets.as_mut());
    let udp_handle = socket_set.add(udp_socket);
    let tcp_handle = socket_set.add(tcp_socket);

cf. #48

@crawford
Copy link
Contributor Author

That gives me the same error as before:

error[E0597]: `udp_rx_payload` does not live long enough
   --> src/main.rs:119:56
    |
119 |         UdpSocketBuffer::new(udp_rx_metadata.as_mut(), udp_rx_payload.as_mut()),
    |                                                        ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
166 | }
    | - borrowed value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...

error[E0597]: `udp_tx_payload` does not live long enough
   --> src/main.rs:120:56
    |
120 |         UdpSocketBuffer::new(udp_tx_metadata.as_mut(), udp_tx_payload.as_mut()),
    |                                                        ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
166 | }
    | - borrowed value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...

Is there something in the surrounding code that I need to check? All of this code exists in main.

@whitequark
Copy link
Contributor

Oh sorry, I didn't go far enough. You need...

    let mut udp_rx_payload = [0; 128];   
    let mut udp_tx_payload = [0; 128];
    let mut tcp_rx_payload = [0; 128];                      
    let mut tcp_tx_payload = [0; 128];
    let mut udp_tx_metadata = [PacketMetadata::EMPTY; 1];
    let mut udp_rx_metadata = [PacketMetadata::EMPTY; 1];
    let udp_rx_buffer = UdpSocketBuffer::new(udp_rx_metadata.as_mut(), udp_rx_payload.as_mut());
    let udp_tx_buffer = UdpSocketBuffer::new(udp_tx_metadata.as_mut(), udp_tx_payload.as_mut());
    let tcp_rx_buffer = TcpSocketBuffer::new(tcp_rx_metadata.as_mut(), tcp_rx_payload.as_mut());
    let tcp_tx_buffer = TcpSocketBuffer::new(tcp_tx_metadata.as_mut(), tcp_tx_payload.as_mut());
    let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);                        
    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
            
    let mut sockets = [None, None];
    let mut socket_set = SocketSet::new(sockets.as_mut());
    let udp_handle = socket_set.add(udp_socket);
    let tcp_handle = socket_set.add(tcp_socket);

@crawford
Copy link
Contributor Author

(There is a small typo above. TcpSocketBuffer::new doesn't need metadata). I still get the same error :(

@whitequark
Copy link
Contributor

Can you post your project somewhere? In any case, here's a working example: https://github.com/m-labs/ionpak/blob/master/firmware/src/main.rs#L158-L194.

@crawford
Copy link
Contributor Author

crawford commented May 31, 2018

I just made it public. Here is the code in question (without the suggested changes): https://github.com/crawford/PoE/blob/3f26e93afc082af7fc9c40eb1b5c55354afa071a/firmware/src/main.rs#L113.

@progval
Copy link
Contributor

progval commented Jun 21, 2018

@crawford Hmm, I can compile your code with the nightly compiler. (Maybe thanks to the NLL?)

@crawford
Copy link
Contributor Author

crawford commented Jul 3, 2018

@progval Did you uncomment line 131?

@crawford
Copy link
Contributor Author

crawford commented Jul 3, 2018

@whitequark I'm now getting an eerily similar error after refactoring my Device implementation. This code fails with the following error message:

error[E0597]: `tx_buffer` does not live long enough
   --> src/main.rs:111:18
    |
111 |             &mut tx_buffer,
    |                  ^^^^^^^^^ borrowed value does not live long enough
...
178 | }
    | - `tx_buffer` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created

I wonder if both this failure and the original actually stem from the type definition of Interface and InterfaceBuilder. Both of these structs dictate that DeviceT is a Device of any lifetime (including 'static), but my Device does not implement 'static (unlike the Device in IonPak). I've been trying to modify smoltcp to lift that restriction, but I haven't been able to satisfy the borrow checker yet.

EDIT:

I was able to fix this last error by breaking up the lifetimes. Changing something like this:

struct MAC<'a> {
    rx_buffer: &'a mut RxBuffer<'a>,
    tx_buffer: &'a mut TxBuffer<'a>,
}

into this:

struct MAC<'a, 'b: 'a> {
    rx_buffer: &'a mut RxBuffer<'b>,
    tx_buffer: &'a mut TxBuffer<'b>,
}

@birkenfeld
Copy link

Does it change anything if you move rx_buffer/tx_buffer above the creation of neighbor_cache and ip_addrs?

@crawford
Copy link
Contributor Author

crawford commented Jul 3, 2018

@birkenfeld Unfortunately, no.

@crawford
Copy link
Contributor Author

This has been fixed by #304.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants