-
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.
big refactor of serialization and more (#32)
* add field num_server_addresses to ConnectTokenClient * rename ConnectTokenClient to ConnectTokenPacket * add abstract type AbstractPacket * add compact get_serialized_size method for AbstractPacket * add a generic write method for AbstractPacket * remove older write method for ConnectionRequestPacket * create and write a ConnectTokenPacket as the response * add function write_fields * add function get_serialized_size_fields * add function get_padding_size * remove struct PaddedConnectToken * remove unused commented code * remove struct PaddedPrivateConnectToken * remove get_serialized_size and write methods for ConnectToken * store explicit fields in PrivateConnectToken * store explicit fields in PrivateConnectTokenAssociatedData * clean up associated data writing * remove struct EncryptedPrivateConnectToken * rename ConnectToken to ConnectTokenInfo and connect_token to connect_token_info * add convenient constructors for PrivateConnectToken and PrivateConnectTokenAssociatedData * clean up some stuff in ConnectTokenPacket constructor * add function encrypt * rename connect_token_client to connect_token_packet * just do a while !eof(io) instead of getting padding size and so on * remove get_padding_size function * update get_serialized_size method for PrivateConnectToken * no need of value in get_serialized_size method for ConnectTokenPacket * add functions write_fields_and_padding and get_serialize_data * add protocol_constants.jl and types.jl * rename SIZE_OF_PADDED_CONNECT_TOKEN to SIZE_OF_CONNECT_TOKEN_PACKET * rename PACKET_TYPE_CONNECTION_REQUEST to PACKET_TYPE_CONNECTION_REQUEST_PACKET * add SIZE_OF_KEY instead of SIZE_OF_CLIENT_TO_SERVER_KEY, SIZE_OF_SERVER_TO_CLIENT_KEY, AND SIZE_OF_SERVER_SIDE_SHARED_KEY * remove bunch of unused constants * rename MAX_GAME_SERVERS to MAX_NUM_SERVER_ADDRESSES * add serialization.jl * move try_read methods to serialization.jl * move a bunch of constructors and other methods to types.jl
- Loading branch information
1 parent
5982fa0
commit ae357ea
Showing
4 changed files
with
452 additions
and
604 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 |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Sockets | ||
|
||
const NETCODE_VERSION_INFO = Vector{UInt8}("NETCODE 1.02\0") | ||
const SIZE_OF_NETCODE_VERSION_INFO = length(NETCODE_VERSION_INFO) | ||
|
||
const TYPE_OF_PROTOCOL_ID = UInt64 | ||
|
||
const TYPE_OF_TIMESTAMP = UInt64 | ||
|
||
const TYPE_OF_TIMEOUT_SECONDS = UInt32 | ||
|
||
const TYPE_OF_CLIENT_ID = UInt64 | ||
|
||
const SIZE_OF_USER_DATA = 32 | ||
|
||
const SIZE_OF_NONCE = 24 | ||
|
||
const SIZE_OF_KEY = 32 | ||
|
||
const SIZE_OF_HMAC = 16 | ||
|
||
const SIZE_OF_ENCRYPTED_PRIVATE_CONNECT_TOKEN_DATA = 1024 | ||
|
||
const TYPE_OF_ADDRESS_TYPE = UInt8 | ||
const SIZE_OF_ADDRESS_TYPE = sizeof(TYPE_OF_ADDRESS_TYPE) | ||
|
||
const ADDRESS_TYPE_IPV4 = TYPE_OF_ADDRESS_TYPE(1) | ||
const TYPE_OF_IPV4_HOST = fieldtype(Sockets.IPv4, :host) | ||
const TYPE_OF_IPV4_PORT = fieldtype(Sockets.InetAddr{Sockets.IPv4}, :port) | ||
|
||
const ADDRESS_TYPE_IPV6 = TYPE_OF_ADDRESS_TYPE(2) | ||
const TYPE_OF_IPV6_HOST = fieldtype(Sockets.IPv6, :host) | ||
const TYPE_OF_IPV6_PORT = fieldtype(Sockets.InetAddr{Sockets.IPv6}, :port) | ||
|
||
const TYPE_OF_NUM_SERVER_ADDRESSES = UInt32 | ||
const MAX_NUM_SERVER_ADDRESSES = 32 | ||
|
||
const TYPE_OF_PACKET_TYPE = UInt8 | ||
|
||
const SIZE_OF_CONNECT_TOKEN_PACKET = 2048 | ||
|
||
const PACKET_TYPE_CONNECTION_REQUEST_PACKET = TYPE_OF_PACKET_TYPE(0) | ||
const SIZE_OF_CONNECTION_REQUEST_PACKET = 1078 |
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,223 @@ | ||
function get_serialized_size(value::Integer) | ||
if !isbits(value) | ||
error("Currently only isbits Integer values are supported for serialization") | ||
else | ||
return sizeof(value) | ||
end | ||
end | ||
|
||
get_serialized_size(value::Vector{UInt8}) = length(value) | ||
|
||
get_serialized_size(value::Union{Sockets.IPv4, Sockets.IPv6}) = get_serialized_size(value.host) | ||
|
||
get_serialized_size(value::Union{Sockets.InetAddr{Sockets.IPv4}, Sockets.InetAddr{Sockets.IPv6}}) = get_serialized_size(value.host) + sizeof(value.port) | ||
|
||
get_serialized_size(value::NetcodeInetAddr) = SIZE_OF_ADDRESS_TYPE + get_serialized_size(value.address) | ||
|
||
get_serialized_size(value::Vector{NetcodeInetAddr}) = sum(get_serialized_size, value) | ||
|
||
get_serialized_size_fields(value) = sum(get_serialized_size(getfield(value, i)) for i in 1:fieldcount(typeof(value))) | ||
|
||
get_serialized_size(::PrivateConnectToken) = SIZE_OF_ENCRYPTED_PRIVATE_CONNECT_TOKEN_DATA - SIZE_OF_HMAC | ||
|
||
get_serialized_size(value::PrivateConnectTokenAssociatedData) = get_serialized_size_fields(value) | ||
|
||
get_serialized_size(packet::AbstractPacket) = get_serialized_size_fields(packet) | ||
|
||
get_serialized_size(::ConnectTokenPacket) = SIZE_OF_CONNECT_TOKEN_PACKET | ||
|
||
function get_serialized_data(value) | ||
data = zeros(UInt8, get_serialized_size(value)) | ||
|
||
io = IOBuffer(data, write = true, maxsize = length(data)) | ||
|
||
num_bytes_written = write(io, value) | ||
|
||
@assert num_bytes_written == length(data) "$(num_bytes_written), $(length(data))" | ||
|
||
return data | ||
end | ||
|
||
function Base.write(io::IO, netcode_inetaddr::NetcodeInetAddr) | ||
n = 0 | ||
|
||
n += write(io, get_address_type(netcode_inetaddr)) | ||
n += write(io, netcode_inetaddr.address.host.host) | ||
n += write(io, netcode_inetaddr.address.port) | ||
|
||
return n | ||
end | ||
|
||
function Base.write(io::IO, netcode_addresses::Vector{NetcodeInetAddr}) | ||
n = 0 | ||
|
||
for netcode_address in netcode_addresses | ||
n += write(io, netcode_address) | ||
end | ||
|
||
return n | ||
end | ||
|
||
function write_fields(io::IO, value) | ||
n = 0 | ||
|
||
for i in 1:fieldcount(typeof(value)) | ||
n += write(io, getfield(value, i)) | ||
end | ||
|
||
return n | ||
end | ||
|
||
function write_fields_and_padding(io::IO, value) | ||
n = write_fields(io, value) | ||
|
||
serialized_size = get_serialized_size(value) | ||
|
||
padding_size = serialized_size - n | ||
|
||
for i in 1 : padding_size | ||
n += write(io, UInt8(0)) | ||
end | ||
|
||
return n | ||
end | ||
|
||
Base.write(io::IO, private_connect_token::PrivateConnectToken) = write_fields_and_padding(io, private_connect_token) | ||
|
||
Base.write(io::IO, private_connect_token_associated_data::PrivateConnectTokenAssociatedData) = write_fields(io, private_connect_token_associated_data) | ||
|
||
Base.write(io::IO, packet::AbstractPacket) = write_fields(io, packet) | ||
|
||
Base.write(io::IO, packet::ConnectTokenPacket) = write_fields_and_padding(io, packet) | ||
|
||
function try_read(io::IO, ::Type{NetcodeInetAddr}) | ||
address_type = read(io, TYPE_OF_ADDRESS_TYPE) | ||
|
||
if address_type == ADDRESS_TYPE_IPV4 | ||
host = Sockets.IPv4(read(io, TYPE_OF_IPV4_HOST)) | ||
port = read(io, TYPE_OF_IPV4_PORT) | ||
elseif address_type == ADDRESS_TYPE_IPV6 | ||
host = Sockets.IPv6(read(io, TYPE_OF_IPV6_HOST)) | ||
port = read(io, TYPE_OF_IPV6_PORT) | ||
else | ||
return nothing | ||
end | ||
|
||
return NetcodeInetAddr(Sockets.InetAddr(host, port)) | ||
end | ||
|
||
function try_read(data::Vector{UInt8}, ::Type{ConnectTokenPacket}) | ||
if length(data) != SIZE_OF_CONNECT_TOKEN_PACKET | ||
return nothing | ||
end | ||
|
||
io = IOBuffer(data) | ||
|
||
netcode_version_info = read(io, SIZE_OF_NETCODE_VERSION_INFO) | ||
if netcode_version_info != NETCODE_VERSION_INFO | ||
return nothing | ||
end | ||
|
||
protocol_id = read(io, TYPE_OF_PROTOCOL_ID) | ||
if protocol_id != PROTOCOL_ID | ||
return nothing | ||
end | ||
|
||
create_timestamp = read(io, TYPE_OF_TIMESTAMP) | ||
expire_timestamp = read(io, TYPE_OF_TIMESTAMP) | ||
if expire_timestamp < create_timestamp | ||
return nothing | ||
end | ||
|
||
nonce = read(io, SIZE_OF_NONCE) | ||
|
||
encrypted_private_connect_token_data = read(io, SIZE_OF_ENCRYPTED_PRIVATE_CONNECT_TOKEN_DATA) | ||
|
||
timeout_seconds = read(io, TYPE_OF_TIMEOUT_SECONDS) | ||
|
||
num_server_addresses = read(io, TYPE_OF_NUM_SERVER_ADDRESSES) | ||
if !(1 <= num_server_addresses <= MAX_NUM_SERVER_ADDRESSES) | ||
return nothing | ||
end | ||
|
||
netcode_addresses = NetcodeInetAddr[] | ||
|
||
for i in 1:num_server_addresses | ||
netcode_address = try_read(io, NetcodeInetAddr) | ||
if !isnothing(netcode_address) | ||
push!(netcode_addresses, netcode_address) | ||
else | ||
return nothing | ||
end | ||
end | ||
|
||
client_to_server_key = read(io, SIZE_OF_KEY) | ||
|
||
server_to_client_key = read(io, SIZE_OF_KEY) | ||
|
||
while !eof(io) | ||
x = read(io, UInt8) | ||
if x != 0 | ||
return nothing | ||
end | ||
end | ||
|
||
connect_token_packet = ConnectTokenPacket( | ||
netcode_version_info, | ||
protocol_id, | ||
create_timestamp, | ||
expire_timestamp, | ||
nonce, | ||
encrypted_private_connect_token_data, | ||
timeout_seconds, | ||
num_server_addresses, | ||
netcode_addresses, | ||
client_to_server_key, | ||
server_to_client_key, | ||
) | ||
|
||
return connect_token_packet | ||
end | ||
|
||
function try_read(data::Vector{UInt8}, ::Type{ConnectionRequestPacket}) | ||
if length(data) != SIZE_OF_CONNECTION_REQUEST_PACKET | ||
return nothing | ||
end | ||
|
||
io = IOBuffer(data) | ||
|
||
packet_type = read(io, TYPE_OF_PACKET_TYPE) | ||
if packet_type != PACKET_TYPE_CONNECTION_REQUEST_PACKET | ||
return nothing | ||
end | ||
|
||
netcode_version_info = read(io, SIZE_OF_NETCODE_VERSION_INFO) | ||
if netcode_version_info != NETCODE_VERSION_INFO | ||
return nothing | ||
end | ||
|
||
protocol_id = read(io, TYPE_OF_PROTOCOL_ID) | ||
if protocol_id != PROTOCOL_ID | ||
return nothing | ||
end | ||
|
||
expire_timestamp = read(io, TYPE_OF_TIMESTAMP) | ||
if expire_timestamp <= time_ns() | ||
return nothing | ||
end | ||
|
||
nonce = read(io, SIZE_OF_NONCE) | ||
|
||
encrypted_private_connect_token_data = read(io, SIZE_OF_ENCRYPTED_PRIVATE_CONNECT_TOKEN_DATA) | ||
|
||
connection_request_packet = ConnectionRequestPacket( | ||
packet_type, | ||
netcode_version_info, | ||
protocol_id, | ||
expire_timestamp, | ||
nonce, | ||
encrypted_private_connect_token_data, | ||
) | ||
|
||
return connection_request_packet | ||
end |
Oops, something went wrong.