aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.rs
blob: f16a3c3142c4064cec57b6438365b6badbad3989 (plain)
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
use crate::connection::CraftConnection;
use crate::reader::CraftReader;
use crate::writer::CraftWriter;
use mcproto_rs::protocol::{PacketDirection, State};
use std::io::BufReader as StdBufReader;
use std::net::TcpStream;

#[cfg(any(feature = "futures-io", feature = "tokio-io"))]
use crate::{CraftAsyncReader, CraftAsyncWriter};

#[cfg(feature = "tokio-io")]
use tokio::{
    net::{
        TcpStream as TokioTcpStream,
        tcp::{
            OwnedReadHalf as TokioReadHalf,
            OwnedWriteHalf as TokioWriteHalf,
        },
        ToSocketAddrs as TokioToSocketAddrs,
    },
    io::{
        BufReader as TokioBufReader,
        Error as TokioIoError,
    },
};

pub const BUF_SIZE: usize = 8192;

pub type CraftTcpConnection = CraftConnection<StdBufReader<TcpStream>, TcpStream>;

impl CraftTcpConnection {
    pub fn connect_server_std<A>(to: A) -> Result<Self, std::io::Error> where A: std::net::ToSocketAddrs {
        Self::from_std(TcpStream::connect(to)?, PacketDirection::ClientBound)
    }

    pub fn wrap_client_stream_std(stream: TcpStream) -> Result<Self, std::io::Error> {
        Self::from_std(stream, PacketDirection::ServerBound)
    }

    pub fn from_std(
        s1: TcpStream,
        read_direction: PacketDirection,
    ) -> Result<Self, std::io::Error> {
        Self::from_std_with_state(s1, read_direction, State::Handshaking)
    }

    pub fn from_std_with_state(
        s1: TcpStream,
        read_direction: PacketDirection,
        state: State,
    ) -> Result<Self, std::io::Error> {
        let write = s1.try_clone()?;
        let read = StdBufReader::with_capacity(BUF_SIZE, s1);

        Ok(Self {
            reader: CraftReader::wrap_with_state(read, read_direction, state),
            writer: CraftWriter::wrap_with_state(write, read_direction.opposite(), state),
        })
    }
}

#[cfg(feature = "tokio-io")]
pub type CraftTokioConnection = CraftConnection<TokioBufReader<TokioReadHalf>, TokioWriteHalf>;

#[cfg(feature = "tokio-io")]
impl CraftTokioConnection {
    pub async fn connect_server_tokio<A>(
        to: A
    ) -> Result<Self, TokioIoError>
    where
        A: TokioToSocketAddrs
    {
        let conn = TokioTcpStream::connect(to).await?;
        conn.set_nodelay(true)?;
        let (reader, writer) = conn.into_split();
        let reader = TokioBufReader::with_capacity(BUF_SIZE, reader);
        Ok(Self::from_async((reader, writer), PacketDirection::ClientBound))
    }
}

#[cfg(feature = "tokio-io")]
pub type CraftUnbufferedTokioConnection = CraftConnection<TokioReadHalf, TokioWriteHalf>;

#[cfg(feature = "tokio-io")]
impl CraftUnbufferedTokioConnection {
    pub async fn connect_server_tokio_unbuffered<A>(
        to: A
    ) -> Result<Self, TokioIoError>
    where
        A: TokioToSocketAddrs
    {
        let conn = TokioTcpStream::connect(to).await?;
        conn.set_nodelay(true)?;

        Ok(Self::from_async(
            conn.into_split(),
            PacketDirection::ClientBound,
        ))
    }
}

#[cfg(any(feature = "futures-io", feature = "tokio-io"))]
impl<R, W> CraftConnection<R, W>
where
    CraftReader<R>: CraftAsyncReader,
    CraftWriter<W>: CraftAsyncWriter,
{
    pub fn from_async(tuple: (R, W), read_direction: PacketDirection) -> Self {
        Self::from_async_with_state(tuple, read_direction, State::Handshaking)
    }

    pub fn from_async_with_state(
        tuple: (R, W),
        read_direction: PacketDirection,
        state: State,
    ) -> Self {
        let (reader, writer) = tuple;
        Self {
            reader: CraftReader::wrap_with_state(reader, read_direction, state),
            writer: CraftWriter::wrap_with_state(writer, read_direction.opposite(), state),
        }
    }
}