/*
 *  Copyright (c) 2012 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 "NETEQTEST_DummyRTPpacket.h"

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include <algorithm>  // max

#ifdef WIN32
#include <winsock2.h>
#else
#include <netinet/in.h> // for htons, htonl, etc
#endif

int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
{
    if (!fp)
    {
        return -1;
    }

    uint16_t length, plen;
    uint32_t offset;

    if (fread(&length, 2, 1, fp) == 0)
    {
        reset();
        return -2;
    }
    length = ntohs(length);

    if (fread(&plen, 2, 1, fp) == 0)
    {
        reset();
        return -1;
    }
    int packetLen = ntohs(plen);

    if (fread(&offset, 4, 1, fp) == 0)
    {
        reset();
        return -1;
    }
    // Store in local variable until we have passed the reset below.
    uint32_t receiveTime = ntohl(offset);

    // Use length here because a plen of 0 specifies rtcp.
    length = (uint16_t) (length - _kRDHeaderLen);

    // check buffer size
    if (_datagram && _memSize < length + 1)
    {
        reset();
    }

    if (!_datagram)
    {
        // Add one extra byte, to be able to fake a dummy payload of one byte.
        _datagram = new uint8_t[length + 1];
        _memSize = length + 1;
    }
    memset(_datagram, 0, length + 1);

    if (length == 0)
    {
        _datagramLen = 0;
        return packetLen;
    }

    // Read basic header
    if (fread(_datagram, 1, _kBasicHeaderLen, fp)
        != (size_t)_kBasicHeaderLen)
    {
        reset();
        return -1;
    }
    _receiveTime = receiveTime;
    _datagramLen = _kBasicHeaderLen;
    int header_length = _kBasicHeaderLen;

    // Parse the basic header
    WebRtcNetEQ_RTPInfo tempRTPinfo;
    int P, X, CC;
    parseBasicHeader(&tempRTPinfo, &P, &X, &CC);

    // Check if we have to extend the header
    if (X != 0 || CC != 0)
    {
        int newLen = _kBasicHeaderLen + CC * 4 + X * 4;
        assert(_memSize >= newLen + 1);

        // Read extension from file
        size_t readLen = newLen - _kBasicHeaderLen;
        if (fread(_datagram + _kBasicHeaderLen, 1, readLen,
            fp) != readLen)
        {
            reset();
            return -1;
        }
        _datagramLen = newLen;
        header_length = newLen;

        if (X != 0)
        {
            int totHdrLen = calcHeaderLength(X, CC);
            assert(_memSize >= totHdrLen);

            // Read extension from file
            size_t readLen = totHdrLen - newLen;
            if (fread(_datagram + newLen, 1, readLen, fp)
                != readLen)
            {
                reset();
                return -1;
            }
            _datagramLen = totHdrLen;
            header_length = totHdrLen;
        }
    }
    // Make sure that we have at least one byte of dummy payload.
    _datagramLen = std::max(static_cast<int>(length), header_length + 1);
    assert(_datagramLen <= _memSize);

    if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
    {
        // discard this payload
        return readFromFile(fp);
    }

    if (_filterSSRC && _selectSSRC != SSRC())
    {
        // Discard this payload.
        return(readFromFile(fp));
    }

    return packetLen;

}

int NETEQTEST_DummyRTPpacket::writeToFile(FILE *fp)
{
    if (!fp)
    {
        return -1;
    }

    uint16_t length, plen;
    uint32_t offset;

    // length including RTPplay header
    length = htons(_datagramLen + _kRDHeaderLen);
    if (fwrite(&length, 2, 1, fp) != 1)
    {
        return -1;
    }

    // payload length
    plen = htons(_datagramLen);
    if (fwrite(&plen, 2, 1, fp) != 1)
    {
        return -1;
    }

    // offset (=receive time)
    offset = htonl(_receiveTime);
    if (fwrite(&offset, 4, 1, fp) != 1)
    {
        return -1;
    }

    // Figure out the length of the RTP header.
    int headerLen;
    if (_datagramLen == 0)
    {
        // No payload at all; we are done writing to file.
        headerLen = 0;
    }
    else
    {
        parseHeader();
        headerLen = _payloadPtr - _datagram;
        assert(headerLen >= 0);
    }

    // write RTP header
    if (fwrite((unsigned short *) _datagram, 1, headerLen, fp) !=
        static_cast<size_t>(headerLen))
    {
        return -1;
    }

    return (headerLen + _kRDHeaderLen); // total number of bytes written

}

