Add Connection trait and implement UnixConnection

This commit is contained in:
Patrick Auernig 2018-03-22 22:54:49 +01:00
parent 43c8a6af5f
commit 53bab6857e
6 changed files with 109 additions and 46 deletions

View File

@ -4,12 +4,13 @@ extern crate discord_rpc_client;
use simplelog::*;
use std::{thread, time};
use discord_rpc_client::Client as DiscordRPC;
use discord_rpc_client::UnixConnection as Connection;
fn main() {
TermLogger::init(LevelFilter::Debug, Config::default()).unwrap();
let mut drpc =
DiscordRPC::new(425407036495495169)
DiscordRPC::<Connection>::new(425407036495495169)
.and_then(|rpc| rpc.start())
.expect("Failed to start client");

View File

@ -1,26 +1,24 @@
use std::env;
use std::io::{Write, Read, Result};
use std::os::unix::net::UnixStream;
use std::time;
use std::fmt::Debug;
use models::{Message, Handshake, Payload};
use std::io::Result;
use connection::Connection;
use models::Handshake;
#[cfg(feature = "rich_presence")]
use models::{SetActivityArgs, SetActivity};
#[derive(Debug)]
pub struct Client {
pub struct Client<T>
where T: Connection
{
client_id: u64,
version: u32,
socket: UnixStream,
socket: T,
}
impl Client {
impl<T> Client<T>
where T: Connection
{
pub fn new(client_id: u64) -> Result<Self> {
let connection_name = Self::ipc_path();
let socket = UnixStream::connect(connection_name)?;
socket.set_write_timeout(Some(time::Duration::from_secs(30)))?;
socket.set_read_timeout(Some(time::Duration::from_secs(30)))?;
Ok(Self { version: 1, client_id, socket })
let socket = T::connect()?;
Ok(Self { version: 1, client_id, socket})
}
pub fn start(mut self) -> Result<Self> {
@ -33,7 +31,7 @@ impl Client {
where F: FnOnce(SetActivity) -> SetActivity
{
let args = SetActivityArgs::command(f(SetActivity::new()));
self.send(1, args)?;
self.socket.send(1, args)?;
Ok(())
}
@ -42,35 +40,7 @@ impl Client {
fn handshake(&mut self) -> Result<()> {
let client_id = self.client_id;
let version = self.version;
self.send(0, Handshake::new(client_id, version))?;
Ok(())
}
fn ipc_path() -> String {
let tmp = env::var("XDG_RUNTIME_DIR").unwrap_or("/tmp".into());
format!("{}/discord-ipc-0", tmp)
}
fn send<T>(&mut self, opcode: u32, payload: T) -> Result<()>
where T: Payload + Debug
{
debug!("payload: {:#?}", payload);
match Message::new(opcode, payload).encode() {
Err(why) => error!("{:?}", why),
Ok(bytes) => {
self.socket.write_all(bytes.as_ref())?;
debug!("sent opcode: {}", opcode);
self.receive()?;
}
};
Ok(())
}
fn receive(&mut self) -> Result<()> {
let mut buf: Vec<u8> = Vec::with_capacity(1024);
self.socket.read(buf.as_mut_slice())?;
debug!("{:?}", buf);
self.socket.send(0, Handshake::new(client_id, version))?;
Ok(())
}
}

15
src/connection/base.rs Normal file
View File

@ -0,0 +1,15 @@
use std::io::Result;
use std::marker::Sized;
use std::fmt::Debug;
use models::Payload;
pub trait Connection
where Self: Sized
{
fn connect() -> Result<Self>;
fn send<T>(&mut self, opcode: u32, payload: T) -> Result<()>
where T: Payload + Debug;
fn recv(&mut self) -> Result<Vec<u8>>;
}

8
src/connection/mod.rs Normal file
View File

@ -0,0 +1,8 @@
mod base;
#[cfg(unix)]
mod unix;
pub use self::base::Connection;
#[cfg(unix)]
pub use self::unix::UnixConnection;

65
src/connection/unix.rs Normal file
View File

@ -0,0 +1,65 @@
use std::os::unix::net::UnixStream;
use std::io::{Write, Read, Result};
use std::time;
use std::path::PathBuf;
use std::env;
use std::fmt::Debug;
use models::Payload;
use models::Message;
use super::base::Connection;
pub struct UnixConnection {
socket: UnixStream,
}
impl UnixConnection {
fn ipc_path() -> PathBuf {
let tmp = env::var("XDG_RUNTIME_DIR")
.or_else(|_| env::var("TMPDIR"))
.or_else(|_| {
match env::temp_dir().to_str() {
None => Err("Failed to convert temp_dir"),
Some(tmp) => Ok(tmp.to_string())
}
})
.unwrap_or("/tmp".to_string());
PathBuf::from(tmp)
}
fn socket_path(n: u8) -> PathBuf {
Self::ipc_path().join(format!("discord-ipc-{}", n))
}
}
impl Connection for UnixConnection {
fn connect() -> Result<Self> {
let connection_name = Self::socket_path(0);
let socket = UnixStream::connect(connection_name)?;
socket.set_write_timeout(Some(time::Duration::from_secs(30)))?;
socket.set_read_timeout(Some(time::Duration::from_secs(30)))?;
Ok(Self { socket })
}
fn send<T>(&mut self, opcode: u32, payload: T) -> Result<()>
where T: Payload + Debug
{
debug!("payload: {:#?}", payload);
match Message::new(opcode, payload).encode() {
Err(why) => error!("{:?}", why),
Ok(bytes) => {
self.socket.write_all(bytes.as_ref())?;
debug!("sent opcode: {}", opcode);
self.recv()?;
}
};
Ok(())
}
fn recv(&mut self) -> Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::with_capacity(1024);
self.socket.read(buf.as_mut_slice())?;
debug!("{:?}", buf);
Ok(buf)
}
}

View File

@ -12,8 +12,12 @@ extern crate uuid;
#[macro_use]
mod macros;
mod connection;
mod models;
pub mod client;
pub use models::prelude;
pub use client::Client;
pub use models::prelude;
#[cfg(unix)]
pub use connection::UnixConnection;