static int
dlinfoack(int fd, char *bufp, char *ebuf)
{

	return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
}
static int
dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
{

	return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
}
static int
dlokack(int fd, const char *what, char *bufp, char *ebuf)
{

	return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));
}
/**
 * void process_dgram(char *dgram, struct sockaddr_in *addr)
 * 
 * Processes accepted datagram. Checks if sequential ID is correct, if it's lower,
 * we resend the ACK packet and dont bother with that datagram anymore, because
 * it was already processed before.
 */
void process_dgram(char *dgram, struct sockaddr_in *addr) {
    /* Protocol token */
    char *token;
    /* Token length */
    int token_len;
    /* Command */
    char *type;
    /* Generic char buffer */
    char *generic_chbuff;
    /* Sequential ID of received packet */
    int packet_seq_id;
    /* Client which we receive from */
    client_t *client;
    /* Generic unsigned int var */
    unsigned int generic_uint;
    /* String representation of address */
    char addr_str[INET_ADDRSTRLEN];

    inet_ntop(AF_INET, &addr->sin_addr, addr_str, INET_ADDRSTRLEN);
    
    /* Log */
    sprintf(log_buffer,
            "DATA_IN: %s <--- %s:%d",
            dgram,
	    addr_str,
	    htons(addr->sin_port)
            );
    log_line(log_buffer, LOG_DEBUG);
    
    token = strtok(dgram, ";");
    token_len = strlen(token);
    
    generic_chbuff = strtok(NULL, ";");
    packet_seq_id = (int) strtol(generic_chbuff, NULL, 0);
    
    /* Check if datagram belongs to us */
    if( (token_len == strlen(STRINGIFY(APP_TOKEN))) &&
            strncmp(token, STRINGIFY(APP_TOKEN), strlen(STRINGIFY(APP_TOKEN))) == 0 &&
            packet_seq_id > 0) {
        
        type = strtok(NULL, ";");
        
        /* New client connection */
        if(strncmp(type, "CONNECT", 7) == 0) {
            
            add_client(addr);            
            client = get_client_by_addr(addr);
            
            if(client) {
                send_ack(client, 1, 0);
                send_reconnect_code(client);
                
                /* Release client */
                release_client(client);
            }
            
        }
        /* Reconnect */
        else if(strncmp(type, "RECONNECT", 9) == 0) {            
            client = get_client_by_index(get_client_index_by_rcode(strtok(NULL, ";")));
            
            if(client) {
                /* Sends ACK aswell after resetting clients SEQ_ID */
                reconnect_client(client, addr);
                
                /* Release client */
                release_client(client);
            }
        }
        /* Client should already exist */
        else {
            client = get_client_by_addr(addr);
            
            if(client != NULL) {
                /* Check if expected seq ID matches */
                if(packet_seq_id == client->pkt_recv_seq_id) {
                    
                    /* Get command */
                    if(strncmp(type, "CREATE_GAME", 11) == 0) {
                                                
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        create_game(client);
                        
                    }
                    /* Receive ACK packet */
                    else if(strncmp(type, "ACK", 3) == 0) {
                        
                        recv_ack(client, 
                                (int) strtoul(strtok(NULL, ";"), NULL, 10));
                        
                        update_client_timestamp(client);
                        
                    }
                    /* Close client connection */
                    else if(strncmp(type, "CLOSE", 5) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        leave_game(client);
                        remove_client(&client);
                        
                    }
                    /* Keepalive loop */
                    else if(strncmp(type, "KEEPALIVE", 9) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                    }
                    /* Join existing game */
                    else if(strncmp(type, "JOIN_GAME", 9) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        join_game(client, strtok(NULL, ";"));
                        
                    }
                    /* Leave existing game */
                    else if(strncmp(type, "LEAVE_GAME", 10) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        leave_game(client);
                    }
                    /* Start game */
                    else if(strncmp(type, "START_GAME", 10) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        start_game(client);
                    }
                    /* Rolling die */
                    else if(strncmp(type, "DIE_ROLL", 8) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        roll_die(client);
                    }
                    /* Moving figure */
                    else if(strncmp(type, "FIGURE_MOVE", 11) == 0) {
                        
                        /* ACK client */
                        send_ack(client, packet_seq_id, 0);
                        
                        /* Parse figure id */
                        generic_chbuff = strtok(NULL, ";");
                        generic_uint = (unsigned int) strtoul(generic_chbuff, NULL, 10);

                        move_figure(client, generic_uint);
                    }

		   else if(strncmp(type, "MESSAGE", 7) == 0) {
			
			/* ACK client */
			send_ack(client, packet_seq_id, 0);
			
			broadcast_message(client, strtok(NULL, ";"));
		   }
                                        
                }
                /* Packet was already processed */
                else if(packet_seq_id < client->pkt_recv_seq_id &&
                        strncmp(type, "ACK", 3) != 0) {
                    
                    send_ack(client, packet_seq_id, 1);
                    
                }
                
                /* If client didnt close conection */
                if(client != NULL) {
                    
                    /* Release client */
                    release_client(client);
                }
            }
        }
    }
}