-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Uncle Jack <[email protected]>
- Loading branch information
1 parent
300034d
commit c743488
Showing
6 changed files
with
151 additions
and
2 deletions.
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.env | ||
/target | ||
/node_modules | ||
/.wrangler |
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 |
---|---|---|
|
@@ -3,4 +3,5 @@ use uuid::Uuid; | |
pub struct Config { | ||
pub uuid: Uuid, | ||
pub host: String, | ||
pub outbound: String, | ||
} |
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
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,4 @@ | ||
pub mod vless; | ||
pub mod vmess; | ||
pub use vless::*; | ||
pub use vmess::*; |
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,130 @@ | ||
use crate::config::Config; | ||
|
||
use std::pin::Pin; | ||
use std::task::{Context, Poll}; | ||
|
||
use bytes::{BufMut, BytesMut}; | ||
use futures_util::Stream; | ||
use pin_project_lite::pin_project; | ||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; | ||
use worker::*; | ||
|
||
pin_project! { | ||
pub struct VlessStream<'a> { | ||
pub config: Config, | ||
pub ws: &'a WebSocket, | ||
pub buffer: BytesMut, | ||
#[pin] | ||
pub events: EventStream<'a>, | ||
} | ||
} | ||
|
||
impl<'a> VlessStream<'a> { | ||
pub fn new(config: Config, ws: &'a WebSocket, events: EventStream<'a>) -> Self { | ||
let buffer = BytesMut::new(); | ||
|
||
Self { | ||
config, | ||
ws, | ||
buffer, | ||
events, | ||
} | ||
} | ||
|
||
pub async fn process(&mut self) -> Result<()> { | ||
// https://xtls.github.io/Xray-docs-next/en/development/protocols/vless.html | ||
// +------------------+-----------------+---------------------------------+---------------------------------+-------------+---------+--------------+---------+--------------+ | ||
// | 1 byte | 16 bytes | 1 byte | M bytes | 1 byte | 2 bytes | 1 byte | S bytes | X bytes | | ||
// +------------------+-----------------+---------------------------------+---------------------------------+-------------+---------+--------------+---------+--------------+ | ||
// | Protocol Version | Equivalent UUID | Additional Information Length M | Additional Information ProtoBuf | Instruction | Port | Address Type | Address | Request Data | | ||
// +------------------+-----------------+---------------------------------+---------------------------------+-------------+---------+--------------+---------+--------------+ | ||
|
||
// ignore protocl version | ||
self.read_u8().await?; | ||
|
||
// UUID | ||
let mut uuid = [0u8; 16]; | ||
self.read_exact(&mut uuid).await?; | ||
let uuid = uuid::Uuid::from_bytes(uuid); | ||
if self.config.uuid != uuid { | ||
return Err(Error::RustError("incorrect uuid".to_string())); | ||
} | ||
|
||
// additional information | ||
let len = self.read_u8().await?; | ||
let mut addon = vec![0u8; len as _]; | ||
self.read_exact(&mut addon).await?; | ||
|
||
// instruction | ||
self.read_u8().await?; | ||
|
||
// port | ||
let mut port = [0u8; 2]; | ||
self.read_exact(&mut port).await?; | ||
let port = u16::from_be_bytes(port); | ||
|
||
let addr = crate::common::parse_addr(self).await?; | ||
|
||
console_log!("connecting to upstream {}:{}", addr, port); | ||
let mut upstream = Socket::builder().connect(addr, port)?; | ||
|
||
// +-----------------------------------------------+------------------------------------+------------------------------------+---------------+ | ||
// | 1 Byte | 1 Byte | N Bytes | Y Bytes | | ||
// +-----------------------------------------------+------------------------------------+------------------------------------+---------------+ | ||
// | Protocol Version, consistent with the request | Length of additional information N | Additional information in ProtoBuf | Response data | | ||
// +-----------------------------------------------+------------------------------------+------------------------------------+---------------+ | ||
self.write(&[0u8; 2]).await?; // no additional information | ||
tokio::io::copy_bidirectional(self, &mut upstream).await?; | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
impl<'a> AsyncRead for VlessStream<'a> { | ||
fn poll_read( | ||
self: Pin<&mut Self>, | ||
cx: &mut Context<'_>, | ||
buf: &mut ReadBuf<'_>, | ||
) -> Poll<tokio::io::Result<()>> { | ||
let mut this = self.project(); | ||
|
||
loop { | ||
let size = std::cmp::min(this.buffer.len(), buf.remaining()); | ||
if size > 0 { | ||
buf.put_slice(&this.buffer.split_to(size)); | ||
return Poll::Ready(Ok(())); | ||
} | ||
|
||
match this.events.as_mut().poll_next(cx) { | ||
Poll::Ready(Some(Ok(WebsocketEvent::Message(msg)))) => { | ||
msg.bytes().iter().for_each(|x| this.buffer.put_slice(&x)); | ||
} | ||
Poll::Pending => return Poll::Pending, | ||
_ => return Poll::Ready(Ok(())), | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl<'a> AsyncWrite for VlessStream<'a> { | ||
fn poll_write( | ||
self: Pin<&mut Self>, | ||
_: &mut Context<'_>, | ||
buf: &[u8], | ||
) -> Poll<tokio::io::Result<usize>> { | ||
return Poll::Ready( | ||
self.ws | ||
.send_with_bytes(buf) | ||
.map(|_| buf.len()) | ||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())), | ||
); | ||
} | ||
|
||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<tokio::io::Result<()>> { | ||
Poll::Ready(Ok(())) | ||
} | ||
|
||
fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<tokio::io::Result<()>> { | ||
unimplemented!() | ||
} | ||
} |
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