-- Define the protocol
IPCC_PROTOCOL = Proto("IPCC", "IPCC")

-- Define protocol fields
local f_sof1 = ProtoField.uint8("IPCC_PROTOCOL.sof1", "SOF1", base.HEX)
local f_ipcc_ctrl = ProtoField.uint8("IPCC_PROTOCOL.ipcc_ctrl", "IPCC Ctrl", base.HEX)
local f_timestamp = ProtoField.uint32("IPCC_PROTOCOL.timestamp", "Timestamp", base.HEX)
local f_seq_no = ProtoField.uint16("IPCC_PROTOCOL.seq_no", "Sequence No", base.HEX)
local f_qos = ProtoField.uint8("IPCC_PROTOCOL.qos", "QoS", base.HEX)
local f_sa_id = ProtoField.uint16("IPCC_PROTOCOL.sa_id", "SA Id", base.HEX)
local f_da_id = ProtoField.uint16("IPCC_PROTOCOL.da_id", "DA Id", base.HEX)
local f_ipcc_id = ProtoField.uint8("IPCC_PROTOCOL.ipcc_id", "IPCC Id", base.HEX)
local f_ipcc_len = ProtoField.uint16("IPCC_PROTOCOL.ipcc_len", "IPCC Len", base.HEX)
local f_ipcc_data = ProtoField.uint8("IPCC_PROTOCOL.ipcc_data", "IPCC Data", base.HEX)
local f_keys = ProtoField.uint8("IPCC_PROTOCOL.keys", "Keys", base.HEX)
local f_sec_cfg = ProtoField.uint16("IPCC_PROTOCOL.sec_cfg", "Security Config", base.HEX)
local f_mac_cfg = ProtoField.uint16("IPCC_PROTOCOL.mac_cfg", "MAC Config", base.HEX)
local f_crc_32 = ProtoField.uint32("IPCC_PROTOCOL.crc_32", "CRC 32", base.HEX)
local f_cmac_hmac = ProtoField.uint8("IPCC_PROTOCOL.cmac_hmac", "CMAC/HMAC", base.HEX)
local disp = ProtoField.uint8("IPCC_PROTOCOL.disp", "disp", base.HEX)
-- Add the fields to the protocol
IPCC_PROTOCOL.fields = {
    f_sof1, f_ipcc_ctrl, f_timestamp, f_seq_no, f_qos, f_sa_id, f_da_id,
    f_ipcc_id, f_ipcc_len, f_ipcc_data, f_keys, f_sec_cfg, f_mac_cfg, 
    f_crc_32, f_cmac_hmac
}

--------------------------------------------------------------------------------------------------------------------------------------------

-- Dissector function for Telemetry (OBC to GS)
function IPCC_TM_dissector(buffer, pinfo, tree)  
 --pinfo.cols.protocol = "IPCC" 
--local tcp_flags = buffer(13, 1):uint()
--if bit.band(tcp_flags, 0x10) == 0x10  then  -- ACK flag (0x10)
     --Handle ACK packets or empty packets
  --  local subtree = tree:add(IPCC_PROTOCOL, buffer(), "IPCC")	
    --subtree:add(disp, buffer())
--else

    local subtree = tree:add(IPCC_PROTOCOL, buffer(), "IPCC")    
    local add=0
    local magic=0
    local info_display 
    -- Add the fields to the protocol subtree
    subtree:add(f_sof1, buffer(add, 1):le_uint())
	add=add+1
    subtree:add(f_ipcc_ctrl, buffer(add, 1):le_uint())
	add=add+1
    subtree:add(f_timestamp, buffer(add, 4):le_uint())
	add=add+4
    subtree:add(f_seq_no, buffer(add, 2):le_uint())
	add=add+2
    subtree:add(f_qos, buffer(add, 1):le_uint())
	add=add+1
-- logic for SA_ID-----
    	magic =buffer(add,1):le_uint()
	if bit.band(magic, 0x80) == 0 then
        	subtree:add(f_sa_id, buffer(add, 1):le_uint())  -- SA Id in HEX
		add=add+1
    	else
		magic=buffer(add, 2):le_uint()
		local dummy=magic & 0x8000    --to check 7th byte is 1
		if dummy == 0 then
			magic = magic & 0xff7f -- if 15th bit is 0 set 7th bit 0
		else 
			magic = magic & 0x7fff -- if 15 bit is 1 set 15th bit to 0
		end
        	subtree:add(f_sa_id, magic)  -- SAT Id in HEX
		add=add+2
    	end
 -- logic for DA_ID---
	magic =buffer(add,1):le_uint()
	if bit.band(magic, 0x80) == 0 then
        	subtree:add(f_da_id, buffer(add, 1):le_uint())  -- DA Id in HEX
		add=add+1
    	else
		magic=buffer(add, 2):le_uint()
		local dummy=magic & 0x8000    --to check 7th byte is 1
		if dummy == 0 then
			magic = magic & 0xff7f -- if 15th bit is 0 set 7th bit 0
		else 
			magic = magic & 0x7fff -- if 15 bit is 1 set 15th bit to 0
		end
        subtree:add(f_da_id, magic)  -- SAT Id in HEX
	add=add+2
    	end
	
    subtree:add(f_ipcc_id, buffer(add, 1):le_uint())
	 info_display= {buffer(add, 1):le_uint(),buffer(3, 4):le_uint() ,buffer(6, 2):le_uint()}
	add=add+1
    magic=buffer(add, 2):le_uint()
    subtree:add(f_ipcc_len, buffer(add, 2):le_uint())
	add=add+2

     local subtree2 = subtree:add(IPCC_PROTOCOL, buffer(), "IPCC_DATA")
    subtree2:add(f_ipcc_data, buffer(add,1))  -- Rest of the data
	add=add+magic
    subtree:add(f_keys, buffer(buffer:len() - 10, 1))         -- Keys
    subtree:add(f_sec_cfg, buffer(buffer:len() - 9, 1))       -- Security Config
    subtree:add(f_mac_cfg, buffer(buffer:len() - 8, 1))       -- MAC Config
    subtree:add(f_crc_32, buffer(buffer:len() - 4, 4))        -- CRC 32
    subtree:add(f_cmac_hmac, buffer(buffer:len() - 1, 1))     -- CMAC/HMAC




	pinfo.cols.info ="IPSS_ID=" ..info_display[1] .." TS=" ..info_display[2].." SEQ_NO="..info_display[3]  -- for info display in wireshark
end
--end
--------------------------------------------------------------------------------------------------------------------------------------------

-- Register the dissector function to the protocol
function IPCC_PROTOCOL.dissector(buffer, pinfo, tree)
    -- Set protocol column name in Wireshark
    pinfo.cols.protocol = "IPCC"

    -- Call the Telemetry dissector for the current packet
    IPCC_TM_dissector(buffer, pinfo, tree)
end

--------------------------------------------------------------------------------------------------------------------------------------------

-- Register the dissector for TCP port 8774
local tcp_port = 8774
local tcp_table = DissectorTable.get("tcp.port")

-- Add our custom dissector to the TCP table for the specified port
tcp_table:add(tcp_port, IPCC_PROTOCOL)
