-
Notifications
You must be signed in to change notification settings - Fork 29
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
Client side of the registration service. #58
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* 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/. */ | ||
|
||
/// This manages registration of the foxbox with the discovery endpoint. | ||
/// For now it simply register itselfs every N minutes with the endpoint, | ||
/// after trying more aggressively at first run. | ||
|
||
extern crate get_if_addrs; | ||
extern crate hyper; | ||
|
||
use self::hyper::Client; | ||
use self::hyper::header::Connection; | ||
use self::hyper::status::StatusCode; | ||
use self::get_if_addrs::IfAddr; | ||
use std::io::Read; | ||
use std::time::Duration; | ||
use std::thread; | ||
|
||
const DEFAULT_ENDPOINT: &'static str = "http://localhost:4242/register"; | ||
const REGISTRATION_INTERVAL: u32 = 1; // in minutes. | ||
|
||
pub struct Registrar; | ||
|
||
impl Registrar { | ||
pub fn new() -> Registrar { | ||
Registrar | ||
} | ||
|
||
pub fn start(&self, endpoint: Option<String>) { | ||
let url = match endpoint { | ||
Some(u) => u, | ||
_ => DEFAULT_ENDPOINT.to_owned() | ||
}; | ||
|
||
info!("Starting registration with {}", url); | ||
let ip_addr = self.get_ip_addr(); | ||
if ip_addr == None { | ||
// TODO: retry later, in case we're racing with the network | ||
// configuration. | ||
return; | ||
} | ||
|
||
info!("Got ip address: {}", ip_addr.clone().unwrap()); | ||
let full_address = format!("{}?ip={}", url, ip_addr.unwrap()); | ||
|
||
// Spawn a thread to register every REGISTRATION_INTERVAL minutes. | ||
thread::Builder::new().name("Registrar".to_owned()) | ||
.spawn(move || { | ||
loop { | ||
let client = Client::new(); | ||
let res = client.get(&full_address) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: not to be done in this pr but in the service, perhaps this should be a post. |
||
.header(Connection::close()) | ||
.send(); | ||
|
||
// Sanity checks, mostly to debug errors since we don't try | ||
// to recover from failures. | ||
if let Ok(mut response) = res { | ||
if response.status == StatusCode::Ok { | ||
let mut body = String::new(); | ||
if let Ok(_) = response.read_to_string(&mut body) { | ||
info!("Server responded with: {}", body); | ||
} else { | ||
info!("Unable to read answer from {}", full_address); | ||
} | ||
} | ||
} else { | ||
info!("Unable to send request to {}", full_address); | ||
} | ||
|
||
// Go to sleep. | ||
thread::sleep(Duration::from_secs(REGISTRATION_INTERVAL as u64 * 60)) | ||
} | ||
}).unwrap(); | ||
} | ||
|
||
pub fn get_ip_addr(&self) -> Option<String> { | ||
// Look for an ipv4 interface on eth* or wlan*. | ||
if let Ok(ifaces) = get_if_addrs::get_if_addrs() { | ||
if ifaces.is_empty() { | ||
error!("No IP interfaces found!"); | ||
return None; | ||
} | ||
|
||
let mut ip_addr: Option<String> = None; | ||
|
||
for iface in ifaces { | ||
if ! (iface.name.starts_with("eth") || | ||
iface.name.starts_with("wlan") || | ||
iface.name.starts_with("en")) { | ||
continue; | ||
} | ||
if let IfAddr::V4(ref v4) = iface.addr { | ||
ip_addr = Some(format!("{}", v4.ip)); | ||
} | ||
} | ||
|
||
ip_addr | ||
} else { | ||
error!("No IP interfaces found!"); | ||
None | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn check_ip_addr() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can add this as a test module to avoid compilation when non testing: #[cfg(test)] ... |
||
let registrar = Registrar::new(); | ||
let ip_addr = registrar.get_ip_addr(); | ||
assert!(ip_addr != None); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
|
||
use context::{ ContextTrait, Shared }; | ||
use iron::{Request, Response, IronResult}; | ||
use iron::headers::ContentType; | ||
use iron::headers::{ ContentType, AccessControlAllowOrigin }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are the changes in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added them to get my demo client working. I guess we'll change/revert once we have proper user authentication working. |
||
use iron::status::Status; | ||
use router::Router; | ||
use core::marker::Reflect; | ||
|
@@ -21,6 +21,7 @@ pub fn create<Ctx: Send + Reflect + ContextTrait + 'static> (context: Shared<Ctx | |
|
||
let mut response = Response::with(serialized); | ||
response.status = Some(Status::Ok); | ||
response.headers.set(AccessControlAllowOrigin::Any); | ||
response.headers.set(ContentType::json()); | ||
|
||
Ok(response) | ||
|
@@ -36,6 +37,7 @@ pub fn create<Ctx: Send + Reflect + ContextTrait + 'static> (context: Shared<Ctx | |
None => { | ||
let mut response = Response::with(format!("No Such Service: {}", id)); | ||
response.status = Some(Status::BadRequest); | ||
response.headers.set(AccessControlAllowOrigin::Any); | ||
response.headers.set(ContentType::plaintext()); | ||
Ok(response) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we validate the url passed?
Not needed in this PR we could do a follow up.