/***************************************************************************************
 *
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 *
 *  By downloading, copying, installing or using the software you agree to this license.
 *  If you do not agree to this license, do not download, install, 
 *  copy or use the software.
 *
 *  Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
 *
 *  Redistribution and use in binary forms, with or without modification, are permitted.
 *
 *  Unless required by applicable law or agreed to in writing, software distributed 
 *  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 *  language governing permissions and limitations under the License.
 *
****************************************************************************************/

#include "sys_inc.h"
#include "rtsp_ws.h"
#include "rtp.h"


int rtsp_ws_decode_data(WSMSG * p_msg)
{
    int length, has_mask;
    char * p_buff = p_msg->buff;
    
    /**
	 * Extracting information from frame
	 */
	has_mask = p_buff[1] & 0x80 ? 1 : 0;
	length = p_buff[1] & 0x7f;

	p_msg->opcode = (p_buff[0] & 0xF);
	p_msg->finbit = ((p_buff[0] & 0x80) ? 1 : 0);

    /**
	 * We need to handle the received frame differently according to which
	 * length that the frame has set.
	 *
	 * length <= 125: We know that length is the actual length of the message,
	 * 				  and that the maskin data must be placed 2 bytes further 
	 * 				  ahead.
	 * length == 126: We know that the length is an unsigned 16 bit integer,
	 * 				  which is placed at the 2 next bytes, and that the masking
	 * 				  data must be further 2 bytes away.
	 * length == 127: We know that the length is an unsigned 64 bit integer,
	 * 				  which is placed at the 8 next bytes, and that the masking
	 * 				  data must be further 2 bytes away.
	 */
	if (length <= 125) 
	{
	    if (p_msg->rcv_len < 6)
	    {
	        return 0;
	    }
	    
		p_msg->msg_len = length;	
		p_msg->skip = 2;

		if (has_mask)
		{
		    p_msg->skip += 4;
		    memcpy(&p_msg->mask, p_buff + 2, sizeof(p_msg->mask));
		}
	}
	else if (length == 126) 
	{
	    if (p_msg->rcv_len < 8)
	    {
	        return 0;
	    }
	    
		p_msg->msg_len = rtp_read_uint16((uint8 *)p_buff + 2);
		p_msg->skip = 4;

		if (has_mask)
		{
		    p_msg->skip += 4;
		    memcpy(&p_msg->mask, p_buff + 4, sizeof(p_msg->mask));
		}
	} 
	else if (length == 127) 
	{
	    if (p_msg->rcv_len < 14)
	    {
	        return 0;
	    }

		p_msg->msg_len = (uint32)rtp_read_uint64((uint8 *)p_buff + 2);
		p_msg->skip = 10;

		if (has_mask)
		{
		    p_msg->skip += 4;
		    memcpy(&p_msg->mask, p_buff + 10, sizeof(p_msg->mask));
		}
	} 
	else 
	{
		log_print(HT_LOG_ERR, "%s, Obscure length received from client: %d\r\n", __FUNCTION__, length);
		return -1;	
	}

	/**
	 * If the message length is greater that our WS_MAXMESSAGE constant, we
	 * skip the message and close the connection.
	 */
	if (p_msg->msg_len > WS_MAXMESSAGE) 
	{
		log_print(HT_LOG_ERR, "%s, Message received was bigger than WS_MAXMESSAGE\r\n", __FUNCTION__);
		return -1;
	}

	uint32 buf_len = (p_msg->rcv_len - p_msg->skip);

	/**
	 * The message read from recv is larger than the message we are supposed
	 * to receive. This means that we have received the first part of the next
	 * message as well.
	 */
	if (buf_len >= p_msg->msg_len) 
	{
	    if (has_mask)
	    {
	        char * buff = p_msg->buff + p_msg->skip;
	        
            /**
             * If everything went well, we have to remove the masking from the data.
             */
        	for (uint32 i = 0; i < p_msg->msg_len; i++)
        	{
        		buff[i] = buff[i] ^ p_msg->mask[i % 4];
        	}
    	}
	
		return 1;
	}
	
	return 0;
}

/***
 * websocket encod data, add websocket header before p_data
 * The p_data pointer must reserve a certain amount of space
 */
int rtsp_ws_encode_data(uint8 * p_data, int len, uint8 opcode, uint8 have_mask)
{
    int offset = 0;
    uint8 mask[4];

    if (have_mask)
    {
        mask[0] = rand();
        mask[1] = rand();
        mask[2] = rand();
        mask[3] = rand();

        for (int32 i = 0; i < len; i++)
    	{
    		p_data[i] = p_data[i] ^ mask[i % 4];
    	}
	}
    	
    /**
     * RFC6455 message encoding
     */
    if (len <= 125) 
    {
        p_data -= have_mask ? 6 : 2;
        p_data[0] = opcode;
        p_data[1] = have_mask ? (len | 0x80) : len;
        if (have_mask)
        {
            memcpy(p_data+2, mask, 4);
        }
        offset = have_mask ? 6 : 2;
    } 
    else if (len <= 65535) 
    {
        p_data -= have_mask ? 8 : 4;
        p_data[0] = opcode;
        p_data[1] = have_mask ? (126 | 0x80) : 126;
        rtp_write_uint16(p_data + 2, len);
        if (have_mask)
        {
            memcpy(p_data+4, mask, 4);
        }
        offset = have_mask ? 8 : 4;
    }
    else 
    {
        uint64 len64 = len;
        p_data -= have_mask ? 14 : 10;
        p_data[0] = opcode;
        p_data[1] = have_mask ? (127 | 0x80) : 127;
        rtp_write_uint32(p_data + 2, len64 & 0xFFFF);
        rtp_write_uint32(p_data + 6, (len64 >> 32) & 0xFFFF);
        if (have_mask)
        {
            memcpy(p_data+10, mask, 4);
        }
        offset = have_mask ? 14 : 10;
    }

    return offset;
}


