Skip to main content

orinium_browser/platform/network/
mod.rs

1//! Network processing module, providing HTTP communication, cache, and cookie management.
2
3pub mod cache;
4pub mod config;
5pub mod cookie_store;
6mod core;
7pub mod error;
8pub mod sender_pool;
9
10pub use cache::Cache;
11pub use config::NetworkConfig;
12pub use cookie_store::CookieStore;
13pub use core::{Response, StatusCode};
14pub use error::NetworkError;
15pub use hyper::http::Request;
16use ipc_channel::IpcError;
17pub use sender_pool::HostKey;
18pub use sender_pool::{HttpSender, SenderPool};
19
20use serde::{Deserialize, Serialize};
21
22use core::AsyncNetworkCore;
23
24use crate::ParentChannels;
25use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
26use std::{env, io, process};
27
28#[derive(Deserialize, Serialize)]
29pub enum NetworkCommand {
30    Fetch { url: String, msg_id: usize },
31    SetConfig(NetworkConfig),
32}
33
34#[derive(Deserialize, Serialize)]
35pub struct NetworkMessage {
36    pub msg_id: usize,
37    pub response: Result<Response, NetworkError>,
38}
39
40pub struct NetworkCore {
41    cmd_tx: IpcSender<NetworkCommand>,
42    msg_rx: IpcReceiver<NetworkMessage>, // UI スレッド用
43}
44
45impl Default for NetworkCore {
46    fn default() -> Self {
47        Self::new().unwrap()
48    }
49}
50
51impl NetworkCore {
52    pub fn new() -> Result<Self, io::Error> {
53        let (server, server_name) =
54            IpcOneShotServer::<ParentChannels<NetworkCommand, NetworkMessage>>::new()?;
55
56        process::Command::new(env::current_exe()?)
57            .arg("--child")
58            .arg(&server_name)
59            .arg("--type=network")
60            .spawn()?;
61
62        let (_, channels) = server.accept().unwrap();
63
64        Ok(Self {
65            cmd_tx: channels.cmd_tx,
66            msg_rx: channels.msg_rx,
67        })
68    }
69
70    pub fn set_network_config(&self, cfg: NetworkConfig) {
71        let _ = self.cmd_tx.send(NetworkCommand::SetConfig(cfg));
72    }
73
74    /// 非同期送信のみ。結果は try_receive で取得
75    pub fn fetch_async(&self, url: String, msg_id: usize) {
76        let _ = self.cmd_tx.send(NetworkCommand::Fetch { url, msg_id });
77    }
78
79    /// UIスレッドから呼ぶ: 完了しているメッセージを取り込む
80    pub fn try_receive(&self) -> Vec<NetworkMessage> {
81        let mut msgs = Vec::new();
82        while let Ok(msg) = self.msg_rx.try_recv() {
83            log::info!("NetworkCore: received message for msg_id={}", msg.msg_id);
84            msgs.push(msg);
85        }
86        msgs
87    }
88
89    pub fn fetch_blocking(&self, url: &str) -> Result<Response, NetworkError> {
90        self.fetch_async(url.to_string(), 0);
91        loop {
92            if let Some(v) = self.try_receive().into_iter().next() {
93                return v.response;
94            }
95            std::thread::yield_now();
96        }
97    }
98}
99
100/// ネットワークプロセスエントリ
101pub fn network_main(rx: IpcReceiver<NetworkCommand>, tx: IpcSender<NetworkMessage>) -> ! {
102    let mut core = AsyncNetworkCore::new();
103
104    while let Ok(cmd) = rx.recv() {
105        match cmd {
106            NetworkCommand::SetConfig(cfg) => core.set_network_config(cfg),
107            NetworkCommand::Fetch { url, msg_id } => {
108                let res = core.fetch_blocking(&url);
109                log::info!("NetworkCore: fetched URL for msg_id={}", msg_id);
110                let _ = tx.send(NetworkMessage {
111                    msg_id,
112                    response: res,
113                });
114            }
115        }
116    }
117
118    let err = rx.recv().err().unwrap();
119
120    if matches!(err, IpcError::Disconnected) {
121        log::info!(target: "network", "IPC channel closed, exiting normally.");
122        std::process::exit(0)
123    } else {
124        panic!("IPC channel unexpectedly closed: {err}")
125    }
126}