-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5670e3a
commit 9bf076d
Showing
5 changed files
with
286 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "pollws" | ||
version = "0.1.0" | ||
authors = ["Probable Basilisk"] | ||
|
||
[dependencies] | ||
url = "2.1.0" | ||
|
||
[dependencies.ws] | ||
version = "0.9.0" | ||
|
||
[lib] | ||
name = "pollws" | ||
crate-type = ["dylib"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,22 @@ | ||
# pollws | ||
Single DLL, C api, polling-based websocket client | ||
Single DLL, C api, polling-based websocket client. Basically | ||
a wrapper to the "ws" Rust library. | ||
|
||
## Warning | ||
This is probably the worst piece of Rust code ever written. | ||
|
||
## Building | ||
Assuming you're on a 64 bit machine, | ||
building for 64 bit: | ||
``` | ||
cargo build --release | ||
``` | ||
|
||
However to use this from a 32 bit Windows binary (e.g., Noita), | ||
you'll need to build for 32 bit: | ||
``` | ||
rustup target add i686-pc-windows-msvc | ||
cargo build --target=i686-pc-windows-msvc --release | ||
``` | ||
|
||
The resulting .dll will end up in `target/i686-pc-windows-msvc/release/pollws.dll`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
local ffi = ffi or _G.ffi or require("ffi") | ||
ffi.cdef[[ | ||
struct pollsocket* pollws_open(const char* url); | ||
void pollws_close(struct pollsocket* ctx); | ||
int pollws_status(struct pollsocket* ctx); | ||
void pollws_send(struct pollsocket* ctx, const char* msg); | ||
int pollws_poll(struct pollsocket* ctx); | ||
unsigned int pollws_get(struct pollsocket* ctx, char* dest, unsigned int dest_size); | ||
unsigned int pollws_pop(struct pollsocket* ctx, char* dest, unsigned int dest_size); | ||
]] | ||
|
||
local pollws = ffi.load("pollws") | ||
|
||
local socket_mt = {} | ||
function socket_mt:open(url, scratch_size) | ||
if self._socket then self:close() end | ||
if not scratch_size then scratch_size = 64000 end | ||
self._socket = pollws.pollws_open(url), | ||
self._scratch = ffi.new("int8_t[?]", scratch_size), | ||
self._scratch_size = scratch_size | ||
end | ||
function socket_mt:poll() | ||
if not self._socket then return end | ||
local msg_size = pollws.pollws_pop(self._socket, self._scratch, self._scratch_size) | ||
if msg_size > 0 then | ||
local smsg = ffi.string(self._scratch, msg_size) | ||
return smsg | ||
else | ||
return nil | ||
end | ||
end | ||
function socket_mt:send(msg) | ||
if not self._socket then return end | ||
pollws.pollws_send(self._socket, msg) | ||
end | ||
function socket_mt:close() | ||
pollws.pollws_close(self._socket) | ||
self._socket = nil | ||
end | ||
|
||
local function open(url, scratch_size) | ||
local socket = setmetatable({}, {__index = socket_mt}) | ||
socket:open(url, scratch_size) | ||
return socket | ||
end | ||
|
||
return {open = open, pollws = pollws} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include <stddef.h> | ||
|
||
typedef enum pollws_status_type | ||
{ | ||
CLOSED, | ||
OPENING, | ||
OPEN, | ||
ERROR, | ||
} pollws_status_t; | ||
|
||
typedef struct PollWSSocket PollWSSocket; | ||
|
||
PollWSSocket* pollws_open(const char* url); | ||
void pollws_close(PollWSSocket* ctx); | ||
pollws_status_t pollws_status(PollWSSocket* ctx); | ||
void pollws_send(PollWSSocket* ctx, const char* msg); | ||
int pollws_poll(PollWSSocket* ctx); | ||
unsigned int pollws_get(PollWSSocket* ctx, char* dest, unsigned int dest_size); | ||
unsigned int pollws_pop(PollWSSocket* ctx, char* dest, unsigned int dest_size); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
extern crate ws; | ||
extern crate url; | ||
|
||
use std::thread; | ||
use std::sync::mpsc::channel; | ||
//use libc::c_char; | ||
use std::os::raw::c_char; | ||
use std::ffi::CStr; | ||
|
||
#[repr(C)] | ||
#[derive(Copy, Clone)] | ||
pub enum PollWSStatus { | ||
CLOSED, | ||
OPENING, | ||
OPEN, | ||
ERROR, | ||
} | ||
|
||
// working version? | ||
|
||
enum SocketMessage { | ||
Connect, | ||
Disconnect, | ||
Message(ws::Message), | ||
} | ||
|
||
|
||
pub struct PollWSSocket { | ||
status: PollWSStatus, | ||
sender: ws::Sender, | ||
thread: Option<thread::JoinHandle<()>>, | ||
rx: std::sync::mpsc::Receiver<SocketMessage>, | ||
message: Option<ws::Message>, | ||
} | ||
|
||
impl PollWSSocket { | ||
fn poll(&mut self) -> bool { | ||
let mut got_message = false; | ||
while let Ok(msg) = self.rx.try_recv() { | ||
println!("We got a message!"); | ||
match msg { | ||
SocketMessage::Connect => { | ||
self.status = PollWSStatus::OPEN; | ||
}, | ||
SocketMessage::Disconnect => { | ||
self.status = PollWSStatus::CLOSED; | ||
break | ||
}, | ||
SocketMessage::Message(msg) => { | ||
self.message = Some(msg); | ||
got_message = true; | ||
break | ||
}, | ||
}; | ||
}; | ||
got_message | ||
} | ||
|
||
fn send(&mut self, msg: ws::Message) { | ||
match self.status { | ||
PollWSStatus::OPEN => self.sender.send(msg).unwrap_or_default(), | ||
_ => (), | ||
}; | ||
} | ||
|
||
fn close(&mut self) { | ||
match self.status { | ||
PollWSStatus::OPEN | PollWSStatus::OPENING => { | ||
self.sender.shutdown().unwrap_or_default(); | ||
self.status = PollWSStatus::CLOSED; | ||
}, | ||
_ => (), | ||
} | ||
if let Some(handle) = self.thread.take() { | ||
handle.join().unwrap_or_default(); | ||
}; | ||
} | ||
|
||
fn new(url: String) -> PollWSSocket { | ||
println!("Trying to make a socket!"); | ||
let (tx, rx) = channel(); | ||
let mut socket = ws::Builder::new().build(move |_| { | ||
tx.send(SocketMessage::Connect).unwrap_or_default(); | ||
println!("Sending the message that we connecte!"); | ||
let tx2 = tx.clone(); | ||
move |msg| { | ||
tx2.send(SocketMessage::Message(msg)).unwrap_or_default(); | ||
Ok(()) | ||
} | ||
}).unwrap(); | ||
let handle = socket.broadcaster(); | ||
let t = thread::spawn(move || { | ||
let actual_url = url::Url::parse(&url).unwrap(); | ||
match socket.connect(actual_url) { | ||
Ok(_) => { | ||
println!("So far so good!"); | ||
socket.run(); | ||
true | ||
}, | ||
Err(err) => { | ||
println!("Failed to create WebSocket due to: {:?}", err); | ||
false | ||
}, | ||
}; | ||
}); | ||
|
||
PollWSSocket { | ||
status: PollWSStatus::OPENING, | ||
sender: handle, | ||
thread: Some(t), | ||
rx: rx, | ||
message: None, | ||
} | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_open(url: *const c_char) -> *mut PollWSSocket { | ||
let url = unsafe { CStr::from_ptr(url).to_string_lossy().into_owned() }; | ||
Box::into_raw(Box::new(PollWSSocket::new(url))) | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_close(ctx: *mut PollWSSocket) { | ||
let ctx = unsafe{&mut *ctx}; | ||
ctx.close(); | ||
|
||
// take ownership and drop | ||
let b = unsafe{ Box::from_raw(ctx) }; | ||
drop(b); | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_status(ctx: *mut PollWSSocket) -> PollWSStatus { | ||
let ctx = unsafe{&*ctx}; | ||
ctx.status | ||
} | ||
|
||
// #[no_mangle] | ||
// pub extern fn pollws_send(ctx: *mut PollWSSocket, msg: *const u8, msg_len: u32) { | ||
// let ctx = unsafe{&mut *ctx}; | ||
// let bytes = unsafe { std::slice::from_raw_parts(msg, msg_len) }; | ||
// ctx.send(ws_msg); | ||
// } | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_send(ctx: *mut PollWSSocket, msg: *const c_char) { | ||
let ctx = unsafe{&mut *ctx}; | ||
let msg = unsafe { CStr::from_ptr(msg).to_string_lossy().into_owned() }; | ||
ctx.send(ws::Message::text(msg)); | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_poll(ctx: *mut PollWSSocket) -> bool { | ||
let ctx = unsafe{&mut *ctx}; | ||
ctx.poll() | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_get(ctx: *mut PollWSSocket, dest: *mut u8, dest_size: u32) -> u32 { | ||
let ctx = unsafe{&mut *ctx}; | ||
match ctx.message.take() { | ||
Some(msg) => { | ||
let ncopy = msg.len(); | ||
if ncopy < (dest_size as usize) { | ||
unsafe { | ||
std::ptr::copy_nonoverlapping(msg.into_data().as_ptr(), dest, ncopy); | ||
} | ||
ncopy as u32 | ||
} else { | ||
0 | ||
} | ||
}, | ||
None => 0, | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn pollws_pop(ctx: *mut PollWSSocket, dest: *mut u8, dest_size: u32) -> u32 { | ||
if pollws_poll(ctx) { | ||
pollws_get(ctx, dest, dest_size) | ||
} else { | ||
0 | ||
} | ||
} |