ENet reliable UDP networking library

Overview
Please visit the ENet homepage at http://enet.bespin.org for installation
and usage instructions.

If you obtained this package from github, the quick description on how to build
is:

# Generate the build system.

autoreconf -vfi

# Compile and install the library.

./configure && make && make install


Issues
  • Possible bug in transmission logic of fragmented packets

    Possible bug in transmission logic of fragmented packets

    I've noticed a suspicious behavior when unreliable packets that exceed MTU (without using any packet flags) prevent sending of unreliable packets that below MTU. For example:

    1. Sending and receiving packets continuously every 15 milliseconds in the loop.
    2. Creating and enqueuing for sending an unreliable packet with 64 bytes in size.
    3. Creating and enqueuing for sending an unreliable packet with 2048 bytes in size.
    4. Invoking service or flushing the host.
    5. The packet that exceeded MTU delivered successfully, but the packet below MTU is most likely not (with ~90% of probability).

    It happens on localhost and on remote connections. Packets that exceed MTU and flagged as ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT makes this a non-issue.

    It also happens when packets that exceed MTU are flagged as reliable.

    opened by Zerolean 11
  • How do I use SOCKS protocol in enet?

    How do I use SOCKS protocol in enet?

    Hello!

    I have been playing around with SOCKS protocol lately, and I was wondering how do you use SOCKS protocol in enet? Does it require custom logic for data receiving and sending?

    Best regards: Olli.

    opened by GitOlli 10
  • enet crashing upon sending packets

    enet crashing upon sending packets

    Hello, so i was wandering when enet crashes. When i create packets with c++, it works. (by creating packets, i mean copying data/adding new data to a byte array). Then i create an ENet packet, then send it which works.

    But when i do the same functions on nodejs, it crashes. I pass the created packet to the c++ addon, then create an enet packet, then after sending, it crashes. Any reason why?

    04 00 00 00 01 00 00 00 ff ff ff ff 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00
     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
    0 00 00 00 00 00 00 02 00 02 10 00 00 00 4f 6e 43 6f 6e 73 6f 6c 65 4d 65 73 73
    61 67 65 01 02 07 00 00 00 54 65 73 74 69 6e 67 00
    

    this is the bytes of the packet being sent. c++ & nodejs outputs the both though

    opened by Alexander9673 10
  • Enet Send and recieve in two threads will crash

    Enet Send and recieve in two threads will crash

    I encapsulated the sending and receiving of Enet, the receiving function will be called in a thread all the time, and the sending will be called in other threads, so there will be a segmentation error. my part of code is as follows. I now want know mybe I cannot understand the Enet library ? for this case ,if one why to fix to use mutex lock ?

    typedef struct _ASD_RELIABLE_UDP { ENetHost *host; ENetPeer *peer; }ASD_RELIABLE_UDP;

    init function: int asd_reliable_udp_init(ASD_RELIABLE_UDP *udp, enet_uint32 sockfd, enet_uint8 *ip, enet_uint16 port) { ENetEvent event; int retry = 0; if(enet_initialize()) { return -1; } //memset(&(udp->event), 0, sizeof(udp->event)); pthread_mutex_init(&(udp->hmutex),NULL);

    if (NULL == ip && 0 != port)
    {
    	ENetAddress address;
    	address.host=ENET_HOST_ANY;
    	address.port=port;
    
    	udp->host = enet_host_create(&address, sockfd, 1, 0,0,0);/*init server*/
    	
    	//udp->host->checksum = asd_check_buffer_sums;
    	printf("==== rudp host:%x\n ",udp->host);
    	if(udp->host) return 0;
    	else return -1;
    }
    else if (NULL != ip && 0 != port)
    {
    	int ret;
    	
    	udp->host = enet_host_create(NULL, sockfd, 1, 0,0,0);/*init client*/
    
    	ENetAddress svraddr;
    	memset(&svraddr, 0, sizeof(ENetAddress));
    
    	if (0 != enet_address_set_host(&svraddr,ip))
    	{
    		ret = -1;
    		goto final;
    		//return -1;
    	}
    	svraddr.port = port;
    

    again: udp->peer = enet_host_connect(udp->host, &svraddr, 2,0); if (NULL == udp->peer) { ret = -1; goto final; //return -1; } if (enet_host_service (udp->host, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { fprintf(stdout,"#### connect host success ....\n");

    		ret = 0;
    		goto final;
    		//return 0;
    	}
    	else
    	{
    		enet_peer_reset (udp->peer);
    		if(retry < 3){
    			retry ++ ;
    			fprintf(stderr," ### connect host again ....\n");
    			goto again;
    		}
    		else{
    			ret = -1;
    			goto final;
    			//return -1;
    		}
    	}
    

    final: return ret; } }

    send function:

    int asd_reliable_udp_send(ASD_RELIABLE_UDP *udp, const void *data, size_t len) { ENetEvent event; if (NULL == udp->host || NULL == udp->peer || NULL == data || len <= 0) { fprintf(stderr,"param is error,host:%x,event.peer:%x,data:%x,len:%d\n",udp->host,udp->peer,len); return -1; }

    ENetPacket *packet = enet_packet_create(data,len,ENET_PACKET_FLAG_RELIABLE);
    if (NULL == packet)
    {
    	fprintf(stderr,"enet_packet_create failed\n");
    	return -1;
    }
    
    if (0 != enet_peer_send(udp->peer,1,packet))
    {
    	fprintf(stderr,"enet_peer_send failed,errno:%d\n",errno);
    	enet_packet_destroy(packet);
    	return -1;
    }
    
    {
    	enet_host_flush (udp->host);
    }
    return len;
    

    }

    int asd_reliable_udp_recv(ASD_RELIABLE_UDP *udp, void *data, size_t len,size_t timeout) { int datalen = 0; ENetEvent event; if (NULL == udp || NULL == udp->host || NULL == data || len <= 0) { return -1; } int err = enet_host_service(udp->host, &event, timeout); if(err >= 0) { if (event.type == ENET_EVENT_TYPE_NONE) { //fprintf(stderr,"ENET_EVNET_TYPE_NONE ..:%d\n",errno); goto fin; } else if (event.type == ENET_EVENT_TYPE_CONNECT) { goto fin; } else if(event.type == ENET_EVENT_TYPE_RECEIVE) { //fprintf(stderr,"Request len:%d,dataLeng:%d\n",len,event.packet->dataLength); memcpy(data, event.packet->data, event.packet->dataLength); datalen = event.packet->dataLength; enet_packet_destroy(event.packet); goto fin; } else if (event.type == ENET_EVENT_TYPE_DISCONNECT) { //fprintf(stderr,"event disconnect ****\n"); return -ENET_EVENT_TYPE_DISCONNECT; } } fin: return datalen; }

    opened by zhengchengbin610 10
  • Enet File sync simulation: The performance (file transfer speed) is far worse than 'scp'

    Enet File sync simulation: The performance (file transfer speed) is far worse than 'scp'

    I wanna use ENet to speed the file transfer between two hosts which have worse network connection (packet loss ratio over 5%).

    I am disappointed by the performance, it is only 110KB/S, however 'scp' can be over 1024KB/S.

    I do not think ENet fails to do such task, It must be my fault.

    The following code is very simple:

    I use 3 channels to finish the task:

    In server side:

    1)Ignite file sync by channel 0 (CONNECT event) 2) Send packet by channel 2 (Would send max 4 packets to speed the transfer and take into account of RECEIVE event delay issue) 3) Send finished message by channel 1

    In client side:

    1) Ignite file sync by channel 0 ( RECEIVE event) 2) Receive packet by channel 2 and send the received packet count by channel 0 , Server will consume the packet and reply file packet with channel 2. 3) Close file by channel 1 (RECEIVE event)

    I found some RECEIVE interval of server could be very huge( over 10s). Why? because such huge delay could degrade the file transfer speed.

    The following is my example code:

    Server.c

    `#include <stdio.h>

    include <errno.h>

    include <string.h>

    include <stdlib.h>

    include <assert.h>

    include <enet/enet.h>

    include "config.h"

    define FILENAME "/relay/100MB-tokyo.bin"

    static char file_buffer[256*1024];

    int main (int argc, char *argv[]) { ENetAddress address; ENetHost *server; ENetPacket *packet; ENetEvent event; char host_ip[32] = {0}; char peer_info[32] = {0}; char msg_notify[64] = {0}; int lastEvent = -1; int enableDebug = 0;

    FILE *fp = fopen(FILENAME, "rb");
    if (!fp) {
        fprintf(stderr, "Fail to open file.\n");
        exit(0);
    }
    
    /* Initialize the ENet */
    if (enet_initialize() != 0) {
        fprintf(stderr, "An error (%s) occured while initializing ENet.\n", strerror(errno));
        return EXIT_FAILURE;
    }
    atexit(enet_deinitialize);
    
    /* Create the server */
    address.host = ENET_HOST_ANY;
    address.port = SHUTTLE_SERVER_PORT;
    server = enet_host_create(&address, 64, 6, 0, 0);
    if (server == NULL) {
        fprintf(stderr, "An error (%s) occured while trying to create ENet server host.\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    
    enet_uint32 time0 = 0, time1 = 0, time2 = 0;
    uint64_t packet_size = 0;
    uint64_t packet_count = 0;
    int connected = 0;
    int finished = 0;
    
    printf("(Slice) Server is running.\n");
    while (1) {
        /* Event dispatcher: MUST not be hanged up. */
        int eventStatus = enet_host_service(server, &event, 2);
        if (eventStatus >= 0) {
            switch (event.type) {
            case ENET_EVENT_TYPE_NONE:
                /* Silence huge repeated NONE events. */
                if (lastEvent != ENET_EVENT_TYPE_NONE) {
                    if (enableDebug)
                        printf("(Slice) No event.\n");
                }
                break;
            case ENET_EVENT_TYPE_CONNECT:
                /* Store any relevant server information here. */
                enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                if (event.peer->data)
                    free(event.peer->data);
                event.peer->data = malloc(strlen(peer_info) + 1);
                if (event.peer->data)
                    strcpy(event.peer->data, peer_info);
                snprintf(msg_notify, sizeof(msg_notify), "%s has connected to server", peer_info);
                connected = 1;
                finished = 0;
                time0 = enet_time_get();
                /* Ignite packet sync */
                packet = enet_packet_create(msg_notify, strlen(msg_notify) + 1, ENET_PACKET_FLAG_RELIABLE);
                enet_peer_send(event.peer, 0, packet);
                enet_host_flush(server);
                printf("(Slice) Got a connection from peer: %s:%d.\n", host_ip, event.peer->address.port);
                break;
            case ENET_EVENT_TYPE_RECEIVE:
                time1 = enet_time_get() - time0;
                printf("(Slice) Time: %d, Channel: %d.\n", time1 - time2, event.channelID);
                time2 = time1;
                if (connected) {
                    int64_t received_count = atoi((char*)event.packet->data);
                    while (!finished && received_count + 4 > packet_count) {
                        int ret = fread(file_buffer, 1, sizeof(file_buffer), fp);
                        if (!ret) {
                            printf("(Slice) File sync has finished.\n");
                            if (received_count == packet_count) {
                                finished = 1;
                                snprintf(file_buffer, sizeof(file_buffer), "%d", 1);
                                packet = enet_packet_create(file_buffer, strlen(file_buffer) + 1, ENET_PACKET_FLAG_RELIABLE);
                                enet_peer_send(event.peer, 1, packet);
                                enet_host_flush(server);
                            }
                            break;
                        }
                        packet_size += ret;
                        packet = enet_packet_create(file_buffer, ret, ENET_PACKET_FLAG_RELIABLE);
                        packet_count++;
                        enet_peer_send(event.peer, 2, packet);
                        enet_host_flush(server);
                    }
                    printf("(Slice) packet: received:%d, send: %d, speed: %dKB/S.\n",
                           (int)received_count, (int)packet_count, (int)(packet_size*1000/(time1 * 1024)));
                }
                /* Clean up the packet now that we're done using it. */
                enet_packet_destroy(event.packet);
                break;
            case ENET_EVENT_TYPE_DISCONNECT:
                /* A connected peer has either explicitly disconnected or timed out. */
                if (event.peer->data) {
                    printf("(Slice) %s is disconnected.\n", (char*)event.peer->data);
                    free(event.peer->data);
                } else {
                    enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                    snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                    printf("(Slice) Unknown (%s) connection is disconnected.\n", peer_info);
                }
                /* Reset the peer's information. */
                event.peer->data = NULL;
                enet_peer_reset(event.peer);
                lastEvent = -1;
                break;
            default:
                assert(0);
                break;
            }
    
            lastEvent = event.type;
        } else {
            fprintf(stderr, "(Slice) Something went wrong: %d.\n", eventStatus);
            lastEvent = -1;
        }
    }
    
    enet_host_flush(server);
    fclose(fp);
    
    enet_host_destroy(server);
    printf("Server is terminated.\n");
    
    return 0;
    

    } `

    Clinet.c

    `#include <stdio.h>

    include <errno.h>

    include <string.h>

    include <stdlib.h>

    include <assert.h>

    include <pthread.h>

    include <enet/enet.h>

    include "config.h"

    typedef struct ChatContext { ENetHost *client; ENetPeer *peer; volatile int connected; volatile int terminated; } ChatContext;

    int main (int argc, char *argv[]) { ENetAddress address; ENetEvent event; ChatContext cc, *pcc = &cc; char host_ip[32] = {0}; char peer_info[32] = {0}; int lastEvent = -1; int enableDebug = 0; int trycount = 0; int ret;

    memset(pcc, 0, sizeof(*pcc));
    
    /* Initialize the ENet */
    if (enet_initialize() != 0) {
        fprintf(stderr, "An error (%s) occured while initializing ENet.\n", strerror(errno));
        return EXIT_FAILURE;
    }
    atexit(enet_deinitialize);
    
    /* Create the client host */
    pcc->client = enet_host_create(NULL, 64, 6, 0, 0);
    if (pcc->client == NULL) {
        fprintf(stderr, "An error (%s) occured while trying to create an ENet client host.\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    
    /* Connect to the server */
    enet_address_set_host(&address, SHUTTLE_SERVER_HOST);
    address.port = SHUTTLE_SERVER_PORT;
    pcc->peer = enet_host_connect(pcc->client, &address, 6, 0);
    if (pcc->peer == NULL) {
        fprintf(stderr, "No available peers for initializing an ENet connection.\n");
        exit(EXIT_FAILURE);
    }
    
    do {
        trycount++;
        printf("(Peer) Try to connect to server: the %dth tryouts.\n", trycount);
        if (enet_host_service(pcc->client, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
            /* We can send packet to server only after we have received ENET_EVENT_TYPE_CONNECT */
            pcc->connected = 1;
            enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
            snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
            if (event.peer->data)
                free(event.peer->data);
            event.peer->data = malloc(strlen(peer_info) + 1);
            if (event.peer->data)
                strcpy(event.peer->data, peer_info);
            printf("(Peer) Connected to server (%s:%d).\n", host_ip, event.peer->address.port);
        }
    } while (trycount < 4 && !pcc->connected);
    
    if (!pcc->connected) {
        fprintf(stderr, "Fail to connect to server.\n");
        enet_peer_reset(pcc->peer);
        enet_host_destroy(pcc->client);
        exit(EXIT_FAILURE);
    }
    
    FILE *fp = fopen("/mnt/sdc/tmp/file_sync.bin", "wb");
    if (!fp) {
        fprintf(stderr, "Fail to write file.\n");
        exit(0);
    }
    
    enet_uint32 time0 = 0, time1 = 0, time2 = 0;
    int64_t packet_size = 0;
    int64_t packet_count = 0;
    char packet_info[32] = {0};
    
    while (1) {
        /* Event dispatcher: MUST not be hanged up */
        int eventStatus = enet_host_service(pcc->client, &event, 2);
        if (eventStatus >= 0) {
            switch (event.type) {
            case ENET_EVENT_TYPE_NONE:
                /* Silence huge repeated NONE events */
                if (lastEvent != ENET_EVENT_TYPE_NONE) {
                    if (enableDebug)
                        printf("(Peer) No event.\n");
                }
                break;
            case ENET_EVENT_TYPE_CONNECT:
                /* Store any relevant client information here. */
                pcc->connected = 1;
                enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                if (event.peer->data)
                    free(event.peer->data);
                event.peer->data = malloc(strlen(peer_info));
                if (event.peer->data)
                    strcpy(event.peer->data, peer_info);
                printf("(Peer) Connected to server (%s:%d).\n", host_ip, event.peer->address.port);
                break;
            case ENET_EVENT_TYPE_RECEIVE:
                if (time0 != 0) {
                    time1 = enet_time_get() - time0;
                    printf("(Peer) Time: %d, Channel: %d.\n", time1 - time2, event.channelID);
                    time2 = time1;
                }
                if (event.channelID == 0) {
                    /* Ignite packet sync */
                    packet_count = 0;
                    snprintf(packet_info, sizeof(packet_info), "%d", (int)packet_count);
                    ENetPacket *packet = enet_packet_create(packet_info, strlen(packet_info) + 1, ENET_PACKET_FLAG_RELIABLE);
                    enet_peer_send(event.peer, 0, packet);
                    enet_host_flush(pcc->client);
                    time0 = enet_time_get();
                }
                else if (event.channelID == 2) {
                    packet_count++;
                    time1 = enet_time_get() - time0;
                    packet_size += event.packet->dataLength;
                    if (fp) {
                        printf("(Peer) channelID:%d, len:%ld.\n", event.channelID, event.packet->dataLength);
                        fwrite(event.packet->data, 1, event.packet->dataLength, fp);
                    }
                    printf("(Peer) Receive speed: %d KB/S.\n", (int)(packet_size*1000/(time1*1024)));
                    snprintf(packet_info, sizeof(packet_info), "%d", (int)packet_count);
                    ENetPacket *packet = enet_packet_create(packet_info, strlen(packet_info) + 1, ENET_PACKET_FLAG_RELIABLE);
                    enet_peer_send(event.peer, 0, packet);
                    enet_host_flush(pcc->client);
                } else if (event.channelID == 1) {
                    if (fp) {
                        fclose(fp);
                        fp = 0;
                    }
                }
                else 
                    printf("(Peer) Got a chat message: %s.\n", (char*)event.packet->data);
                /* Clean up the packet now that we're done using it. */
                enet_packet_destroy(event.packet);
                break;
            case ENET_EVENT_TYPE_DISCONNECT:
                /* A connected peer has either explicitly disconnected or timed out. */
                printf("(Peer) Connection status: %d.\n", pcc->connected);
                if (event.peer->data) {
                    printf("(Peer) %s is disconnected.\n", (char*)event.peer->data);
                    free(event.peer->data);
                } else {
                    /* We fail to receive CONNECT event becasue the server is down. */
                    enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                    snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                    printf("(Peer) Unknown (%s) connection is disconnected.\n", peer_info);
                }
                /* Reset the peer's information. */
                event.peer->data = NULL;
                pcc->connected = 0;
                lastEvent = -1;
                enet_peer_reset(event.peer);
                /* Reconnect the server */
                pcc->peer = enet_host_connect(pcc->client, &address, 6, 0);
                if (pcc->peer == NULL) {
                    fprintf(stderr, "No available peers for initializing an ENet connection.\n");
                    enet_host_destroy(pcc->client);
                    ret = EXIT_FAILURE;
                    goto cleanup_pos;
                }
                break;
            default:
                assert(0);
                break;
            }
    
            lastEvent = event.type;
        } else {
            fprintf(stderr, "(Peer) Something went wrong: %d.\n", eventStatus);
            lastEvent = -1;
            pcc->connected = 0;
            enet_peer_reset(pcc->peer);
            ret = eventStatus;
            goto cleanup_pos;
        }
    }
    
    ret = 0;
    

    cleanup_pos: if (fp) fclose(fp); pcc->terminated = 1; enet_host_destroy(pcc->client); printf("Client is terminated.\n");

    return ret;
    

    } `

    opened by nxtreaming 10
  • Add the depencies to readme.md

    Add the depencies to readme.md

    Please add the toolchain requirements to the projects readme.md, otherwise it might be difficult to detect compilation errors (m4 is a bit cryptic on that). The depencies on Ubuntu 14.04 are:

    opened by Fohlen 9
  • Connection timeout when 2 enet host in same process

    Connection timeout when 2 enet host in same process

    In the mar 4 commit seems that the connected peer disconnected after ~1 second. This happen when you create 2 enet hosts in same process and connect to one another.

    opened by Benau 7
  • Round trip time varies with update rate

    Round trip time varies with update rate

    Consider the following: if enet_host_service is called once every second (in a while loop, as usual) in one end while the other end is producing packets every 100ms, with no network jitter, the enet_host_service loop should run 10 times thus consuming 10 packets. In the receiving end, it looks as if all packets had arrived at the same time, but on a system level, they have all arrived within 100ms of one another. Do the system calls and structures provide any information about the time a packet arrived? This information is important when measuring relative time quantities such as RTT and synchronizing clocks. Is the only solution to call enet_host_service at a higher rate or even have a dedicated networking thread which calls enet_host_service with no timeout, thus processing incoming packets as quickly as possible?

    The issue described above seems to be the reason why ENetPeer::roundTripTime decreases as the client and server update rates go up (e.g. disabling vsync on the client). If a ping packet arrives right after the enet_host_service loop is done, it will only be processed in the next update (e.g. 16ms later) and the pong will be sent back with a significant delay, thus causing the RTT calculations to be imprecise. At the same time, if the ping packet arrives when enet_host_service is called, the pong with be sent immediately. If the client and server are running on the same machine, it looks like you'd have ping-pong sequences that take 16ms while the next one takes near 0ms, thus resulting in large variance.

    opened by xissburg 6
  • How many consecutive connections can enet handle?

    How many consecutive connections can enet handle?

    I'm using Godot game engine to create a multiplayer game, it supports UDP, TCP and websockets. According to my research UDP is the only one reliable, they use Enet.

    I didn't get a decisive answer from godot community on how many consecutive connections Enet can handle, many create a new server instance using docker per room, I don't like that

    I want to have 8 players per room, how many consecutive connections can Enet handle before that I have to create a new docker instance? If there's no good answer, I'd like to know the safest bet before creating an instance.

    opened by elieobeid7 6
  • Network jitter crashes ENet when ENET_PACKET_FLAG_UNSEQUENCED used with ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT (stacktraces from valgrind included)

    Network jitter crashes ENet when ENET_PACKET_FLAG_UNSEQUENCED used with ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT (stacktraces from valgrind included)

    Hi, I think there might be some bug in ENet that causes it to crash when the network conditions are crap.

    I'm developing online gameplay for the game duel6 where the packets are being sent unreliably most of the time to transfer for example player's positions. I create the packets with flags ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT (on separate channel from the reliable packets if that plays any role). In one test scenario I artifically induce delay and jitter on the server with the command sudo tc qdisc change dev ens3 root netem delay 500ms 150ms 50% - i.e. 500ms additional ping with 150ms variance with the next random element depending 50% on the last one. The amount of data is above the MTU of 1400 bytes, so some fragmentation needs to occur. (I'm doing this test to make sure the game actually works in real life network conditions that we have came across during game testing). In this scenario the game crashes in first seconds after client connects and the server starts pushing game state updates. if I remove the ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT flag, the game does not crash also if I don't induce the jitter the game also does not crash.

    I have run the game with the valgrind with the following finding:

    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE615: enet_protocol_handle_send_unreliable_fragment (protocol.c:732)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d900 is 80 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 4
    ==18474==    at 0x59FE628: enet_protocol_handle_send_unreliable_fragment (protocol.c:732)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d950 is 0 bytes inside a block of size 4 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB477: enet_peer_remove_incoming_commands (peer.c:292)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC953: enet_peer_queue_incoming_command (peer.c:953)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 4
    ==18474==    at 0x59FE649: enet_protocol_handle_send_unreliable_fragment (protocol.c:734)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d8f8 is 72 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid write of size 4
    ==18474==    at 0x59FE653: enet_protocol_handle_send_unreliable_fragment (protocol.c:734)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d8f8 is 72 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE65A: enet_protocol_handle_send_unreliable_fragment (protocol.c:736)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d900 is 80 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 4
    ==18474==    at 0x59FE66F: enet_protocol_handle_send_unreliable_fragment (protocol.c:736)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d950 is 0 bytes inside a block of size 4 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB477: enet_peer_remove_incoming_commands (peer.c:292)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC953: enet_peer_queue_incoming_command (peer.c:953)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE688: enet_protocol_handle_send_unreliable_fragment (protocol.c:736)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d900 is 80 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid write of size 4
    ==18474==    at 0x59FE697: enet_protocol_handle_send_unreliable_fragment (protocol.c:736)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d950 is 0 bytes inside a block of size 4 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB477: enet_peer_remove_incoming_commands (peer.c:292)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC953: enet_peer_queue_incoming_command (peer.c:953)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE6A7: enet_protocol_handle_send_unreliable_fragment (protocol.c:738)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d908 is 88 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE6AB: enet_protocol_handle_send_unreliable_fragment (protocol.c:738)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x39d54578 is 24 bytes inside a block of size 48 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FAA62: enet_packet_destroy (packet.c:67)
    ==18474==    by 0x59FB45A: enet_peer_remove_incoming_commands (peer.c:288)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FA920: enet_packet_create (packet.c:22)
    ==18474==    by 0x59FC885: enet_peer_queue_incoming_command (peer.c:934)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE6D5: enet_protocol_handle_send_unreliable_fragment (protocol.c:741)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d908 is 88 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 8
    ==18474==    at 0x59FE6D9: enet_protocol_handle_send_unreliable_fragment (protocol.c:741)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x39d54570 is 16 bytes inside a block of size 48 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FAA62: enet_packet_destroy (packet.c:67)
    ==18474==    by 0x59FB45A: enet_peer_remove_incoming_commands (peer.c:288)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FA920: enet_packet_create (packet.c:22)
    ==18474==    by 0x59FC885: enet_peer_queue_incoming_command (peer.c:934)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid write of size 2
    ==18474==    at 0x4C340D3: [email protected]_2.2.5 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59FE6ED: enet_protocol_handle_send_unreliable_fragment (protocol.c:741)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x3aa92de0 is 0 bytes inside a block of size 2,485 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FAA56: enet_packet_destroy (packet.c:66)
    ==18474==    by 0x59FB45A: enet_peer_remove_incoming_commands (peer.c:288)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FA96E: enet_packet_create (packet.c:33)
    ==18474==    by 0x59FC885: enet_peer_queue_incoming_command (peer.c:934)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid read of size 4
    ==18474==    at 0x59FE6F2: enet_protocol_handle_send_unreliable_fragment (protocol.c:745)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x38c6d8f8 is 72 bytes inside a block of size 96 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FB483: enet_peer_remove_incoming_commands (peer.c:294)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FC89E: enet_peer_queue_incoming_command (peer.c:938)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    ==18474== Invalid write of size 1
    ==18474==    at 0x4C3410B: [email protected]_2.2.5 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59FE6ED: enet_protocol_handle_send_unreliable_fragment (protocol.c:741)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474==  Address 0x102b8294 is 2,484 bytes inside a block of size 2,485 free'd
    ==18474==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76D9: enet_free (callbacks.c:51)
    ==18474==    by 0x59FAA56: enet_packet_destroy (packet.c:66)
    ==18474==    by 0x59FB45A: enet_peer_remove_incoming_commands (peer.c:288)
    ==18474==    by 0x59FC403: enet_peer_dispatch_incoming_unreliable_commands (peer.c:779)
    ==18474==    by 0x59FCA33: enet_peer_queue_incoming_command (peer.c:980)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==  Block was alloc'd at
    ==18474==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==18474==    by 0x59F76A3: enet_malloc (callbacks.c:40)
    ==18474==    by 0x59FA96E: enet_packet_create (packet.c:33)
    ==18474==    by 0x59FC885: enet_peer_queue_incoming_command (peer.c:934)
    ==18474==    by 0x59FE5FB: enet_protocol_handle_send_unreliable_fragment (protocol.c:727)
    ==18474==    by 0x59FF71E: enet_protocol_handle_incoming_commands (protocol.c:1168)
    ==18474==    by 0x59FF9AF: enet_protocol_receive_incoming_commands (protocol.c:1261)
    ==18474==    by 0x5A00EA9: enet_host_service (protocol.c:1801)
    ==18474==    by 0x398989: Duel6::net::Service::poll(unsigned int) (Service.cpp:27)
    ==18474==    by 0x39C886: Duel6::Application::syncUpdateAndRender(Duel6::Context&) (Application.cpp:303)
    ==18474==    by 0x39C8F5: Duel6::Application::run() (Application.cpp:311)
    ==18474==    by 0x3F02AA: main (Main.cpp:42)
    ==18474== 
    

    The ENet version used is the latest master version (5de0a6f76). I have previously used 1.3.12 (version available in Ubuntu repos) with the exact same result (game crashes when ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT was used and network jitter applied).

    I suspect the bug is in the function enet_peer_dispatch_incoming_unreliable_commands where the enet_peer_remove_incoming_commands gets called.

    opened by fanick1 5
  • Q: Right usage of host service and check events

    Q: Right usage of host service and check events

    Since documentation is so minimalistic and examples do not cover enet_host_check_events() usage like at all I want to make sure I understand correctly how things works. Consider the following piece:

    Some data:

    std::shared_ptr<ENetHost> host;
    struct {
        std::queue<std::vector<unsigned char>/**/> data;
    }receiver;
    

    Main loop:

    ENetEvent event;
            if (enet_host_service(host.get(), &event, 0) > 0)
            {
                /* Wait up to 0 milliseconds for an event. */
                do
                {
                    switch (event.type)
                    {
                    case ENET_EVENT_TYPE_CONNECT:
                    {
                        enet_peer_ping_interval(event.peer, 100);
                        break;
                    }
                    case ENET_EVENT_TYPE_RECEIVE:
                    {
                        if (event.packet->dataLength < 1)
                        {
                            enet_packet_destroy(event.packet);
                            continue;
                        }
    
                        receiver.data.push(std::vector<unsigned char>(event.packet->dataLength));
                        std::vector<unsigned char>& data = receiver.data.back();
    
                        memcpy(data.data(), event.packet->data, data.size());
                        /* Clean up the packet now that we're done using it. */
                        enet_packet_destroy(event.packet);
    
                        break;
                    }
    
                    case ENET_EVENT_TYPE_DISCONNECT:
                    {
                        event.peer->data = NULL;
    
                        break;
                    }
                    default:
                        break;
                    }
                } while (enet_host_check_events(host.get(), &event) > 0);
            }
    

    The logic behind this is that I assume calling enet_host_service() once will check for events and process all incoming and outgoing data, ping remote hosts/peers and so on. Then enet_host_check_events() loop will process all queued events.

    1. Am i right there or maybe missing something?
    2. What the difference would be if I use enet_host_service(host.get(), NULL, 0) > 0 instead and then enet_host_check_events(host.get(), &event) > 0 for events in a loop?
    3. Also I want to know what the difference would be if I write while (enet_host_service(host.get(), &event, 0) > 0) instead of if (enet_host_service(host.get(), &event, 0) > 0) ?
    opened by oktonion 5
  • data (4th) argument of enet_host_connect() is not set in the CONNECT event received on the CLIENT side.

    data (4th) argument of enet_host_connect() is not set in the CONNECT event received on the CLIENT side.

    (Updated after stand-alone repro showed the the SERVER side sees the value, but the CLIENT side does not.)

    The docs for enet_host_connect() state that the final argument, enet_uint32 data is "user data supplied to the receiving host". Sadly when the sending (client) host receives the ENET_EVENT_TYPE_CONNECT event, that data value is NOT set in the ENetEvent->data member; the value is always zero. In fact, none of the data members reachable from the event (such as event->peer->data or event->peer->eventData) have the magic 32-bit value that I specified in my call to enet_host_connect().

    My intent was to use this value on the server side to allow the server to reject a client that did not specify the expected 32-bit value. However, my own project uses common code (both the client and server end) to run the ENet "while / switch" event pump.

    Confirmed w/ GDB:

    // 32-bit value sent from client to server when connecting.
    // The server end will reject any client that fails to provide this value.
    // This is to reduce errant connection attempts from other ENet clients.
    constexpr uint32_t kConnectionSentinal = 0x50564500; // "PVE\000"
    ...
      std::unique_lock<std::mutex> enet_lock(enet_mutex_);
      enet_host_connect(enet_host_.get(), &address, kMaxChannels, kConnectionSentinal);
    ...
    
    Thread 3 "unit_tests" hit Breakpoint 1, pve::NetworkDriver::HandleConnect (this=0x7fffffffd5f0, event=0x7ffff6f2bc20) at ../src/lib/common/net_driver.cc:336
    336     void NetworkDriver::HandleConnect(ENetEvent *event) {
    (gdb) p event
    $1 = (ENetEvent *) 0x7ffff6f2bc20
    (gdb) p *event
    $2 = {type = ENET_EVENT_TYPE_CONNECT, peer = 0x5555558e94f0, channelID = 0 '\000', data = 0, packet = 0x0}
    

    Application logs:

    [2022-03-29 21:38:35.262] [warning] NetworkDriver::HandleConnect 127.0.0.1:58676 Client provided invalid sentinal value of 0, expecting 1347831040
    <onehittoaster> ../src/lib/common/net_driver_test.cc:90: Failure
    

    I can confirm w/ wireshark that my uint32 is present in the UDP packet going from the client to the server. The last 4 bytes of the outbound packet (wireshark capture is from a different run of the same test, so the UDP port numbers are different, as is the connectionID; but its all the same code):

    00000000  8f ff b0 0c 82 ff 00 01  00 00 ff ff 00 00 05 78   ........ .......x
    00000010  00 01 00 00 00 00 00 02  00 00 00 00 00 00 00 00   ........ ........
    00000020  00 00 13 88 00 00 00 02  00 00 00 02 25 a4 f6 38   ........ ....%..8
    00000030  50 56 45 00                                        PVE.
        00000000  80 00 b0 0c 83 ff 00 01  00 00 00 00 00 00 05 78   ........ .......x
        00000010  00 01 00 00 00 00 00 02  00 00 00 00 00 00 00 00   ........ ........
        00000020  00 00 13 88 00 00 00 02  00 00 00 02 25 a4 f6 38   ........ ....%..8
    00000034  80 00 b0 0c 01 ff 00 01  00 01 b0 0c 85 ff 00 02   ........ ........
        00000030  00 00 01 ff 00 02 00 02  b0 0c                     ........ ..
    
    opened by dennisjenkins75 8
  • [FIX] CRC32 data race when using multiple ENetHost's from distinct threads

    [FIX] CRC32 data race when using multiple ENetHost's from distinct threads

    Hello!

    I have noticed that when using ENet from multiple threads, the CRC32 checksum sometimes seems to have miscalculations, resulting in unwanted retransmissions within ENet itself when a packet was sent with ENET_PACKET_FLAG_RELIABLE, even worse is that such packets would've been discarded completely if the reliability flag wasn't set, as the checksum wouldn't match...

    As many codebases make use of multithreading (since it is favorable to utilize the CPU to its full extent), the only viable way is to either supply multiple ENetHost's (e.g when wanting to deploy multiple servers for a service), or when wanting to have multiple clients separately with the full performance of all CPU cores.

    image ENet (according to the image), promises to work fine in a multithreaded environment, however I believe this may not apply to the checksum calculation, as that seems to require static global variables such as "crcTable" and "initializedCRC32". This could break the promise of full thread-safety even when the end-user makes sure that the ENetHosts operate distinct and separately.

    As a result, a modification (in my opinion an improvement) had to be done to the design of ENet: enet_uint32 crcTable[256] and int initializedCRC32 are now members of the ENetHost structure. For authenticity, enet_crc32 and the ENetChecksumCallback now have to be called with an ENetHost pointer and enet_crc32 is now called enet_host_crc32. For the internal initialization, enet_host_initialize_crc32 is now being used to initialize ENet's implementation of the CRC32 checksum.

    The reason I believe this is also more authentic, is because the ENetInterceptCallback also requires an ENetHost * - already. Now by making crcTable and initializedCRC32 members of ENetHost, it has also been made necessary to pass an ENetHost * to the checksum callback - in order to fix the data race / minuscule multithreading issue as mentioned above.

    opened by playingoDEERUX 2
  • Add GitHub Actions CI

    Add GitHub Actions CI

    This adds some basic CI builds via GitHub Actions.

    This produces a build matrix [Linux, Windows, MacOS] x [Debug, Release] and builds ENet with CMake with the default detected compiler in the respective GitHub Actions environment (currently: GCC 9, Visual Studio 2019 and Apple Clang 13).

    Later on, this could be extended to cover more compilers, compiler versions and build systems (Makefile, Premake), but it is a start to get some CI going for ENet.

    An exemplary run can be seen here: https://github.com/Croydon/enet/actions/runs/1723356026

    If this is merged, GitHub will run this CI for every future push and pull request, no further configuration is required whatsoever.

    opened by Croydon 0
  • Add install to CMakeLists.txt

    Add install to CMakeLists.txt

    Currently CMakeLists.txt lacks any installation instruction, which is a bit annoying when you wish to install it in system folders (using make install), this PR fixes that.

    opened by SirLynix 1
  • Slow reliable peer

    Slow reliable peer

    I tested ENet library with 2 clients located far from each other: TTL 53, Ping 280 and got maximum bandwidth of reliable packets about 2Mbps With the same conditions I got about 9MBps with LiteNetLib (C#). And TCP gives about 9-10MBps between same clients. Local tests (localhost<->localhost) give about 300MBps. I guess something wrong with buffering or window processing.

    opened by ksubox 3
  • Congesting Control

    Congesting Control

    Hey, Does enet implies any congestion control algorithm or the client which uses the library is responsible to do so ?

    By looking at the following method: enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)

    The incomingBandwidth and outgoingBandwidth can be dynamic if we are over the internet, so for the sake of example, if my connection is 100 mb/s and I set the bandwidth to be 200 mb/s, I will simply suffer from packet loss ? and if the client is responsible for the congestion control, does enet provide the required statists that from it the client can learn and update the incoming/outcoming bandwidth ?

    opened by ihabZhaika 0
Owner
Lee Salzman
Lee Salzman
Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption.

GameNetworkingSockets GameNetworkingSockets is a basic transport layer for games. The features are: Connection-oriented API (like TCP) ... but message

Valve Software 6k May 5, 2022
Data-oriented networking playground for the reliable UDP transports

NetDynamics is a data-oriented networking playground for the reliable UDP transports. The application was created for stress testing and debugging a p

Stanislav Denisov 86 Mar 26, 2022
First Growtopia Private Server made with ENet

GrowtopiaServer First Growtopia Private Server made with ENet. This project has been compiled with Visual Studio 2015 (Visual Studio 2013 or older won

Lyte 10 Oct 21, 2021
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 8.2k May 8, 2022
Portable, single-file, protocol-agnostic TCP and UDP socket wrapper, primarily for game networking

Documentation This is a header-only library, as such most of its functional documentation is contained within the "header section" of the source code

null 62 Mar 23, 2022
:zap: KCP - A Fast and Reliable ARQ Protocol

KCP - A Fast and Reliable ARQ Protocol README in English 简介 KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP

Linwei 11.1k May 10, 2022
Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

Lightway Core NOTE: This is a preview snapshot of the Lightway repository used for both our client and server. We will be publishing a live, actively

ExpressVPN 22 Feb 17, 2022
Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

ExpressVPN 292 May 10, 2022
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Ivan Shynkarenka 834 May 18, 2022
A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols.

evpp Introduction 中文说明 evpp is a modern C++ network library for developing high performance network services using TCP/UDP/HTTP protocols. evpp provid

Qihoo 360 3k May 13, 2022
The C++ Network Library Project -- cross-platform, standards compliant networking library.

C++ Network Library Modern C++ network programming libraries. Join us on Slack: http://slack.cpp-netlib.org/ Subscribe to the mailing list: https://gr

C++ Network Library 1.9k May 10, 2022
QUIC, a multiplexed stream transport over UDP

QUIC, a multiplexed stream transport over UDP QUIC is an experimental protocol aimed at reducing web latency over that of TCP. On the surface, QUIC is

Devsisters Corp. 1.6k May 13, 2022
Built a client-server application using TCP and UDP sockets, in which the clients can subscribe/unsubscribe to various topics.

Built a client-server application using TCP and UDP sockets, in which the clients can subscribe/unsubscribe to various topics.

null 1 Oct 15, 2021
Winpcap-based network packet capture tool, support TLS (part), UDP, ICMP, TCP, ARP, DNS and other protocol analysis, interface reference wireshark.

Winpcap-based network packet capture tool, support TLS (part), UDP, ICMP, TCP, ARP, DNS and other protocol analysis, interface reference wireshark.

null 31 Apr 26, 2022
Provide translation, currency conversion, and voting services. First using telnet you create a connection to a TCP socket, then the server connects to 3 UDP sockets hosted on other servers to do tasks.

to run micro servers g++ translator.cpp -o translator ./translator <port 1> g++ voting.cpp -o voting ./voting <port 2> g++ currency_converter.cpp -o c

Jacob Artuso 1 Oct 29, 2021
A TCP / UDP program supporting multiple test scenarios

sock_test A TCP / UDP program supporting multiple test scenarios The current communication protocol only supports UDP. TCP will be supported later. Ho

null 4 Mar 8, 2022
Simple local P2P chat on UDP sockets

Local P2P Chat This is a fully decentralized chat. To communicate, simply run it on computers in a single local network (using one port). All messages

Anton Khalitov 15 Apr 13, 2022
(Test assignment) Transfer files over the network using a homegrown UDP protocol

Требования Linux x86_64 gcc >= 4.9 (C++11) Сборка $ make Запуск $ make run -j5 -j5 позволяет серверу и четырём клиентам запуститься одновременно. В

Alexander Batischev 2 Dec 18, 2021
Wrapper for linux TCP/UDP/unix/USB socket connections

Socket Connection wrapper shared library Shared library that realize sockets connections and could transfer data-packages. Navigation Navigation Insta

Dmitry Golgovsky 7 Dec 21, 2021