<commit_before>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

extern mod extra;

use std::{os, vec,int};
use extra::arc;

struct Pixel{
    a: int
}

fn readImage( filename:  &[~str]) -> ~ [ ~[Pixel]]{
    ~[~[]]
}

fn main(){
    let argv =  os::args();
    println(argv);
    let length = match std::int::from_string(argv[1]){
        Some(x) => x,
        None() => 0
    };
    let width =  match std::int::from_string(argv[2]){
        Some(x) => x,
        None() => 0
    };

    let mut find_pixels: ~[ ~[Pixel] ] = readImage(argv[0]);
    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[ ~[]];
    let mut len = 0;
    let mut wid = 0;
    loop {
        loop {
            find_arcs[len][wid] = arc::RWArc::new(find_pixels[len][wid]);
            wid ++;
            if(wid == width)
                break;
        }
        len ++;
        if(len == length)
            break;
    }

/*    for i = 0 to length {
        for j = 0 to width {
            find_arcs[i][j] = arc::RWArc::new(find_pixels[i][j];
        }
    } */
    let arcs = find_arcs; // now we have an immutable array that can be shared

}
<commit_msg>something that coing that compiles as a breaking point<commit_after>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

extern mod extra;

use std::*;
use extra::arc;

struct Pixel{
    a: int
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    ~[~[]]
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());
    let length = match from_str::<int>(argv[1]) {
        Some(x) => x,
        None() => 0
    };
    let width = match from_str::<int>(argv[2]) {
        Some(x) => x,
        None() => 0
    };

    let mut find_pixels: ~[ ~[Pixel] ] = readImage(&argv[0]);
    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[ ~[]];
    let mut len = 0;
    let mut wid = 0;
    loop {
        loop {
            find_arcs[len][wid] = arc::RWArc::new(find_pixels[len][wid]);
                wid+=1;
            if(wid == width) {
                break;
            }
        }
        len+=1;
        if(len == length) {
            break;
        }
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

}
<|endoftext|>


<commit_before>//! Zero-capacity channel.
//!
//! This kind of channel is also known as *rendezvous* channel.

use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use internal::channel::RecvNonblocking;
use internal::context;
use internal::select::{Operation, Select, SelectHandle, Token};
use internal::utils::Backoff;
use internal::waker::Waker;

/// A pointer to a packet.
pub type ZeroToken = usize;

/// A slot for passing one message from a sender to a receiver.
struct Packet<T> {
    /// Equals `true` if the packet is allocated on the stack.
    on_stack: bool,

    /// Equals `true` once the packet is ready for reading or writing.
    ready: AtomicBool,

    /// The message.
    msg: ManuallyDrop<UnsafeCell<T>>,
}

impl<T> Packet<T> {
    /// Creates an empty packet on the stack.
    fn empty_on_stack() -> Packet<T> {
        Packet {
            on_stack: true,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }
    }

    /// Creates an empty packet on the heap.
    fn empty_on_heap() -> Box<Packet<T>> {
        Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        })
    }

    /// Creates a packet on the heap, containing a message.
    fn message_on_stack(msg: T) -> Packet<T> {
        Packet {
            on_stack: true,
            ready: AtomicBool::new(false),
            msg: ManuallyDrop::new(UnsafeCell::new(msg)),
        }
    }

    /// Waits until the packet becomes ready for reading or writing.
    fn wait_ready(&self) {
        let backoff = &mut Backoff::new();
        while !self.ready.load(Ordering::Acquire) {
            backoff.step();
        }
    }
}

/// Inner representation of a zero-capacity channel.
struct Inner {
    /// Senders waiting to pair up with a receive operation.
    senders: Waker,

    /// Receivers waiting to pair up with a send operation.
    receivers: Waker,

    /// Equals `true` when the channel is closed.
    is_closed: bool,
}

/// Zero-capacity channel.
pub struct Channel<T> {
    /// Inner representation of the channel.
    inner: Mutex<Inner>,

    /// Indicates that dropping a `Channel<T>` may drop values of type `T`.
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    /// Constructs a new zero-capacity channel.
    pub fn new() -> Self {
        Channel {
            inner: Mutex::new(Inner {
                senders: Waker::new(),
                receivers: Waker::new(),
                is_closed: false,
            }),
            _marker: PhantomData,
        }
    }

    /// Returns a receiver handle to the channel.
    pub fn receiver(&self) -> Receiver<T> {
        Receiver(self)
    }

    /// Returns a sender handle to the channel.
    pub fn sender(&self) -> Sender<T> {
        Sender(self)
    }

    /// Attempts to reserve a slot for sending a message.
    fn start_send(&self, token: &mut Token, short_pause: bool) -> bool {
        let oper = Operation::hook(token);

        {
            let mut inner = self.inner.lock();

            // If there's a waiting receiver, pair up with it.
            if let Some(operation) = inner.receivers.wake_one() {
                token.zero = operation.packet;
                return true;
            }

            if !short_pause {
                return false;
            }

            // Register this send operation so that another receiver can pair up with it.
            context::current_reset();
            let packet = Box::into_raw(Packet::<T>::empty_on_heap());
            inner.senders.register_with_packet(oper, packet as usize);
        }

        // Yield to give receivers a chance to pair up with this operation.
        thread::yield_now();

        let sel = match context::current_try_select(Select::Aborted) {
            Ok(()) => Select::Aborted,
            Err(s) => s,
        };

        match sel {
            Select::Waiting | Select::Closed => unreachable!(),
            Select::Aborted => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().senders.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }
                false
            },
            Select::Operation(_) => {
                // Success! A receiver has paired up with this operation.
                token.zero = context::current_wait_packet();
                true
            },
        }
    }

    /// Writes a message into the packet.
    pub unsafe fn write(&self, token: &mut Token, msg: T) {
        let packet = &*(token.zero as *const Packet<T>);
        packet.msg.get().write(msg);
        packet.ready.store(true, Ordering::Release);
    }

    /// Attempts to pair up with a sender.
    fn start_recv(&self, token: &mut Token, short_pause: bool) -> bool {
        let oper = Operation::hook(token);
        {
            let mut inner = self.inner.lock();

            // If there's a waiting sender, pair up with it.
            if let Some(operation) = inner.senders.wake_one() {
                token.zero = operation.packet;
                return true;
            } else if inner.is_closed {
                token.zero = 0;
                return true;
            }

            if !short_pause {
                return false;
            }

            // Register this receive operation so that another sender can pair up with it.
            context::current_reset();
            let packet = Box::into_raw(Packet::<T>::empty_on_heap());
            inner.receivers.register_with_packet(oper, packet as usize);
        }

        // Yield to give senders a chance to pair up with this operation.
        thread::yield_now();

        let sel = match context::current_try_select(Select::Aborted) {
            Ok(()) => Select::Aborted,
            Err(s) => s,
        };

        match sel {
            Select::Waiting => unreachable!(),
            Select::Aborted => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().receivers.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }
                false
            },
            Select::Closed => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().receivers.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }

                // All senders have just been dropped.
                token.zero = 0;
                true
            },
            Select::Operation(_) => {
                // Success! A sender has paired up with this operation.
                token.zero = context::current_wait_packet();
                true
            },
        }
    }

    /// Reads a message from the packet.
    pub unsafe fn read(&self, token: &mut Token) -> Option<T> {
        // If there is no packet, the channel is closed.
        if token.zero == 0 {
            return None;
        }

        let packet = &*(token.zero as *const Packet<T>);

        if packet.on_stack {
            // The message has been in the packet from the beginning, so there is no need to wait
            // for it. However, after reading the message, we need to set `ready` to `true` in
            // order to signal that the packet can be destroyed.
            let msg = packet.msg.get().read();
            packet.ready.store(true, Ordering::Release);
            Some(msg)
        } else {
            // Wait until the message becomes available, then read it and destroy the
            // heap-allocated packet.
            packet.wait_ready();
            let msg = packet.msg.get().read();
            drop(Box::from_raw(packet as *const Packet<T> as *mut Packet<T>));
            Some(msg)
        }
    }

    /// Sends a message into the channel.
    pub fn send(&self, msg: T) {
        let token = &mut Token::default();
        let oper = Operation::hook(token);
        let packet;
        {
            let mut inner = self.inner.lock();

            // If there's a waiting receiver, pair up with it.
            if let Some(operation) = inner.receivers.wake_one() {
                token.zero = operation.packet;
                drop(inner);
                unsafe { self.write(token, msg); }
                return;
            }

            // Prepare for blocking until a receiver wakes us up.
            context::current_reset();
            packet = Packet::message_on_stack(msg);
            inner.senders.register_with_packet(
                oper,
                &packet as *const Packet<T> as usize,
            );
        }

        // Block the current thread.
        let sel = context::current_wait_until(None);

        match sel {
            Select::Waiting | Select::Aborted | Select::Closed => unreachable!(),
            Select::Operation(_) => {
                // Wait until the message is read, then drop the packet.
                packet.wait_ready();
            },
        }
    }

    /// Receives a message from the channel.
    pub fn recv(&self) -> Option<T> {
        let token = &mut Token::default();
        let oper = Operation::hook(token);
        let packet;
        {
            let mut inner = self.inner.lock();

            // If there's a waiting sender, pair up with it.
            if let Some(operation) = inner.senders.wake_one() {
                token.zero = operation.packet;
                drop(inner);
                unsafe { return self.read(token); }
            }

            if inner.is_closed {
                return None;
            }

            // Prepare for blocking until a sender wakes us up.
            context::current_reset();
            packet = Packet::<T>::empty_on_stack();
            inner.receivers.register_with_packet(
                oper,
                &packet as *const Packet<T> as usize,
            );
        }

        // Block the current thread.
        let sel = context::current_wait_until(None);

        match sel {
            Select::Waiting | Select::Aborted => unreachable!(),
            Select::Closed => {
                self.inner.lock().receivers.unregister(oper).unwrap();
                None
            },
            Select::Operation(_) => {
                // Wait until the message is provided, then read it.
                packet.wait_ready();
                unsafe { Some(packet.msg.get().read()) }
            },
        }
    }

    /// Attempts to receive a message without blocking.
    pub fn recv_nonblocking(&self) -> RecvNonblocking<T> {
        let token = &mut Token::default();
        let mut inner = self.inner.lock();

        // If there's a waiting sender, pair up with it.
        if let Some(operation) = inner.senders.wake_one() {
            token.zero = operation.packet;
            drop(inner);

            match unsafe { self.read(token) } {
                None => RecvNonblocking::Closed,
                Some(msg) => RecvNonblocking::Message(msg),
            }
        } else if inner.is_closed {
            RecvNonblocking::Closed
        } else {
            RecvNonblocking::Empty
        }
    }

    /// Closes the channel and wakes up all blocked receivers.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.is_closed {
            false
        } else {
            inner.is_closed = true;
            inner.receivers.close();
            true
        }
    }

    /// Returns the current number of messages inside the channel.
    pub fn len(&self) -> usize {
        0
    }

    /// Returns the capacity of the channel.
    pub fn capacity(&self) -> Option<usize> {
        Some(0)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        true
    }

    /// Returns `true` if the channel is full.
    pub fn is_full(&self) -> bool {
        true
    }
}

/// Receiver handle to a channel.
pub struct Receiver<'a, T: 'a>(&'a Channel<T>);

/// Sender handle to a channel.
pub struct Sender<'a, T: 'a>(&'a Channel<T>);

impl<'a, T> SelectHandle for Receiver<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_recv(token, false)
    }

    fn retry(&self, token: &mut Token) -> bool {
        self.0.start_recv(token, true)
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, oper: Operation) -> bool {
        let packet = Box::into_raw(Packet::<T>::empty_on_heap());

        let mut inner = self.0.inner.lock();
        inner.receivers.register_with_packet(oper, packet as usize);
        !inner.senders.can_wake_one() && !inner.is_closed
    }

    fn unregister(&self, oper: Operation) {
        if let Some(operation) = self.0.inner.lock().receivers.unregister(oper) {
            unsafe {
                drop(Box::from_raw(operation.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = context::current_wait_packet();
        true
    }
}

impl<'a, T> SelectHandle for Sender<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_send(token, false)
    }

    fn retry(&self, token: &mut Token) -> bool {
        self.0.start_send(token, true)
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, oper: Operation) -> bool {
        let packet = Box::into_raw(Packet::<T>::empty_on_heap());

        let mut inner = self.0.inner.lock();
        inner.senders.register_with_packet(oper, packet as usize);
        !inner.receivers.can_wake_one()
    }

    fn unregister(&self, oper: Operation) {
        if let Some(operation) = self.0.inner.lock().senders.unregister(oper) {
            unsafe {
                drop(Box::from_raw(operation.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = context::current_wait_packet();
        true
    }
}
<commit_msg>Fix erroneous comment for message_on_stack<commit_after>//! Zero-capacity channel.
//!
//! This kind of channel is also known as *rendezvous* channel.

use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use internal::channel::RecvNonblocking;
use internal::context;
use internal::select::{Operation, Select, SelectHandle, Token};
use internal::utils::Backoff;
use internal::waker::Waker;

/// A pointer to a packet.
pub type ZeroToken = usize;

/// A slot for passing one message from a sender to a receiver.
struct Packet<T> {
    /// Equals `true` if the packet is allocated on the stack.
    on_stack: bool,

    /// Equals `true` once the packet is ready for reading or writing.
    ready: AtomicBool,

    /// The message.
    msg: ManuallyDrop<UnsafeCell<T>>,
}

impl<T> Packet<T> {
    /// Creates an empty packet on the stack.
    fn empty_on_stack() -> Packet<T> {
        Packet {
            on_stack: true,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }
    }

    /// Creates an empty packet on the heap.
    fn empty_on_heap() -> Box<Packet<T>> {
        Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        })
    }

    /// Creates a packet on the stack, containing a message.
    fn message_on_stack(msg: T) -> Packet<T> {
        Packet {
            on_stack: true,
            ready: AtomicBool::new(false),
            msg: ManuallyDrop::new(UnsafeCell::new(msg)),
        }
    }

    /// Waits until the packet becomes ready for reading or writing.
    fn wait_ready(&self) {
        let backoff = &mut Backoff::new();
        while !self.ready.load(Ordering::Acquire) {
            backoff.step();
        }
    }
}

/// Inner representation of a zero-capacity channel.
struct Inner {
    /// Senders waiting to pair up with a receive operation.
    senders: Waker,

    /// Receivers waiting to pair up with a send operation.
    receivers: Waker,

    /// Equals `true` when the channel is closed.
    is_closed: bool,
}

/// Zero-capacity channel.
pub struct Channel<T> {
    /// Inner representation of the channel.
    inner: Mutex<Inner>,

    /// Indicates that dropping a `Channel<T>` may drop values of type `T`.
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    /// Constructs a new zero-capacity channel.
    pub fn new() -> Self {
        Channel {
            inner: Mutex::new(Inner {
                senders: Waker::new(),
                receivers: Waker::new(),
                is_closed: false,
            }),
            _marker: PhantomData,
        }
    }

    /// Returns a receiver handle to the channel.
    pub fn receiver(&self) -> Receiver<T> {
        Receiver(self)
    }

    /// Returns a sender handle to the channel.
    pub fn sender(&self) -> Sender<T> {
        Sender(self)
    }

    /// Attempts to reserve a slot for sending a message.
    fn start_send(&self, token: &mut Token, short_pause: bool) -> bool {
        let oper = Operation::hook(token);

        {
            let mut inner = self.inner.lock();

            // If there's a waiting receiver, pair up with it.
            if let Some(operation) = inner.receivers.wake_one() {
                token.zero = operation.packet;
                return true;
            }

            if !short_pause {
                return false;
            }

            // Register this send operation so that another receiver can pair up with it.
            context::current_reset();
            let packet = Box::into_raw(Packet::<T>::empty_on_heap());
            inner.senders.register_with_packet(oper, packet as usize);
        }

        // Yield to give receivers a chance to pair up with this operation.
        thread::yield_now();

        let sel = match context::current_try_select(Select::Aborted) {
            Ok(()) => Select::Aborted,
            Err(s) => s,
        };

        match sel {
            Select::Waiting | Select::Closed => unreachable!(),
            Select::Aborted => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().senders.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }
                false
            },
            Select::Operation(_) => {
                // Success! A receiver has paired up with this operation.
                token.zero = context::current_wait_packet();
                true
            },
        }
    }

    /// Writes a message into the packet.
    pub unsafe fn write(&self, token: &mut Token, msg: T) {
        let packet = &*(token.zero as *const Packet<T>);
        packet.msg.get().write(msg);
        packet.ready.store(true, Ordering::Release);
    }

    /// Attempts to pair up with a sender.
    fn start_recv(&self, token: &mut Token, short_pause: bool) -> bool {
        let oper = Operation::hook(token);
        {
            let mut inner = self.inner.lock();

            // If there's a waiting sender, pair up with it.
            if let Some(operation) = inner.senders.wake_one() {
                token.zero = operation.packet;
                return true;
            } else if inner.is_closed {
                token.zero = 0;
                return true;
            }

            if !short_pause {
                return false;
            }

            // Register this receive operation so that another sender can pair up with it.
            context::current_reset();
            let packet = Box::into_raw(Packet::<T>::empty_on_heap());
            inner.receivers.register_with_packet(oper, packet as usize);
        }

        // Yield to give senders a chance to pair up with this operation.
        thread::yield_now();

        let sel = match context::current_try_select(Select::Aborted) {
            Ok(()) => Select::Aborted,
            Err(s) => s,
        };

        match sel {
            Select::Waiting => unreachable!(),
            Select::Aborted => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().receivers.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }
                false
            },
            Select::Closed => {
                // Unregister and destroy the packet.
                let operation = self.inner.lock().receivers.unregister(oper).unwrap();
                unsafe {
                    drop(Box::from_raw(operation.packet as *mut Packet<T>));
                }

                // All senders have just been dropped.
                token.zero = 0;
                true
            },
            Select::Operation(_) => {
                // Success! A sender has paired up with this operation.
                token.zero = context::current_wait_packet();
                true
            },
        }
    }

    /// Reads a message from the packet.
    pub unsafe fn read(&self, token: &mut Token) -> Option<T> {
        // If there is no packet, the channel is closed.
        if token.zero == 0 {
            return None;
        }

        let packet = &*(token.zero as *const Packet<T>);

        if packet.on_stack {
            // The message has been in the packet from the beginning, so there is no need to wait
            // for it. However, after reading the message, we need to set `ready` to `true` in
            // order to signal that the packet can be destroyed.
            let msg = packet.msg.get().read();
            packet.ready.store(true, Ordering::Release);
            Some(msg)
        } else {
            // Wait until the message becomes available, then read it and destroy the
            // heap-allocated packet.
            packet.wait_ready();
            let msg = packet.msg.get().read();
            drop(Box::from_raw(packet as *const Packet<T> as *mut Packet<T>));
            Some(msg)
        }
    }

    /// Sends a message into the channel.
    pub fn send(&self, msg: T) {
        let token = &mut Token::default();
        let oper = Operation::hook(token);
        let packet;
        {
            let mut inner = self.inner.lock();

            // If there's a waiting receiver, pair up with it.
            if let Some(operation) = inner.receivers.wake_one() {
                token.zero = operation.packet;
                drop(inner);
                unsafe { self.write(token, msg); }
                return;
            }

            // Prepare for blocking until a receiver wakes us up.
            context::current_reset();
            packet = Packet::message_on_stack(msg);
            inner.senders.register_with_packet(
                oper,
                &packet as *const Packet<T> as usize,
            );
        }

        // Block the current thread.
        let sel = context::current_wait_until(None);

        match sel {
            Select::Waiting | Select::Aborted | Select::Closed => unreachable!(),
            Select::Operation(_) => {
                // Wait until the message is read, then drop the packet.
                packet.wait_ready();
            },
        }
    }

    /// Receives a message from the channel.
    pub fn recv(&self) -> Option<T> {
        let token = &mut Token::default();
        let oper = Operation::hook(token);
        let packet;
        {
            let mut inner = self.inner.lock();

            // If there's a waiting sender, pair up with it.
            if let Some(operation) = inner.senders.wake_one() {
                token.zero = operation.packet;
                drop(inner);
                unsafe { return self.read(token); }
            }

            if inner.is_closed {
                return None;
            }

            // Prepare for blocking until a sender wakes us up.
            context::current_reset();
            packet = Packet::<T>::empty_on_stack();
            inner.receivers.register_with_packet(
                oper,
                &packet as *const Packet<T> as usize,
            );
        }

        // Block the current thread.
        let sel = context::current_wait_until(None);

        match sel {
            Select::Waiting | Select::Aborted => unreachable!(),
            Select::Closed => {
                self.inner.lock().receivers.unregister(oper).unwrap();
                None
            },
            Select::Operation(_) => {
                // Wait until the message is provided, then read it.
                packet.wait_ready();
                unsafe { Some(packet.msg.get().read()) }
            },
        }
    }

    /// Attempts to receive a message without blocking.
    pub fn recv_nonblocking(&self) -> RecvNonblocking<T> {
        let token = &mut Token::default();
        let mut inner = self.inner.lock();

        // If there's a waiting sender, pair up with it.
        if let Some(operation) = inner.senders.wake_one() {
            token.zero = operation.packet;
            drop(inner);

            match unsafe { self.read(token) } {
                None => RecvNonblocking::Closed,
                Some(msg) => RecvNonblocking::Message(msg),
            }
        } else if inner.is_closed {
            RecvNonblocking::Closed
        } else {
            RecvNonblocking::Empty
        }
    }

    /// Closes the channel and wakes up all blocked receivers.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.is_closed {
            false
        } else {
            inner.is_closed = true;
            inner.receivers.close();
            true
        }
    }

    /// Returns the current number of messages inside the channel.
    pub fn len(&self) -> usize {
        0
    }

    /// Returns the capacity of the channel.
    pub fn capacity(&self) -> Option<usize> {
        Some(0)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        true
    }

    /// Returns `true` if the channel is full.
    pub fn is_full(&self) -> bool {
        true
    }
}

/// Receiver handle to a channel.
pub struct Receiver<'a, T: 'a>(&'a Channel<T>);

/// Sender handle to a channel.
pub struct Sender<'a, T: 'a>(&'a Channel<T>);

impl<'a, T> SelectHandle for Receiver<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_recv(token, false)
    }

    fn retry(&self, token: &mut Token) -> bool {
        self.0.start_recv(token, true)
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, oper: Operation) -> bool {
        let packet = Box::into_raw(Packet::<T>::empty_on_heap());

        let mut inner = self.0.inner.lock();
        inner.receivers.register_with_packet(oper, packet as usize);
        !inner.senders.can_wake_one() && !inner.is_closed
    }

    fn unregister(&self, oper: Operation) {
        if let Some(operation) = self.0.inner.lock().receivers.unregister(oper) {
            unsafe {
                drop(Box::from_raw(operation.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = context::current_wait_packet();
        true
    }
}

impl<'a, T> SelectHandle for Sender<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_send(token, false)
    }

    fn retry(&self, token: &mut Token) -> bool {
        self.0.start_send(token, true)
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, oper: Operation) -> bool {
        let packet = Box::into_raw(Packet::<T>::empty_on_heap());

        let mut inner = self.0.inner.lock();
        inner.senders.register_with_packet(oper, packet as usize);
        !inner.receivers.can_wake_one()
    }

    fn unregister(&self, oper: Operation) {
        if let Some(operation) = self.0.inner.lock().senders.unregister(oper) {
            unsafe {
                drop(Box::from_raw(operation.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = context::current_wait_packet();
        true
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::io;
use std::mem;

pub use self::native::{close, retry, addr_to_sockaddr, sockaddr_to_addr};

mod native;

#[cfg(windows)] pub type CSocket = libc::SOCKET;
#[cfg(windows)] pub type BufLen = i32;

#[cfg(not(windows))] pub type CSocket = libc::c_int;
#[cfg(not(windows))] pub type BufLen = u64;

// Any file descriptor on unix, only sockets on Windows.
pub struct FileDesc {
    pub fd: CSocket,
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        unsafe {
            close(self.fd);
        }
    }
}

pub fn send_to(socket: CSocket, buffer: &[u8], dst: *const libc::sockaddr, slen: libc::socklen_t)
    -> io::Result<usize> {

    let send_len = retry(&mut || unsafe {
        libc::sendto(socket, buffer.as_ptr() as *const libc::c_void, buffer.len() as BufLen,
                     0, dst, slen)
    });

    if send_len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(send_len as usize)
    }
}

pub fn recv_from(socket: CSocket, buffer: &mut [u8], caddr: *mut libc::sockaddr_storage)
    -> io::Result<usize> {
    let mut caddrlen = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
    let len = retry(&mut || unsafe {
        libc::recvfrom(socket, buffer.as_ptr() as *mut libc::c_void, buffer.len() as BufLen,
                       0, caddr as *mut libc::sockaddr, &mut caddrlen)
    });

    if len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(len as usize)
    }
}

<commit_msg>use libc::size_t instead of u64<commit_after>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::io;
use std::mem;

pub use self::native::{close, retry, addr_to_sockaddr, sockaddr_to_addr};

mod native;

#[cfg(windows)] pub type CSocket = libc::SOCKET;
#[cfg(windows)] pub type BufLen = i32;

#[cfg(not(windows))] pub type CSocket = libc::c_int;
#[cfg(not(windows))] pub type BufLen = libc::size_t;

// Any file descriptor on unix, only sockets on Windows.
pub struct FileDesc {
    pub fd: CSocket,
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        unsafe {
            close(self.fd);
        }
    }
}

pub fn send_to(socket: CSocket, buffer: &[u8], dst: *const libc::sockaddr, slen: libc::socklen_t)
    -> io::Result<usize> {

    let send_len = retry(&mut || unsafe {
        libc::sendto(socket, buffer.as_ptr() as *const libc::c_void, buffer.len() as BufLen,
                     0, dst, slen)
    });

    if send_len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(send_len as usize)
    }
}

pub fn recv_from(socket: CSocket, buffer: &mut [u8], caddr: *mut libc::sockaddr_storage)
    -> io::Result<usize> {
    let mut caddrlen = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
    let len = retry(&mut || unsafe {
        libc::recvfrom(socket, buffer.as_ptr() as *mut libc::c_void, buffer.len() as BufLen,
                       0, caddr as *mut libc::sockaddr, &mut caddrlen)
    });

    if len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(len as usize)
    }
}

<|endoftext|>


<commit_before>use std::collections;
use std::fmt;
use std::error::Error as ErrorTrait;

use rustc_serialize::json;
use rustc_serialize::json::ToJson;

use hyper::header;

use url;

use iron::prelude::*;
use iron::modifiers::Header;
use iron::status;

use urlencoded;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct OauthRequest {
    pub session: Session,
    pub state: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Session {
    pub client_id: String,
    pub uri: url::Url,
    pub permissions: collections::HashMap<String, CategoryPermissions>
}

impl Session {
    pub fn permissions_for_category(&self, category: &str) -> Option<&CategoryPermissions> {
        match self.permissions.get(category) {
            Some(x) => Some(x),
            None => self.permissions.get("")
        }
    }
}

impl ToJson for Session {
    fn to_json(&self) -> json::Json {
        json::Json::Object({
            let mut rv = collections::BTreeMap::new();
            rv.insert("client_id".to_owned(), self.client_id.to_json());
            rv.insert("uri".to_owned(), self.uri.serialize().to_json());
            rv.insert("permissions".to_owned(), self.permissions.to_json());
            rv
        })
    }
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone, Copy)]
pub struct CategoryPermissions {
    pub can_read: bool,
    pub can_write: bool
}

impl ToJson for CategoryPermissions {
    // ToJson for passing to template
    fn to_json(&self) -> json::Json {
        json::Json::Object({
            let mut rv = collections::BTreeMap::new();
            rv.insert("can_read".to_owned(), self.can_read.to_json());
            rv.insert("can_write".to_owned(), self.can_write.to_json());
            rv
        })
    }
}

impl ToJson for OauthRequest {
    // ToJson for passing to template
    fn to_json(&self) -> json::Json {
        self.session.to_json()
    }
}

fn expect_param(query: &urlencoded::QueryMap, key: &str) -> Result<String, Error> {
    match query.get(key) {
        Some(x) if x.len() == 1 => Ok(x[0].clone()),
        _ => Err({
            let mut rv = Error::new(ErrorKind::InvalidRequest);
            rv.msg = Some(format!("Missing query parameter: {:?}", key));
            rv
        })
    }
}

impl OauthRequest {
    pub fn from_http(request: &mut Request) -> Result<Self, Error> {
        let query = match request.get_ref::<urlencoded::UrlEncodedQuery>().ok() {
            Some(x) => x,
            None => return Err({
                let mut e = Error::new(ErrorKind::InvalidRequest);
                e.msg = Some("No query parameters.".to_owned());
                e
            })
        };

        let mut rv = OauthRequest {
            session: Session {
                client_id: "".to_owned(),
                uri: match url::Url::parse(&try!(expect_param(query, "redirect_uri"))[..]) {
                    Ok(x) => x,
                    Err(e) => return Err({
                        let mut ne = Error::new(ErrorKind::InvalidRequest);
                        ne.msg = Some(format!("{}", e));
                        ne
                    })
                },
                permissions: collections::HashMap::new()
            },
            state: expect_param(query, "state").ok()
        };

        rv.session.client_id = match expect_param(query, "client_id") {
            Ok(x) => x,
            Err(mut e) => {
                e.request = Some(rv);
                return Err(e);
            }
        };

        let scope = match expect_param(query, "scope") {
            Ok(x) => x,
            Err(mut e) => {
                e.request = Some(rv);
                return Err(e);
            }
        };

        let scope_err = |x| { Err({
            let mut e = Error::new(ErrorKind::InvalidScope);
            e.msg = Some("Invalid scope.".to_owned());
            e.request = Some(x);
            e
        }) };

        for category_permission in scope.split(' ') {
            let parts = category_permission.split(':').collect::<Vec<_>>();
            if parts.len() != 2 { return scope_err(rv); }

            let (category, permission) = (parts[0], parts[1]);
            if category.len() == 0 || permission.len() == 0 { return scope_err(rv); }

            let key = (if category == "*" { "" } else { category }).to_owned();
            if rv.session.permissions.get(&key).is_some() { return scope_err(rv); }

            rv.session.permissions.insert(key, CategoryPermissions {
                can_read: permission.contains("r"),
                can_write: permission.contains("w")
            });
        }

        Ok(rv)
    }

    pub fn grant(self, token: String) -> Grant {
        Grant { request: self, token: token }
    }

    pub fn reject(self) -> Error {
        let mut e = Error::new(ErrorKind::AccessDenied);
        e.request = Some(self);
        e
    }
}

pub struct Grant {
    pub request: OauthRequest,
    pub token: String
}

impl HttpResponder for Grant {
    fn get_redirect_uri(&self) -> Option<url::Url> {
        Some(self.request.session.uri.clone())
    }

    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String> {
        let mut rv = collections::BTreeMap::new();
        rv.insert("access_token".to_owned(), self.token.clone());
        self.request.state.as_ref().map(|x| rv.insert("state".to_owned(), x.clone()));
        rv
    }
}

#[derive(Debug)]
pub struct Error {
    pub kind: ErrorKind,
    pub request: Option<OauthRequest>,
    pub error_uri: Option<url::Url>,
    pub msg: Option<String>
}

impl Error {
    pub fn new(kind: ErrorKind) -> Self {
        Error {
            kind: kind,
            request: None,
            error_uri: None,
            msg: None
        }
    }
}

#[derive(Debug)]
#[allow(dead_code)]
pub enum ErrorKind {
    InvalidRequest,
    UnauthorizedClient,
    AccessDenied,
    UnsupportedResponseType,
    InvalidScope,
    ServerError,
    TemporarilyUnavailable
}

impl ErrorKind {
    fn as_snake_case(&self) -> &str {
        match *self {
            ErrorKind::InvalidRequest => "invalid_request",
            ErrorKind::UnauthorizedClient => "unauthorized_client",
            ErrorKind::AccessDenied => "access_denied",
            ErrorKind::UnsupportedResponseType => "unsupported_response_type",
            ErrorKind::InvalidScope => "invalid_scope",
            ErrorKind::ServerError => "server_error",
            ErrorKind::TemporarilyUnavailable => "temporarily_unavailable"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) }
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        match self.msg {
            Some(ref x) => x,
            None => self.kind.as_snake_case()
        }
    }
    fn cause(&self) -> Option<&ErrorTrait> { None }
}

pub trait HttpResponder {
    fn get_redirect_uri(&self) -> Option<url::Url>;
    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String>;

    fn get_response(&self) -> Option<Response> {
        self.get_redirect_uri()
            .map(|mut uri| {
                uri.fragment = Some(url::form_urlencoded::serialize(self.get_redirect_uri_params()));
                Response::with(status::Found)
                 // Do not use Redirect modifier here, we need to handle custom URI schemes as well
                 .set(Header(header::Location(uri.serialize())))
            })
    }
}

impl HttpResponder for Error {
    fn get_redirect_uri(&self) -> Option<url::Url> {
        self.request.as_ref().map(|req| req.session.uri.clone())
    }

    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String> {
        let mut rv = collections::BTreeMap::new();
        rv.insert("error".to_owned(), self.kind.as_snake_case().to_owned());
        self.msg.as_ref().map(|x| rv.insert("error_description".to_owned(), x.clone()));
        self.request.as_ref().map(|req| req.state.as_ref().map(|state| rv.insert("state".to_owned(), state.clone())));
        rv
    }
}
<commit_msg>add fixme<commit_after>use std::collections;
use std::fmt;
use std::error::Error as ErrorTrait;

use rustc_serialize::json;
use rustc_serialize::json::ToJson;

use hyper::header;

use url;

use iron::prelude::*;
use iron::modifiers::Header;
use iron::status;

use urlencoded;

// FIXME: oauth module should not be concerned with serialization
#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct OauthRequest {
    pub session: Session,
    pub state: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Session {
    pub client_id: String,
    pub uri: url::Url,
    pub permissions: collections::HashMap<String, CategoryPermissions>
}

impl Session {
    pub fn permissions_for_category(&self, category: &str) -> Option<&CategoryPermissions> {
        match self.permissions.get(category) {
            Some(x) => Some(x),
            None => self.permissions.get("")
        }
    }
}

impl ToJson for Session {
    fn to_json(&self) -> json::Json {
        json::Json::Object({
            let mut rv = collections::BTreeMap::new();
            rv.insert("client_id".to_owned(), self.client_id.to_json());
            rv.insert("uri".to_owned(), self.uri.serialize().to_json());
            rv.insert("permissions".to_owned(), self.permissions.to_json());
            rv
        })
    }
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone, Copy)]
pub struct CategoryPermissions {
    pub can_read: bool,
    pub can_write: bool
}

impl ToJson for CategoryPermissions {
    // ToJson for passing to template
    fn to_json(&self) -> json::Json {
        json::Json::Object({
            let mut rv = collections::BTreeMap::new();
            rv.insert("can_read".to_owned(), self.can_read.to_json());
            rv.insert("can_write".to_owned(), self.can_write.to_json());
            rv
        })
    }
}

impl ToJson for OauthRequest {
    // ToJson for passing to template
    fn to_json(&self) -> json::Json {
        self.session.to_json()
    }
}

fn expect_param(query: &urlencoded::QueryMap, key: &str) -> Result<String, Error> {
    match query.get(key) {
        Some(x) if x.len() == 1 => Ok(x[0].clone()),
        _ => Err({
            let mut rv = Error::new(ErrorKind::InvalidRequest);
            rv.msg = Some(format!("Missing query parameter: {:?}", key));
            rv
        })
    }
}

impl OauthRequest {
    pub fn from_http(request: &mut Request) -> Result<Self, Error> {
        let query = match request.get_ref::<urlencoded::UrlEncodedQuery>().ok() {
            Some(x) => x,
            None => return Err({
                let mut e = Error::new(ErrorKind::InvalidRequest);
                e.msg = Some("No query parameters.".to_owned());
                e
            })
        };

        let mut rv = OauthRequest {
            session: Session {
                client_id: "".to_owned(),
                uri: match url::Url::parse(&try!(expect_param(query, "redirect_uri"))[..]) {
                    Ok(x) => x,
                    Err(e) => return Err({
                        let mut ne = Error::new(ErrorKind::InvalidRequest);
                        ne.msg = Some(format!("{}", e));
                        ne
                    })
                },
                permissions: collections::HashMap::new()
            },
            state: expect_param(query, "state").ok()
        };

        rv.session.client_id = match expect_param(query, "client_id") {
            Ok(x) => x,
            Err(mut e) => {
                e.request = Some(rv);
                return Err(e);
            }
        };

        let scope = match expect_param(query, "scope") {
            Ok(x) => x,
            Err(mut e) => {
                e.request = Some(rv);
                return Err(e);
            }
        };

        let scope_err = |x| { Err({
            let mut e = Error::new(ErrorKind::InvalidScope);
            e.msg = Some("Invalid scope.".to_owned());
            e.request = Some(x);
            e
        }) };

        for category_permission in scope.split(' ') {
            let parts = category_permission.split(':').collect::<Vec<_>>();
            if parts.len() != 2 { return scope_err(rv); }

            let (category, permission) = (parts[0], parts[1]);
            if category.len() == 0 || permission.len() == 0 { return scope_err(rv); }

            let key = (if category == "*" { "" } else { category }).to_owned();
            if rv.session.permissions.get(&key).is_some() { return scope_err(rv); }

            rv.session.permissions.insert(key, CategoryPermissions {
                can_read: permission.contains("r"),
                can_write: permission.contains("w")
            });
        }

        Ok(rv)
    }

    pub fn grant(self, token: String) -> Grant {
        Grant { request: self, token: token }
    }

    pub fn reject(self) -> Error {
        let mut e = Error::new(ErrorKind::AccessDenied);
        e.request = Some(self);
        e
    }
}

pub struct Grant {
    pub request: OauthRequest,
    pub token: String
}

impl HttpResponder for Grant {
    fn get_redirect_uri(&self) -> Option<url::Url> {
        Some(self.request.session.uri.clone())
    }

    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String> {
        let mut rv = collections::BTreeMap::new();
        rv.insert("access_token".to_owned(), self.token.clone());
        self.request.state.as_ref().map(|x| rv.insert("state".to_owned(), x.clone()));
        rv
    }
}

#[derive(Debug)]
pub struct Error {
    pub kind: ErrorKind,
    pub request: Option<OauthRequest>,
    pub error_uri: Option<url::Url>,
    pub msg: Option<String>
}

impl Error {
    pub fn new(kind: ErrorKind) -> Self {
        Error {
            kind: kind,
            request: None,
            error_uri: None,
            msg: None
        }
    }
}

#[derive(Debug)]
#[allow(dead_code)]
pub enum ErrorKind {
    InvalidRequest,
    UnauthorizedClient,
    AccessDenied,
    UnsupportedResponseType,
    InvalidScope,
    ServerError,
    TemporarilyUnavailable
}

impl ErrorKind {
    fn as_snake_case(&self) -> &str {
        match *self {
            ErrorKind::InvalidRequest => "invalid_request",
            ErrorKind::UnauthorizedClient => "unauthorized_client",
            ErrorKind::AccessDenied => "access_denied",
            ErrorKind::UnsupportedResponseType => "unsupported_response_type",
            ErrorKind::InvalidScope => "invalid_scope",
            ErrorKind::ServerError => "server_error",
            ErrorKind::TemporarilyUnavailable => "temporarily_unavailable"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) }
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        match self.msg {
            Some(ref x) => x,
            None => self.kind.as_snake_case()
        }
    }
    fn cause(&self) -> Option<&ErrorTrait> { None }
}

pub trait HttpResponder {
    fn get_redirect_uri(&self) -> Option<url::Url>;
    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String>;

    fn get_response(&self) -> Option<Response> {
        self.get_redirect_uri()
            .map(|mut uri| {
                uri.fragment = Some(url::form_urlencoded::serialize(self.get_redirect_uri_params()));
                Response::with(status::Found)
                 // Do not use Redirect modifier here, we need to handle custom URI schemes as well
                 .set(Header(header::Location(uri.serialize())))
            })
    }
}

impl HttpResponder for Error {
    fn get_redirect_uri(&self) -> Option<url::Url> {
        self.request.as_ref().map(|req| req.session.uri.clone())
    }

    fn get_redirect_uri_params(&self) -> collections::BTreeMap<String, String> {
        let mut rv = collections::BTreeMap::new();
        rv.insert("error".to_owned(), self.kind.as_snake_case().to_owned());
        self.msg.as_ref().map(|x| rv.insert("error_description".to_owned(), x.clone()));
        self.request.as_ref().map(|req| req.state.as_ref().map(|state| rv.insert("state".to_owned(), state.clone())));
        rv
    }
}
<|endoftext|>


<commit_before>use std::net::SocketAddr;

use hyper::header;
use hyper::method::Method;

use url::Position;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

header! { (XForwardedHost, "X-Forwarded-Host") => [String] }
header! { (XForwardedPort, "X-Forwarded-Port") => [u16] }
header! { (XForwardedProto, "X-Forwarded-Proto") => [String] }
header! { (XForwardedFor, "X-Forwarded-For") => [SocketAddr] }

pub struct XForwardedMiddleware;

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        macro_rules! h {
            ($x:path, $n:expr) => {{
                // FIXME: https://github.com/hyperium/hyper/issues/891
                let rv = match request.headers.get::<$x>() {
                    Some(x) => x.0.clone(),
                    None => {
                        panic!("Missing header: {:?}. Turn off use_proxy_headers or set proxy headers.", $n);
                    }
                };
                assert!(request.headers.remove::<$x>());
                rv
            }}
        }
        let host = h!(XForwardedHost, "X-Forwarded-Host");
        let port = h!(XForwardedPort, "X-Forwarded-Port");
        let scheme = h!(XForwardedProto, "X-Forwarded-Proto");
        let remote_addr = h!(XForwardedFor, "X-Forwarded-For");

        // FIXME: https://github.com/iron/iron/pull/475
        let mut url = request.url.clone().into_generic_url();
        url.set_host(Some(&host)).unwrap();
        url.set_port(Some(port)).unwrap();
        url.set_scheme(&scheme).unwrap();

        request.url = iron::Url::from_generic_url(url).unwrap();
        request.remote_addr = remote_addr;
        Ok(())
    }
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut error.response);
        Err(error)
    }
}

impl SecurityHeaderMiddleware {
    fn set_security_headers(rq: &Request, r: &mut Response) {
        Self::set_cors_headers(rq, r);
        r.headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
        r.headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);

        let mut csp = vec!["default-src 'self'"];

        if rq.url.path()[0] != "storage" {
            // It's probably fine to embed user storage data into other documents

            // Prevent clickjacking attacks like described in OAuth RFC
            // https://tools.ietf.org/html/rfc6749#section-10.13
            r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);

            // This is a newer way to do what X-Frame-Options does
            // http://www.w3.org/TR/CSP11/#frame-ancestors-and-frame-options
            csp.push("frame-ancestors 'none'");
        };
        r.headers.set_raw("Content-Security-Policy", vec![csp.join(";").as_bytes().to_vec()]);
    }

    /// Required by remoteStorage spec
    fn set_cors_headers(rq: &Request, r: &mut Response) {
        match &rq.url.path()[0][..] {
            ".well-known" | "storage" => (),
            _ => return
        };

        let origin = match rq.headers.get_raw("Origin") {
            Some(x) => if x.len() == 1 {
                match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                    Ok(x) => x,
                    Err(_) => return
                }
            } else {
                return;
            },
            None => return
        };

        r.headers.set(header::AccessControlAllowOrigin::Value(origin));
        r.headers.set(header::AccessControlExposeHeaders(vec![
            UniCase("ETag".to_owned()),
            UniCase("Content-Length".to_owned())
        ]));
        r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
        r.headers.set(header::AccessControlAllowHeaders(vec![
            UniCase("Authorization".to_owned()),
            UniCase("Content-Type".to_owned()),
            UniCase("Origin".to_owned()),
            UniCase("If-Match".to_owned()),
            UniCase("If-None-Match".to_owned()),
        ]));
    }
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    if let Some(header) = request.headers.get::<header::IfNoneMatch>() {
        if header.matches_etag(etag) {
            return false
        }
    };

    if let Some(header) = request.headers.get::<header::IfMatch>() {
        if !header.matches_etag(etag) {
            return false
        }
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    // FIXME: https://github.com/iron/iron/pull/475
    let url = request.url.clone().into_generic_url();
    let netloc = &url[Position::BeforeHost..Position::AfterPort];
    format!("{}@{}", user.userid, netloc)
}
<commit_msg>Bugfix<commit_after>use std::net::IpAddr;

use hyper::header;
use hyper::method::Method;

use url::Position;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

header! { (XForwardedHost, "X-Forwarded-Host") => [String] }
header! { (XForwardedPort, "X-Forwarded-Port") => [u16] }
header! { (XForwardedProto, "X-Forwarded-Proto") => [String] }
header! { (XForwardedFor, "X-Forwarded-For") => [IpAddr] }

pub struct XForwardedMiddleware;

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        macro_rules! h {
            ($x:path, $n:expr) => {{
                // FIXME: https://github.com/hyperium/hyper/issues/891
                let rv = match request.headers.get::<$x>() {
                    Some(x) => x.0.clone(),
                    None => {
                        panic!("Missing header: {:?}. Turn off use_proxy_headers or set proxy headers.", $n);
                    }
                };
                assert!(request.headers.remove::<$x>());
                rv
            }}
        }
        let host = h!(XForwardedHost, "X-Forwarded-Host");
        let port = h!(XForwardedPort, "X-Forwarded-Port");
        let scheme = h!(XForwardedProto, "X-Forwarded-Proto");
        let remote_addr = h!(XForwardedFor, "X-Forwarded-For");

        // FIXME: https://github.com/iron/iron/pull/475
        let mut url = request.url.clone().into_generic_url();
        url.set_host(Some(&host)).unwrap();
        url.set_port(Some(port)).unwrap();
        url.set_scheme(&scheme).unwrap();

        request.url = iron::Url::from_generic_url(url).unwrap();
        request.remote_addr.set_ip(remote_addr);
        Ok(())
    }
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut error.response);
        Err(error)
    }
}

impl SecurityHeaderMiddleware {
    fn set_security_headers(rq: &Request, r: &mut Response) {
        Self::set_cors_headers(rq, r);
        r.headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
        r.headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);

        let mut csp = vec!["default-src 'self'"];

        if rq.url.path()[0] != "storage" {
            // It's probably fine to embed user storage data into other documents

            // Prevent clickjacking attacks like described in OAuth RFC
            // https://tools.ietf.org/html/rfc6749#section-10.13
            r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);

            // This is a newer way to do what X-Frame-Options does
            // http://www.w3.org/TR/CSP11/#frame-ancestors-and-frame-options
            csp.push("frame-ancestors 'none'");
        };
        r.headers.set_raw("Content-Security-Policy", vec![csp.join(";").as_bytes().to_vec()]);
    }

    /// Required by remoteStorage spec
    fn set_cors_headers(rq: &Request, r: &mut Response) {
        match &rq.url.path()[0][..] {
            ".well-known" | "storage" => (),
            _ => return
        };

        let origin = match rq.headers.get_raw("Origin") {
            Some(x) => if x.len() == 1 {
                match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                    Ok(x) => x,
                    Err(_) => return
                }
            } else {
                return;
            },
            None => return
        };

        r.headers.set(header::AccessControlAllowOrigin::Value(origin));
        r.headers.set(header::AccessControlExposeHeaders(vec![
            UniCase("ETag".to_owned()),
            UniCase("Content-Length".to_owned())
        ]));
        r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
        r.headers.set(header::AccessControlAllowHeaders(vec![
            UniCase("Authorization".to_owned()),
            UniCase("Content-Type".to_owned()),
            UniCase("Origin".to_owned()),
            UniCase("If-Match".to_owned()),
            UniCase("If-None-Match".to_owned()),
        ]));
    }
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    if let Some(header) = request.headers.get::<header::IfNoneMatch>() {
        if header.matches_etag(etag) {
            return false
        }
    };

    if let Some(header) = request.headers.get::<header::IfMatch>() {
        if !header.matches_etag(etag) {
            return false
        }
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    // FIXME: https://github.com/iron/iron/pull/475
    let url = request.url.clone().into_generic_url();
    let netloc = &url[Position::BeforeHost..Position::AfterPort];
    format!("{}@{}", user.userid, netloc)
}
<|endoftext|>


<commit_before>//! Shadowsocks TCP server

use std::{
    future::Future,
    io::{self, ErrorKind},
    net::SocketAddr,
    sync::Arc,
    time::Duration,
};

use log::{debug, error, info, trace, warn};
use shadowsocks::{
    crypto::CipherKind,
    net::{AcceptOpts, TcpStream as OutboundTcpStream},
    relay::tcprelay::{utils::copy_encrypted_bidirectional, ProxyServerStream},
    ProxyListener,
    ServerConfig,
};
use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    net::TcpStream as TokioTcpStream,
    time,
};

use crate::net::{utils::ignore_until_end, MonProxyStream};

use super::context::ServiceContext;

pub struct TcpServer {
    context: Arc<ServiceContext>,
    accept_opts: AcceptOpts,
}

impl TcpServer {
    pub fn new(context: Arc<ServiceContext>, accept_opts: AcceptOpts) -> TcpServer {
        TcpServer { context, accept_opts }
    }

    pub async fn run(self, svr_cfg: &ServerConfig) -> io::Result<()> {
        let listener = ProxyListener::bind_with_opts(self.context.context(), svr_cfg, self.accept_opts).await?;

        info!(
            "shadowsocks tcp server listening on {}, inbound address {}",
            listener.local_addr().expect("listener.local_addr"),
            svr_cfg.addr()
        );

        loop {
            let flow_stat = self.context.flow_stat();

            let (local_stream, peer_addr) =
                match listener.accept_map(|s| MonProxyStream::from_stream(s, flow_stat)).await {
                    Ok(s) => s,
                    Err(err) => {
                        error!("tcp server accept failed with error: {}", err);
                        time::sleep(Duration::from_secs(1)).await;
                        continue;
                    }
                };

            if self.context.check_client_blocked(&peer_addr) {
                warn!("access denied from {} by ACL rules", peer_addr);
                continue;
            }

            let client = TcpServerClient {
                context: self.context.clone(),
                method: svr_cfg.method(),
                peer_addr,
                stream: local_stream,
                timeout: svr_cfg.timeout(),
            };

            tokio::spawn(async move {
                if let Err(err) = client.serve().await {
                    debug!("tcp server stream aborted with error: {}", err);
                }
            });
        }
    }
}

#[inline]
async fn timeout_fut<F, R>(duration: Option<Duration>, f: F) -> io::Result<R>
where
    F: Future<Output = io::Result<R>>,
{
    match duration {
        None => f.await,
        Some(d) => match time::timeout(d, f).await {
            Ok(o) => o,
            Err(..) => Err(ErrorKind::TimedOut.into()),
        },
    }
}

struct TcpServerClient {
    context: Arc<ServiceContext>,
    method: CipherKind,
    peer_addr: SocketAddr,
    stream: ProxyServerStream<MonProxyStream<TokioTcpStream>>,
    timeout: Option<Duration>,
}

impl TcpServerClient {
    async fn serve(mut self) -> io::Result<()> {
        // let target_addr = match Address::read_from(&mut self.stream).await {
        let target_addr = match self.stream.handshake().await {
            Ok(a) => a,
            // Err(Socks5Error::IoError(ref err)) if err.kind() == ErrorKind::UnexpectedEof => {
            //     debug!(
            //         "handshake failed, received EOF before a complete target Address, peer: {}",
            //         self.peer_addr
            //     );
            //     return Ok(());
            // }
            Err(err) if err.kind() == ErrorKind::UnexpectedEof => {
                debug!(
                    "handshake failed, received EOF before a complete target Address, peer: {}",
                    self.peer_addr
                );
                return Ok(());
            }
            Err(err) => {
                // https://github.com/shadowsocks/shadowsocks-rust/issues/292
                //
                // Keep connection open. Except AEAD-2022
                warn!(
                    "handshake failed, maybe wrong method or key, or under replay attacks. peer: {}, error: {}",
                    self.peer_addr, err
                );

                #[cfg(feature = "aead-cipher-2022")]
                if self.method.is_aead_2022() {
                    // Set SO_LINGER(0) for misbehave clients, which will eventually receive RST. (ECONNRESET)
                    // This will also prevent the socket entering TIME_WAIT state.

                    let stream = self.stream.into_inner().into_inner();
                    let _ = stream.set_linger(Some(Duration::ZERO));

                    return Ok(());
                }

                // Unwrap and get the plain stream.
                // Otherwise it will keep reporting decryption error before reaching EOF.
                //
                // Note: This will drop all data in the decryption buffer, which is no going back.
                let mut stream = self.stream.into_inner();

                let res = ignore_until_end(&mut stream).await;

                trace!(
                    "silent-drop peer: {} is now closing with result {:?}",
                    self.peer_addr,
                    res
                );

                return Ok(());
            }
        };

        trace!(
            "accepted tcp client connection {}, establishing tunnel to {}",
            self.peer_addr,
            target_addr
        );

        if self.context.check_outbound_blocked(&target_addr).await {
            error!(
                "tcp client {} outbound {} blocked by ACL rules",
                self.peer_addr, target_addr
            );
            return Ok(());
        }

        let mut remote_stream = match timeout_fut(
            self.timeout,
            OutboundTcpStream::connect_remote_with_opts(
                self.context.context_ref(),
                &target_addr,
                self.context.connect_opts_ref(),
            ),
        )
        .await
        {
            Ok(s) => s,
            Err(err) => {
                error!(
                    "tcp tunnel {} -> {} connect failed, error: {}",
                    self.peer_addr, target_addr, err
                );
                return Err(err);
            }
        };

        // https://github.com/shadowsocks/shadowsocks-rust/issues/232
        //
        // Protocols like FTP, clients will wait for servers to send Welcome Message without sending anything.
        //
        // Wait at most 500ms, and then sends handshake packet to remote servers.
        if self.context.connect_opts_ref().tcp.fastopen {
            let mut buffer = [0u8; 8192];
            match time::timeout(Duration::from_millis(500), self.stream.read(&mut buffer)).await {
                Ok(Ok(0)) => {
                    // EOF. Just terminate right here.
                    return Ok(());
                }
                Ok(Ok(n)) => {
                    // Send the first packet.
                    timeout_fut(self.timeout, remote_stream.write_all(&buffer[..n])).await?;
                }
                Ok(Err(err)) => return Err(err),
                Err(..) => {
                    // Timeout. Send handshake to server.
                    timeout_fut(self.timeout, remote_stream.write(&[])).await?;

                    trace!(
                        "tcp tunnel {} -> {} sent TFO connect without data",
                        self.peer_addr,
                        target_addr
                    );
                }
            }
        }

        debug!(
            "established tcp tunnel {} <-> {} with {:?}",
            self.peer_addr,
            target_addr,
            self.context.connect_opts_ref()
        );

        match copy_encrypted_bidirectional(self.method, &mut self.stream, &mut remote_stream).await {
            Ok((rn, wn)) => {
                trace!(
                    "tcp tunnel {} <-> {} closed, L2R {} bytes, R2L {} bytes",
                    self.peer_addr,
                    target_addr,
                    rn,
                    wn
                );
            }
            Err(err) => {
                trace!(
                    "tcp tunnel {} <-> {} closed with error: {}",
                    self.peer_addr,
                    target_addr,
                    err
                );
            }
        }

        Ok(())
    }
}
<commit_msg>apply timeout on server handshake<commit_after>//! Shadowsocks TCP server

use std::{
    future::Future,
    io::{self, ErrorKind},
    net::SocketAddr,
    sync::Arc,
    time::Duration,
};

use log::{debug, error, info, trace, warn};
use shadowsocks::{
    crypto::CipherKind,
    net::{AcceptOpts, TcpStream as OutboundTcpStream},
    relay::tcprelay::{utils::copy_encrypted_bidirectional, ProxyServerStream},
    ProxyListener,
    ServerConfig,
};
use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    net::TcpStream as TokioTcpStream,
    time,
};

use crate::net::{utils::ignore_until_end, MonProxyStream};

use super::context::ServiceContext;

pub struct TcpServer {
    context: Arc<ServiceContext>,
    accept_opts: AcceptOpts,
}

impl TcpServer {
    pub fn new(context: Arc<ServiceContext>, accept_opts: AcceptOpts) -> TcpServer {
        TcpServer { context, accept_opts }
    }

    pub async fn run(self, svr_cfg: &ServerConfig) -> io::Result<()> {
        let listener = ProxyListener::bind_with_opts(self.context.context(), svr_cfg, self.accept_opts).await?;

        info!(
            "shadowsocks tcp server listening on {}, inbound address {}",
            listener.local_addr().expect("listener.local_addr"),
            svr_cfg.addr()
        );

        loop {
            let flow_stat = self.context.flow_stat();

            let (local_stream, peer_addr) =
                match listener.accept_map(|s| MonProxyStream::from_stream(s, flow_stat)).await {
                    Ok(s) => s,
                    Err(err) => {
                        error!("tcp server accept failed with error: {}", err);
                        time::sleep(Duration::from_secs(1)).await;
                        continue;
                    }
                };

            if self.context.check_client_blocked(&peer_addr) {
                warn!("access denied from {} by ACL rules", peer_addr);
                continue;
            }

            let client = TcpServerClient {
                context: self.context.clone(),
                method: svr_cfg.method(),
                peer_addr,
                stream: local_stream,
                timeout: svr_cfg.timeout(),
            };

            tokio::spawn(async move {
                if let Err(err) = client.serve().await {
                    debug!("tcp server stream aborted with error: {}", err);
                }
            });
        }
    }
}

#[inline]
async fn timeout_fut<F, R>(duration: Option<Duration>, f: F) -> io::Result<R>
where
    F: Future<Output = io::Result<R>>,
{
    match duration {
        None => f.await,
        Some(d) => match time::timeout(d, f).await {
            Ok(o) => o,
            Err(..) => Err(ErrorKind::TimedOut.into()),
        },
    }
}

struct TcpServerClient {
    context: Arc<ServiceContext>,
    method: CipherKind,
    peer_addr: SocketAddr,
    stream: ProxyServerStream<MonProxyStream<TokioTcpStream>>,
    timeout: Option<Duration>,
}

impl TcpServerClient {
    async fn serve(mut self) -> io::Result<()> {
        // let target_addr = match Address::read_from(&mut self.stream).await {
        let target_addr = match timeout_fut(self.timeout, self.stream.handshake()).await {
            Ok(a) => a,
            // Err(Socks5Error::IoError(ref err)) if err.kind() == ErrorKind::UnexpectedEof => {
            //     debug!(
            //         "handshake failed, received EOF before a complete target Address, peer: {}",
            //         self.peer_addr
            //     );
            //     return Ok(());
            // }
            Err(err) if err.kind() == ErrorKind::UnexpectedEof => {
                debug!(
                    "handshake failed, received EOF before a complete target Address, peer: {}",
                    self.peer_addr
                );
                return Ok(());
            }
            Err(err) if err.kind() == ErrorKind::TimedOut => {
                debug!(
                    "handshake failed, timeout before a complete target Address, peer: {}",
                    self.peer_addr
                );
                return Ok(());
            }
            Err(err) => {
                // https://github.com/shadowsocks/shadowsocks-rust/issues/292
                //
                // Keep connection open. Except AEAD-2022
                warn!(
                    "handshake failed, maybe wrong method or key, or under replay attacks. peer: {}, error: {}",
                    self.peer_addr, err
                );

                #[cfg(feature = "aead-cipher-2022")]
                if self.method.is_aead_2022() {
                    // Set SO_LINGER(0) for misbehave clients, which will eventually receive RST. (ECONNRESET)
                    // This will also prevent the socket entering TIME_WAIT state.

                    let stream = self.stream.into_inner().into_inner();
                    let _ = stream.set_linger(Some(Duration::ZERO));

                    return Ok(());
                }

                // Unwrap and get the plain stream.
                // Otherwise it will keep reporting decryption error before reaching EOF.
                //
                // Note: This will drop all data in the decryption buffer, which is no going back.
                let mut stream = self.stream.into_inner();

                let res = ignore_until_end(&mut stream).await;

                trace!(
                    "silent-drop peer: {} is now closing with result {:?}",
                    self.peer_addr,
                    res
                );

                return Ok(());
            }
        };

        trace!(
            "accepted tcp client connection {}, establishing tunnel to {}",
            self.peer_addr,
            target_addr
        );

        if self.context.check_outbound_blocked(&target_addr).await {
            error!(
                "tcp client {} outbound {} blocked by ACL rules",
                self.peer_addr, target_addr
            );
            return Ok(());
        }

        let mut remote_stream = match timeout_fut(
            self.timeout,
            OutboundTcpStream::connect_remote_with_opts(
                self.context.context_ref(),
                &target_addr,
                self.context.connect_opts_ref(),
            ),
        )
        .await
        {
            Ok(s) => s,
            Err(err) => {
                error!(
                    "tcp tunnel {} -> {} connect failed, error: {}",
                    self.peer_addr, target_addr, err
                );
                return Err(err);
            }
        };

        // https://github.com/shadowsocks/shadowsocks-rust/issues/232
        //
        // Protocols like FTP, clients will wait for servers to send Welcome Message without sending anything.
        //
        // Wait at most 500ms, and then sends handshake packet to remote servers.
        if self.context.connect_opts_ref().tcp.fastopen {
            let mut buffer = [0u8; 8192];
            match time::timeout(Duration::from_millis(500), self.stream.read(&mut buffer)).await {
                Ok(Ok(0)) => {
                    // EOF. Just terminate right here.
                    return Ok(());
                }
                Ok(Ok(n)) => {
                    // Send the first packet.
                    timeout_fut(self.timeout, remote_stream.write_all(&buffer[..n])).await?;
                }
                Ok(Err(err)) => return Err(err),
                Err(..) => {
                    // Timeout. Send handshake to server.
                    timeout_fut(self.timeout, remote_stream.write(&[])).await?;

                    trace!(
                        "tcp tunnel {} -> {} sent TFO connect without data",
                        self.peer_addr,
                        target_addr
                    );
                }
            }
        }

        debug!(
            "established tcp tunnel {} <-> {} with {:?}",
            self.peer_addr,
            target_addr,
            self.context.connect_opts_ref()
        );

        match copy_encrypted_bidirectional(self.method, &mut self.stream, &mut remote_stream).await {
            Ok((rn, wn)) => {
                trace!(
                    "tcp tunnel {} <-> {} closed, L2R {} bytes, R2L {} bytes",
                    self.peer_addr,
                    target_addr,
                    rn,
                    wn
                );
            }
            Err(err) => {
                trace!(
                    "tcp tunnel {} <-> {} closed with error: {}",
                    self.peer_addr,
                    target_addr,
                    err
                );
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_has_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap();
    let clippy_lints_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version);
    for package in &clippy_meta.packages[0].dependencies {
        if package.name == "clippy_lints" {
            assert!(package.req.matches(&clippy_lints_meta.packages[0].version));
            return;
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version
    // this way the rust-toolchain file version is honored
    let rustc_version = String::from_utf8(
        std::process::Command::new("rustc")
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<commit_msg>Use bootstrap rustc for versioncheck in Clippy<commit_after>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_has_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap();
    let clippy_lints_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version);
    for package in &clippy_meta.packages[0].dependencies {
        if package.name == "clippy_lints" {
            assert!(package.req.matches(&clippy_lints_meta.packages[0].version));
            return;
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version either from the rustc installed with the toolchain file or from
    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
    let rustc_version = String::from_utf8(
        std::process::Command::new(&rustc)
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<|endoftext|>