/*
 * Copyright (C) 2013, 2014 Giorgio Vazzana
 *
 * This file is part of Seren.
 *
 * Seren is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Seren is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PC_ENGINE_INTERNAL_H
#define PC_ENGINE_INTERNAL_H

#define PCE_PACKET_MASK_MODE           0xC000
#define PCE_PACKET_MASK_UNUSED         0x3000
#define PCE_PACKET_MASK_FAMILY         0x0F00
#define PCE_PACKET_MASK_TYPE           0x00FF

#define PCE_PACKET_MASK_MFTYPE         0xCFFF
#define PCE_PACKET_MASK_FTYPE          0x0FFF

#define PCE_PACKET_MODE_CLEAR          0x0000
#define PCE_PACKET_MODE_SECURE         0x4000
#define PCE_PACKET_MODE_PSK            0x8000
#define PCE_PACKET_MODE_RESERVED       0xC000

#define PCE_PACKET_FAMILY_HANDSHAKE    0x0000
#define PCE_PACKET_FAMILY_DATA         0x0100
#define PCE_PACKET_FAMILY_RELAY        0x0200
#define PCE_PACKET_FAMILY_TELEMETRY    0x0300
#define PCE_PACKET_FAMILY_RTT          0x0400
#define PCE_PACKET_FAMILY_ENCRYPTED    0x0F00

/* A CALL udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be),  (mode, family, type)
 * Payload:
 *   pc_engine_version_major     (uint8)
 *   pc_engine_version_minor     (uint8)
 *   pc_engine_version_subminor  (uint8)
 *   nick                        (NICKLEN bytes)
 *   pgid                        (uint8)
 *   algo                        (uint8)
 *   pklen                       (uint16, be)
 *   pk                          (variable)
 */
#define PCE_PACKET_TYPE_CALL           0
#define PCE_PACKET_FTYPE_CALL          (PCE_PACKET_FAMILY_HANDSHAKE | PCE_PACKET_TYPE_CALL)

/* A CONNECT udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   same as for CALL packet
 */
#define PCE_PACKET_TYPE_CONNECT        1
#define PCE_PACKET_FTYPE_CONNECT       (PCE_PACKET_FAMILY_HANDSHAKE | PCE_PACKET_TYPE_CONNECT)

/* A REFUSE udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   reason                      (uint16, be)
 */
#define PCE_PACKET_TYPE_REFUSE         2
#define PCE_PACKET_FTYPE_REFUSE        (PCE_PACKET_FAMILY_HANDSHAKE | PCE_PACKET_TYPE_REFUSE)

/* A TABLE udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   pklen                       (uint16, be)
 *   pk                          (variable)
 *   table_size                  (uint16, be)
 *   my_nick                     (NICKLEN bytes)
 * repeat table_size-1 times for all other nodes except caller:
 *   nick                        (NICKLEN bytes)
 *   addr                        (uint32, be)
 *   port                        (uint16, be)
 */
#define PCE_PACKET_TYPE_TABLE          3
#define PCE_PACKET_FTYPE_TABLE         (PCE_PACKET_FAMILY_HANDSHAKE | PCE_PACKET_TYPE_TABLE)

/* A BYE udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 */
#define PCE_PACKET_TYPE_BYE            4
#define PCE_PACKET_FTYPE_BYE           (PCE_PACKET_FAMILY_HANDSHAKE | PCE_PACKET_TYPE_BYE)


/* An AUDIO udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 *   sequence_number             (uint32, be)
 * Payload:
 *   data                        (variable size, 4000 byte max)
 *
 * The field sequence_number must start at 0 for the first packet and increase
 * monotonically. The payload data is the opus packet coming out of the encoder.
 */
#define PCE_PACKET_TYPE_AUDIO          0
#define PCE_PACKET_FTYPE_AUDIO         (PCE_PACKET_FAMILY_DATA | PCE_PACKET_TYPE_AUDIO)
#define PCE_PACKET_AUDIO_HEADER_LEN    6
#define PCE_PACKET_AUDIO_PAYLOAD_LEN   4000
#define PCE_PACKET_AUDIO_MAXLEN        (PCE_PACKET_AUDIO_HEADER_LEN + PCE_PACKET_AUDIO_PAYLOAD_LEN)

/* A NOP udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 */
#define PCE_PACKET_TYPE_NOP            1
#define PCE_PACKET_FTYPE_NOP           (PCE_PACKET_FAMILY_DATA | PCE_PACKET_TYPE_NOP)

/* A CHAT udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   data                        (UTF-8 string, null terminated, variable size)
 */
#define PCE_PACKET_TYPE_CHAT           2
#define PCE_PACKET_FTYPE_CHAT          (PCE_PACKET_FAMILY_DATA | PCE_PACKET_TYPE_CHAT)


/* A RELAY udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 *   dest_addr                   (uint32, be)
 *   dest_port                   (uint16, be)
 * Payload:
 *   packet to relay             (variable size)
 */
#define PCE_PACKET_TYPE_RELAY          0
#define PCE_PACKET_FTYPE_RELAY         (PCE_PACKET_FAMILY_RELAY | PCE_PACKET_TYPE_RELAY)

/* A RELAYED udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 *   source_addr                 (uint32, be)
 *   source_port                 (uint16, be)
 * Payload:
 *   packet relayed              (variable size)
 */
#define PCE_PACKET_TYPE_RELAYED        1
#define PCE_PACKET_FTYPE_RELAYED       (PCE_PACKET_FAMILY_RELAY | PCE_PACKET_TYPE_RELAYED)


/* A PLINFO udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   pl10k                       (uint32, be),  (packet_loss_perc * 10000)
 */
#define PCE_PACKET_TYPE_PLINFO         0
#define PCE_PACKET_FTYPE_PLINFO        (PCE_PACKET_FAMILY_TELEMETRY | PCE_PACKET_TYPE_PLINFO)


/* A RTTREQ udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   sec                         (uint32, be)
 *   usec                        (uint32, be)
 */
#define PCE_PACKET_TYPE_RTTREQ         0
#define PCE_PACKET_FTYPE_RTTREQ        (PCE_PACKET_FAMILY_RTT | PCE_PACKET_TYPE_RTTREQ)

/* A RTTANS udp packet has the following structure:
 * Header:
 *   packet_id                   (uint16, be)
 * Payload:
 *   sec                         (uint32, be)
 *   usec                        (uint32, be)
 */
#define PCE_PACKET_TYPE_RTTANS         1
#define PCE_PACKET_FTYPE_RTTANS        (PCE_PACKET_FAMILY_RTT | PCE_PACKET_TYPE_RTTANS)


/* A ENCRYPTED udp packet has the following structure:
 * Header:
 *   packet_id             (uint16, be)
 *   initialization_vector (2x uint32 or 2x uint64, be)
 * Payload:
 *   encrypted packet      (variable size)
 *
 * The payload is encrypted with XTEA, CAST-128, BLOWFISH or CAMELLIA.
 * Its size must be a multiple of the blocksize of the used cipher (16 bytes for
 * CAMELLIA and TWOFISH, 8 bytes otherwise). To obtain this, a padding at the
 * end of the packet is added, which consists of exactly n bytes all with value n.
 *
 * Note: Considering a blocksize of 8 bytes, if the size of the packet is already
 * multiple of 8, another 8 bytes will be added, all with value 8. This means
 * that n>0 always and (packetlen + n) % 8 = 0.
 */
#define PCE_PACKET_TYPE_XTEA           0
#define PCE_PACKET_TYPE_CAST128        1
#define PCE_PACKET_TYPE_BLOWFISH       2
#define PCE_PACKET_TYPE_CAMELLIA       3
#define PCE_PACKET_TYPE_TWOFISH        4

#define PCE_PACKET_FTYPE_XTEA          (PCE_PACKET_FAMILY_ENCRYPTED | PCE_PACKET_TYPE_XTEA)
#define PCE_PACKET_FTYPE_CAST128       (PCE_PACKET_FAMILY_ENCRYPTED | PCE_PACKET_TYPE_CAST128)
#define PCE_PACKET_FTYPE_BLOWFISH      (PCE_PACKET_FAMILY_ENCRYPTED | PCE_PACKET_TYPE_BLOWFISH)
#define PCE_PACKET_FTYPE_CAMELLIA      (PCE_PACKET_FAMILY_ENCRYPTED | PCE_PACKET_TYPE_CAMELLIA)
#define PCE_PACKET_FTYPE_TWOFISH       (PCE_PACKET_FAMILY_ENCRYPTED | PCE_PACKET_TYPE_TWOFISH)

#endif