tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

net.rs (4770B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 use serde::Serialize;
      6 use std::{time, thread};
      7 use std::net::TcpStream;
      8 use tungstenite::{WebSocket, stream::MaybeTlsStream};
      9 use webrender_api::debugger::DebuggerMessage;
     10 
     11 // Network interfaces for interacting with a WR remote debugger instance
     12 
     13 // Simple HTTP connection used to issue most commands and queries
     14 pub struct HttpConnection {
     15    host: String,
     16 }
     17 
     18 impl HttpConnection {
     19    pub fn new(host: &str) -> Self {
     20        let host = format!("http://{}", host);
     21 
     22        HttpConnection {
     23            host,
     24        }
     25    }
     26 
     27    pub fn get(
     28        &mut self,
     29        endpoint: &str,
     30    ) -> Result<Option<String>, String> {
     31        self.get_with_query(
     32            endpoint,
     33            &[],
     34        )
     35    }
     36 
     37    pub fn get_with_query(
     38        &mut self,
     39        endpoint: &str,
     40        params: &[(&str, &str)],
     41    ) -> Result<Option<String>, String> {
     42        let url = format!("{}/{}", self.host, endpoint);
     43 
     44        match reqwest::blocking::Client::builder()
     45            .build()
     46            .expect("bug")
     47            .get(url)
     48            .query(params)
     49            .send() {
     50            Ok(response) => {
     51                let text = response.text().expect("no content");
     52                if text.is_empty() {
     53                    Ok(None)
     54                } else {
     55                    Ok(Some(text))
     56                }
     57            }
     58            Err(error) => {
     59                Err(error.to_string())
     60            }
     61        }
     62    }
     63 
     64    pub fn post_with_content<T: Serialize>(
     65        &mut self,
     66        endpoint: &str,
     67        content: &T,
     68    ) -> Result<Option<String>, String> {
     69        let url = format!("{}/{}", self.host, endpoint);
     70        let body = serde_json::to_string(content).expect("bug");
     71 
     72        match reqwest::blocking::Client::builder()
     73            .build()
     74            .expect("bug")
     75            .post(url)
     76            .body(body)
     77            .send() {
     78            Ok(response) => {
     79                let text = response.text().expect("no content");
     80                if text.is_empty() {
     81                    Ok(None)
     82                } else {
     83                    Ok(Some(text))
     84                }
     85            }
     86            Err(error) => {
     87                Err(error.to_string())
     88            }
     89        }
     90    }
     91 
     92    pub fn post(
     93        &mut self,
     94        endpoint: &str,
     95    ) -> Result<Option<String>, String> {
     96        self.post_with_content(
     97            endpoint,
     98            &"",
     99        )
    100    }
    101 }
    102 
    103 // Network events that can be received from the stream socket
    104 pub enum NetworkEvent {
    105    Connected,
    106    Disconnected,
    107    Message(DebuggerMessage),
    108 }
    109 
    110 pub struct NetworkEventStream;
    111 
    112 // Thread that connects to a WR instance and reads realtime updates as provided, such as
    113 // profiler updates, debug flag changes etc. The messages are pushed pushed via a callback.
    114 impl NetworkEventStream {
    115    pub fn spawn<F>(
    116        host: &str,
    117        callback: F,
    118    ) where
    119        F: Fn(NetworkEvent) + Send + 'static,
    120    {
    121        let host = host.to_string();
    122        let mut connection: Option<WebSocket<MaybeTlsStream<TcpStream>>> = None;
    123 
    124        loop {
    125            match connection {
    126                Some(ref mut socket) => {
    127                    match socket.read() {
    128                        Ok(msg) => {
    129                            let msg = match msg {
    130                                tungstenite::Message::Text(text) => text,
    131                                _ => todo!(),
    132                            };
    133                            let msg: DebuggerMessage = serde_json::from_str(msg.as_str()).expect("bug");
    134                            callback(NetworkEvent::Message(msg));
    135                        }
    136                        Err(..) => {
    137                            // Connection dropped
    138                            connection = None;
    139                            callback(NetworkEvent::Disconnected);
    140                        }
    141                    }
    142                }
    143                None => {
    144                    // Try connect
    145                    let uri = format!("ws://{}/debugger-socket", host);
    146                    match tungstenite::connect(uri) {
    147                        Ok((socket, _)) => {
    148                            // Connected
    149                            connection = Some(socket);
    150                            callback(NetworkEvent::Connected);
    151                        }
    152                        Err(..) => {
    153                            // Wait until try again
    154                            thread::sleep(time::Duration::new(1, 0));
    155                        }
    156                    }
    157                }
    158            }
    159        }
    160    }
    161 }