require"socket"
module(...,package.seeall)

--[[
Ϊӣݺ󣬽ģʽȻʱ˳ģʽٷݣѭ

1Ӻ̨λð"loc data\r\n"̨ʱʱΪ2ӣ2ʧܣһֱԣͳɹ߳ʱ󶼽ģʽ
2ģʽ5Ӻ˳ģʽȻ1
ѭ2
2յ̨ʱrcvдӡ
ʱԼķ޸PROTADDRPORT֧IPַ
]]

local ssub,schar,smatch,sbyte,slen = string.sub,string.char,string.match,string.byte,string.len
--ʱԼķ
local SCK_IDX,PROT,ADDR,PORT = 1,"TCP","120.26.196.195",9999
--ÿӺ̨쳣
--һڵĶӺ̨ʧܣ᳢ΪRECONN_PERIOD룬RECONN_MAX_CNT
--һڶûӳɹȴRECONN_CYCLE_PERIOD·һ
--RECONN_CYCLE_MAX_CNTεڶûӳɹ
local RECONN_MAX_CNT,RECONN_PERIOD,RECONN_CYCLE_MAX_CNT,RECONN_CYCLE_PERIOD = 3,5,1,20
--reconncnt:ǰڣѾĴ
--reconncyclecnt:ٸڣûӳɹ
--һӳɹḴλ
--conning:Ƿڳ
local reconncnt,reconncyclecnt,conning = 0,0

--[[
print
  ӡӿڣļедӡtestǰ׺
  
ֵ
]]
local function print(...)
	_G.print("test",...)
end

--[[
snd
  ÷ͽӿڷ
  
        data͵ݣڷͽ¼ntfyУḳֵitem.data
		para͵Ĳڷͽ¼ntfyУḳֵitem.para 
ֵ÷ͽӿڵĽݷǷɹĽݷǷɹĽntfyеSEND¼֪ͨtrueΪɹΪʧ
]]
function snd(data,para)
	return socket.send(SCK_IDX,data,para)
end


--[[
locrptimeout
  λðݷͳʱֱӽģʽ
    
ֵ
]]
local function locrptimeout()
	print("locrptimeout")
	locrptcb(true)
end

--[[
locrpt
  λðݵ̨
   
ֵ
]]
function locrpt()
	print("locrpt")	
	--÷ͽӿڳɹݷͳɹݷǷɹntfyеSEND¼֪ͨ
	if snd("loc data\r\n","LOCRPT")	then
		--2Ӷʱʱ2ݶûзͳɹֱӽģʽ
		sys.timer_start(locrptimeout,120000)
	--÷ͽӿʧܣ
	else
		locrptcb()
	end	
end

--[[
locrptcb
  λðͽͳɹ߳ʱģʽ5ӵġ˳ģʽӺ̨ʱ
    
        result boolͣͽǷʱtrueΪɹ߳ʱΪʧ
		itemtableͣ{data=,para=}ϢشĲݣsocket.sendʱĵ2͵3ֱΪdatparitem={data=dat,para=par}
ֵ
]]
function locrptcb(result,item)
	print("locrptcb",result)
	if result then
		socket.disconnect(SCK_IDX)
		link.shut()
		misc.setflymode(true)
		sys.timer_start(connect,300000)
		sys.timer_stop(locrptimeout)
	else
		sys.timer_start(reconn,RECONN_PERIOD*1000)
	end
end

--[[
sndcb
  ݽ¼Ĵ
    
        result boolͣϢ¼trueΪɹΪʧ
		itemtableͣ{data=,para=}ϢشĲݣsocket.sendʱĵ2͵3ֱΪdatparitem={data=dat,para=par}
ֵ
]]
local function sndcb(item,result)
	print("sndcb",item.para,result)
	if not item.para then return end
	if item.para=="LOCRPT" then
		locrptcb(result,item)
	end	
end

--[[
reconn
  ̨
        һڵĶӺ̨ʧܣ᳢ΪRECONN_PERIOD룬RECONN_MAX_CNT
        һڶûӳɹȴRECONN_CYCLE_PERIOD·һ
        RECONN_CYCLE_MAX_CNTεڶûӳɹ
  
ֵ
]]
function reconn()
	print("reconn",reconncnt,conning,reconncyclecnt)
	--conningʾڳӺ̨һҪжϴ˱пܷ𲻱Ҫreconncntӣʵʵ
	if conning then return end
	--һڵ
	if reconncnt < RECONN_MAX_CNT then		
		reconncnt = reconncnt+1
		link.shut()
		connect()
	--һڵʧ
	else
		reconncnt,reconncyclecnt = 0,reconncyclecnt+1
		if reconncyclecnt >= RECONN_CYCLE_MAX_CNT then
			dbg.restart("connect fail")
		end
		sys.timer_start(reconn,RECONN_CYCLE_PERIOD*1000)
	end
end

--[[
ntfy
  socket״̬Ĵ
  
        idxnumberͣsocket.luaάsocket idxsocket.connectʱĵһͬԺԲ
        evtstringͣϢ¼
		result boolͣϢ¼trueΪɹΪʧ
		itemtableͣ{data=,para=}ϢشĲݣĿǰֻSEND͵¼õ˴˲socket.sendʱĵ2͵3ֱΪdatparitem={data=dat,para=par}
ֵ
]]
function ntfy(idx,evt,result,item)
	print("ntfy",evt,result,item)
	--ӽsocket.connect첽¼
	if evt == "CONNECT" then
		conning = false
		--ӳɹ
		if result then
			reconncnt,reconncyclecnt = 0,0
			--ֹͣʱ
			sys.timer_stop(reconn)			
			--λð̨
			locrpt()
		--ʧ
		else
			--RECONN_PERIOD
			sys.timer_start(reconn,RECONN_PERIOD*1000)
		end	
	--ݷͽsocket.send첽¼
	elseif evt == "SEND" then
		if item then
			sndcb(item,result)
		end
	--ӱϿ
	elseif evt == "STATE" and result == "CLOSED" then
		--Զ幦ܴ
	--Ͽlink.shut첽¼
	elseif evt == "STATE" and result == "SHUTED" then
		--Զ幦ܴ
	--Ͽsocket.disconnect첽¼
	elseif evt == "DISCONNECT" then
		--Զ幦ܴ			
	end
	--
	if smatch((type(result)=="string") and result or "","ERROR") then
		--Ͽ·¼
		link.shut()
	end
end

--[[
rcv
  socketݵĴ
  
        idx socket.luaάsocket idxsocket.connectʱĵһͬԺԲ
        dataյ
ֵ
]]
function rcv(idx,data)
	print("rcv",data)
end

--[[
connect
  ̨ӣ
        Ѿ׼ãӺ̨ᱻ𣬵׼ԶȥӺ̨
		ntfysocket״̬Ĵ
		rcvsocketݵĴ
  
ֵ
]]
function connect()
	misc.setflymode(false)
	socket.connect(SCK_IDX,PROT,ADDR,PORT,ntfy,rcv)
	conning = true
end

connect()
