#include <gtest/gtest.h>

#include "packet_helper.h"

/*
 * Layer 2 Tunneling Protocol
 *     Flags: 0xc802, Type: Control Message, Length Bit, Sequence Bit
 *         1... .... .... .... = Type: Control Message (1)
 *         .1.. .... .... .... = Length Bit: Length field is present
 *         .... 1... .... .... = Sequence Bit: Ns and Nr fields are present
 *         .... ..0. .... .... = Offset bit: Offset size field is not present
 *         .... ...0 .... .... = Priority: No priority
 *         .... .... .... 0010 = Version: 2
 *     Length: 105
 *     Tunnel ID: 0
 *     Session ID: 0
 *     Ns: 0
 *     Nr: 0
 *     Control Message AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1000 = Length: 8
 *         Vendor ID: Reserved (0)
 *         AVP Type: Control Message (0)
 *         Message Type: Start_Control_Request (1)
 *     Protocol Version AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1000 = Length: 8
 *         Vendor ID: Reserved (0)
 *         AVP Type: Protocol Version (2)
 *         Version: 1
 *         Revision: 0
 *     Framing Capabilities AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1010 = Length: 10
 *         Vendor ID: Reserved (0)
 *         AVP Type: Framing Capabilities (3)
 *         .... .... .... .... .... .... .... ..0. = Async Framing Supported: False
 *         .... .... .... .... .... .... .... ...1 = Sync Framing Supported: True
 *     Bearer Capabilities AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1010 = Length: 10
 *         Vendor ID: Reserved (0)
 *         AVP Type: Bearer Capabilities (4)
 *         .... .... .... .... .... .... .... ..0. = Analog Access Supported: False
 *         .... .... .... .... .... .... .... ...0 = Digital Access Supported: False
 *     Firmware Revision AVP
 *         0... .... .... .... = Mandatory: False
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1000 = Length: 8
 *         Vendor ID: Reserved (0)
 *         AVP Type: Firmware Revision (6)
 *         Firmware Revision: 1537 (0x0601)
 *     Host Name AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0001 0010 = Length: 18
 *         Vendor ID: Reserved (0)
 *         AVP Type: Host Name (7)
 *         Host Name: IIE-SM-THINK
 *     Vendor Name AVP
 *         0... .... .... .... = Mandatory: False
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1111 = Length: 15
 *         Vendor ID: Reserved (0)
 *         AVP Type: Vendor Name (8)
 *         Vendor Name: Microsoft
 *     Assigned Tunnel ID AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1000 = Length: 8
 *         Vendor ID: Reserved (0)
 *         AVP Type: Assigned Tunnel ID (9)
 *         Assigned Tunnel ID: 1
 *     Receive Window Size AVP
 *         1... .... .... .... = Mandatory: True
 *         .0.. .... .... .... = Hidden: False
 *         .... ..00 0000 1000 = Length: 8
 *         Vendor ID: Reserved (0)
 *         AVP Type: Receive Window Size (10)
 *         Receive Window Size: 8
 */

unsigned char v2_over_udp_ctrl_msg[] = {
    0xc8, 0x02, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
    0x01, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
    0x00, 0x06, 0x06, 0x01, 0x80, 0x12, 0x00, 0x00, 0x00, 0x07, 0x49, 0x49, 0x45, 0x2d, 0x53, 0x4d, 0x2d, 0x54, 0x48, 0x49, 0x4e, 0x4b, 0x00, 0x0f, 0x00, 0x00,
    0x00, 0x08, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x80, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00,
    0x08};

TEST(L2TPV2_OVER_UDP_UTILS, CRTL_MSG)
{
    const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v2_over_udp_ctrl_msg;

    EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 2);
    EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 1);
    EXPECT_TRUE(calc_udp_l2tpv2_hdr_len((const char *)v2_over_udp_ctrl_msg, sizeof(v2_over_udp_ctrl_msg)) == 105);
}

/*
 * Layer 2 Tunneling Protocol
 *     Flags: 0x4002, Type: Data Message, Length Bit
 *         0... .... .... .... = Type: Data Message (0)
 *         .1.. .... .... .... = Length Bit: Length field is present
 *         .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present
 *         .... ..0. .... .... = Offset bit: Offset size field is not present
 *         .... ...0 .... .... = Priority: No priority
 *         .... .... .... 0010 = Version: 2
 *     Length: 78
 *     Tunnel ID: 28998
 *     Session ID: 2
 */

unsigned char v2_over_udp_data_msg[] = {
    0x40, 0x02, 0x00, 0x4e, 0x71, 0x46, 0x00, 0x02};

TEST(L2TPV2_OVER_UDP_UTILS, DATA_MSG)
{
    const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v2_over_udp_data_msg;

    EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 2);
    EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 0);
    EXPECT_TRUE(calc_udp_l2tpv2_hdr_len((const char *)v2_over_udp_data_msg, sizeof(v2_over_udp_data_msg)) == 8);
}

/*
 * TODO
 */

unsigned char v3_over_udp_ctrl_msg[] = {};

TEST(L2TPV3_OVER_UDP_UTILS, CRTL_MSG)
{
    // TODO
}

/*
 * Layer 2 Tunneling Protocol version 3
 *     Flags: 0x0003, Type: Data Message
 *         0... .... .... .... = Type: Data Message (0)
 *         .0.. .... .... .... = Length Bit: Length field is not present
 *         .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present
 *         .... .... .... 0011 = Version: 3
 *     Reserved: 0x0000
 *     Session ID: 0x00000fa0
 *     [Pseudowire Type: Unknown (0)]
 *     Cookie: 00000000
 */

unsigned char v3_over_udp_data_msg[] = {
    0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa0, 0x00, 0x00, 0x00, 0x00};

TEST(L2TPV3_OVER_UDP_UTILS, DATA_MSG)
{
    const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v3_over_udp_data_msg;

    EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 3);
    EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 0);
    EXPECT_TRUE(calc_udp_l2tpv3_hdr_len((const char *)v3_over_udp_data_msg, sizeof(v3_over_udp_data_msg)) == 12);
}

/*
 * TODO
 */

unsigned char v3_over_ip_ctrl_msg[] = {};

TEST(L2TPV3_OVER_IP_UTILS, CRTL_MSG)
{
    // TODO
}

/*
 * Layer 2 Tunneling Protocol version 3
 *     Session ID: 0x00009652
 *     [Pseudowire Type: Unknown (0)]
 *     Cookie: ca031078
 */

unsigned char v3_over_ip_data_msg[] = {
    0x00, 0x00, 0x96, 0x52, 0xca, 0x03, 0x10, 0x78};

TEST(L2TPV3_OVER_IP_UTILS, DATA_MSG)
{
    EXPECT_TRUE(ntohl(*((uint32_t *)v3_over_ip_data_msg)) != 0); // data message
    EXPECT_TRUE(calc_ip_l2tpv3_hdr_len((const char *)v3_over_ip_data_msg, sizeof(v3_over_ip_data_msg)) == 8);
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
