/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "media/base/turnutils.h"

#include <stddef.h>

#include "rtc_base/gunit.h"

namespace cricket {

// Invalid TURN send indication messages. Messages are proper STUN
// messages with incorrect values in attributes.
TEST(TurnUtilsTest, InvalidTurnSendIndicationMessages) {
  size_t content_pos = SIZE_MAX;
  size_t content_size = SIZE_MAX;

  // Stun Indication message with Zero length
  uint8_t kTurnSendIndicationMsgWithNoAttributes[] = {
      0x00, 0x16, 0x00, 0x00,  // Zero length
      0x21, 0x12, 0xA4, 0x42,  // magic cookie
      '0',  '1',  '2',  '3',   // transaction id
      '4',  '5',  '6',  '7',  '8', '9', 'a', 'b',
  };
  EXPECT_FALSE(UnwrapTurnPacket(kTurnSendIndicationMsgWithNoAttributes,
                                sizeof(kTurnSendIndicationMsgWithNoAttributes),
                                &content_pos, &content_size));
  EXPECT_EQ(SIZE_MAX, content_pos);
  EXPECT_EQ(SIZE_MAX, content_size);

  // Stun Send Indication message with invalid length in stun header.
  const uint8_t kTurnSendIndicationMsgWithInvalidLength[] = {
      0x00, 0x16, 0xFF, 0x00,  // length of 0xFF00
      0x21, 0x12, 0xA4, 0x42,  // magic cookie
      '0',  '1',  '2',  '3',   // transaction id
      '4',  '5',  '6',  '7',  '8', '9', 'a', 'b',
  };
  EXPECT_FALSE(UnwrapTurnPacket(kTurnSendIndicationMsgWithInvalidLength,
                                sizeof(kTurnSendIndicationMsgWithInvalidLength),
                                &content_pos, &content_size));
  EXPECT_EQ(SIZE_MAX, content_pos);
  EXPECT_EQ(SIZE_MAX, content_size);

  // Stun Send Indication message with no DATA attribute in message.
  const uint8_t kTurnSendIndicatinMsgWithNoDataAttribute[] = {
      0x00, 0x16, 0x00, 0x08,  // length of
      0x21, 0x12, 0xA4, 0x42,  // magic cookie
      '0',  '1',  '2',  '3',   // transaction id
      '4',  '5',  '6',  '7',  '8',  '9', 'a',  'b',
      0x00, 0x20, 0x00, 0x04,  // Mapped address.
      0x00, 0x00, 0x00, 0x00,
  };
  EXPECT_FALSE(
      UnwrapTurnPacket(kTurnSendIndicatinMsgWithNoDataAttribute,
                       sizeof(kTurnSendIndicatinMsgWithNoDataAttribute),
                       &content_pos, &content_size));
  EXPECT_EQ(SIZE_MAX, content_pos);
  EXPECT_EQ(SIZE_MAX, content_size);
}

// Valid TURN Send Indication messages.
TEST(TurnUtilsTest, ValidTurnSendIndicationMessage) {
  size_t content_pos = SIZE_MAX;
  size_t content_size = SIZE_MAX;
  // A valid STUN indication message with a valid RTP header in data attribute
  // payload field and no extension bit set.
  const uint8_t kTurnSendIndicationMsgWithoutRtpExtension[] = {
      0x00, 0x16, 0x00, 0x18,  // length of
      0x21, 0x12, 0xA4, 0x42,  // magic cookie
      '0',  '1',  '2',  '3',   // transaction id
      '4',  '5',  '6',  '7',  '8',  '9',  'a',  'b',
      0x00, 0x20, 0x00, 0x04,  // Mapped address.
      0x00, 0x00, 0x00, 0x00,
      0x00, 0x13, 0x00, 0x0C,  // Data attribute.
      0x80, 0x00, 0x00, 0x00,  // RTP packet.
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  EXPECT_TRUE(UnwrapTurnPacket(
      kTurnSendIndicationMsgWithoutRtpExtension,
      sizeof(kTurnSendIndicationMsgWithoutRtpExtension), &content_pos,
      &content_size));
  EXPECT_EQ(12U, content_size);
  EXPECT_EQ(32U, content_pos);
}

// Verify that parsing of valid TURN Channel Messages.
TEST(TurnUtilsTest, ValidTurnChannelMessages) {
  const uint8_t kTurnChannelMsgWithRtpPacket[] = {
      0x40, 0x00, 0x00, 0x0C,
      0x80, 0x00, 0x00, 0x00,  // RTP packet.
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  size_t content_pos = 0, content_size = 0;
  EXPECT_TRUE(UnwrapTurnPacket(
      kTurnChannelMsgWithRtpPacket,
      sizeof(kTurnChannelMsgWithRtpPacket), &content_pos, &content_size));
  EXPECT_EQ(12U, content_size);
  EXPECT_EQ(4U, content_pos);
}

TEST(TurnUtilsTest, ChannelMessageZeroLength) {
  const uint8_t kTurnChannelMsgWithZeroLength[] = {0x40, 0x00, 0x00, 0x00};
  size_t content_pos = SIZE_MAX;
  size_t content_size = SIZE_MAX;
  EXPECT_TRUE(UnwrapTurnPacket(kTurnChannelMsgWithZeroLength,
                               sizeof(kTurnChannelMsgWithZeroLength),
                               &content_pos, &content_size));
  EXPECT_EQ(4, content_pos);
  EXPECT_EQ(0, content_size);
}

}  // namespace cricket
