[enet-cvs] CVS: enet/docs FAQ.dox,NONE,1.1 design.dox,NONE,1.1 install.dox,NONE,1.1 license.dox,NONE,1.1 mainpage.dox,NONE,1.1 tutorial.dox,NONE,1.1

Brian Hook (ENet CVS) enet-discuss@lists.puremagic.com
Sat, 8 Mar 2003 16:56:31 -0700


Update of /home/enet/cvsroot/enet/docs
In directory sferik:/tmp/cvs-serv10499/docs

Added Files:
	FAQ.dox design.dox install.dox license.dox mainpage.dox 
	tutorial.dox 
Log Message:



--- NEW FILE: FAQ.dox ---
/**
 @page FAQ Frequently Answered Questions

@section Q1 Is ENet thread safe?

ENet does not use any significant global variables, the vast majority
of state is encapsulated in the ENetHost structure.  As such, as long
as the application guards access to this structure, then ENet should
operate fine in a multithreaded environment.
   
@section Q2 Isn't ENet just re-inventing TCP?!  What's the point?

In a perfect world, that would be true.  But as many have found, using
TCP either in lieu of or in conjunction with UDP can lead to all kinds
of nightmares.  TCP is a good, solid protocol, however it simply isn't
up to the task of real-time games.  Too much of TCP's implementation
dictates a policy that isn't practical for games.  If you want to use
TCP, then do so -- this library is for people that either don't want
to use TCP or have tried and ended up being discouraged with the
performance.

*/



--- NEW FILE: design.dox ---
/**
@page Features Features and Architecture

ENet evolved specifically as a UDP networking layer for the
multiplayer first person shooter Cube. Cube necessitated low latency
communcation with data sent out very frequently, so TCP was an
unsuitable choice due to its high latency and stream orientation. UDP,
however, lacks many sometimes necessary features from TCP such as
reliability, sequencing, unrestricted packet sizes, and connection
management. So UDP by itself was not suitable as a network protocol
either. No suitable freely available networking libraries existed at
the time of ENet's creation to fill this niche.

UDP and TCP could have been used together in Cube to benefit somewhat
from both of their features, however, the resulting combinations of
protocols still leaves much to be desired. TCP lacks multiple streams
of communication without resorting to opening many sockets and
complicates delineation of packets due to its buffering behavior. UDP
lacks sequencing, connection management, management of bandwidth
resources, and imposes limitations on the size of packets. A
significant investment is required to integrate these two protocols,
and the end result is worse off in features and performance than the
uniform protocol presented by ENet.

ENet thus attempts to address these issues and provide a single,
uniform protocol layered over UDP to the developer with the best
features of UDP and TCP as well as some useful features neither
provide, with a much cleaner integration than any resulting from a
mixture of UDP and TCP.

@section CM Connection Management

ENet provides a simple connection interface over which to communicate
with a foreign host. The liveness of the connection is actively
monitored by pinging the foreign host at frequent intervals, and also
monitors the network conditions from the local host to the foreign
host such as the mean round trip time and packet loss in this fashion.

@section Sequencing Sequencing
    
Rather than a single byte stream that complicates the delineation of
packets, ENet presents connections as multiple, properly sequenced
packet streams that simplify the transfer of various types of data.

ENet provides sequencing for all packets by assigning to to each sent
packet a sequence number that is incremented as packets are sent. ENet
guarentees that no packet with a higher sequence number will be
delivered before a packet with a higher sequence number, thus ensuring
packets are delivered exactly in the order they are sent.

For unreliable packets, ENet will simply discard the lower sequence
number packet if a packet with a higher sequence number has already
been delivered. This allows the packets to be dispatched immediately
as they arrive, and reduce latency of unreliable packets to an
absolute minimum.  For reliable packets, if a higher sequence number
packet arrives, but the preceding packets in the sequence have not yet
arrived, ENet will stall delivery of the higher sequence number
packets until its predecessors have arrived.

@section Channels Channels

Since ENet will stall delivery of reliable packets to ensure proper
sequencing, and consequently any packets of higher sequence number
whether reliable or unreliable, in the event the reliable packet's
predecessors have not yet arrived, this can introduce latency into the
delivery of other packets which may not need to be as strictly ordered
with respect to the packet that stalled their delivery.

To combat this latency and reduce the ordering restrictions on
packets, ENet provides multiple channels of communication over a given
connection.  Each channel is independently sequenced, and so the
delivery status of a packet in one channel will not stall the delivery
of other packets in another channel.

@section Reliability Reliability

ENet provides optional reliability of packet delivery by ensuring the
foreign host acknowledges receipt of all reliable packets. ENet will
attempt to resend the packet up to a reasonable amount of times, if no
acknowledgement of the packet's receipt happens within a specified
timeout. Retry timeouts are progressive and become more lenient with
every failed attempt to allow for temporary turbulence in network
conditions.

@section FaR Fragmentation and Reassembly

ENet will send and deliver packets regardless of size. Large packets
are fragmented into many smaller packets of suitable size, and
reassembled on the foreign host to recover the original packet for
delivery. The process is entirely transparent to the developer.

@section Aggregation Aggregation

ENet aggregates all protocol commands, including acknowledgements and
packet transfer, into larger protocol packets to ensure the proper
utilization of the connection and to limit the opportunities for
packet loss that might otherwise result in further delivery latency.

@section Adaptability Adaptability

ENet provides an in-flight data window for reliable packets to ensure
connections are not overwhelmed by volumes of packets. It also
provides a static bandwidth allocation mechanism to ensure the total
volume of packets sent and received to a host don't exceed the host's
capabilities. Further, ENet also provides a dynamic throttle that
responds to deviations from normal network connections to rectify
various types of network congestion by further limiting the volume of
packets sent.

@section Portability Portability
    
ENet works on Windows and any other Unix or Unix-like platform
providing a BSD sockets interface. The library has a small and stable
code base that can easily be extended to support other platforms and
integrates easily.  ENet makes no assumptions about the underlying
platform's endianess or word size.

@section Freedom Freedom

ENet demands no royalties and doesn't carry a viral license that would
restrict you in how you might use it in your programs. ENet is
licensed under a short-and-sweet MIT-style license, which gives you
the freedom to do anything you want with it (well, almost anything).

*/


--- NEW FILE: install.dox ---
/**
@page Installation Installation

ENet should be trivially simple to integrate with most applications.
First, make sure you download the latest source distribution here @ref
SourceDistro.

@section Unix Unix-like Operating Systems

[to be completed]

@subsection SolarisBSD Solaris and BSD

When building UDPLib under Solaris, you must specify the -lsocket and
-lnsl parameters to your compiler to ensure that the sockets library
is linked in.

@section Windows Microsoft Windows

Using MSVC 6 under Windows simply drag all the ENet source files into
your main project or, better yet, create a new static library project
and make your executable dependent (Project|Dependencies) on ENet.

@subsection DLL DLL

If you wish to build ENet as a DLL be sure to define ENET_DLL within
the project (Project Settings | Preprocessor) or, more invasively,
simply define ENET_DLL at the top of enet.h.

*/


--- NEW FILE: license.dox ---
/**
 @page License License
 
Copyright (c) 2002 Lee Salzman

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/


--- NEW FILE: mainpage.dox ---
/** @mainpage enet
 <center>http://enet.cubik.org</center>
 <hr>

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.

ENet is NOT intended to be a general purpose high level networking
library that handles authentication, lobbying, server discovery,
compression, encryption and other high level, often application level
or dependent tasks.

@ref Features

@ref SourceDistro

@ref Installation

@ref Tutorial

@ref MailingList

@ref Extending

@ref FAQ

@ref License

 */

/**
@page SourceDistro Source Distribution

You can retrieve the source to ENet by downloading it in either .zip
form, .tar.gz form, or accessing the cvs distribution directly.

The most recent CVS can be downloaded <a href="http://enet.cubik.org/download/enet.tar.gz">here</a>

To access ENet via anonymous CVS, you must use the CVSROOT
:pserver:anoncvs\@sferik.cubik.org:/home/enet/cvsroot with an empty
password.

@code
	$ cvs -z3 -d :pserver:anoncvs@sferik.cubik.org:/home/enet/cvsroot login
@endcode
	Hit the return key when prompted for a password.
@code
	$ cvs -z3 co -l .
	$ cvs -z3 co enet
@endcode

This will create a CVS directory in the current directory, and with
the second command will proceed to check the enet module out of CVS.
Any problems with CVS access or request for write access should be
sent via email to @ref MailingList.

*/

/**
@page Extending Extending and Modifying ENet

Since ENet is distributed in source form, you can easily extend and
modify it to suit your needs.  For example, some users prefer to use
their own memory management routines and can thus replace the
appropriate functions in memory.c

*/

/**
@page MailingList ENet Related Mailing Lists

The <a
href="http://lists.puremagic.com/mailman/listinfo/enet-discuss">
enet-discuss</a> list is for discussion of ENet, including bug reports
or feature requests.

The CVS commits are also sent to <a
href="http://lists.puremagic.com/mailman/listinfo/enet-cvs">enet-cvs</a>,
so feel free to subscribe if you want to keep up with the latest
developments.

*/

--- NEW FILE: tutorial.dox ---
/**
@page Tutorial Tutorial

@ref Initialization

@ref CreateServer

@ref CreateClient

@ref ManageHost

@ref SendingPacket

@ref Disconnecting

@ref Connecting

@section Initialization Initialization

Before using ENet, you must call enet_initialize() to initialize the
library. Upon program exit, you should call enet_deinitialize() so
that the library may clean up any used resources.

@code
int 
main (int argc, char ** argv) 
{
    if (enet_initialize () != 0)
    {
        fprintf (stderr, "An error occurred while initializing ENet.\n");
        return EXIT_FAILURE;
    }
    atexit (enet_deinitialize);
    ...
    ...
    ...
}
@endcode
        
@section CreateServer Creating an ENet server

Servers in ENet are constructed with enet_host_create(). You must
specify an address on which to receive data and new connections, as
well as the maximum allowable numbers of connected peers. You may
optionally specify the incoming and outgoing bandwidth of the server
in bytes per second so that ENet may try to statically manage
bandwidth resources among connected peers in addition to its dynamic
throttling algorithm; specifying 0 for these two options will cause
ENet to rely entirely upon its dynamic throttling algorithm to manage
bandwidth.

When done with a host, the host may be destroyed with
enet_host_destroy().  All connected peers to the host will be reset,
and the resources used by the host will be freed.

@code
    ENetAddress address;
    ENetHost * server;

    /* Bind the server to the default localhost.     */
    /* A specific host address can be specified by   */
    /* enet_address_set_host (& address, "x.x.x.x"); */

    address.host = ENET_HOST_ANY;
    /* Bind the server to port 1234. */
    address.port = 1234;

    server = enet_host_create (& address /* the address to bind the server host to */, 
                                 32      /* allow up to 32 clients and/or outgoing connections */,
                                  0      /* assume any amount of incoming bandwidth */,
                                  0      /* assume any amount of outgoing bandwidth */);
    if (server == NULL)
    {
        fprintf (stderr, 
                 "An error occurred while trying to create an ENet server host.\n");
        exit (EXIT_FAILURE);
    }
    ...
    ...
    ...
    enet_host_destroy(server);
@endcode

@section CreateClient Creating an ENet client

Clients in ENet are similarly constructed with enet_host_create() when
no address is specified to bind the host to. Bandwidth may be
specified for the client host as in the above example. The peer count
controls the maximum number of connections to other server hosts that
may be simultaneously open.

@code
    ENetHost * client;

    clienet = enet_host_create (NULL /* create a client host */,
                1 /* only allow 1 outgoing connection */,
                57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
                14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);

    if (client == NULL)
    {
        fprintf (stderr, 
                 "An error occurred while trying to create an ENet client host.\n");
        exit (EXIT_FAILURE);
    }
    ...
    ...
    ...
    enet_host_destroy(client);
@endcode

@section ManageHost Managing an ENet host

ENet uses a polled event model to notify the programmer of significant
events. ENet hosts are polled for events with enet_host_service(),
where an optional timeout value in milliseconds may be specified to
control how long ENet will poll; if a timeout of 0 is specified,
enet_host_service() will return immediately if there are no events to
dispatch. enet_host_service() will return 1 if an event was dispatched
within the specified timeout.

Currently there are only four types of significant events in ENet:

An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred
within the specified time limit. enet_host_service() will return 0
with this event.

An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client
host has connected to the server host or when an attempt to establish a 
connection with a foreign host has succeeded. Only the "peer" field of the 
event structure is valid for this event and contains the newly connected peer.

An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received
from a connected peer. The "peer" field contains the peer the packet was 
received from, "channelID" is the channel on which the packet was sent, and 
"packet" is the packet that was sent. The packet contained in the "packet" 
field must be destroyed with enet_packet_destroy() when you are done 
inspecting its contents.

An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer
has either explicitly disconnected or timed out. Only the "peer" field of the
event structure is valid for this event and contains the peer that 
disconnected. Only the "data" field of the peer is still valid on a 
disconnect event and must be explicitly reset.

@code
    ENetEvent event;
    
    /* Wait up to 1000 milliseconds for an event. */
    while (enet_host_service (client, & event, 1000) > 0)
    {
        switch (event.type)
        {
        case ENET_EVENT_TYPE_CONNECT:
            printf ("A new client connected from %x:%u.\n", 
                    event.peer -> address.host,
                    event.peer -> address.port);

            /* Store any relevant client information here. */
            event.peer -> data = "Client information";

            break;

        case ENET_EVENT_TYPE_RECEIVE:
            printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
                    event.packet -> dataLength,
                    event.packet -> data,
                    event.peer -> data,
                    event.channelID);

            /* Clean up the packet now that we're done using it. */
            enet_packet_destroy (event.packet);
            
            break;
           
        case ENET_EVENT_TYPE_DISCONNECT:
            printf ("%s disconected.\n", event.peer -> data);

            /* Reset the peer's client information. */

            event.peer -> data = NULL;
        }
    }
    ...
    ...
    ...
@endcode

@section SendingPacket Sending a packet to an ENet peer            

Packets in ENet are created with enet_packet_create(), where the size
of the packet must be specified. Optionally, initial data may be
specified to copy into the packet.

Certain flags may also be supplied to enet_packet_create() to control
various packet features:

ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable
delivery.  A reliable packet is guarenteed to be delivered, and a
number of retry attempts will be made until an acknowledgement is
received from the foreign host the packet is sent to. If a certain
number of retry attempts is reached without any acknowledgement, ENet
will assume the peer has disconnected and forcefully reset the
connection. If this flag is not specified, the packet is assumed an
unreliable packet, and no retry attempts will be made nor
acknowledgements generated.

A packet may be resized (extended or truncated) with
enet_packet_resize().

A packet is sent to a foreign host with
enet_peer_send(). enet_peer_send() accepts a channel id over which to
send the packet to a given peer. Once the packet is handed over to
ENet with enet_peer_send(), ENet will handle its deallocation and
enet_packet_destroy() should not be used upon it.

One may also use enet_host_broadcast() to send a packet to all
connected peers on a given host over a specified channel id, as with
enet_peer_send().

Queued packets will be sent on a call to enet_host_service().
Alternatively, enet_host_flush() will send out queued packets without
dispatching any events.

@code
    /* Create a reliable packet of size 7 containing "packet\0" */
    ENetPacket * packet = enet_packet_create ("packet", 
                                              strlen ("packet") + 1, 
                                              ENET_PACKET_FLAG_RELIABLE);

    /* Extend the packet so and append the string "foo", so it now */
    /* contains "packetfoo\0"                                      */
    enet_packet_resize (packet, strlen ("packetfoo") + 1);
    strcpy (& packet -> data [strlen ("packet")], "foo");
    
    /* Send the packet to the peer over channel id 3. */
    /* One could also broadcast the packet by         */
    /* enet_host_broadcast (host, 3, packet);         */
    enet_peer_send (peer, 3, packet);
    ...
    ...
    ...
    /* One could just use enet_host_service() instead. */
    enet_host_flush (host);
@endcode

@section Disconnecting Disconnecting an ENet peer

Peers may be gently disconnected with enet_peer_disconnect(). A
disconnect request will be sent to the foreign host, and ENet will
wait for an acknowledgement from the foreign host before finally
disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be
generated once the disconnection succeeds. Normally timeouts apply to
the disconnect acknowledgement, and so if no acknowledgement is
received after a length of time the peer will be forcefully
disconnected.

enet_peer_reset() will forcefully disconnect a peer. The foreign host
will get no notification of a disconnect and will time out on the
foreign host. No event is generated.

@code
    ENetEvent event;
    
    enet_peer_disconnect (& client -> peers [0]);

    /* Allow up to 3 seconds for the disconnect to succeed
     * and drop any packets received packets.
     */
    while (enet_host_service (client, & event, 3000) > 0)
    {
        switch (event.type)
        {
        case ENET_EVENT_TYPE_RECEIVE:
            enet_packet_destroy (event.packet);
            break;

        case ENET_EVENT_TYPE_DISCONNECT:
            puts ("Disconnection succeeded.");
            return;
        ...
        ...
        ...
        }
    }
    
    /* We've arrived here, so the disconnect attempt didn't */
    /* succeed yet.  Force the connection down.             */
    enet_peer_reset (& client -> peers [0]);
    ...
    ...
    ...
@endcode

@section Connecting Connecting to an ENet host

A connection to a foreign host is initiated with enet_host_connect().
It accepts the address of a foreign host to connect to, and the number
of channels that should be allocated for communication. If N channels
are allocated for use, their channel ids will be numbered 0 through
N-1.  A peer representing the connection attempt is returned, or NULL
if there were no available peers over which to initiate the
connection. When the connection attempt succeeds, an event of type
ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt
times out or otherwise fails, an event of type
ENET_EVENT_TYPE_DISCONNECT will be generated.

@code
    ENetAddress address;
    ENetEvent event;
    ENetPeer *peer;

    /* Connect to some.server.net:1234. */
    enet_address_set_host (& address, "some.server.net");
    address.port = 1234;

    /* Initiate the connection, allocating the two channels 0 and 1. */
    peer = enet_host_connect (client, & address, 2);    
    
    if (peer == NULL)
    {
       fprintf (stderr, 
                "No available peers for initiating an ENet connection.\n");
       exit (EXIT_FAILURE);
    }
    
    /* Wait up to 5 seconds for the connection attempt to succeed.
    if (enet_host_service (client, & event, 5000) > 0 &&
        event.type == ENET_EVENT_TYPE_CONNECT)
    {
        puts ("Connection to some.server.net:1234 succeeded.");
        ...
        ...
        ...
    }
    else
    {
        /* Either the 5 seconds are up or a disconnect event was */
        /* received. Reset the peer in the event the 5 seconds   */
        /* had run out without any significant event.            */
        enet_peer_reset (peer);

        puts ("Connection to some.server.net:1234 failed.");
    }
    ...
    ...
    ...
@endcode
*/