<commit_before>use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::Dimensions;
use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use specs;
use gfx_app::graphics::load_texture;
use character::gfx_macros::{pipe, VertexData, CharacterSheet, Position};
use game::gfx_macros::Projection;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE, RUN_SPRITE_OFFSET};
use gfx_app::mouse_controls::MouseInputState;
use graphics::camera::CameraInputState;
use character::controls::CharacterInputState;
use data;
use character::orientation::{Orientation, Stance};
use character::character::{CharacterSprite, CharacterData};

mod audio;
pub mod gfx_macros;
pub mod character;
pub mod orientation;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("character.f.glsl");

impl VertexData {
  fn new(pos: [f32; 3], buf_pos: [f32; 2]) -> VertexData {
    VertexData {
      pos,
      buf_pos,
    }
  }
}

pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, VIEW_DISTANCE),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Normal,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mouse_input: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if let Some(_) = mouse_input.left_click_point {
      self.stance = Stance::Firing;
      self.audio.play_pistol();
    } else {
      self.stance = Stance::Normal;
    }

    let dx = new_position.position[0] - self.position.position[0];
    let dy = new_position.position[1] - self.position.position[1];
    self.orientation =
      if dx == 0.0 && dy < 0.0       { Orientation::Down }
      else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
      else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
      else if dx == 0.0 && dy == 0.0 { Orientation::Still }
      else if dx > 0.0 && dy == 0.0  { Orientation::Right }
      else if dx < 0.0 && dy == 0.0  { Orientation::Left }
      else if dx == 0.0 && dy > 0.0  { Orientation::Up }
      else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
      else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
      else { unreachable!() };
    self.position = new_position;
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CharacterData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> DrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let tilesheet_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, tilesheet_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let charsheet_total_width = 16128f32;
    let offset = 2.0;

    let char_sprite = if drawable.orientation == Orientation::Still && drawable.stance == Stance::Normal {
      let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else if drawable.stance == Stance::Normal {
      drawable.direction = drawable.orientation;
      let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else {
      let idx = (character_idx as f32 * 4.0 / 14.0).floor() as usize;
      let sprite_idx = (drawable.orientation as usize * 8 + idx) as usize;
      (&self.data[sprite_idx], sprite_idx)
    };

    let elements_x = charsheet_total_width / (char_sprite.0.data[2] + offset);
    let char = CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    };
    char
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb, &mut self.get_next_sprite(character.character_idx, &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<CameraInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<MouseInputState>()));

    for (c, i, ci, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(i);
      c.update(&world_to_clip, ci, mi);
    }
  }
}
<commit_msg>Rename terrain_input<commit_after>use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::Dimensions;
use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use specs;
use gfx_app::graphics::load_texture;
use character::gfx_macros::{pipe, VertexData, CharacterSheet, Position};
use game::gfx_macros::Projection;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE, RUN_SPRITE_OFFSET};
use gfx_app::mouse_controls::MouseInputState;
use graphics::camera::CameraInputState;
use character::controls::CharacterInputState;
use data;
use character::orientation::{Orientation, Stance};
use character::character::{CharacterSprite, CharacterData};

mod audio;
pub mod gfx_macros;
pub mod character;
pub mod orientation;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("character.f.glsl");

impl VertexData {
  fn new(pos: [f32; 3], buf_pos: [f32; 2]) -> VertexData {
    VertexData {
      pos,
      buf_pos,
    }
  }
}

pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, VIEW_DISTANCE),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Normal,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mouse_input: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if let Some(_) = mouse_input.left_click_point {
      self.stance = Stance::Firing;
      self.audio.play_pistol();
    } else {
      self.stance = Stance::Normal;
    }

    let dx = new_position.position[0] - self.position.position[0];
    let dy = new_position.position[1] - self.position.position[1];
    self.orientation =
      if dx == 0.0 && dy < 0.0       { Orientation::Down }
      else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
      else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
      else if dx == 0.0 && dy == 0.0 { Orientation::Still }
      else if dx > 0.0 && dy == 0.0  { Orientation::Right }
      else if dx < 0.0 && dy == 0.0  { Orientation::Left }
      else if dx == 0.0 && dy > 0.0  { Orientation::Up }
      else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
      else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
      else { unreachable!() };
    self.position = new_position;
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CharacterData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> DrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let tilesheet_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, tilesheet_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let charsheet_total_width = 16128f32;
    let offset = 2.0;

    let char_sprite = if drawable.orientation == Orientation::Still && drawable.stance == Stance::Normal {
      let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else if drawable.stance == Stance::Normal {
      drawable.direction = drawable.orientation;
      let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else {
      let idx = (character_idx as f32 * 4.0 / 14.0).floor() as usize;
      let sprite_idx = (drawable.orientation as usize * 8 + idx) as usize;
      (&self.data[sprite_idx], sprite_idx)
    };

    let elements_x = charsheet_total_width / (char_sprite.0.data[2] + offset);
    let char = CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    };
    char
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb, &mut self.get_next_sprite(character.character_idx, &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<CameraInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<MouseInputState>()));

    for (c, ti, ci, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(ti);
      c.update(&world_to_clip, ci, mi);
    }
  }
}
<|endoftext|>


<commit_before>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.branches.iter().any(|branch| branch.name == "auto") &&
                status_event.target_url.is_some()
            {
                builds::ingest_status_event(status_event.target_url.unwrap())?
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
pub struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
pub enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
pub struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
pub struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
pub struct StatusEvent {
    state: String,
    target_url: Option<String>,
    branches: Vec<Branch>,
}

#[derive(Debug, Deserialize)]
pub struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
pub struct Branch {
    name: String,
}
<commit_msg>Only scrape data for head of auto branch<commit_after>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.branches.iter().any(|branch| {
                    branch.name == "auto" &&
                    branch.commit.sha == status_event.sha
                })
            {
                if let Some(url) = status_event.target_url {
                    builds::ingest_status_event(url)?
                }
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
pub struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
pub enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
pub struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
pub struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
pub struct StatusEvent {
    sha: String,
    state: String,
    target_url: Option<String>,
    branches: Vec<Branch>,
}

#[derive(Debug, Deserialize)]
pub struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
pub struct Branch {
    name: String,
    commit: Commit,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    sha: String
}
<|endoftext|>


<commit_before>use std::path::Path;

/// Shortcut to path->filename conversion.
///
/// Returns the unchanged `path` if there is a character encoding error or something.
pub fn filename<'a> (path: &'a str) -> &'a str {
  match Path::new (path) .file_name() {
    Some (filename) => match filename.to_str() {
      Some (fstr) => if fstr.ends_with (".rs") {&fstr[0 .. fstr.len() - 3]} else {fstr},
      None => path},
    None => path}}

// A trick to use the `try_s` macro from both the outside and inside of the crate.
//mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {::filename (path)}}

/// Returns on error, converting the `Err` value to `String` and prepending the current location.
///
/// cf. http://www.reddit.com/r/rust/comments/29wwzw/error_handling_and_result_types/cipcm9a
#[macro_export] macro_rules! try_s {
  ($e: expr) => {match $e {Ok (ok) => ok, Err (err) => {return Err (format! ("{}:{}] {}", ::gstuff::filename (file!()), line!(), err));}}}}

// Like `try_s`, but takes a reference.
#[macro_export] macro_rules! try_sp {
  ($e: expr) => {match $e {&Ok (ref ok) => ok,
    &Err (ref err) => {return Err (format! ("{}:{}] {:?}", ::gstuff::filename (file!()), line!(), err));}}}}

/// Returns a `Err(String)`, prepending the current location (file name and line number) to the string.
///
/// Examples: `ERR! ("too bad")`; `ERR! ("{}", foo)`;
#[macro_export] macro_rules! ERR {
  ($format: expr, $($args: tt)+) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!(), $($args)+))};
  ($format: expr) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!()))}}

/// A helper to build a string on the stack.
///
/// Given an array it makes a writeable cursor available to the passed code block.
///
/// Returns a &str slice pointing at memory between the array start and the cursor.
///
/// Example:
///
///     use std::io::Write;
///     let mut foobar: [u8; 128] = unsafe {std::mem::uninitialized()};
///     let foobar = gstring! (foobar, {
///         write! (foobar, "foo") .expect ("!write");
///         write! (foobar, "bar") .expect ("!write");
///     });
///
/// Alternatives: https://crates.io/crates/stack.
#[macro_export] macro_rules! gstring {($array: ident, $code: block) => {{
  let end = {
    let mut $array = ::std::io::Cursor::new (&mut $array[..]);
    let $array = &mut $array;
    $code;
    $array.position() as usize};
  unsafe {::std::str::from_utf8_unchecked (&$array[0..end])}}}}

/// Takes a netstring from the front of the slice.
///
/// Returns the unpacked netstring and the remainder of the slice.
fn netstring (at: &[u8]) -> Result<(&[u8], &[u8]), String> {
  let length_end = match at.iter().position (|&ch| ch < b'0' || ch > b'9') {Some (l) if l > 0 => l, _ => return ERR! ("No len.")};
  match at.get (length_end) {Some (&ch) if ch == b':' => (), _ => return ERR! ("No colon.")};
  let length = unsafe {from_utf8_unchecked (&at[0 .. length_end])};
  let length: usize = try_s! (length.parse());
  let bulk_pos = 0 + length_end + 1;
  let bulk_end = bulk_pos + length;
  match at.get (bulk_end) {Some (&ch) if ch == b',' => (), _ => return ERR! ("No comma.")}
  Ok ((&at[bulk_pos .. bulk_end], &at[bulk_end + 1 ..]))}
<commit_msg>Fix the `netstring` to work from here.<commit_after>use std::path::Path;
use std::str::from_utf8_unchecked;

/// Shortcut to path->filename conversion.
///
/// Returns the unchanged `path` if there is a character encoding error or something.
pub fn filename<'a> (path: &'a str) -> &'a str {
  match Path::new (path) .file_name() {
    Some (filename) => match filename.to_str() {
      Some (fstr) => if fstr.ends_with (".rs") {&fstr[0 .. fstr.len() - 3]} else {fstr},
      None => path},
    None => path}}

mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {super::filename (path)}}

// A trick to use the `try_s` macro from both the outside and inside of the crate.
//mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {::filename (path)}}

/// Returns on error, converting the `Err` value to `String` and prepending the current location.
///
/// cf. http://www.reddit.com/r/rust/comments/29wwzw/error_handling_and_result_types/cipcm9a
#[macro_export] macro_rules! try_s {
  ($e: expr) => {match $e {Ok (ok) => ok, Err (err) => {return Err (format! ("{}:{}] {}", ::gstuff::filename (file!()), line!(), err));}}}}

// Like `try_s`, but takes a reference.
#[macro_export] macro_rules! try_sp {
  ($e: expr) => {match $e {&Ok (ref ok) => ok,
    &Err (ref err) => {return Err (format! ("{}:{}] {:?}", ::gstuff::filename (file!()), line!(), err));}}}}

/// Returns a `Err(String)`, prepending the current location (file name and line number) to the string.
///
/// Examples: `ERR! ("too bad")`; `ERR! ("{}", foo)`;
#[macro_export] macro_rules! ERR {
  ($format: expr, $($args: tt)+) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!(), $($args)+))};
  ($format: expr) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!()))}}

/// A helper to build a string on the stack.
///
/// Given an array it makes a writeable cursor available to the passed code block.
///
/// Returns a &str slice pointing at memory between the array start and the cursor.
///
/// Example:
///
///     use std::io::Write;
///     let mut foobar: [u8; 128] = unsafe {std::mem::uninitialized()};
///     let foobar = gstring! (foobar, {
///         write! (foobar, "foo") .expect ("!write");
///         write! (foobar, "bar") .expect ("!write");
///     });
///
/// Alternatives: https://crates.io/crates/stack.
#[macro_export] macro_rules! gstring {($array: ident, $code: block) => {{
  let end = {
    let mut $array = ::std::io::Cursor::new (&mut $array[..]);
    let $array = &mut $array;
    $code;
    $array.position() as usize};
  unsafe {::std::str::from_utf8_unchecked (&$array[0..end])}}}}

/// Takes a netstring from the front of the slice.
///
/// Returns the unpacked netstring and the remainder of the slice.
pub fn netstring (at: &[u8]) -> Result<(&[u8], &[u8]), String> {
  let length_end = match at.iter().position (|&ch| ch < b'0' || ch > b'9') {Some (l) if l > 0 => l, _ => return ERR! ("No len.")};
  match at.get (length_end) {Some (&ch) if ch == b':' => (), _ => return ERR! ("No colon.")};
  let length = unsafe {from_utf8_unchecked (&at[0 .. length_end])};
  let length: usize = try_s! (length.parse());
  let bulk_pos = 0 + length_end + 1;
  let bulk_end = bulk_pos + length;
  match at.get (bulk_end) {Some (&ch) if ch == b',' => (), _ => return ERR! ("No comma.")}
  Ok ((&at[bulk_pos .. bulk_end], &at[bulk_end + 1 ..]))}
<|endoftext|>


<commit_before>// This example demonstrates use of the callback-based `Resolver`.
extern crate c_ares;
extern crate c_ares_resolver;

use std::error::Error;
use std::sync::mpsc;

use c_ares_resolver::Resolver;

fn print_a_results(result: &c_ares::Result<c_ares::AResults>) {
    match *result {
        Err(ref e) => {
            println!("Query failed with error '{}'", e.description());
        }
        Ok(ref a_results) => {
            println!("Successful A lookup...");
            for a_result in a_results {
                println!("IPv4: {}, TTL {}", a_result.ipv4(), a_result.ttl());
            }
        }
    }
}

fn main() {
    // We'll need to be careful while we're waiting for our callback.  Dropping
    // the resolver would cause the outstanding query to fail - and if we
    // exited the main thread too soon we wouldn't see even that happen.
    //
    // Create a channel that the callback will use to tell the main thread that
    // it is done.
    let (tx, rx) = mpsc::channel();

    // Create a resolver and make a query.
    let resolver = Resolver::new().expect("Failed to create resolver");
    resolver.query_a("apple.com", move |result| {
        print_a_results(&result);
        tx.send(()).unwrap();
    });

    // Wait to be told that the callback has happened.
    rx.recv().unwrap();
}
<commit_msg>reflowing comments<commit_after>// This example demonstrates use of the callback-based `Resolver`.
extern crate c_ares;
extern crate c_ares_resolver;

use std::error::Error;
use std::sync::mpsc;

use c_ares_resolver::Resolver;

fn print_a_results(result: &c_ares::Result<c_ares::AResults>) {
    match *result {
        Err(ref e) => {
            println!("Query failed with error '{}'", e.description());
        }
        Ok(ref a_results) => {
            println!("Successful A lookup...");
            for a_result in a_results {
                println!("IPv4: {}, TTL {}", a_result.ipv4(), a_result.ttl());
            }
        }
    }
}

fn main() {
    // We'll need to be careful while we're waiting for our callback.  Dropping the resolver would
    // cause the outstanding query to fail - and if we exited the main thread too soon we wouldn't
    // see even that happen.
    //
    // Create a channel that the callback will use to tell the main thread that it is done.
    let (tx, rx) = mpsc::channel();

    // Create a resolver and make a query.
    let resolver = Resolver::new().expect("Failed to create resolver");
    resolver.query_a("apple.com", move |result| {
        print_a_results(&result);
        tx.send(()).unwrap();
    });

    // Wait to be told that the callback has happened.
    rx.recv().unwrap();
}
<|endoftext|>


<commit_before>extern crate mio;
extern crate mioco;
extern crate env_logger;

use std::net::SocketAddr;
use std::str::FromStr;

use mio::buf::{MutSliceBuf, SliceBuf};
use mio::udp::{UdpSocket};
const DEFAULT_LISTEN_ADDR : &'static str = "127.0.0.1:5555";

fn listend_addr() -> SocketAddr {
    FromStr::from_str(DEFAULT_LISTEN_ADDR).unwrap()
}

fn main() {
    env_logger::init().unwrap();

    mioco::start(move |mioco| {
        let addr = listend_addr();

        let sock = try!(UdpSocket::v4());
        try!(sock.bind(&addr));

        println!("Starting udp echo server on {:?}", sock.local_addr().unwrap());

        let mut sock = mioco.wrap(sock);

        let mut buf = [0u8; 1024 * 16];

        loop {
            let addr = try!(sock.read(&mut MutSliceBuf::wrap(&mut buf)));
            try!(sock.write(&mut SliceBuf::wrap(&buf), &addr));
        }
    });
}
<commit_msg>Make UDP example multiport.<commit_after>extern crate mio;
extern crate mioco;
extern crate env_logger;

use std::net::{SocketAddr, SocketAddrV4};
use mio::buf::{MutSliceBuf, SliceBuf};
use mio::udp::{UdpSocket};
use mio::Ipv4Addr;

const START_PORT : u16 = 60000;
const END_PORT   : u16 = 65535;

fn main() {
    env_logger::init().unwrap();

    mioco::start(move |mioco| {
        println!("Starting udp echo server on ports: {}-{}", START_PORT, END_PORT);

        for port in START_PORT..END_PORT {
            mioco.spawn(move |mioco| {
                let ip = Ipv4Addr::new(0, 0, 0, 0);
                let addr = SocketAddr::V4(SocketAddrV4::new(ip, port));

                let sock = try!(UdpSocket::v4());
                try!(sock.bind(&addr));
                let mut sock = mioco.wrap(sock);

                let mut buf = [0u8; 1024 * 16];
                loop {
                    let addr = try!(sock.read(&mut MutSliceBuf::wrap(&mut buf)));
                    try!(sock.write(&mut SliceBuf::wrap(&buf), &addr));
                }
            });
        }
        Ok(())
    });
}
<|endoftext|>


<commit_before>use docopt::{self, Docopt};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use toml;

use git::repo_hash;
use library;
use library::Library;
use super::external_libraries::{read_external_libraries, ExternalLibrary};
use super::WorkMode;
use super::gobjects;
use super::error::*;
use version::Version;

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help              Show this message.
    -c CONFIG               Config file path (default: Gir.toml)
    -d GIRSPATH             Directory for girs
    -m MODE                 Work mode: doc, normal, sys or not_bound
    -o PATH                 Target path
    --doc-target-path PATH  Doc target path
    -b, --make_backup       Make backup before generating
    -s, --stats             Show statistics
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: PathBuf,
    pub girs_version: String, //Version in girs_dir, detected by git
    pub library_name: String,
    pub library_version: String,
    pub target_path: PathBuf,
    pub doc_target_path: PathBuf,
    pub external_libraries: Vec<ExternalLibrary>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
    pub generate_safety_asserts: bool,
    pub deprecate_by_min_version: bool,
    pub show_statistics: bool,
    pub concurrency: library::Concurrency,
}

impl Config {
    pub fn new() -> Result<Config> {
        let args = try!(Docopt::new(USAGE).and_then(|dopt| dopt.parse()));

        let config_file: PathBuf = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        }.into();

        let config_dir = match config_file.parent() {
            Some(path) => path.into(),
            None => PathBuf::new(),
        };

        let toml =
            try!(read_toml(&config_file).chain_err(|| ErrorKind::ReadConfig(config_file.clone())));

        Config::process_options(&args, &toml, &config_dir)
            .chain_err(|| ErrorKind::Options(config_file))
    }

    fn process_options(
        args: &docopt::ArgvMap,
        toml: &toml::Value,
        config_dir: &Path,
    ) -> Result<Config> {
        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode")),
            a => a,
        };
        let work_mode = try!(WorkMode::from_str(work_mode_str));

        let girs_dir: PathBuf = match args.get_str("-d") {
            "" => {
                let path = try!(toml.lookup_str("options.girs_dir", "No options.girs_dir"));
                config_dir.join(path)
            }
            a => a.into(),
        };
        let girs_version = repo_hash(&girs_dir).unwrap_or_else(|_| "???".into());

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
                ("", "") => (
                    try!(toml.lookup_str("options.library", "No options.library")),
                    try!(toml.lookup_str("options.version", "No options.version")),
                ),
                ("", _) | (_, "") => bail!("Library and version can not be specified separately"),
                (a, b) => (a, b),
            };

        let target_path: PathBuf = match args.get_str("-o") {
            "" => {
                let path = try!(toml.lookup_str(
                    "options.target_path",
                    "No target path specified",
                ));
                config_dir.join(path)
            }
            a => a.into(),
        };

        let doc_target_path: PathBuf = match args.get_str("--doc-target-path") {
            "" => {
                match toml.lookup("options.doc_target_path") {
                    Some(p) => config_dir.join(try!(p.as_result_str("options.doc_target_path"))),
                    None => target_path.join("vendor.md"),
                }
            },
            p => config_dir.join(p),
        };

        let concurrency = match toml.lookup("options.concurrency") {
            Some(v) => try!(try!(v.as_result_str("options.concurrency")).parse()),
            None => Default::default(),
        };

        // options.concurrency is the default of all objects if nothing
        // else is configured
        let mut objects = toml.lookup("object")
            .map(|t| gobjects::parse_toml(t, concurrency))
            .unwrap_or_default();
        gobjects::parse_status_shorthands(&mut objects, toml, concurrency);

        let external_libraries = try!(read_external_libraries(toml));

        let min_cfg_version = match toml.lookup("options.min_cfg_version") {
            Some(v) => try!(try!(v.as_result_str("options.min_cfg_version")).parse()),
            None => Default::default(),
        };

        let make_backup = args.get_bool("-b");

        let generate_safety_asserts = match toml.lookup("options.generate_safety_asserts") {
            Some(v) => try!(v.as_result_bool("options.generate_safety_asserts")),
            None => false,
        };

        let deprecate_by_min_version = match toml.lookup("options.deprecate_by_min_version") {
            Some(v) => try!(v.as_result_bool("options.deprecate_by_min_version")),
            None => false,
        };

        let show_statistics = args.get_bool("-s");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir,
            girs_version: girs_version,
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path,
            doc_target_path: doc_target_path,
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
            generate_safety_asserts: generate_safety_asserts,
            deprecate_by_min_version: deprecate_by_min_version,
            show_statistics: show_statistics,
            concurrency: concurrency,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }

    pub fn filter_version(&self, version: Option<Version>) -> Option<Version> {
        version.and_then(|v| if v > self.min_cfg_version {
            Some(v)
        } else {
            None
        })
    }

    pub fn resolve_type_ids(&mut self, library: &Library) {
        gobjects::resolve_type_ids(&mut self.objects, library)
    }
}

fn read_toml<P: AsRef<Path>>(filename: P) -> Result<toml::Value> {
    if !filename.as_ref().is_file() {
        bail!("Config don't exists or not file");
    }
    let mut input = String::new();
    try!(File::open(&filename).and_then(|mut f| f.read_to_string(&mut input)));

    let toml = try!(toml::from_str(&input));

    Ok(toml)
}
<commit_msg>Replace underscore in "make-backup" command line option<commit_after>use docopt::{self, Docopt};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use toml;

use git::repo_hash;
use library;
use library::Library;
use super::external_libraries::{read_external_libraries, ExternalLibrary};
use super::WorkMode;
use super::gobjects;
use super::error::*;
use version::Version;

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help              Show this message.
    -c CONFIG               Config file path (default: Gir.toml)
    -d GIRSPATH             Directory for girs
    -m MODE                 Work mode: doc, normal, sys or not_bound
    -o PATH                 Target path
    --doc-target-path PATH  Doc target path
    -b, --make-backup       Make backup before generating
    -s, --stats             Show statistics
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: PathBuf,
    pub girs_version: String, //Version in girs_dir, detected by git
    pub library_name: String,
    pub library_version: String,
    pub target_path: PathBuf,
    pub doc_target_path: PathBuf,
    pub external_libraries: Vec<ExternalLibrary>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
    pub generate_safety_asserts: bool,
    pub deprecate_by_min_version: bool,
    pub show_statistics: bool,
    pub concurrency: library::Concurrency,
}

impl Config {
    pub fn new() -> Result<Config> {
        let args = try!(Docopt::new(USAGE).and_then(|dopt| dopt.parse()));

        let config_file: PathBuf = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        }.into();

        let config_dir = match config_file.parent() {
            Some(path) => path.into(),
            None => PathBuf::new(),
        };

        let toml =
            try!(read_toml(&config_file).chain_err(|| ErrorKind::ReadConfig(config_file.clone())));

        Config::process_options(&args, &toml, &config_dir)
            .chain_err(|| ErrorKind::Options(config_file))
    }

    fn process_options(
        args: &docopt::ArgvMap,
        toml: &toml::Value,
        config_dir: &Path,
    ) -> Result<Config> {
        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode")),
            a => a,
        };
        let work_mode = try!(WorkMode::from_str(work_mode_str));

        let girs_dir: PathBuf = match args.get_str("-d") {
            "" => {
                let path = try!(toml.lookup_str("options.girs_dir", "No options.girs_dir"));
                config_dir.join(path)
            }
            a => a.into(),
        };
        let girs_version = repo_hash(&girs_dir).unwrap_or_else(|_| "???".into());

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
                ("", "") => (
                    try!(toml.lookup_str("options.library", "No options.library")),
                    try!(toml.lookup_str("options.version", "No options.version")),
                ),
                ("", _) | (_, "") => bail!("Library and version can not be specified separately"),
                (a, b) => (a, b),
            };

        let target_path: PathBuf = match args.get_str("-o") {
            "" => {
                let path = try!(toml.lookup_str(
                    "options.target_path",
                    "No target path specified",
                ));
                config_dir.join(path)
            }
            a => a.into(),
        };

        let doc_target_path: PathBuf = match args.get_str("--doc-target-path") {
            "" => {
                match toml.lookup("options.doc_target_path") {
                    Some(p) => config_dir.join(try!(p.as_result_str("options.doc_target_path"))),
                    None => target_path.join("vendor.md"),
                }
            },
            p => config_dir.join(p),
        };

        let concurrency = match toml.lookup("options.concurrency") {
            Some(v) => try!(try!(v.as_result_str("options.concurrency")).parse()),
            None => Default::default(),
        };

        // options.concurrency is the default of all objects if nothing
        // else is configured
        let mut objects = toml.lookup("object")
            .map(|t| gobjects::parse_toml(t, concurrency))
            .unwrap_or_default();
        gobjects::parse_status_shorthands(&mut objects, toml, concurrency);

        let external_libraries = try!(read_external_libraries(toml));

        let min_cfg_version = match toml.lookup("options.min_cfg_version") {
            Some(v) => try!(try!(v.as_result_str("options.min_cfg_version")).parse()),
            None => Default::default(),
        };

        let make_backup = args.get_bool("-b");

        let generate_safety_asserts = match toml.lookup("options.generate_safety_asserts") {
            Some(v) => try!(v.as_result_bool("options.generate_safety_asserts")),
            None => false,
        };

        let deprecate_by_min_version = match toml.lookup("options.deprecate_by_min_version") {
            Some(v) => try!(v.as_result_bool("options.deprecate_by_min_version")),
            None => false,
        };

        let show_statistics = args.get_bool("-s");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir,
            girs_version: girs_version,
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path,
            doc_target_path: doc_target_path,
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
            generate_safety_asserts: generate_safety_asserts,
            deprecate_by_min_version: deprecate_by_min_version,
            show_statistics: show_statistics,
            concurrency: concurrency,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }

    pub fn filter_version(&self, version: Option<Version>) -> Option<Version> {
        version.and_then(|v| if v > self.min_cfg_version {
            Some(v)
        } else {
            None
        })
    }

    pub fn resolve_type_ids(&mut self, library: &Library) {
        gobjects::resolve_type_ids(&mut self.objects, library)
    }
}

fn read_toml<P: AsRef<Path>>(filename: P) -> Result<toml::Value> {
    if !filename.as_ref().is_file() {
        bail!("Config don't exists or not file");
    }
    let mut input = String::new();
    try!(File::open(&filename).and_then(|mut f| f.read_to_string(&mut input)));

    let toml = try!(toml::from_str(&input));

    Ok(toml)
}
<|endoftext|>


<commit_before>use hyper::header::{ContentLength, Headers};
use std::ops::Deref;

use Byte;

/// Trait to extend functionalities of the Headers type, from `hyper`
pub trait GetContentLength {
    /// Function to get the content length of a remote document.
    /// The returned type is `Byte`.
    fn get_content_length(&self) -> Option<Byte>;
}

impl GetContentLength for Headers {
    /// Function to get the `content-length` container, from a given header.
    /// This function returns an Option that contains a `Byte` type.
    fn get_content_length(&self) -> Option<Byte> {
        if self.has::<ContentLength>() {
            return Some(*self.get::<ContentLength>().unwrap().deref())
        }
        None
    }
}<commit_msg>Update Byte type to Bytes<commit_after>use hyper::header::{ContentLength, Headers};
use std::ops::Deref;

use Bytes;

/// Trait to extend functionalities of the Headers type, from `hyper`
pub trait GetContentLength {
    /// Function to get the content length of a remote document.
    /// The returned type is `Option<Bytes>`.
    fn get_content_length(&self) -> Option<Bytes>;
}

impl GetContentLength for Headers {
    /// Function to get the `content-length` container, from a given header.
    /// This function returns an Option that contains a `Bytes` type.
    fn get_content_length(&self) -> Option<Bytes> {
        if self.has::<ContentLength>() {
            return Some(*self.get::<ContentLength>().unwrap().deref());
        }
        None
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::RingBuf;

use gc_object::GCObjectRef;
use line_allocator::LineAllocator;

pub struct ImmixCollector;

impl ImmixCollector {
    pub fn collect(line_allocator: &mut LineAllocator, roots: &[GCObjectRef]) {
        let next_live_mark = !line_allocator.current_live_mark();
        debug!("Start Immix collection with {} roots and next_live_mark: {}",
               roots.len(), next_live_mark);
        let mut object_queue = roots.iter().map(|o| *o)
                                    .collect::<RingBuf<GCObjectRef>>();
        line_allocator.prepare_immix_collection();
        while let Some(object) =  object_queue.pop_front() {
            debug!("Process object {} in Immix closure", object);
            if !unsafe { (*object).set_marked(next_live_mark) } {
                debug!("Object {} was unmarked: process children", object);
                line_allocator.set_gc_object(object);
                line_allocator.increment_lines(object);
                for child in unsafe{ (*object).children() }.into_iter() {
                    if !unsafe{ (*child).is_marked(next_live_mark) } {
                        debug!("Push child {} into object queue", child);
                        object_queue.push_back(child);
                    }
                }
            }
        }
        line_allocator.complete_immix_collection();
        debug!("Complete collection");
    }
}
<commit_msg>Implement pinning of roots in ImmixCollector<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::RingBuf;

use gc_object::GCObjectRef;
use line_allocator::LineAllocator;

pub struct ImmixCollector;

impl ImmixCollector {
    pub fn collect(line_allocator: &mut LineAllocator, roots: &[GCObjectRef]) {
        let next_live_mark = !line_allocator.current_live_mark();
        debug!("Start Immix collection with {} roots and next_live_mark: {}",
               roots.len(), next_live_mark);
        line_allocator.prepare_immix_collection();
        let mut object_queue = RingBuf::new();
        for root in roots.iter().map(|o| *o) {
            unsafe{ (*root).set_pinned(true); }
            object_queue.push_back(root);
        }
        while let Some(object) =  object_queue.pop_front() {
            debug!("Process object {} in Immix closure", object);
            if !unsafe { (*object).set_marked(next_live_mark) } {
                debug!("Process object {} in Immix closure", object);
                if !unsafe { (*object).set_marked(next_live_mark) } {
                    debug!("Object {} was unmarked: process children", object);
                    line_allocator.set_gc_object(object);
                    line_allocator.increment_lines(object);
                    for child in unsafe{ (*object).children() }.into_iter() {
                        if !unsafe{ (*child).is_marked(next_live_mark) } {
                            debug!("Push child {} into object queue", child);
                            object_queue.push_back(child);
                        }
                    }
                }
            }
        }
        for root in roots.iter() {
            unsafe{ (**root).set_pinned(false); }
        }
        line_allocator.complete_immix_collection();
        debug!("Complete collection");
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]
#![feature(path_ext)]
extern crate eve;
extern crate hyper;
extern crate cookie;
extern crate mime;
extern crate url;
extern crate websocket;
extern crate rustc_serialize;
extern crate conduit_mime_types;
extern crate cbor;

use std::io::Read;
use std::io::Write;
use std::fs::File;
use std::error::Error;
use hyper::net::Fresh;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::Url;
use hyper::header::{Headers,ContentType,Location,SetCookie};
use cookie::Cookie;
use mime::Mime;
use url::SchemeData::Relative;
use rustc_serialize::json;
use rustc_serialize::json::ToJson;
use std::path::Path;
use std::fs::PathExt;
use conduit_mime_types::Types;
use std::str::FromStr;
use std::env;
use websocket::{client,Client,stream,Message,Sender,Receiver};
use std::thread;
use cbor::ToCbor;

use eve::value::Value;
use eve::server::Event;
use eve::relation::Change;
use eve::server;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Session {
    client: String,
    id: String,
    user_id: String,
    object: String,
    created_at: f64,
    expires_at: f64,
    ip: String,
    user: User,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct User {
    custom: Custom,
    id: String,
    realm_id: String,
    username: String,
    state: String,
    user_type: String,
    reference: Option<String>,
    name: String,
    email: String,
    object: String,
    last_login_at: f64,
    last_login_on: f64,
    created_at: f64,
    first_name: Option<String>,
    last_name: Option<String>,
    credentials: Vec<Credential>,
    membership_count: f64,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Custom;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Credential {
    id: String,
    credential_type: String,
    object: String,
}

fn main() {
    // TODO high thread-count is a workaround for https://github.com/hyperium/hyper/issues/368
    Server::http("0.0.0.0:8080").unwrap().handle_threads(login, 100).unwrap();
}

fn read_file_bytes(filename: &str) -> Vec<u8> {
    let mut file = File::open(&filename).unwrap();
    let mut contents: Vec<u8> = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    contents
}

fn file_exists(path: &str) -> bool {
    let path_obj = Path::new(path);
    path_obj.is_file() && path_obj.exists()
}

fn serve_local_or_file(mut res: Response<Fresh>, path: &Vec<String>, default_file: &str) {
    let mime_types = Types::new().unwrap();
    let local_path = path[1..].iter().fold("../ui".to_owned(), |end, cur| end + "/" + cur);
    let file;
    let file_path: &str;
    if file_exists(&local_path) {
        file = read_file_bytes(&local_path);
        file_path = &local_path;
    } else {
        let content = read_file_bytes(default_file);
        //@HACK, @TODO: absolutize the html file so that it looks in the right place
        //this allows us to use file:/// locally, while still doing the right thing
        //when we're hooked up to the server
        let mut str = String::from_utf8(content).unwrap();
        str = str.replace("href=\"", "href=\"/app/");
        str = str.replace("src=\"", "src=\"/app/");
        str = str.replace("/app/http", "http");
        file = str.as_bytes().to_owned();
        file_path = default_file;
    }
    let mime: Mime = Mime::from_str(mime_types.mime_for_path(Path::new(&file_path))).unwrap();
    res.headers_mut().set(ContentType(mime));
    let mut res = res.start().unwrap();
    res.write_all(&file).unwrap();
    res.end().unwrap();
}

fn login(req: Request, mut res: Response<Fresh>) {

    // Don't use a port if we're running in local mode
    let mut port = ":8000";
    for argument in env::args() {
        match &*argument {
            "local" => {
                port = "";
            },
            _ => continue,
        }
    }

    match (&req.method.clone(), &req.uri.clone()) {
        (&hyper::Get, &RequestUri::AbsolutePath(ref relative_path)) => {

            // Form a url from the path
            let absolute_path = "http://localhost".to_string() + relative_path;
            let url = Url::parse(&*absolute_path).unwrap();

            // Get the file name
            let scheme_data = &url.scheme_data;

            let requested_file = match scheme_data {
                &Relative(ref rsd) => rsd.path[0].clone(),
                _ => panic!("Expected relative path"),
            };
            let path_info = match scheme_data {
                &Relative(ref rsd) => rsd,
                _ => panic!("Expected relative path"),
            };

            // Parse the query string
            let query_pairs = &url.query_pairs();

            // Handle login
            match &*requested_file {
                "app.html" | "app" => {
                    serve_local_or_file(res, &path_info.path, "../ui/app.html");
                },
                "editor.html" | "editor" => {
                    serve_local_or_file(res, &path_info.path, "../ui/editor.html");
                },
                "login.html" => {
                    println!("Authenticating User");

                    let referer = format!("{}",req.headers.get::<hyper::header::Referer>().unwrap());
                    let referer_url = Url::parse(&*referer).unwrap();

                    let pairs = query_pairs.clone().unwrap();
                    match &pairs[..] {
                        [(_ , ref page), (ref token_type, ref token), ..] if token_type.clone() == "token".to_string() => {

                            // We have a login token, now to authenticate
                            let client = hyper::client::Client::new();
                            let api_call = "https://api-e1.authrocket.com/v1/sessions/".to_string() + token;
                            let req = client.request(hyper::method::Method::Get,&*api_call);

                            // Set the appropriate headers for authorocket
                            let mut headers = Headers::new();
                            let json: Mime = "application/json".parse().unwrap();
                            let content_type = ContentType(json);
                            headers.set_raw("X-Authrocket-Account",vec!["org_0vC7wPw9XphPGQnSqYB6bz".to_string().into_bytes()]);
                            headers.set_raw("X-Authrocket-Api-Key",vec!["key_jtnCRWxQvDD0p5HATR9RBIe4WnxnwV6pWNzwmZQLnSZ".to_string().into_bytes()]);
                            headers.set_raw("X-Authrocket-Realm",vec!["rl_0vC7wd03CqwhpK7kT8fvAc".to_string().into_bytes()]);
                            headers.set_raw("Accept",vec!["application/json".to_string().into_bytes()]);
                            headers.set(content_type);

                            // Send the request and receive a response with session data
                            let mut client_res = req.headers(headers).send().unwrap();

                            match client_res.status_raw() {

                                &hyper::http::RawStatus(200,_) => {

                                    let mut body = String::new();
                                    client_res.read_to_string(&mut body).unwrap();
                                    let session_data: Session = json::decode(&body).unwrap();
                                    println!("Welcome to Eve, {:?}!",session_data.user.username);
                                    println!("Login Successful. Redirecting to user area.");

                                    // Connect to the Eve runtime and add the user to the eveusers table
                                    let ws_result = open_websocket("ws://0.0.0.0:2794");
                                    match ws_result {
                                        // If things went okay, redirect to the Eve UI
                                        Ok(mut sender) => {
                                            // Form the response
                                            *res.status_mut() = hyper::status::StatusCode::PermanentRedirect;

                                            // Form the response headers
                                            let mut headers = Headers::new();
                                            let redirect_url = referer_url.scheme.clone() + "://" + referer_url.domain().unwrap().clone() + port + "/" + page;
                                            let location = Location(redirect_url);
                                            let user_cookie = Cookie::new("userid".to_string(),session_data.user.id.clone());
                                            let cookies = SetCookie(vec![user_cookie]);
                                            headers.set(location);
                                            headers.set(cookies);
                                            *res.headers_mut() = headers;

                                            // Create eveusers table and insert the new user
                                            let change = ("eveusers".to_owned(),
                                                Change{
                                                    fields: vec!["eveusers: id".to_owned(), "eveusers: username".to_owned()],
                                                    insert: vec![vec![
                                                        Value::String(session_data.user.id.clone()),
                                                        Value::String(session_data.user.username.clone())
                                                    ]],
                                                    remove: vec![],
                                                });
                                            let event = Event{changes: vec![change], session: "".to_owned(), commands: vec![]};
                                            send_event(event, &mut sender);
                                            let _ = sender.send_message(Message::Close(None));
                                        }
                                        // Otherwise, throw an error... maybe redirect to a special page.
                                        Err(e) => {
                                            println!("ERROR: Had trouble connecting to the Eve runtime: {}. Is the server running?",e);
                                            *res.status_mut() = hyper::status::StatusCode::NotFound;
                                            panic!("Oh no!");
                                            //serve_file("404.html",res);
                                        }
                                    }

                                    println!("Login complete.");
                                }
                                _ => {
                                    println!("ERROR: Could not authenticate user with token {}",token);
                                    *res.status_mut() = hyper::status::StatusCode::Forbidden;
                                    panic!("Oh no!");
                                    //serve_file("404.html",res);
                                }
                            };
                        },
                        _ => panic!("Oh no!"), //serve_file("404.html",res),
                    }
                },
                "logout.html" => {
                    println!("Logging out...");
                    let user_id = server::get_user_id(req.headers.get::<hyper::header::Cookie>());
                    println!("{:?}",user_id);
                },
                "favicon.ico" => (),
                other => panic!("Cannot serve {}",other), //serve_file(&*requested_file,res),
            };
        }
        _ => panic!("Oh no!"),
    }
}

pub fn open_websocket(url_string: &str) -> Result<client::sender::Sender<stream::WebSocketStream>,String> {

    //let mut context = SslContext::new(SslMethod::Tlsv1).unwrap();
    //let _ = context.set_certificate_file(&(Path::new("server.crt")), X509FileType::PEM);
    //let _ = context.set_private_key_file(&(Path::new("server.key")), X509FileType::PEM);

    let url = Url::parse(url_string).unwrap();
    println!("Connecting to {}", url);

    let request = match Client::connect(url) {
        Ok(t) => t,
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    let response = match request.send() {
        Ok(t) => t,
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    match response.validate() {
        Ok(_) => println!("Response valid. Start sending/receiving..."),
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    let (sender, mut receiver) = response.begin().split();

    thread::spawn(move || {
        for message in receiver.incoming_messages() {
            let message = match message {
                Ok(m) => m,
                Err(_) => return,
            };
            match message {
                Message::Text(_) => {
                    //let json = Json::from_str(&text).unwrap();
                    //let event: Event = FromJson::from_json(&json);
                },
                Message::Close(_) => {
                    println!("Received close message");
                    return;
                }
                _ => println!("Unknown message: {:?}", message)
            }
        }
    });

    Ok(sender)
}

pub fn send_event(event: Event, sender: &mut client::sender::Sender<stream::WebSocketStream>) {
    let mut e = cbor::Encoder::from_memory();
    let json = event.to_json();
    let cbor = json.to_cbor();
    e.encode(vec![cbor]).unwrap();
    sender.send_message(Message::Binary(e.into_bytes())).unwrap();
}<commit_msg>Add comments for the login server<commit_after>#![feature(slice_patterns)]
#![feature(path_ext)]
extern crate eve;
extern crate hyper;
extern crate cookie;
extern crate mime;
extern crate url;
extern crate websocket;
extern crate rustc_serialize;
extern crate conduit_mime_types;
extern crate cbor;

use std::io::Read;
use std::io::Write;
use std::fs::File;
use std::error::Error;
use hyper::net::Fresh;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::Url;
use hyper::header::{Headers,ContentType,Location,SetCookie};
use cookie::Cookie;
use mime::Mime;
use url::SchemeData::Relative;
use rustc_serialize::json;
use rustc_serialize::json::ToJson;
use std::path::Path;
use std::fs::PathExt;
use conduit_mime_types::Types;
use std::str::FromStr;
use std::env;
use websocket::{client,Client,stream,Message,Sender,Receiver};
use std::thread;
use cbor::ToCbor;

use eve::value::Value;
use eve::server::Event;
use eve::relation::Change;
use eve::server;

// The (increasingly misnamed) login server is responsible for:
// * handling authentication via authrocket
// * serving static files for the editor and clients
// TODO needs review

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Session {
    client: String,
    id: String,
    user_id: String,
    object: String,
    created_at: f64,
    expires_at: f64,
    ip: String,
    user: User,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct User {
    custom: Custom,
    id: String,
    realm_id: String,
    username: String,
    state: String,
    user_type: String,
    reference: Option<String>,
    name: String,
    email: String,
    object: String,
    last_login_at: f64,
    last_login_on: f64,
    created_at: f64,
    first_name: Option<String>,
    last_name: Option<String>,
    credentials: Vec<Credential>,
    membership_count: f64,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Custom;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
struct Credential {
    id: String,
    credential_type: String,
    object: String,
}

fn main() {
    // TODO high thread-count is a workaround for https://github.com/hyperium/hyper/issues/368
    Server::http("0.0.0.0:8080").unwrap().handle_threads(login, 100).unwrap();
}

fn read_file_bytes(filename: &str) -> Vec<u8> {
    let mut file = File::open(&filename).unwrap();
    let mut contents: Vec<u8> = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    contents
}

fn file_exists(path: &str) -> bool {
    let path_obj = Path::new(path);
    path_obj.is_file() && path_obj.exists()
}

fn serve_local_or_file(mut res: Response<Fresh>, path: &Vec<String>, default_file: &str) {
    let mime_types = Types::new().unwrap();
    let local_path = path[1..].iter().fold("../ui".to_owned(), |end, cur| end + "/" + cur);
    let file;
    let file_path: &str;
    if file_exists(&local_path) {
        file = read_file_bytes(&local_path);
        file_path = &local_path;
    } else {
        let content = read_file_bytes(default_file);
        //@HACK, @TODO: absolutize the html file so that it looks in the right place
        //this allows us to use file:/// locally, while still doing the right thing
        //when we're hooked up to the server
        let mut str = String::from_utf8(content).unwrap();
        str = str.replace("href=\"", "href=\"/app/");
        str = str.replace("src=\"", "src=\"/app/");
        str = str.replace("/app/http", "http");
        file = str.as_bytes().to_owned();
        file_path = default_file;
    }
    let mime: Mime = Mime::from_str(mime_types.mime_for_path(Path::new(&file_path))).unwrap();
    res.headers_mut().set(ContentType(mime));
    let mut res = res.start().unwrap();
    res.write_all(&file).unwrap();
    res.end().unwrap();
}

fn login(req: Request, mut res: Response<Fresh>) {

    // Don't use a port if we're running in local mode
    let mut port = ":8000";
    for argument in env::args() {
        match &*argument {
            "local" => {
                port = "";
            },
            _ => continue,
        }
    }

    match (&req.method.clone(), &req.uri.clone()) {
        (&hyper::Get, &RequestUri::AbsolutePath(ref relative_path)) => {

            // Form a url from the path
            let absolute_path = "http://localhost".to_string() + relative_path;
            let url = Url::parse(&*absolute_path).unwrap();

            // Get the file name
            let scheme_data = &url.scheme_data;

            let requested_file = match scheme_data {
                &Relative(ref rsd) => rsd.path[0].clone(),
                _ => panic!("Expected relative path"),
            };
            let path_info = match scheme_data {
                &Relative(ref rsd) => rsd,
                _ => panic!("Expected relative path"),
            };

            // Parse the query string
            let query_pairs = &url.query_pairs();

            // Handle login
            match &*requested_file {
                "app.html" | "app" => {
                    serve_local_or_file(res, &path_info.path, "../ui/app.html");
                },
                "editor.html" | "editor" => {
                    serve_local_or_file(res, &path_info.path, "../ui/editor.html");
                },
                "login.html" => {
                    println!("Authenticating User");

                    let referer = format!("{}",req.headers.get::<hyper::header::Referer>().unwrap());
                    let referer_url = Url::parse(&*referer).unwrap();

                    let pairs = query_pairs.clone().unwrap();
                    match &pairs[..] {
                        [(_ , ref page), (ref token_type, ref token), ..] if token_type.clone() == "token".to_string() => {

                            // We have a login token, now to authenticate
                            let client = hyper::client::Client::new();
                            let api_call = "https://api-e1.authrocket.com/v1/sessions/".to_string() + token;
                            let req = client.request(hyper::method::Method::Get,&*api_call);

                            // Set the appropriate headers for authorocket
                            let mut headers = Headers::new();
                            let json: Mime = "application/json".parse().unwrap();
                            let content_type = ContentType(json);
                            headers.set_raw("X-Authrocket-Account",vec!["org_0vC7wPw9XphPGQnSqYB6bz".to_string().into_bytes()]);
                            headers.set_raw("X-Authrocket-Api-Key",vec!["key_jtnCRWxQvDD0p5HATR9RBIe4WnxnwV6pWNzwmZQLnSZ".to_string().into_bytes()]);
                            headers.set_raw("X-Authrocket-Realm",vec!["rl_0vC7wd03CqwhpK7kT8fvAc".to_string().into_bytes()]);
                            headers.set_raw("Accept",vec!["application/json".to_string().into_bytes()]);
                            headers.set(content_type);

                            // Send the request and receive a response with session data
                            let mut client_res = req.headers(headers).send().unwrap();

                            match client_res.status_raw() {

                                &hyper::http::RawStatus(200,_) => {

                                    let mut body = String::new();
                                    client_res.read_to_string(&mut body).unwrap();
                                    let session_data: Session = json::decode(&body).unwrap();
                                    println!("Welcome to Eve, {:?}!",session_data.user.username);
                                    println!("Login Successful. Redirecting to user area.");

                                    // Connect to the Eve runtime and add the user to the eveusers table
                                    let ws_result = open_websocket("ws://0.0.0.0:2794");
                                    match ws_result {
                                        // If things went okay, redirect to the Eve UI
                                        Ok(mut sender) => {
                                            // Form the response
                                            *res.status_mut() = hyper::status::StatusCode::PermanentRedirect;

                                            // Form the response headers
                                            let mut headers = Headers::new();
                                            let redirect_url = referer_url.scheme.clone() + "://" + referer_url.domain().unwrap().clone() + port + "/" + page;
                                            let location = Location(redirect_url);
                                            let user_cookie = Cookie::new("userid".to_string(),session_data.user.id.clone());
                                            let cookies = SetCookie(vec![user_cookie]);
                                            headers.set(location);
                                            headers.set(cookies);
                                            *res.headers_mut() = headers;

                                            // Create eveusers table and insert the new user
                                            let change = ("eveusers".to_owned(),
                                                Change{
                                                    fields: vec!["eveusers: id".to_owned(), "eveusers: username".to_owned()],
                                                    insert: vec![vec![
                                                        Value::String(session_data.user.id.clone()),
                                                        Value::String(session_data.user.username.clone())
                                                    ]],
                                                    remove: vec![],
                                                });
                                            let event = Event{changes: vec![change], session: "".to_owned(), commands: vec![]};
                                            send_event(event, &mut sender);
                                            let _ = sender.send_message(Message::Close(None));
                                        }
                                        // Otherwise, throw an error... maybe redirect to a special page.
                                        Err(e) => {
                                            println!("ERROR: Had trouble connecting to the Eve runtime: {}. Is the server running?",e);
                                            *res.status_mut() = hyper::status::StatusCode::NotFound;
                                            panic!("Oh no!");
                                            //serve_file("404.html",res);
                                        }
                                    }

                                    println!("Login complete.");
                                }
                                _ => {
                                    println!("ERROR: Could not authenticate user with token {}",token);
                                    *res.status_mut() = hyper::status::StatusCode::Forbidden;
                                    panic!("Oh no!");
                                    //serve_file("404.html",res);
                                }
                            };
                        },
                        _ => panic!("Oh no!"), //serve_file("404.html",res),
                    }
                },
                "logout.html" => {
                    println!("Logging out...");
                    let user_id = server::get_user_id(req.headers.get::<hyper::header::Cookie>());
                    println!("{:?}",user_id);
                },
                "favicon.ico" => (),
                other => panic!("Cannot serve {}",other), //serve_file(&*requested_file,res),
            };
        }
        _ => panic!("Oh no!"),
    }
}

pub fn open_websocket(url_string: &str) -> Result<client::sender::Sender<stream::WebSocketStream>,String> {

    //let mut context = SslContext::new(SslMethod::Tlsv1).unwrap();
    //let _ = context.set_certificate_file(&(Path::new("server.crt")), X509FileType::PEM);
    //let _ = context.set_private_key_file(&(Path::new("server.key")), X509FileType::PEM);

    let url = Url::parse(url_string).unwrap();
    println!("Connecting to {}", url);

    let request = match Client::connect(url) {
        Ok(t) => t,
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    let response = match request.send() {
        Ok(t) => t,
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    match response.validate() {
        Ok(_) => println!("Response valid. Start sending/receiving..."),
        Err(e) => {
            return Err(format!("{}", e).to_string());
        }
    };

    let (sender, mut receiver) = response.begin().split();

    thread::spawn(move || {
        for message in receiver.incoming_messages() {
            let message = match message {
                Ok(m) => m,
                Err(_) => return,
            };
            match message {
                Message::Text(_) => {
                    //let json = Json::from_str(&text).unwrap();
                    //let event: Event = FromJson::from_json(&json);
                },
                Message::Close(_) => {
                    println!("Received close message");
                    return;
                }
                _ => println!("Unknown message: {:?}", message)
            }
        }
    });

    Ok(sender)
}

pub fn send_event(event: Event, sender: &mut client::sender::Sender<stream::WebSocketStream>) {
    let mut e = cbor::Encoder::from_memory();
    let json = event.to_json();
    let cbor = json.to_cbor();
    e.encode(vec![cbor]).unwrap();
    sender.send_message(Message::Binary(e.into_bytes())).unwrap();
}<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;

#[derive(Default)]
pub struct DecodeRegister {
    addr_init: u16,
    addr_intermediate: u16,
    addr_final: u16,

    value_init: u8,
    value_intermediate: u8,
    value_final: u8,

    info: OpcodeExecInfo,
}

#[allow(non_snake_case)]
#[derive(Default)]
pub struct CpuState {
    pub pc: u16,
    pub sp: u8,
    pub a:  u8,
    pub x:  u8,
    pub y:  u8,

    // flags
    pub C: bool, // carry
    pub Z: bool, // zero
    pub I: bool, // interrupt
    pub D: bool, // decimal
    pub B: bool, // break
             // bit 5 is not used by the nes and is always 1
    pub V: bool, // overflow
    pub S: bool, // sign/negative

    // these are not strictly 6502 registers, but are useful for modeling the cpu
    pub instruction_register: u16,
    pub decode_register:DecodeRegister,
}

impl CpuState {
    pub fn unpack_flags(self: &CpuState) -> u8 {
        ( (self.C as u8) << 0)
      | ( (self.Z as u8) << 1)
      | ( (self.I as u8) << 2)
      | ( (self.D as u8) << 3)
      | ( (self.B as u8) << 4)
      | ( (1           ) << 5) // flag 5 is unused
      | ( (self.V as u8) << 6)
      | ( (self.S as u8) << 7)
    }
    pub fn pack_flags(self: &mut CpuState,flags:u8) {
        self.C        = ( (flags >> 0) & 1) == 1;
        self.Z        = ( (flags >> 1) & 1) == 1;
        self.I        = ( (flags >> 2) & 1) == 1;
        self.D        = ( (flags >> 3) & 1) == 1;
        self.B        = ( (flags >> 4) & 1) == 1;
        // flags 5 is unused
        self.V        = ( (flags >> 6) & 1) == 1;
        self.S        = ( (flags >> 7) & 1) == 1;
    }
}
<commit_msg>instruction_register is now u8<commit_after>use cpu::common_defs::OpcodeExecInfo;

#[derive(Default)]
pub struct DecodeRegister {
    addr_init: u16,
    addr_intermediate: u16,
    addr_final: u16,

    value_init: u8,
    value_intermediate: u8,
    value_final: u8,

    info: OpcodeExecInfo,
}

#[allow(non_snake_case)]
#[derive(Default)]
pub struct CpuState {
    pub pc: u16,
    pub sp: u8,
    pub a:  u8,
    pub x:  u8,
    pub y:  u8,

    // flags
    pub C: bool, // carry
    pub Z: bool, // zero
    pub I: bool, // interrupt
    pub D: bool, // decimal
    pub B: bool, // break
             // bit 5 is not used by the nes and is always 1
    pub V: bool, // overflow
    pub S: bool, // sign/negative

    // these are not strictly 6502 registers, but are useful for modeling the cpu
    pub instruction_register: u8,
    pub decode_register:DecodeRegister,
}

impl CpuState {
    pub fn unpack_flags(self: &CpuState) -> u8 {
        ( (self.C as u8) << 0)
      | ( (self.Z as u8) << 1)
      | ( (self.I as u8) << 2)
      | ( (self.D as u8) << 3)
      | ( (self.B as u8) << 4)
      | ( (1           ) << 5) // flag 5 is unused
      | ( (self.V as u8) << 6)
      | ( (self.S as u8) << 7)
    }
    pub fn pack_flags(self: &mut CpuState,flags:u8) {
        self.C        = ( (flags >> 0) & 1) == 1;
        self.Z        = ( (flags >> 1) & 1) == 1;
        self.I        = ( (flags >> 2) & 1) == 1;
        self.D        = ( (flags >> 3) & 1) == 1;
        self.B        = ( (flags >> 4) & 1) == 1;
        // flags 5 is unused
        self.V        = ( (flags >> 6) & 1) == 1;
        self.S        = ( (flags >> 7) & 1) == 1;
    }
}
<|endoftext|>