1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
//! # Rust-engineio-client
//!
//! An implementation of a engine.io client written in the rust programming language. This implementation currently
//! supports revision 4 of the engine.io protocol. If you have any connection issues with this client,
//! make sure the server uses at least revision 4 of the engine.io protocol.
//!
//! ## Example usage
//!
//! ``` rust
//! use rust_engineio::{ClientBuilder, Client, packet::{Packet, PacketId}};
//! use url::Url;
//! use bytes::Bytes;
//!
//! // get a client with an `on_open` callback
//! let client: Client = ClientBuilder::new(Url::parse("http://localhost:4201").unwrap())
//! .on_open(|_| println!("Connection opened!"))
//! .build()
//! .expect("Creating client failed");
//!
//! // connect to the server
//! client.connect().expect("Connection failed");
//!
//! // create a packet, in this case a message packet and emit it
//! let packet = Packet::new(PacketId::Message, Bytes::from_static(b"Hello World"));
//! client.emit(packet).expect("Server unreachable");
//!
//! // disconnect from the server
//! client.disconnect().expect("Disconnect failed")
//! ```
//!
//! The main entry point for using this crate is the [`ClientBuilder`] which provides
//! the opportunity to define how you want to connect to a certain endpoint.
//! The following connection methods are available:
//! * `build`: Build websocket if allowed, if not fall back to polling. Standard configuration.
//! * `build_polling`: enforces a `polling` transport.
//! * `build_websocket_with_upgrade`: Build socket with a polling transport then upgrade to websocket transport (if possible).
//! * `build_websocket`: Build socket with only a websocket transport, crashes when websockets are not allowed.
//!
//!
//! ## Current features
//!
//! This implementation now supports all of the features of the engine.io protocol mentioned [here](https://github.com/socketio/engine.io-protocol).
//! This includes various transport options, the possibility of sending engine.io packets and registering the
//! commmon engine.io event callbacks:
//! * on_open
//! * on_close
//! * on_data
//! * on_error
//! * on_packet
//!
//! It is also possible to pass in custom tls configurations via the `TlsConnector` as well
//! as custom headers for the opening request.
//!
#![allow(clippy::rc_buffer)]
#![warn(clippy::complexity)]
#![warn(clippy::style)]
#![warn(clippy::perf)]
#![warn(clippy::correctness)]
/// A small macro that spawns a scoped thread. Used for calling the callback
/// functions.
macro_rules! spawn_scoped {
($e:expr) => {
crossbeam_utils::thread::scope(|s| {
s.spawn(|_| $e);
})
.unwrap();
};
}
mod callback;
pub mod client;
/// Generic header map
pub mod header;
pub mod packet;
pub(self) mod socket;
pub mod transport;
pub mod transports;
pub const ENGINE_IO_VERSION: i32 = 4;
/// Contains the error type which will be returned with every result in this
/// crate. Handles all kinds of errors.
pub mod error;
pub use client::{Client, ClientBuilder};
pub use error::Error;
pub use packet::{Packet, PacketId};
#[cfg(test)]
pub(crate) mod test {
use super::*;
use native_tls::TlsConnector;
const CERT_PATH: &str = "../ci/cert/ca.crt";
use native_tls::Certificate;
use std::fs::File;
use std::io::Read;
pub(crate) fn tls_connector() -> error::Result<TlsConnector> {
let cert_path = std::env::var("CA_CERT_PATH").unwrap_or_else(|_| CERT_PATH.to_owned());
let mut cert_file = File::open(cert_path)?;
let mut buf = vec![];
cert_file.read_to_end(&mut buf)?;
let cert: Certificate = Certificate::from_pem(&buf[..]).unwrap();
Ok(TlsConnector::builder()
// ONLY USE FOR TESTING!
.danger_accept_invalid_hostnames(true)
.add_root_certificate(cert)
.build()
.unwrap())
}
/// The `engine.io` server for testing runs on port 4201
const SERVER_URL: &str = "http://localhost:4201";
/// The `engine.io` server that refuses upgrades runs on port 4203
const SERVER_POLLING_URL: &str = "http://localhost:4203";
const SERVER_URL_SECURE: &str = "https://localhost:4202";
use url::Url;
pub(crate) fn engine_io_server() -> crate::error::Result<Url> {
let url = std::env::var("ENGINE_IO_SERVER").unwrap_or_else(|_| SERVER_URL.to_owned());
Ok(Url::parse(&url)?)
}
pub(crate) fn engine_io_polling_server() -> crate::error::Result<Url> {
let url = std::env::var("ENGINE_IO_POLLING_SERVER")
.unwrap_or_else(|_| SERVER_POLLING_URL.to_owned());
Ok(Url::parse(&url)?)
}
pub(crate) fn engine_io_server_secure() -> crate::error::Result<Url> {
let url = std::env::var("ENGINE_IO_SECURE_SERVER")
.unwrap_or_else(|_| SERVER_URL_SECURE.to_owned());
Ok(Url::parse(&url)?)
}
}