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

Rust language reimplementation #105

Merged
merged 1 commit into from
Jul 7, 2017
Merged

Rust language reimplementation #105

merged 1 commit into from
Jul 7, 2017

Conversation

majorz
Copy link
Collaborator

@majorz majorz commented Jun 28, 2017

Connects-To: #104
Change-Type: minor
---- Autogenerated Waffleboard Connection: Connects to #104

@majorz majorz force-pushed the 104-rust-binary branch 2 times, most recently from fc3e475 to 1a31569 Compare June 29, 2017 09:43
@majorz
Copy link
Collaborator Author

majorz commented Jun 29, 2017

This new PR includes all of the Rust implementation code in a single commit.

This is the new flow of the application:

New Flow

Copy link
Contributor

@jbaldwinroberts jbaldwinroberts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good!

Cargo.toml Outdated
@@ -0,0 +1,28 @@
[package]
name = "resin-wifi-connect"
version = "0.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the version should match

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will place a matching "2.0.8"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@majorz this will be 3.0.0 - the last coffeescript version we release will be 2.0.8

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephroberts, it will be bumped to 3.0.0 by VersionBot automatically when 104-rust lands in master. So I think it is better to keep the Cargo version with the changelog one in sync.

Cargo.toml Outdated
[package]
name = "resin-wifi-connect"
version = "0.1.0"
authors = ["Joe Roberts <joe@resin.io>"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add yourself

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D

env_logger = "0.4"

[dependencies.network_manager]
git = "https://github.com/resin-io-modules/network_manager"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should release network_managed as a crate before merging this in
balena-io-modules/network-manager#57
balena-io-modules/network-manager#56

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good - let's leave that for a next PR


let interface: Option<String> = matches.value_of("interface").map_or_else(
|| {
env::var("PORTAL_INTERFACE").ok()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there no default?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no device is specified, we default to the first Wi-Fi device. Do we really need to default to 'wlan0'? For example on my laptop the internal one is called 'wlo1' and this one makes more sense as a default one for my system. Or I am missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, that makes total sense. ignore me :)


let password: Option<String> = matches.value_of("password").map_or_else(
|| {
env::var("PORTAL_PASSPHRASE").ok()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there no default?

Copy link
Collaborator Author

@majorz majorz Jun 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same as in the current implementation - the default is for creating an open hotspot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

- if [ $TRAVIS_RUST_VERSION == nightly ]; then
cargo clippy -- -D warnings;
fi
- cargo build
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

travis should build for the required architectures, push to S3 and create the github releases

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to update the docker file to always pull the latest release for the correct architecture. If this PR was merged today it would break resin-wifi-connect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to update the readme. We also need to release the 2.x version with the warnings we spoke about in the arch call before this can be merged

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we talked on the chat about those items - the PR will go into 104-rust, not master and we will make the changes in consecutive PRs.

@@ -0,0 +1,1003 @@
[root]
name = "resin-wifi-connect"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should a binary have this lock file? I thought it was only recommended for libraries

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hotspot_connection = None;
}

let access_points = match get_access_points(&device) {
Copy link
Contributor

@jbaldwinroberts jbaldwinroberts Jun 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is some code duplication throughout, for example this section is repeated on line 95. It would be good to go through and try to extract these parts into functions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have used this for go code - not sure if there is something similar for rust. I am surprised clippy does not catch this to be honest

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are actually some small changes (like a missing let in one of the cases) and maybe this is why clippy does not catch it. It is still a duplication, but I suggest that we leave it like that for now and address it all at once when we refactor that whole function with a better design.

unsafe impl Send for RequestSharedState {}
unsafe impl Sync for RequestSharedState {}

#[derive(Debug)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this, you have the display trait implemented below

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to remove it and the compiler complains with required by "std::error::Error".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, any idea why?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Error trait is defined as dependent on the Debug and Display traits: pub trait Error: Debug + Display {...}.

Copy link

@abrodersen abrodersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good start! Appears to be coming along nicely. :)


use config::Config;

pub fn start_dnsmasq(config: &Config, device: &Device) -> Result<Child, String> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String errors make me sad. Have you looked at using error_chain?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed that earlier on during one of the network_manager PRs, but left it for a later stage. @josephroberts, what's your opinion on the improved error reporting - should we pursue that before release or after?

Copy link
Contributor

@jbaldwinroberts jbaldwinroberts Jun 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should release now and have this as one of the first things we "fix" - unless its like a couple of hours of work in which case we should do it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely it will take more time to get it done in both repos. We will address it later on then.

src/network.rs Outdated
ssid,
password,
} => {
if hotspot_connection.is_some() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be an if let Some(value)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch!

src/network.rs Outdated
let command = match network_rx.recv() {
Ok(command) => command,
Err(e) => {
return exit_with_error(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of calling exit_with_error all over the place, it might make sense to convert all this main loop logic into a dispatch function that returns a Result. You can then use the handy ? operator inside the function to avoid all the matching. The main loop can then check for an Err result and send the exit command.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I am not happy with that long function either. It definitely needs a better design and I was thinking that we can address that in the next development phase. Joe had some ideas about incorporating some form of state machine as well. @josephroberts, what's your opinion on this - should we try to come up with a better design for the network related thread function, or we should address that at a post-3.0 phase?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address it later on

ssid: &str,
gateway: &Ipv4Addr,
password: &Option<&str>,
) -> Result<Connection, String> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the rustfmt approved way of formatting a function? It looks really wonky to me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is how rustfmt is configured now for us to avoid right-side drifting (I am not really sure what is the current rustfmt default, since they improved many aspects of those recently). We need to catch up with rustfmt soon, since they introduced a new crate that runs on nightly only, which will be the maintained version: http://www.ncameron.org/blog/rustfmt-changes/

src/server.rs Outdated
format!("{}", request_state.gateway)
};

let host = req.headers.get::<headers::Host>().unwrap();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a client crash the server by not sending a Host header?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another nice catch, will fix that.

src/server.rs Outdated
let host = req.headers.get::<headers::Host>().unwrap();

if host.hostname != gateway {
let url = Url::parse(&format!("http://{}/", gateway)).unwrap();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with sending a malformed Url

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix that too :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at this one and it will actually never fail, since the gateway is already parsed Ipv4Addr instance.

@majorz
Copy link
Collaborator Author

majorz commented Jul 4, 2017

I updated the source code and recommitted with all the changes discussed above.

Additionally I ported the following functionality from the existing implementation:

  1. Starting the NetworkManager service if stopped for some reason
  2. Checking for Internet connectivity after connection to access point is established - when new connection is created using the hotspot and webserver. If connectivity is not established, the connection will be deleted and the webserver will continue to run waiting for new credentials to be added.

src/config.rs Outdated
const DEFAULT_GATEWAY: &str = "192.168.42.1";
const DEFAULT_DHCP_RANGE: &str = "192.168.42.2,192.168.42.254";
const DEFAULT_SSID: &str = "ResinAP";
const DEFAULT_TIMEOUT: &str = "15000";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should specify that this timeout is in ms, either with a comment or by naming the variable DEFAULT_TIMEOUT_MS

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I changed it to DEFAULT_TIMEOUT_MS.


pub fn get_config() -> Config {
let matches = App::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about CARGO_PKG_... - very nice :)

unsafe impl Send for RequestSharedState {}
unsafe impl Sync for RequestSharedState {}

#[derive(Debug)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, any idea why?

@majorz majorz force-pushed the 104-rust-binary branch 3 times, most recently from a82d236 to c5c6a55 Compare July 5, 2017 11:06
Connects-To: #104
Change-Type: major
@majorz
Copy link
Collaborator Author

majorz commented Jul 5, 2017

In addition to the DEFAULT_TIMEOUT_MS change I added one fix for the travis builds:

When clippy was compiled with an older Rust nightly (like from the previous day), but no new clippy version was found, then clippy is not working with the new Rust nightly (because it links to the compiled Rust binary libs). In that case although a new clippy version is not available, we still need to recompile the current clippy version towards the new nightly. The check I did is run cargo clippy -V and then if the exit code is non-zero something is wrong (like the described case) and we force reinstall.

Copy link

@abrodersen abrodersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@majorz majorz merged commit e178987 into 104-rust Jul 7, 2017
@majorz majorz deleted the 104-rust-binary branch July 7, 2017 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants