enet

Documentation
Login

ENet API

This CHICKEN module exposes a binding to the ENet network library for Scheme.

Synopsis

(import enet)

;; Client side
(define host (make-host))
(define peer (host-connect host #:address "localhost" #:port 1234))

(let loop ()
  (let ([event (host-service host 3)])
    (if event
      (case (car event)
        [(connect)
         (when (equal? (cadr event) peer)
           (peer-send peer "Hello world!" #:flags '(reliable)))
         (loop)]
        [(receive)
         (when (equal? (cadr event) peer)
           (display (packet->string (cadddr event)))
           (newline)
           (peer-disconnect peer))
         (loop)]
        [(disconnect)
         (unless (equal? (cadr event) peer)
           (loop))])
      (begin
        (print "... waiting ...")
        (loop)))))

;; Server side
(define host (make-host #:port 1234 #:max-peers 8))

(let loop ()
  (let ([event (host-service host 3)])
    (when event
      (case (car event)
        [(connect disconnect)
         => (lambda (kind)
              (let ([peer (cadr event)]
                    [data (caddr event)])
                (print kind " -- peer: " peer ", data: " data)))]
        [(receive)
         (let ([peer (cadr event)]
               [channel (caddr event)]
               [packet (cadddr event)])
           (print "receive -- peer: " peer ", channel: " channel)
           (peer-send peer
             (string-append "echo: " (packet->string packet))
             #:flags (packet-flags packet)
             #:channel channel))]))
      (loop)))

Host Management

(host? [v any/c]) → boolean?

Check whether a value is an ENet host.

(make-host #!key [address (or/c string? address-info? #f)] [port (or/c integer? #f)] [numeric? boolean?] [max-peers integer?] [channels integer?] [incoming integer?] [outgoing integer?]) → host?

Create a new ENet host at some network endpoint.

If address is not specified or #f, the procedure creates a host bound to a random network endpoint, suitable for use by a client.

If address is a host name or IP address and port a port number, or if address is an address-info object, the procedure creates a host bound to the specified network endpoint, suitable for use by a server. The numeric? argument is internally passed to the address-infos lookup function.

For a server host, max-peers would also normally be set to a value larger than one, which is the default.

The number of channels can be limited to a specific number or left at the maximum the library can support.

The incoming and outgoing network bandwidth can be limited to specific numbers of bytes/second or left unlimited.

(host-channels-limit! [host host?] #!optional [channels integer?]) → void?

Limit the maximum allowed channels of future incoming connections. If channels is not given, the limit is reset to the maximum the library can support.

(host-bandwidth-limit! [host host?] #!key [incoming integer?] [outgoing integer?]) → void?

Limit the bandwidth used by a host. If the incoming and/or outgoing network bandwidth are not given, the corresponding limit is removed.

(host-compress! [host host?] #!optional [compression symbol?]) → void?

Set the packet compression algorithm for the host. If the compression argument is omitted or the symbol 'range-coder, the default range coder is used for compression. If the argument is set to #f, no compression is used. Other options are currently not supported by this API.

Peer Management

(peer? [v any/c]) → boolean?

Check whether a value is an ENet peer.

(host-connect [host host?] #!key [address (or/c string? address-info? #f)] [port (or/c integer? #f)] [numeric? boolean?] [channels integer?] [cookie integer?]) → peer?

When address is a host name or IP address and port a port number, or when address is an address-info object, the procedure creates a new connection to the specified network endpoint. The numeric? argument is internally passed to the address-infos lookup function.

The number of channels requested for the connection can be specified explicitly but defaults to 1.

A numerical cookie may be passed to the server in the connection request.

(peer-disconnect [peer peer?] #!key [cookie integer?] [mode (or/c now later #f)]) → void?

Terminate communication with the given remote peer.

A numerical cookie may be passed to the server in the disconnect notification.

The mode argument controls how the connection is closed:

'now
The connection is immediately abandoned. No notification is sent and the server will only notice termination through a timeout.
'later
All pending packets for the connection are processed, then a disconnect notification is sent to the server. This procedure does not wait for connection termination, which will happen during a future call to host-service.
#f
Pending packets for the connection are discarded, but a disconnect notification is sent to the server. This procedure does not wait for connection termination, which will happen during a future call to host-service. This is the default behaviour.

(peer-address [peer peer?]) → address-info?

Retrieve an address-info object representing the network endpoint of the given remote peer.

(peer-channels [peer peer?]) → integer?

Retrieve the number of channels allocated for communication with the given remote peer.

(peer-bandwidth [peer peer?]) → (values/c integer? integer?)

Retrieve the current bandwidth statistics for communication with the given remote peer. Returns two values representing the average number of incoming and outgoing bytes/second.

(peer-packet-loss [peer peer?]) → rational?

Retrieve the current packet loss quota for communication with the given remote peer.

(peer-round-trip-time [peer peer?]) → real?

Retrieve the current mean packet roundtrip time in fractional seconds for communication with the given remote peer.

(peer-ping [peer peer?]) → void?

Send a ping to the given remote peer to keep the connection alive. Usually it is not necessary to invoke this procedure manually as pings are sent out automatically in regular intervals during calls to host-servicei f there is no data traffic.

(peer-ping-interval! [peer peer?] #!optional [interval real?]) → void?

Set the automatic ping interval for the given remote peer. The interval may be given as a fractional number of seconds. If no interval is specified, the library reverts to its automatic behaviour.

Packet Management

(packet? [v any/c]) → boolean?

Check whether a value is an ENet packet.

(make-packet [data (or/c string? u8vector? blob?)] #!optional [flags list?]) → packet?

Create a new ENet packet. Since peer-send and host-broadcast also accept packet data and flags directly for implicit conversion, it will often not be necessary to create a packet explicitly.

The data represented by the packet can be given as a string, byte vector or blob object. Note that the packet shares the underlying data storage with the scheme object!

The optional list of flags can contain any of the following symbols:

'reliable
Unreliable delivery is acceptable for the packet.
'unsequenced
Out of sequence delivery is acceptable for the packet.
'unreliable-fragment
If the packet has to be split into multiple fragments, unreliable delivery is acceptable for the fragments.

(packet-flags [packet packet?]) → list?

Retrieve the flags set for a given packet. The resulting list can contain any of the following symbols:

'reliable
Unreliable delivery is acceptable for the packet.
'unsequenced
Out of sequence delivery is acceptable for the packet.
'no-allocate
Memory management for the packet's data content is handled outside the ENet library.
'unreliable-fragment
If the packet has to be split into multiple fragments, unreliable delivery is acceptable for the fragments.
'sent
The packet has been sent from all queues it has been entered into.

(packet-length [packet packet?]) → integer?

Retrieve the number of data bytes contained in the given packet.

(packet-null? [packet packet?]) → boolean?

Check whether the given packet has empty data content.

(packet->string [packet packet?]) → string?

Convert the data content of the given packet into a string.

(packet->u8vector [packet packet?]) → u8vector?

Convert the data content of the given packet into a byte vector.

(packet->blob [packet packet?]) → blob?

Convert the data content of the given packet into a blob object.

(packet-input-port [packet packet?]) → input-port?

Create a new input port that reads from the data content of the given packet.

(call-with-input-packet [packet packet?] [read (-> input-port? T)] #!key [partial? boolean?] [null? boolean?]) → T

Create a new input port that reads from the data content of the given packet, then call the given reader procedure on that port. Returns whatever the reader procedure returns, but signals an error if the packet was not fully consumed or an end of file object was returned (unless instructed not to do so).

If partial? is given and not #f, no error is signalled if the packet was not fully consumed by the reader procedure.

If null? is given and not #f, no error is signalled if the reader returned an end of file object.

(with-input-from-packet [packet packet?] [read (-> T)] #!key [partial? boolean?] [null? boolean?]) → T

Create a new input port that reads from the data content of the given packet, then call the given reader procedure with no arguments in a dynamic environment where current-input-port is bound to that port. Returns whatever the reader procedure returns, but signals an error if the packet was not fully consumed or an end of file object was returned (unless instructed not to do so).

If partial? is given and not #f, no error is signalled if the packet was not fully consumed by the reader procedure.

If null? is given and not #f, no error is signalled if the reader returned an end of file object.

Communication Functions

(host-service [host host?] [timeout real?]) → (or/c list? #f)

Wait for events on the given host and shuttle packets between the host and its peers. This procedure will block for up to timeout fractional seconds and return one pending event, if any.

The events returned from this procedure have one of the following forms:

(connect PEER COOKIE)
(disconnect PEER COOKIE)
A peer has connected or disconnected from this host. PEER is an ENet peer object, and the COOKIE is the number passed to host-connect or peer-disconnect respectively.
(receive PEER CHANNEL PACKET)
A peer has sent a packet to this host. PEER is an ENet peer object, CHANNEL is the channel number passed to peer-send or host-broadcast, and PACKET is a packet object containing the data and flags.

(peer-send [peer peer?] [data (or/c packet? string? u8vector? blob?)] #!key [flags list?] [channel integer?]) → packet?

Queue a packet to be sent to the given remote peer. If the given data is not already a packet object, (make-packet data flags) is implicitly invoked to form a new packet. The procedure returns the packet that will be sent.

Optionally, the number of the channel on which the packet should be sent can be specified.

It is possible to determine whether the packet has already been sent by inspecting its flags.

(host-broadcast [host host?] [data (or/c packet? string? u8vector? blob?)] #!key [flags list?] [channel integer?]) → packet?

Queue a packet to be sent to all remote peers connected to the given host. If the given data is not already a packet object, (make-packet data flags) is implicitly invoked to form a new packet. The procedure returns the packet that will be sent.

Optionally, the number of the channel on which the packet should be sent can be specified.

It is possible to determine whether the packet has already been sent by inspecting its flags.

(host-flush [host host?]) → void?

Immediately sends all packets queued on the given host to their target remote peers. Usually it is not necessary to invoke this procedure manually as packets are dispatched automatically during calls to host-service.