/**\file n_network_msg.c
 *  network messages function
 *  Network Engine
 *\author Castagnier Mickael
 *\version 1.0
 *\date 10/05/2005
 */
#include "nilorea/n_common.h"
#include "nilorea/n_log.h"
#include "nilorea/n_network.h"
#include "nilorea/n_network_msg.h"

/*!\fn static double double_swap( double value )
 *\brief Swap bytes endiannes for a double
 *\param value The double to swap
 *\return A swapped double
 */
double double_swap(double value) {
    double swaped = 0;
    unsigned char* src = (unsigned char*)&value;
    unsigned char* dst = (unsigned char*)&swaped;

    /* swap bytes */
    dst[0] = src[7];
    dst[1] = src[6];
    dst[2] = src[5];
    dst[3] = src[4];
    dst[4] = src[3];
    dst[5] = src[2];
    dst[6] = src[1];
    dst[7] = src[0];

    return swaped;
} /* double_swap() */

/*!\fn static double htond( double value )
 *\brief If needed swap bytes for a double
 *\param value The value to eventually swap
 *\return The modified value
 */
double htond(double value) {
    double ret = value;
    /* if byte order is little like x86, PC, ... we swap to network notation */
#if (BYTEORDER_ENDIAN == BYTEORDER_LITTLE_ENDIAN)
    ret = double_swap(value);
#endif
    return ret;
} /* htond() */

/*!\fn static double ntohd( double value )
 *\brief If needed swap bytes for a double
 *\param value The value to eventually swap
 *\return The modified value
 */
double ntohd(double value) {
    double ret = value;
    /* if byte order is little like x86, PC, ... we swap to network notation */
#if (BYTEORDER_ENDIAN == BYTEORDER_LITTLE_ENDIAN)
    ret = double_swap(value);
#endif
    return ret;
} /* ntohd() */

/*!\fn create_msg( NETW_MSG **msg )
 *\brief Create a NETW_MSG *object
 *\param msg A NETW_MSG *object
 *\return TRUE or FALSE
 */
int create_msg(NETW_MSG** msg) {
    if ((*msg)) {
        n_log(LOG_ERR, "create_msg destination is valid and should be NULL !");
        return FALSE;
    }

    Malloc((*msg), NETW_MSG, 1);
    __n_assert(msg && (*msg), return FALSE);

    (*msg)->tabstr = new_generic_list(-1);
    __n_assert((*msg)->tabstr, return FALSE);
    (*msg)->tabint = new_generic_list(-1);
    __n_assert((*msg)->tabint, return FALSE);
    (*msg)->tabflt = new_generic_list(-1);
    __n_assert((*msg)->tabflt, return FALSE);

    return TRUE;
} /* create_msg( ... ) */

/*!\fn delete_msg( NETW_MSG **msg )
 *\brief Delete a NETW_MSG *object
 *\param msg A NETW_MSG *object to delete
 *\return TRUE or FALSE
 */
int delete_msg(NETW_MSG** msg) {
    if ((*msg)) {
        if ((*msg)->tabint) {
            list_destroy(&(*msg)->tabint);
        }
        if ((*msg)->tabflt) {
            list_destroy(&(*msg)->tabflt);
        }
        if ((*msg)->tabstr) {
            list_destroy(&(*msg)->tabstr);
        }
        Free((*msg));
    } else {
        n_log(LOG_ERR, "(*msg) already NULL");
        return FALSE;
    }
    return TRUE;
} /* delete_msg */

/*!\fn empty_msg( NETW_MSG **msg )
 *\brief Empty a NETW_MSG *object
 *\param msg A NETW_MSG **object
 *\return TRUE or FALSE
 */
int empty_msg(NETW_MSG** msg) {
    __n_assert(msg && (*msg), return FALSE);

    list_empty((*msg)->tabint);
    list_empty((*msg)->tabflt);
    list_empty((*msg)->tabstr);

    return TRUE;
} /* empty_msg(...) */

/*!\fn add_nb_to_msg( NETW_MSG *msg , double value )
 *\brief Add an float to the message
 *\param msg A NETW_MSG *object to complete with the value
 *\param value The value to add to the message
 *\warning The floating value will be rounded by the network serialization !
 *\return TRUE or FALSE
 */
int add_nb_to_msg(NETW_MSG* msg, double value) {
    double* new_val = NULL;

    __n_assert(msg, return FALSE);

    Malloc(new_val, double, 1);
    __n_assert(new_val, return FALSE);

    new_val[0] = value;

    return list_push(msg->tabflt, new_val, free);
} /* add_nb_to_msg( ... ) */

/*!\fn add_int_to_msg( NETW_MSG *msg , int value )
 *\brief Add an int to the int list int the message
 *\param msg A NETW_MSG *object to complete with the value
 *\param value The value to add to the message
 *\return TRUE or FALSE
 */
int add_int_to_msg(NETW_MSG* msg, int value) {
    int* new_val = NULL;

    __n_assert(msg, return FALSE);

    Malloc(new_val, int, 1);
    __n_assert(new_val, return FALSE);

    new_val[0] = value;

    return list_push(msg->tabint, new_val, free);
} /* add_int_to_msg( ... ) */

/*!\fn add_nstrptr_to_msg( NETW_MSG *msg , N_STR *str)
 *\brief Add a string to the string list in the message
 *\param msg A NETW_MSG *object to complete with the string
 *\param str The string to add to the message
 *\return TRUE or FALSE
 */
int add_nstrptr_to_msg(NETW_MSG* msg, N_STR* str) {
    __n_assert(msg, return FALSE);
    __n_assert(str, return FALSE);
    __n_assert(str->data, return FALSE);
    return list_push(msg->tabstr, str, free_nstr_ptr);
} /* add_nstrptr_to_msg(...) */

/*!\fn add_nstrdup_to_msg( NETW_MSG *msg , N_STR *str)
 *\brief Add a copy of str to the string list in the message
 *\param msg A NETW_MSG *object to complete with the string
 *\param str The string to add to the message
 *\return TRUE or FALSE
 */
int add_nstrdup_to_msg(NETW_MSG* msg, N_STR* str) {
    __n_assert(msg, return FALSE);
    __n_assert(str, return FALSE);
    __n_assert(str->data, return FALSE);

    return list_push(msg->tabstr, nstrdup(str), free_nstr_ptr);
} /* add_nstrdup_to_msg(...) */

/*!\fn add_strdup_to_msg( NETW_MSG *msg , const char *str)
 *\brief Add a copy of char *str to the string list in the message
 *\param msg A NETW_MSG *object to complete with the string
 *\param str The string to add to the message
 *\return TRUE or FALSE
 */
int add_strdup_to_msg(NETW_MSG* msg, const char* str) {
    __n_assert(msg, return FALSE);
    __n_assert(str, return FALSE);

    N_STR* dup = char_to_nstr(str);
    __n_assert(dup, return FALSE);

    return list_push(msg->tabstr, dup, free_nstr_ptr);
} /* add_strdup_to_msg(...) */

/*!\fn int get_nb_from_msg( NETW_MSG *msg , double *value )
 *\brief Get a number from a message number list
 *\param msg A NETW_MSG *object for extracting number
 *\param value A int value where you want to store the result
 *\return A pointer to the N_STR, Do not forget to free it !
 */
int get_nb_from_msg(NETW_MSG* msg, double* value) {
    double* val = NULL;

    __n_assert(msg, return FALSE);

    val = list_shift(msg->tabflt, double);
    if (val) {
        (*value) = val[0];
        Free(val);
        return TRUE;
    }
    return FALSE;
} /* get_nb_from_msg(...) */

/*!\fn get_int_from_msg( NETW_MSG *msg , int *value )
 *\brief Get a number from a message number list
 *\param msg A NETW_MSG *object for extracting number
 *\param value A int value where you want to store the result
 *\return A pointer to the N_STR, Do not forget to free it !
 */
int get_int_from_msg(NETW_MSG* msg, int* value) {
    int* val = NULL;

    __n_assert(msg, return FALSE);

    val = list_shift(msg->tabint, int);
    if (val) {
        (*value) = val[0];
        Free(val);
        return TRUE;
    }
    return FALSE;

} /* get_int_from_msg(...) */

/*!\fn get_nstr_from_msg( NETW_MSG *msg , N_STR **value )
 *\brief Get a string from a message string list
 *\param msg The NETW_MSG where you have a str to get
 *\param value A pointer to a NULL N_STR for storage
 *\return TRUE or FALSE
 */
int get_nstr_from_msg(NETW_MSG* msg, N_STR** value) {
    N_STR* val = NULL;

    __n_assert(msg, return FALSE);

    val = list_shift(msg->tabstr, N_STR);
    if (val) {
        if ((*value)) {
            n_log(LOG_ERR, "Previous pointer value %p overriden by pointer %p", (*value), val);
        }
        (*value) = val;
        return TRUE;
    }
    return FALSE;
} /* get_nstr_from_msg(...) */

/*!\fn get_str_from_msg( NETW_MSG *msg , char **value )
 *\brief Get a string from a message string list
 *\param msg The NETW_MSG where you have a str to get
 *\param value A pointer to a NULL N_STR for storage
 *\return TRUE or FALSE
 */
int get_str_from_msg(NETW_MSG* msg, char** value) {
    N_STR* val = NULL;

    __n_assert(msg, return FALSE);

    val = list_shift(msg->tabstr, N_STR);
    if (val) {
        if ((*value)) {
            n_log(LOG_ERR, "Previous pointer value %p overriden by pointer %p", (*value), val);
        }

        (*value) = val->data;
        Free(val);
        return TRUE;
    }
    return FALSE;
} /* get_str_from_msg(...) */

/*!\fn make_str_from_msg( NETW_MSG *msg )
 *\brief Make a single string of the message
 *\param msg A NETW_MSG structure to convert into a N_STR one
 *\return A pointer to the generated N_STR, do not forget to free it after use !
 */
N_STR* make_str_from_msg(NETW_MSG* msg) {
    int str_length = 0;
    LIST_NODE* node = NULL;

    N_STR *strptr = NULL,
          *generated_str = NULL;

    char* charptr = NULL;

    __n_assert(msg, return NULL);

    /* the first thing to do is to computer the resulting string size
       the first 12 octets are for the number of ints , floats, strings in the message
       */
    str_length = 3 * sizeof(int32_t) + (msg->tabint->nb_items * sizeof(int32_t)) + (msg->tabflt->nb_items * sizeof(double));

    /* let's count the eventual string blocks */
    node = msg->tabstr->start;
    while (node) {
        strptr = (N_STR*)node->ptr;
        str_length += sizeof(int32_t) + sizeof(int32_t) + strptr->written;
        node = node->next;
    }

    /* preparing the new string */
    Malloc(generated_str, N_STR, 1);
    __n_assert(generated_str, return NULL);
    Malloc(generated_str->data, char, str_length + 1);
    __n_assert(generated_str->data, return NULL);

    generated_str->length = str_length + 1;
    generated_str->written = str_length;

    /* copying header */
    charptr = generated_str->data;

    /* byte order */
    msg->tabint->nb_items = htonl(msg->tabint->nb_items);
    msg->tabflt->nb_items = htonl(msg->tabflt->nb_items);
    msg->tabstr->nb_items = htonl(msg->tabstr->nb_items);

    /* number of ints inside the message */
    memcpy(charptr, &msg->tabint->nb_items, sizeof(int32_t));
    charptr += sizeof(int32_t);
    /* number of doubles inside the message */
    memcpy(charptr, &msg->tabflt->nb_items, sizeof(int32_t));
    charptr += sizeof(int32_t);
    /* number of string inside the message */
    memcpy(charptr, &msg->tabstr->nb_items, sizeof(int32_t));
    charptr += sizeof(int32_t);

    /*reversing byte order to default host order */
    msg->tabint->nb_items = ntohl(msg->tabint->nb_items);
    msg->tabflt->nb_items = ntohl(msg->tabflt->nb_items);
    msg->tabstr->nb_items = ntohl(msg->tabstr->nb_items);

    /* if there are numbers, copy all them ! */
    node = msg->tabint->start;
    while (node) {
        int32_t* nbptr = (int32_t*)node->ptr;
        int32_t val = htonl(nbptr[0]);
        memcpy(charptr, &val, sizeof(int32_t));
        charptr += sizeof(int32_t);
        node = node->next;
    }

    /* if there are numbers, copy all them ! */
    node = msg->tabflt->start;
    while (node) {
        double* nbptr = (double*)node->ptr;
        double val = htond(nbptr[0]);
        memcpy(charptr, &val, sizeof(double));
        charptr += sizeof(double);
        node = node->next;
    }

    /* if there are strings, copy all them ! */
    if (msg->tabstr->nb_items > 0) {
        node = msg->tabstr->start;
        while (node) {
            strptr = (N_STR*)node->ptr;

            int32_t var = htonl(strptr->length);
            memcpy(charptr, &var, sizeof(int32_t));
            charptr += sizeof(int32_t);

            var = htonl(strptr->written);
            memcpy(charptr, &var, sizeof(int32_t));
            charptr += sizeof(int32_t);

            memcpy(charptr, strptr->data, strptr->written);
            charptr += strptr->written;
            node = node->next;
        }
    }

    return generated_str;
} /* make_str_from_msg(...) */

/*!\fn make_msg_from_str( N_STR *str )
 *\brief Make a single message of the string
 *\param str A N_STR structure to convert into a NETW_MSG one
 *\return A pointer to the generated NETW_MSG, do not forget to free it after use !
 */
NETW_MSG* make_msg_from_str(N_STR* str) {
    NETW_MSG* generated_msg = NULL;
    N_STR* tmpstr = NULL;

    char* charptr = NULL;

    int32_t it,
        nb_int = 0,
        nb_flt = 0,
        nb_str = 0,
        tmpnb = 0;

    double tmpflt = 0;

    __n_assert(str, return NULL);

    charptr = str->data;

    create_msg(&generated_msg);

    __n_assert(generated_msg, return NULL);

    memcpy(&nb_int, charptr, sizeof(int32_t));
    charptr += sizeof(int32_t);
    nb_int = ntohl(nb_int);

    memcpy(&nb_flt, charptr, sizeof(int32_t));
    charptr += sizeof(int32_t);
    nb_flt = ntohl(nb_flt);

    memcpy(&nb_str, charptr, sizeof(int32_t));
    charptr += sizeof(int32_t);
    nb_str = ntohl(nb_str);

    if (nb_int > 0) {
        for (it = 0; it < nb_int; it++) {
            memcpy(&tmpnb, charptr, sizeof(int32_t));
            tmpnb = ntohl(tmpnb);
            charptr += sizeof(int32_t);
            add_int_to_msg(generated_msg, tmpnb);
        }
    }

    if (nb_flt > 0) {
        for (it = 0; it < nb_flt; it++) {
            memcpy(&tmpflt, charptr, sizeof(double));
            tmpflt = ntohd(tmpflt);
            charptr += sizeof(double);
            add_nb_to_msg(generated_msg, tmpflt);
        }
    }

    if (nb_str > 0) {
        for (it = 0; it < nb_str; it++) {
            Malloc(tmpstr, N_STR, 1);
            __n_assert(tmpstr, return NULL);
            int32_t var = 0;
            memcpy(&var, charptr, sizeof(int32_t));
            charptr += sizeof(int32_t);
            tmpstr->length = ntohl(var);

            memcpy(&var, charptr, sizeof(int32_t));
            charptr += sizeof(int32_t);
            tmpstr->written = ntohl(var);

            Malloc(tmpstr->data, char, tmpstr->length);
            __n_assert(tmpstr->data, return NULL);

            memcpy(tmpstr->data, charptr, tmpstr->written);
            charptr += tmpstr->written;

            add_nstrptr_to_msg(generated_msg, tmpstr);
        }
    }
    return generated_msg;
} /* make_msg_from_str(...) */

#ifndef NO_NETMSG_API

/*!\fn netmsg_make_ping( int type , int id_from , int id_to , int time )
 *\brief Make a ping message to send to a network
 *\param type NETW_PING_REQUEST or NETW_PING_REPLY
 *\param id_from Identifiant of the sender
 *\param id_to Identifiant of the destination, -1 if the serveur itslef is targetted
 *\param time The time it was when the ping was sended
 *\return A N_STR *message or NULL
 */
N_STR* netmsg_make_ping(int type, int id_from, int id_to, int time) {
    NETW_MSG* msg = NULL;

    N_STR* tmpstr = NULL;

    create_msg(&msg);

    __n_assert(msg, return NULL);

    if (add_int_to_msg(msg, type) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }
    if (add_int_to_msg(msg, id_from) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }
    if (add_int_to_msg(msg, id_to) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }
    if (add_int_to_msg(msg, time) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }

    tmpstr = make_str_from_msg(msg);
    delete_msg(&msg);

    return tmpstr;
} /* netmsg_make_ping() */

/*!\fn N_STR *netmsg_make_ident( int type , int id , N_STR *name , N_STR *passwd  )
 *\brief Add a formatted NETWMSG_IDENT message to the specified network
 *\param type type of identification ( NETW_IDENT_REQUEST , NETW_IDENT_NEW )
 *\param id The ID of the sending client
 *\param name Username
 *\param passwd Password
 *\return N_STR *netmsg or NULL
 */
N_STR* netmsg_make_ident(int type, int id, N_STR* name, N_STR* passwd) {
    NETW_MSG* msg = NULL;
    N_STR* tmpstr = NULL;

    create_msg(&msg);
    __n_assert(msg, return FALSE);

    if (add_int_to_msg(msg, type) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }
    if (add_int_to_msg(msg, id) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }

    if (add_nstrdup_to_msg(msg, name) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }
    if (add_nstrdup_to_msg(msg, passwd) == FALSE) {
        delete_msg(&msg);
        return NULL;
    }

    tmpstr = make_str_from_msg(msg);
    delete_msg(&msg);

    return tmpstr;
} /* netmsg_make_ident() */

/*!\fn N_STR *netmsg_make_position_msg( int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp )
 *\brief make a network NETMSG_POSITION message with given parameters
 *\param id The ID of the sending client
 *\param X x position
 *\param Y y position
 *\param vx x speed
 *\param vy y speed
 *\param acc_x x acceleration
 *\param acc_y y acceleration
 *\param time_stamp time when the position were copier
 *\return N_STR *netmsg or NULL
 */
N_STR* netmsg_make_position_msg(int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp) {
    NETW_MSG* msg = NULL;
    N_STR* tmpstr = NULL;

    create_msg(&msg);

    __n_assert(msg, return NULL);

    add_int_to_msg(msg, NETMSG_POSITION);
    add_int_to_msg(msg, id);
    add_nb_to_msg(msg, X);
    add_nb_to_msg(msg, Y);
    add_nb_to_msg(msg, vx);
    add_nb_to_msg(msg, vy);
    add_nb_to_msg(msg, acc_x);
    add_nb_to_msg(msg, acc_y);
    add_int_to_msg(msg, time_stamp);

    tmpstr = make_str_from_msg(msg);
    delete_msg(&msg);
    return tmpstr;
} /* netmsg_make_position_msg() */

/*!\fn N_STR *netmsg_make_string_msg( int id_from, int id_to, N_STR *name, N_STR *chan, N_STR *txt, int color )
 *\brief make a network NETMSG_STRING message with given parameters
 *\param id_from The ID of the sending client
 *\param id_to id of the destination
 *\param name name of the user
 *\param chan targeted channel
 *\param txt text to send
 *\param color color of the text
 *\return N_STR *netmsg or NULL
 */
N_STR* netmsg_make_string_msg(int id_from, int id_to, N_STR* name, N_STR* chan, N_STR* txt, int color) {
    NETW_MSG* msg = NULL;

    N_STR* tmpstr = NULL;

    create_msg(&msg);

    __n_assert(msg, return NULL);

    add_int_to_msg(msg, NETMSG_STRING);
    add_int_to_msg(msg, id_from);
    add_int_to_msg(msg, id_to);
    add_int_to_msg(msg, color);

    add_nstrdup_to_msg(msg, nstrdup(name));
    add_nstrdup_to_msg(msg, nstrdup(chan));
    add_nstrdup_to_msg(msg, nstrdup(txt));

    tmpstr = make_str_from_msg(msg);
    delete_msg(&msg);
    __n_assert(tmpstr, return NULL);

    return tmpstr;

} /* netmsg_make_string_msg */

/*!\fn N_STR *netmsg_make_quit_msg( void )
 *\brief make a generic network NETMSG_QUIT message
 *\return N_STR *netmsg or NULL
 */
N_STR* netmsg_make_quit_msg(void) {
    NETW_MSG* msg = NULL;
    N_STR* tmpstr = NULL;

    create_msg(&msg);
    __n_assert(msg, return FALSE);

    add_int_to_msg(msg, NETMSG_QUIT);
    tmpstr = make_str_from_msg(msg);
    delete_msg(&msg);
    __n_assert(tmpstr, return NULL);

    return tmpstr;
} /* netmsg_make_quit_msg() */

/*!\fn netw_msg_get_type( N_STR *msg )
 *\param msg A char *msg_object you want to have type
 *\brief Get the type of message without killing the first number. Use with netw_get_XXX
 *\return The value corresponding to the type or FALSE
 */
int netw_msg_get_type(N_STR* msg) {
    int32_t tmpnb = 0;
    char* charptr = NULL;

    __n_assert(msg, return FALSE);

    charptr = msg->data;

    /* here we bypass the number of int, numebr of flt, number of str, (4+4+4) to get the
     * first number which should be type */
    charptr += 3 * sizeof(int32_t);
    memcpy(&tmpnb, charptr, sizeof(int32_t));
    tmpnb = ntohl(tmpnb);

    return tmpnb;
} /* netw_msg_get_type(...) */

/*!\fn  int netw_get_ident( N_STR *msg , int *type ,int *ident , N_STR **name , N_STR **passwd  )
 *\brief Retrieves identification from netwmsg
 *\param msg The source string from which we are going to extract the data
 *\param type NETMSG_IDENT_NEW , NETMSG_IDENT_REPLY_OK , NETMSG_IDENT_REPLY_NOK , NETMSG_IDENT_REQUEST
 *\param ident ID for the user
 *\param name Name of the user
 *\param passwd Password of the user
 *\return TRUE or FALSE
 */
int netw_get_ident(N_STR* msg, int* type, int* ident, N_STR** name, N_STR** passwd) {
    NETW_MSG* netmsg = NULL;

    __n_assert(msg, return FALSE);

    netmsg = make_msg_from_str(msg);

    __n_assert(netmsg, return FALSE);

    get_int_from_msg(netmsg, &(*type));
    get_int_from_msg(netmsg, &(*ident));

    if ((*type) != NETMSG_IDENT_REQUEST && (*type) != NETMSG_IDENT_REPLY_OK && (*type) != NETMSG_IDENT_REPLY_NOK) {
        n_log(LOG_ERR, "unknow (*type) %d", (*type));
        delete_msg(&netmsg);
        return FALSE;
    }

    get_nstr_from_msg(netmsg, &(*name));
    get_nstr_from_msg(netmsg, &(*passwd));

    delete_msg(&netmsg);

    return TRUE;
} /* netw_get_ident( ... ) */

/*!\fn int netw_get_position( N_STR *msg , int *id , double *X , double *Y , double *vx , double *vy , double *acc_x , double *acc_y , int *time_stamp )
 *\brief Retrieves position from netwmsg
 *\param msg The source string from which we are going to extract the data
 *\param id
 *\param X X position inside a big grid
 *\param Y Y position inside a big grid
 *\param vx X speed
 *\param vy Y speed
 *\param acc_x X acceleration
 *\param acc_y Y acceleration
 *\param time_stamp Current Time when it was sended (for some delta we would want to compute )
 *\return TRUE or FALSE
 */
int netw_get_position(N_STR* msg, int* id, double* X, double* Y, double* vx, double* vy, double* acc_x, double* acc_y, int* time_stamp) {
    NETW_MSG* netmsg = NULL;

    int type = 0;

    __n_assert(msg, return FALSE);

    netmsg = make_msg_from_str(msg);

    __n_assert(netmsg, return FALSE);

    get_int_from_msg(netmsg, &type);

    if (type != NETMSG_POSITION) {
        delete_msg(&netmsg);
        return FALSE;
    }

    get_int_from_msg(netmsg, &(*id));
    get_nb_from_msg(netmsg, &(*X));
    get_nb_from_msg(netmsg, &(*Y));
    get_nb_from_msg(netmsg, &(*vx));
    get_nb_from_msg(netmsg, &(*vy));
    get_nb_from_msg(netmsg, &(*acc_x));
    get_nb_from_msg(netmsg, &(*acc_y));
    get_int_from_msg(netmsg, &(*time_stamp));

    delete_msg(&netmsg);

    return TRUE;
} /* netw_get_position( ... ) */

/*!\fn netw_get_string( N_STR *msg , int *id , N_STR **name , N_STR **chan , N_STR **txt , int *color )
 *\brief Retrieves string from netwmsg
 *\param msg The source string from which we are going to extract the data
 *\param id The ID of the sending client
 *\param name Name of user
 *\param chan Target Channel, if any. Pass "ALL" to target the default channel
 *\param txt The text to send
 *\param color The color of the text
 *
 *\return TRUE or FALSE
 */
int netw_get_string(N_STR* msg, int* id, N_STR** name, N_STR** chan, N_STR** txt, int* color) {
    NETW_MSG* netmsg = NULL;

    int type = 0;

    __n_assert(msg, return FALSE);

    netmsg = make_msg_from_str(msg);

    __n_assert(netmsg, return FALSE);

    get_int_from_msg(netmsg, &type);

    if (type != NETMSG_STRING) {
        delete_msg(&netmsg);
        return FALSE;
    }

    get_int_from_msg(netmsg, id);
    get_int_from_msg(netmsg, color);

    get_nstr_from_msg(netmsg, &(*name));
    get_nstr_from_msg(netmsg, &(*chan));
    get_nstr_from_msg(netmsg, &(*txt));

    delete_msg(&netmsg);

    return TRUE;

} /* netw_get_string( ... ) */

/*!\fn netw_get_ping( N_STR *msg , int *type , int *from , int *to , int *time )
 *\brief Retrieves a ping travel elapsed time
 *\param msg The source string from which we are going to extract the data
 *\param type NETW_PING_REQUEST or NETW_PING_REPLY
 *\param from Identifiant of the sender
 *\param to Targetted Identifiant, -1 for server ping
 *\param time The time it was when the ping was sended
 *\return TRUE or FALSE
 */
int netw_get_ping(N_STR* msg, int* type, int* from, int* to, int* time) {
    NETW_MSG* netmsg;

    __n_assert(msg, return FALSE);

    netmsg = make_msg_from_str(msg);

    __n_assert(netmsg, return FALSE);

    get_int_from_msg(netmsg, &(*type));

    if ((*type) != NETMSG_PING_REQUEST && (*type) != NETMSG_PING_REPLY) {
        delete_msg(&netmsg);
        return FALSE;
    }

    get_int_from_msg(netmsg, &(*from));
    get_int_from_msg(netmsg, &(*to));
    get_int_from_msg(netmsg, &(*time));

    delete_msg(&netmsg);

    return TRUE;
} /* netw_get_ping( ... ) */

/*!\fn int netw_get_quit( N_STR *msg )
 *\brief get a formatted NETWMSG_QUIT message from the specified network
 *\param msg The source string from which we are going to extract the data
 *\return TRUE or FALSE
 */
int netw_get_quit(N_STR* msg) {
    __n_assert(msg, return FALSE);

    NETW_MSG* netmsg = NULL;
    netmsg = make_msg_from_str(msg);
    __n_assert(netmsg, return FALSE);

    int type = -1;
    get_int_from_msg(netmsg, &type);
    if (type != NETMSG_QUIT) {
        delete_msg(&netmsg);
        return FALSE;
    }
    delete_msg(&netmsg);
    return TRUE;
} /* netw_get_quit( ... ) */

#endif  // NO_NETMSG_API
