├── shard.lock ├── src ├── enet │ ├── version.cr │ ├── server.cr │ ├── channel.cr │ ├── event.cr │ ├── address.cr │ ├── client.cr │ ├── packet.cr │ ├── host_service_loop.cr │ ├── host.cr │ ├── peer.cr │ └── lib_enet.cr └── enet.cr ├── .gitignore ├── shard.yml ├── samples ├── server.cr └── client.cr ├── README.md └── LICENSE /shard.lock: -------------------------------------------------------------------------------- 1 | version: 2.0 2 | shards: {} 3 | -------------------------------------------------------------------------------- /src/enet/version.cr: -------------------------------------------------------------------------------- 1 | module Enet 2 | VERSION = "0.1.1" 3 | end 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editors files 2 | *~ 3 | .#* 4 | 5 | # Our build stuff 6 | client 7 | server 8 | -------------------------------------------------------------------------------- /shard.yml: -------------------------------------------------------------------------------- 1 | name: enet 2 | version: 0.1.1 3 | 4 | authors: 5 | - Elthariel 6 | - Ivan "rndtrash" Kuzmenko 7 | 8 | crystal: ">= 1.0.0" 9 | 10 | license: MIT 11 | -------------------------------------------------------------------------------- /src/enet/server.cr: -------------------------------------------------------------------------------- 1 | # 2 | # High level server class 3 | # 4 | 5 | require "./host_service_loop" 6 | 7 | macro event_handler(name) 8 | def on_{{name.id}}(event) 9 | puts "Received a {{name}} event. Override #on_{{name.id}} to handle it" 10 | end 11 | end 12 | 13 | module Enet 14 | class Server < HostServiceLoop 15 | def on_event(event) 16 | end 17 | 18 | def on_none(event) 19 | puts "No event received within #{timeout}ms (#on_none). Retrying..." 20 | end 21 | 22 | event_handler :connect 23 | event_handler :disconnect 24 | event_handler :receive 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /samples/server.cr: -------------------------------------------------------------------------------- 1 | require "../src/enet" 2 | 3 | class MyServer < Enet::Server 4 | BANDWIDTH = 32_u32 * 1024 5 | 6 | def initialize 7 | super("0.0.0.0:42042", 32_u32, 32_u32, BANDWIDTH, BANDWIDTH) 8 | end 9 | 10 | def on_connect(event) 11 | puts "#{event.peer.to_s} connected" 12 | end 13 | 14 | def on_disconnected(event) 15 | puts "#{event.peer.to_s} connected" 16 | end 17 | 18 | def on_receive(event) 19 | puts "#{event.peer.to_s} received data" 20 | peer = event.peer 21 | 22 | unless peer.nil? 23 | peer.channel(0_u8).send("Pong") 24 | end 25 | end 26 | end 27 | 28 | Enet.init 29 | server = MyServer.new 30 | server.run 31 | Enet.deinit 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crystal binding of the ENet networking library 2 | 3 | ENet's purpose is to provide a relatively thin, simple and robust network communication layer on top of UDP (User Datagram Protocol).The primary feature it provides is optional reliable, in-order delivery of packets. 4 | 5 | See Enet's documentation here: http://enet.bespin.org/index.html 6 | 7 | ## Dependencies 8 | 9 | - libenet 10 | - pkg-config 11 | 12 | ### Install dependencies on Debian 13 | 14 | `apt-get install -y libenet pkg-config` 15 | 16 | ### Install dependencies on OSX 17 | 18 | `brew install libenet pkg-config` 19 | 20 | ## Run samples 21 | 22 | - `crystal samples/server.cr` 23 | - `crystal samples/client.cr localhost:42042` 24 | -------------------------------------------------------------------------------- /samples/client.cr: -------------------------------------------------------------------------------- 1 | require "../src/enet" 2 | 3 | if ARGV.size != 1 4 | puts "usage ./client host:port" 5 | exit 42 6 | end 7 | 8 | class MyClient < Enet::Client 9 | BANDWIDTH = 32_u32 * 1024 10 | 11 | def initialize(addr) 12 | super(addr, 32_u32, 32_u32, BANDWIDTH, BANDWIDTH) 13 | end 14 | 15 | # Calls when the receive call timesout, i.e. no event was received 16 | def on_none(event) 17 | if connected? 18 | puts "Sending a ping..." 19 | channel(0_u8).send("Ping") 20 | end 21 | end 22 | 23 | def on_receive(event) 24 | puts "Received a pong" 25 | end 26 | end 27 | 28 | Enet.init 29 | puts "Running Enet version: #{Enet.version}" 30 | client = MyClient.new(ARGV[0]) 31 | client.run 32 | Enet.deinit 33 | -------------------------------------------------------------------------------- /src/enet/channel.cr: -------------------------------------------------------------------------------- 1 | # 2 | # Represent a communication channel of a peer 3 | # 4 | 5 | module Enet 6 | class Channel 7 | def initialize(peer : Peer, channel : UInt8) 8 | @peer = peer 9 | @channel = channel 10 | end 11 | 12 | def send(*args) 13 | packet = Packet.new *args 14 | send packet 15 | end 16 | 17 | def send(packet : Packet) 18 | # Once a packet is sent, LibEnet own it and will free it 19 | packet.disown! 20 | 21 | # Send the packet 22 | LibEnet.enet_peer_send(@peer, @channel, packet) == 0 23 | end 24 | 25 | def receive 26 | packet = LibEnet.enet_peer_receive(@peer, @channel) 27 | 28 | Packet.new packet unless packet.null? 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /src/enet.cr: -------------------------------------------------------------------------------- 1 | # 2 | # Main module for Enet 3 | # 4 | 5 | require "./enet/*" 6 | 7 | module Enet 8 | extend self 9 | 10 | class Error < Exception 11 | end 12 | 13 | class FunctionError < Error 14 | def initialize(fun_name : String, msg : String = "error") 15 | super "#{fun_name}: #{msg}" 16 | end 17 | end 18 | 19 | class NullPointerError < Error 20 | end 21 | 22 | def self.init 23 | if LibEnet.enet_initialize != 0 24 | raise FunctionError.new("enet_initialize") 25 | end 26 | end 27 | 28 | def self.deinit 29 | LibEnet.enet_deinitialize 30 | end 31 | 32 | def self.version : String 33 | raw_version = LibEnet.enet_linked_version 34 | major = (raw_version & 0xFF0000) >> 16 35 | minor = (raw_version & 0xFF00) >> 8 36 | patch = raw_version & 0xFF 37 | 38 | "#{major}.#{minor}.#{patch}" 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Lion Tech Associates 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /src/enet/event.cr: -------------------------------------------------------------------------------- 1 | # 2 | # Enet's event class 3 | # 4 | 5 | require "./peer" 6 | 7 | macro event_type_query(name) 8 | def {{name.id}}? 9 | event_type == {{name}} 10 | end 11 | end 12 | 13 | module Enet 14 | class Event 15 | def initialize(event_ptr : LibEnet::Event*) 16 | @event = event_ptr 17 | 18 | raise NullPointerError.new if @event.null? 19 | end 20 | 21 | def peer : (Peer | Nil) 22 | Peer.new @event.value.peer unless @event.value.peer.null? 23 | end 24 | 25 | def channel_id 26 | @event.value.channel_id 27 | end 28 | 29 | def code 30 | @event.value.data 31 | end 32 | 33 | def event_type 34 | case @event.value.type 35 | when LibEnet::EventType::None 36 | :none 37 | when LibEnet::EventType::Connect 38 | :connect 39 | when LibEnet::EventType::Disconnect 40 | :disconnect 41 | when LibEnet::EventType::Receive 42 | :receive 43 | end 44 | end 45 | 46 | def to_s 47 | "Event##{event_type}:#{channel_id}:#{code}" 48 | end 49 | 50 | event_type_query :none 51 | event_type_query :connect 52 | event_type_query :disconnect 53 | event_type_query :receive 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /src/enet/address.cr: -------------------------------------------------------------------------------- 1 | # 2 | # Address class 3 | # 4 | 5 | module Enet 6 | class Address 7 | def initialize(host : String, port : UInt16) 8 | @addr = LibEnet::Address.new 9 | 10 | self.ip = host 11 | self.port = port 12 | end 13 | 14 | def initialize(host_and_port : String) 15 | @addr = LibEnet::Address.new 16 | 17 | split = host_and_port.split(":") 18 | raise "Use host:port format when creating an Address" if split.size != 2 19 | 20 | self.ip = split[0] 21 | self.port = split[1].to_u16 22 | 23 | puts "New address: #{to_s}" 24 | end 25 | 26 | def initialize(other : LibEnet::Address) 27 | @addr = other 28 | end 29 | 30 | def port 31 | @addr.port 32 | end 33 | 34 | def port=(value) 35 | @addr.port = value 36 | end 37 | 38 | def ip 39 | net_ip = @addr.host.dup 40 | bytes = pointerof(net_ip).as(UInt8*).to_slice(4) 41 | bytes.join(".") 42 | end 43 | 44 | def ip=(value : String) 45 | LibEnet.enet_address_set_host(pointerof(@addr), value.to_unsafe) 46 | end 47 | 48 | def to_s 49 | "#{ip}:#{port}" 50 | end 51 | 52 | def to_unsafe 53 | pointerof(@addr) 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /src/enet/client.cr: -------------------------------------------------------------------------------- 1 | # 2 | # High-level ENet client class. Subclass your own 3 | # 4 | 5 | require "./host_service_loop" 6 | 7 | module Enet 8 | class Client < HostServiceLoop 9 | alias State = LibEnet::PeerState 10 | 11 | @peer = uninitialized Peer 12 | @connected = false 13 | 14 | def initialize(address : String, 15 | peers : UInt32 = 32_u32, 16 | channels : UInt32 = 32_u32, 17 | down_bw : UInt32 = 64_u32 * 1024 / 8, 18 | up_bw : UInt32 = 16_u32 * 1024 / 8) 19 | super nil, peers, channels, down_bw, up_bw 20 | 21 | addr = Address.new(address) 22 | peer = @host.connect(addr, channels.to_u64) 23 | if peer.nil? 24 | raise NullPointerError.new "Host.connect" 25 | else 26 | @peer = peer 27 | end 28 | end 29 | 30 | def connected? 31 | @connected 32 | end 33 | 34 | def on_event(event) 35 | end 36 | 37 | def on_connect(event) 38 | puts "Enet::Client: Connection established." 39 | @connected = true 40 | end 41 | 42 | def on_disconnect(event) 43 | puts "Enet::Client: Connection closed." 44 | @connected = false 45 | end 46 | 47 | def on_receive(event) 48 | puts "Received data from server. Handle it by overriding #on_receive" 49 | end 50 | 51 | def on_none(event) 52 | end 53 | 54 | def channel(id) 55 | @peer.channel(id) 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /src/enet/packet.cr: -------------------------------------------------------------------------------- 1 | # 2 | # ENet's Packet class 3 | # 4 | 5 | module Enet 6 | class Packet 7 | alias Flag = LibEnet::PacketFlag 8 | 9 | def initialize(ptr : Void*, size : LibC::SizeT, 10 | flags : UInt32 = Flag::Reliable.value) 11 | @owned = true 12 | @packet = LibEnet.enet_packet_create(ptr, size, flags) 13 | 14 | raise NullPointerError.new if @packet.null? 15 | end 16 | 17 | def initialize(bytes : Bytes, flags : UInt32 = Flag::Reliable.value) 18 | initialize(bytes.to_unsafe.as(Void*), bytes.size.to_u64, flags) 19 | end 20 | 21 | def initialize(str : String, flags : UInt32 = Flag::Reliable.value) 22 | initialize(str.to_slice, flags) 23 | end 24 | 25 | def initialize(packet : LibEnet::Packet*, owned = true) 26 | @owned = owned 27 | @packet = packet 28 | raise NullPointerError.new if @packet.null? 29 | end 30 | 31 | def finalize 32 | LibEnet.enet_packet_destroy(@packet) if @owned 33 | end 34 | 35 | def size 36 | @packet.value.size 37 | end 38 | 39 | def bytes 40 | Bytes.new(@packet.value.data, @packet.value.size) 41 | end 42 | 43 | def flag_enable(flag) 44 | @packet.value.flags |= flag 45 | end 46 | 47 | def flag_disable(flag) 48 | @packet.value.flags &= flag 49 | end 50 | 51 | def owned? 52 | @owned 53 | end 54 | 55 | def own! 56 | @onwed = true 57 | end 58 | 59 | def disown! 60 | @owned = false 61 | end 62 | 63 | def to_unsafe 64 | @packet 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /src/enet/host_service_loop.cr: -------------------------------------------------------------------------------- 1 | # 2 | # High level wrapper around the Host class providing a main loop 3 | # 4 | 5 | require "./host" 6 | 7 | module Enet 8 | abstract class HostServiceLoop 9 | @running = false 10 | 11 | def initialize(bind_addr : String?, 12 | max_peers : UInt32, 13 | max_chans : UInt32, 14 | down_bw : UInt32, 15 | up_bw : UInt32) 16 | if bind_addr.nil? 17 | addr = nil 18 | else 19 | addr = Address.new bind_addr 20 | end 21 | @host = Host.new(addr, max_peers, max_chans, down_bw, up_bw) 22 | end 23 | 24 | def running? 25 | @running 26 | end 27 | 28 | def stop 29 | @running = false 30 | end 31 | 32 | def timeout 33 | 500 34 | end 35 | 36 | def run 37 | @running = true 38 | 39 | puts "ENet main loop starting..." 40 | 41 | while @running 42 | @host.service(timeout) do |event| 43 | peer = event.peer 44 | 45 | on_event(event) 46 | case event.event_type 47 | when :connect 48 | on_connect(event) 49 | when :disconnect 50 | on_disconnect(event) 51 | when :receive 52 | on_receive(event) 53 | when :none 54 | on_none(event) 55 | end 56 | end 57 | end 58 | end 59 | 60 | # Called for every event (event the :none event) 61 | abstract def on_event(event) 62 | abstract def on_connect(event) 63 | abstract def on_disconnect(event) 64 | abstract def on_receive(event) 65 | abstract def on_none(event) 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /src/enet/host.cr: -------------------------------------------------------------------------------- 1 | # 2 | # Enet's Host class. Mostly a big wrapper around a socket :) 3 | # 4 | 5 | require "./peer" 6 | require "./event" 7 | 8 | module Enet 9 | class Host 10 | def initialize(bind_addr : Address? = nil, 11 | peers : UInt32 = 32_u32, 12 | channels : UInt32 = 32_u32, 13 | down_bandwidth : UInt32 = 64_u32 * 1024 / 8, 14 | up_bandwidth : UInt32 = 16_u32 * 1024 / 8) 15 | @addr = bind_addr 16 | @peers = peers 17 | @channels = channels 18 | @down_bandwidth = down_bandwidth 19 | @up_bandwidth = up_bandwidth 20 | 21 | if bind_addr.nil? 22 | addr = Pointer(LibEnet::Address).null 23 | else 24 | addr = bind_addr.to_unsafe 25 | end 26 | @host = LibEnet.enet_host_create(addr, peers, channels, 27 | down_bandwidth, up_bandwidth) 28 | raise NullPointerError.new("enet_host_create") if @host.null? 29 | end 30 | 31 | def flush 32 | LibEnet.enet_host_flush(@host) 33 | end 34 | 35 | def service(timeout = 1000) 36 | result = LibEnet.enet_host_service(@host, out event, timeout) 37 | unless event.peer.null? 38 | # puts event.peer.value.inspect 39 | end 40 | 41 | yield Enet::Event.new(pointerof(event)) 42 | result > 0 43 | end 44 | 45 | def connect(address : Address, 46 | channels : LibC::SizeT = 32_u64, 47 | data : UInt32 = 0_u32) : Peer 48 | res = LibEnet.enet_host_connect(@host, address, channels, data) 49 | 50 | raise NullPointerError.new("enet_host_connect") if res.null? 51 | Peer.new res 52 | end 53 | 54 | def finalize 55 | LibEnet.enet_host_destroy(@host) 56 | @host = Pointer(LibEnet::Host).null 57 | end 58 | 59 | def to_unsafe 60 | @host 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /src/enet/peer.cr: -------------------------------------------------------------------------------- 1 | # 2 | # The Peer class 3 | # 4 | 5 | require "./channel" 6 | 7 | module Enet 8 | class Peer 9 | def initialize(peer_ptr : LibEnet::Peer*) 10 | @peer = peer_ptr 11 | raise Enet::NullPointerError.new if @peer.null? 12 | end 13 | 14 | # 15 | # Library functions calls 16 | # 17 | def ping 18 | LibEnet.enet_peer_ping(@peer) 19 | end 20 | 21 | def ping_interval(interval) 22 | LibEnet.enet_peer_ping_interval(@peer, interval) 23 | end 24 | 25 | def timeout(limit, min, max) 26 | LibEnet.enet_peer_timeout(@peer, limit, min, max) 27 | end 28 | 29 | def disconnect(code) 30 | LibEnet.enet_peer_disconnect(@peer, code) 31 | end 32 | 33 | def disconnect_later(code) 34 | LibEnet.enet_peer_disconnect_later(@peer, code) 35 | end 36 | 37 | def disconnect_now(code) 38 | LibEnet.enet_peer_disconnect_now(@peer, code) 39 | end 40 | 41 | def reset! 42 | LibEnet.enet_peer_reset(@peer) 43 | end 44 | 45 | def channel(id : UInt8 = 0) 46 | Channel.new(self, id) 47 | end 48 | 49 | # 50 | # Accessors 51 | # 52 | def address 53 | Address.new(@peer.value.address) 54 | end 55 | 56 | def state 57 | case @peer.value.state 58 | when LibEnet::PeerState::Disconnected 59 | :disconnected 60 | when LibEnet::PeerState::Connecting 61 | :connecting 62 | when LibEnet::PeerState::AckConnect 63 | :ack_connect 64 | when LibEnet::PeerState::ConnectionPending 65 | :connection_pending 66 | when LibEnet::PeerState::ConnectionSucceeded 67 | :connection_succeeded 68 | when LibEnet::PeerState::Connected 69 | :connected 70 | when LibEnet::PeerState::DisconnectLater 71 | :disconnect_later 72 | when LibEnet::PeerState::AckDisconnect 73 | :ack_disconnect 74 | when LibEnet::PeerState::Zombie 75 | :zombie 76 | end 77 | end 78 | 79 | def to_s 80 | "Peer:#{address.to_s}:#{state}" 81 | end 82 | 83 | def hexdump 84 | bytes = @peer.as(UInt8*).to_slice(sizeof(typeof(LibEnet::Peer))) 85 | bytes.hexdump 86 | end 87 | 88 | def to_unsafe 89 | @peer 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /src/enet/lib_enet.cr: -------------------------------------------------------------------------------- 1 | @[Link("enet")] 2 | lib LibEnet 3 | # Configuration constants 4 | HOST_RECEIVE_BUFFER_SIZE = 256 * 1024 5 | HOST_SEND_BUFFER_SIZE = 256 * 1024 6 | HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000 7 | HOST_DEFAULT_MTU = 1400 8 | HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024 9 | HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024 10 | 11 | PEER_DEFAULT_ROUND_TRIP_TIME = 500 12 | PEER_DEFAULT_PACKET_THROTTLE = 32 13 | PEER_PACKET_THROTTLE_SCALE = 32 14 | PEER_PACKET_THROTTLE_COUNTER = 7 15 | PEER_PACKET_THROTTLE_ACCELERATION = 2 16 | PEER_PACKET_THROTTLE_DECELERATION = 2 17 | PEER_PACKET_THROTTLE_INTERVAL = 5000 18 | PEER_PACKET_LOSS_SCALE = (1 << 16) 19 | PEER_PACKET_LOSS_INTERVAL = 10000 20 | PEER_WINDOW_SIZE_SCALE = 64 * 1024 21 | PEER_TIMEOUT_LIMIT = 32 22 | PEER_TIMEOUT_MINIMUM = 5000 23 | PEER_TIMEOUT_MAXIMUM = 30000 24 | PEER_PING_INTERVAL = 500 25 | PEER_UNSEQUENCED_WINDOWS = 64 26 | PEER_UNSEQUENCED_WINDOW_SIZE_DIV32 = 32 27 | PEER_UNSEQUENCED_WINDOW_SIZE = PEER_UNSEQUENCED_WINDOW_SIZE_DIV32 * 32 28 | PEER_FREE_UNSEQUENCED_WINDOWS = 32 29 | PEER_RELIABLE_WINDOWS = 16 30 | PEER_RELIABLE_WINDOW_SIZE = 0x1000 31 | PEER_FREE_RELIABLE_WINDOWS = 8 32 | 33 | # Enums 34 | enum EventType 35 | None 36 | Connect 37 | Disconnect 38 | Receive 39 | end 40 | 41 | enum PeerState 42 | Disconnected 43 | Connecting 44 | AckConnect 45 | ConnectionPending 46 | ConnectionSucceeded 47 | Connected 48 | DisconnectLater 49 | Disconnecting 50 | AckDisconnect 51 | Zombie 52 | end 53 | 54 | @[Flags] 55 | enum PacketFlag : UInt32 56 | Reliable = 1 << 0 57 | Unsequenced = 1 << 1 58 | NoAllocate = 1 << 2 59 | UnreliableFragment = 1 << 3 60 | Sent = 1 << 8 61 | end 62 | 63 | # Opaque types 64 | type List = Pointer(Void) 65 | type Host = Void 66 | 67 | # Structs 68 | struct ListNode 69 | next : Pointer(Void) 70 | prev : Pointer(Void) 71 | end 72 | 73 | struct Address 74 | host : UInt32 75 | port : UInt16 76 | end 77 | 78 | struct Channel 79 | out_reliable_seq : UInt16 80 | out_unreliable_seq : UInt16 81 | used_reliable_windows : UInt16 82 | reliable_windows : UInt16[PEER_RELIABLE_WINDOWS] 83 | in_reliable_seq : UInt16 84 | in_unreliable_seq : UInt16 85 | in_reliable_cmds : List 86 | in_unreliable_cmds : List 87 | end 88 | 89 | struct Peer 90 | dispatch_list : ListNode 91 | host : Pointer(Host) 92 | out_peer_id : UInt16 93 | in_peer_id : UInt16 94 | connect_id : UInt32 95 | out_session_id : UInt8 96 | in_session_id : UInt8 97 | address : Address 98 | data : Pointer(Void) 99 | state : PeerState 100 | channels : Pointer(Channel) 101 | channel_count : LibC::SizeT 102 | in_bandwidth : UInt32 103 | out_bandwidth : UInt32 104 | in_bandwidth_throttle_epoch : UInt32 105 | out_bandwidth_throttle_epoch : UInt32 106 | in_data_total : UInt32 107 | out_data_total : UInt32 108 | last_send_time : UInt32 109 | last_receive_time : UInt32 110 | next_timeout : UInt32 111 | earliest_timeout : UInt32 112 | packet_loss_epoch : UInt32 113 | packets_sent : UInt32 114 | packets_lost : UInt32 115 | packet_loss : UInt32 116 | packate_loss_variance : UInt32 117 | packet_throttle : UInt32 118 | packet_throttle_limit : UInt32 119 | packet_throttle_counter : UInt32 120 | packet_throttle_epoch : UInt32 121 | packet_throttle_acceleration : UInt32 122 | packet_throttle_decelaration : UInt32 123 | packet_throttle_interval : UInt32 124 | ping_interval : UInt32 125 | timeout_limit : UInt32 126 | timeout_min : UInt32 127 | timeout_max : UInt32 128 | last_rtt : UInt32 129 | lowest_rtt : UInt32 130 | last_rtt_variance : UInt32 131 | highest_rtt_variance : UInt32 132 | rtt : UInt32 133 | rtt_variance : UInt32 134 | mtu : UInt32 135 | window_size : UInt32 136 | reliable_data_in_transit : UInt32 137 | out_reliable_seq : UInt16 138 | acks : List 139 | sent_reliable_cmds : List 140 | sent_unreliable_cmds : List 141 | out_reliable_cmds : List 142 | out_unreliable_cmds : List 143 | dispatched_cmds : List 144 | needs_dispatch : Int32 145 | in_unseq_group : UInt16 146 | out_unseq_group : UInt16 147 | unseq_window : UInt32[PEER_UNSEQUENCED_WINDOW_SIZE_DIV32] 148 | event_data : UInt32 149 | total_waiting_data : LibC::SizeT 150 | end 151 | 152 | struct Packet 153 | data : Pointer(UInt8) 154 | size : LibC::SizeT 155 | flags : UInt32 156 | free_callback : Pointer(Void) -> Void 157 | reference_count : LibC::SizeT 158 | user_data : Pointer(Void) 159 | end 160 | 161 | struct Event 162 | type : EventType 163 | peer : Pointer(Peer) 164 | channel_id : UInt8 165 | data : UInt32 166 | packet : Pointer(Packet) 167 | end 168 | 169 | struct Buffer 170 | data : Pointer(Void) 171 | data_length : LibC::SizeT 172 | end 173 | 174 | HOST_ANY = 0 175 | HOST_BROADCAST = 0xFFFFFFFF 176 | PORT_ANY = 0 177 | 178 | # Global functions 179 | fun enet_initialize : Int32 180 | fun enet_deinitialize : Void 181 | fun enet_linked_version : UInt32 182 | 183 | # Address functions 184 | fun enet_address_get_host(Address*, LibC::Char*, LibC::SizeT) : Int32 185 | fun enet_address_get_host_ip(Address*, LibC::Char*, LibC::SizeT) : Int32 186 | fun enet_address_set_host(Address*, LibC::Char*) : Int32 187 | 188 | # Host functions 189 | fun enet_host_create(Address*, LibC::SizeT, LibC::SizeT, UInt32, UInt32) : Host* 190 | fun enet_host_destroy(Host*) : Void 191 | fun enet_host_flush(Host*) : Void 192 | fun enet_host_service(Host*, Event*, UInt32) : Int32 193 | fun enet_host_connect(Host*, Address*, LibC::SizeT, UInt32) : Pointer(Peer) 194 | fun enet_host_bandwidth_limit(Host*, UInt32, UInt32) 195 | fun enet_host_bandwidth_throttle(Host*) 196 | fun enet_host_broadcast(Host*, UInt8, Packet*) 197 | fun enet_host_channel_limit(Host*, LibC::SizeT) 198 | fun enet_host_check_events(Host*, Event*) : Int32 199 | 200 | # Peer functions 201 | fun enet_peer_send(Peer*, UInt8, Packet*) : Int32 202 | fun enet_peer_receive(Peer*, UInt8) : Pointer(Packet) 203 | fun enet_peer_ping(Peer*) 204 | fun enet_peer_ping_interval(Peer*, UInt32) 205 | fun enet_peer_timeout(Peer*, UInt32, UInt32, UInt32) 206 | fun enet_peer_reset(Peer*) 207 | fun enet_peer_reset_queues(Peer*) 208 | fun enet_peer_disconnect(Peer*, UInt32) 209 | fun enet_peer_disconnect_later(Peer*, UInt32) 210 | fun enet_peer_disconnect_now(Peer*, UInt32) 211 | fun enet_peer_throttle(Peer*, UInt32) : Int32 212 | 213 | # Packet functions 214 | fun enet_crc32(Buffer*, LibC::SizeT) : UInt32 215 | fun enet_packet_create(Void*, LibC::SizeT, UInt32) : Pointer(Packet) 216 | fun enet_packet_destroy(Packet*) 217 | fun enet_packet_resize(Packet*, LibC::SizeT) : Int32 218 | end 219 | --------------------------------------------------------------------------------