--[[
ģƣ·SOCKET
ģ鹦ܣ缤SOCKETĴӡշ״̬ά
ģ޸ʱ䣺2017.02.14
]]

--ģ,
local base = _G
local string = require"string"
local table = require"table"
local sys = require"sys"
local ril = require"ril"
local net = require"net"
local rtos = require"rtos"
local sim = require"sim"
module(...,package.seeall)

--سõȫֺ
local print = base.print
local pairs = base.pairs
local tonumber = base.tonumber
local tostring = base.tostring
local req = ril.request

--socket id0ʼͬʱֵ֧socket8
local MAXLINKS = 7
--IPʧʱ5
local IPSTART_INTVL = 5000

--socketӱ
local linklist = {}
--ipstatusIP״̬
--shutingǷڹر
local ipstatus,shuting = "IP INITIAL"
--GPRS總״̬"1"ţδ
local cgatt
local DEFAULT_APN = "CMIOT"
--apnû
local apnname = DEFAULT_APN
local username=''
local password=''
--socketconnectnoretintervalûκӦconnectnoretrestartΪtrue
local connectnoretrestart = false
local connectnoretinterval
--apnflgģǷԶȡapnϢtrueǣfalseûӦýűԼsetapnӿapnû
--checkciicrtmִAT+CIICRcheckciicrtmcheckciicrtmûмɹ;ִAT+CIPSHUT
--flymodeǷڷģʽ
--updatingǷִԶ(update.lua)
--dbgingǷִdbg(dbg.lua)
--ntpingǷִNTPʱͬ(ntp.lua)
--shutpendingǷеȴĽAT+CIPSHUT
local apnflag,checkciicrtm,ciicrerrcb,flymode,updating,dbging,ntping,shutpending=true

--[[
setapn
  apnû
  
		aapn
		bû
		c
ֵ
]]
function setapn(a,b,c)
	apnname,username,password = a,b or '',c or ''
	apnflag=false
end

--[[
getapn
  ȡapn
  
ֵapn
]]
function getapn()
	return apnname
end

--[[
connectingtimerfunc
  socketӳʱûӦ
  
		idsocket id
ֵ
]]
local function connectingtimerfunc(id)
	print("connectingtimerfunc",id,connectnoretrestart)
	if connectnoretrestart then
		sys.restart("link.connectingtimerfunc")
	end
end

--[[
stopconnectingtimer
  رաsocketӳʱûӦ𡱶ʱ
  
		idsocket id
ֵ
]]
local function stopconnectingtimer(id)
	print("stopconnectingtimer",id)
	sys.timer_stop(connectingtimerfunc,id)
end

--[[
startconnectingtimer
  socketӳʱûӦ𡱶ʱ
  
		idsocket id
ֵ
]]
local function startconnectingtimer(id)
	print("startconnectingtimer",id,connectnoretrestart,connectnoretinterval)
	if id and connectnoretrestart and connectnoretinterval and connectnoretinterval > 0 then
		sys.timer_start(connectingtimerfunc,connectnoretinterval,id)
	end
end

--[[
setconnectnoretrestart
  ásocketӳʱûӦ𡱵ĿƲ
  
		flagܿأtruefalse
		intervalʱʱ䣬λ
ֵ
]]
function setconnectnoretrestart(flag,interval)
	connectnoretrestart = flag
	connectnoretinterval = interval
end

--[[
setupIP
  ͼIP
  
ֵ
]]
function setupIP()
	print("link.setupIP:",ipstatus,cgatt,flymode)
	--Ѽߴڷģʽֱӷ
	if ipstatus ~= "IP INITIAL" or flymode then
		return
	end
	--gprsûи
	if cgatt ~= "1" then
		print("setupip: wait cgatt")
		return
	end

	--IP
	req("AT+CSTT=\""..apnname..'\",\"'..username..'\",\"'..password.. "\"")
	req("AT+CIICR")
	--ѯ״̬
	req("AT+CIPSTATUS")
	ipstatus = "IP START"
end

--[[
emptylink
  ȡõsocket id
  
ֵõsocket idûпõķnil
]]
local function emptylink()
	for i = 0,MAXLINKS do
		if linklist[i] == nil then
			return i
		end
	end

	return nil
end

--[[
validaction
  ĳsocket idĶǷЧ
  
		idsocket id
		action
ֵtrueЧfalseЧ
]]
local function validaction(id,action)
	--socketЧ
	if linklist[id] == nil then
		print("link.validaction:id nil",id)
		return false
	end

	--ͬһ״̬ظִ
	if action.."ING" == linklist[id].state then
		print("link.validaction:",action,linklist[id].state)
		return false
	end

	local ing = string.match(linklist[id].state,"(ING)",-3)

	if ing then
		--ڴʱ,,߹رǿԵ
		if action == "CONNECT" then
			print("link.validaction: action running",linklist[id].state,action)
			return false
		end
	end

	-- ִ,ִ
	return true
end

--[[
openid
  socketĲϢ
  
		idsocket id
		notifysocket״̬
		recvsocketݽմ
		tagsocket
ֵtrueɹfalseʧ
]]
function openid(id,notify,recv,tag)
	--idԽidsocketѾ
	if id > MAXLINKS or linklist[id] ~= nil then
		print("openid:error",id)
		return false
	end

	local link = {
		notify = notify,
		recv = recv,
		state = "INITIAL",
		tag = tag,
	}

	linklist[id] = link

	--עurc
	ril.regurc(tostring(id),urc)

	--IP
	if ipstatus ~= "IP STATUS" and ipstatus ~= "IP PROCESSING" then
		setupIP()
	end

	return true
end

--[[
open
  һsocket
  
		notifysocket״̬
		recvsocketݽմ
		tagsocket
ֵnumber͵idʾɹnilʾʧ
]]
function open(notify,recv,tag)
	local id = emptylink()

	if id == nil then
		return nil,"no empty link"
	end

	openid(id,notify,recv,tag)

	return id
end

--[[
close
  رһsocketsocketвϢ
  
		idsocket id
ֵtrueɹfalseʧ
]]
function close(id)
	--Ƿر
	if validaction(id,"CLOSE") == false then
		return false
	end
	--ڹر
	linklist[id].state = "CLOSING"
	--ATر
	req("AT+CIPCLOSE="..id)

	return true
end

--[[
asyncLocalEvent
  socket첽֪ͨϢĴ
  
		msg첽֪ͨϢ"LINK_ASYNC_LOCAL_EVENT"
		cbfuncϢص
		idsocket id
		val֪ͨϢĲ
ֵtrueɹfalseʧ
]]
function asyncLocalEvent(msg,cbfunc,id,val)
	cbfunc(id,val)
end

--עϢLINK_ASYNC_LOCAL_EVENTĴ
sys.regapp(asyncLocalEvent,"LINK_ASYNC_LOCAL_EVENT")

--[[
connect
  socketӷ
  
		idsocket id
		protocolЭ飬TCPUDP
		addressַ
		port˿
ֵɹͬtruefalse
]]
function connect(id,protocol,address,port)
	--Ӷ
	if validaction(id,"CONNECT") == false or linklist[id].state == "CONNECTED" then
		return false
	end
	print("link.connect",id,protocol,address,port,ipstatus,shuting,shutpending)

	linklist[id].state = "CONNECTING"

	if cc and cc.anycallexist() then
		--ͨ ҵǰͨʹ첽֪ͨʧ
		print("link.connect:failed cause call exist")
		sys.dispatch("LINK_ASYNC_LOCAL_EVENT",statusind,id,"CONNECT FAIL")
		return true
	end

	local connstr = string.format("AT+CIPSTART=%d,\"%s\",\"%s\",%s",id,protocol,address,port)

	if (ipstatus ~= "IP STATUS" and ipstatus ~= "IP PROCESSING") or shuting or shutpending then
		--ipδ׼ȼȴ
		linklist[id].pending = connstr
	else
		--ATӷ
		req(connstr)
		startconnectingtimer(id)
	end

	return true
end

--[[
disconnect
  ϿһsocketsocketвϢ
  
		idsocket id
ֵtrueɹfalseʧ
]]
function disconnect(id)
	--Ͽ
	if validaction(id,"DISCONNECT") == false then
		return false
	end
	--socket idӦӻڵȴУû
	if linklist[id].pending then
		linklist[id].pending = nil
		if ipstatus ~= "IP STATUS" and ipstatus ~= "IP PROCESSING" and linklist[id].state == "CONNECTING" then
			print("link.disconnect: ip not ready",ipstatus)
			linklist[id].state = "DISCONNECTING"
			sys.dispatch("LINK_ASYNC_LOCAL_EVENT",closecnf,id,"DISCONNECT","OK")
			return
		end
	end

	linklist[id].state = "DISCONNECTING"
	--ATϿ
	req("AT+CIPCLOSE="..id)

	return true
end

--[[
send
  ݵ
  
		idsocket id
		dataҪ͵
ֵtrueɹfalseʧ
]]
function send(id,data)
	--socketЧsocketδ
	if linklist[id] == nil or linklist[id].state ~= "CONNECTED" then
		print("link.send:error",id)
		return false
	end

	if cc and cc.anycallexist() then
		-- ͨ ҵǰͨʹ첽֪ͨʧ
		print("link.send:failed cause call exist")
		return false
	end
	--ATִݷ
	req(string.format("AT+CIPSEND=%d,%d",id,string.len(data)),data)

	return true
end

--[[
getstate
  ȡһsocket״̬
  
		idsocket id
ֵsocketЧ򷵻״̬򷵻"NIL LINK"
]]
function getstate(id)
	return linklist[id] and linklist[id].state or "NIL LINK"
end

--[[
recv
  ĳsocketݽմ
  
		idsocket id
		lenյݳȣֽΪλ
		dataյ
ֵ
]]
local function recv(id,len,data)
	--socket idЧ
	if linklist[id] == nil then
		print("link.recv:error",id)
		return
	end
	--socket idӦûעݽմ
	if linklist[id].recv then
		linklist[id].recv(id,data)
	else
		print("link.recv:nil recv",id)
	end
end

--[[ ipstatusѯص״̬ʾ
function linkstatus(data)
end
]]

--[[
usersckisactive
  жûsocketǷڼ״̬
  
ֵֻҪκһûsocket״̬ͷtrue򷵻nil
]]
local function usersckisactive()
	for i = 0,MAXLINKS do
		--ûԶsocketûtagֵ
		if linklist[i] and not linklist[i].tag and linklist[i].state=="CONNECTED" then
			return true
		end
	end
end

--[[
usersckntfy
  ûsocket״̬仯֪ͨ
  
		idsocket id
ֵ
]]
local function usersckntfy(id)
	--һڲϢ"USER_SOCKET_CONNECT"֪ͨûsocket״̬仯
	if not linklist[id].tag then sys.dispatch("USER_SOCKET_CONNECT",usersckisactive()) end
end

--[[
sendcnf
  socketݷͽȷ
  
		idsocket id
		resultͽַ
ֵ
]]
local function sendcnf(id,result)
	local str = string.match(result,"([%u ])")
	--ʧ
	if str == "TCP ERROR" or str == "UDP ERROR" or str == "ERROR" then
		linklist[id].state = result
	end
	--ûע״̬
	linklist[id].notify(id,"SEND",result)
end

--[[
closecnf
  socketرսȷ
  
		idsocket id
		resultرսַ
ֵ
]]
function closecnf(id,result)
	--socket idЧ
	if not id or not linklist[id] then
		print("link.closecnf:error",id)
		return
	end
	--κεclose,ǳɹϿ,ֱӰӶϿ
	if linklist[id].state == "DISCONNECTING" then
		linklist[id].state = "CLOSED"
		linklist[id].notify(id,"DISCONNECT","OK")
		usersckntfy(id,false)
		stopconnectingtimer(id)
	--ע,άϢ,urcע
	elseif linklist[id].state == "CLOSING" then		
		local tlink = linklist[id]
		usersckntfy(id,false)
		linklist[id] = nil
		ril.deregurc(tostring(id),urc)
		tlink.notify(id,"CLOSE","OK")		
		stopconnectingtimer(id)
	else
		print("link.closecnf:error",linklist[id].state)
	end
end

--[[
statusind
  socket״̬ת
  
		idsocket id
		state״ַ̬
ֵ
]]
function statusind(id,state)
	--socketЧ
	if linklist[id] == nil then
		print("link.statusind:nil id",id)
		return
	end

	--췢ģʽ£ݷʧ
	if state == "SEND FAIL" then
		if linklist[id].state == "CONNECTED" then
			linklist[id].notify(id,"SEND",state)
		else
			print("statusind:send fail state",linklist[id].state)
		end
		return
	end

	local evt
	--socketӵ״̬߷ӳɹ״̬֪ͨ
	if linklist[id].state == "CONNECTING" or state == "CONNECT OK" then
		--͵¼
		evt = "CONNECT"		
	else
		--״̬͵¼
		evt = "STATE"
	end

	--ӳɹ,Ȼڹر״̬
	if state == "CONNECT OK" then
		linklist[id].state = "CONNECTED"		
	else
		linklist[id].state = "CLOSED"
	end
	--usersckntfyжǷҪ֪ͨûsocket״̬仯
	usersckntfy(id,state == "CONNECT OK")
	--ûע״̬
	linklist[id].notify(id,evt,state)
	stopconnectingtimer(id)
end

--[[
connpend
  ִIPδ׼ñsocket
  
ֵ
]]
local function connpend()
	for i = 0,MAXLINKS do
		if linklist[i] ~= nil then
			if linklist[i].pending then
				req(linklist[i].pending)
				local id = string.match(linklist[i].pending,"AT%+CIPSTART=(%d)")
				if id then
					startconnectingtimer(tonumber(id))
				end
				linklist[i].pending = nil
			end
		end
	end	
end

local ipstatusind
function regipstatusind()
	ipstatusind = true
end

local function ciicrerrtmfnc()
	print("ciicrerrtmfnc")
	if ciicrerrcb then
		ciicrerrcb()
	else
		sys.restart("ciicrerrtmfnc")
	end
end

--[[
setIPStatus
  IP״̬
  
		statusIP״̬
ֵ
]]
local function setIPStatus(status)
	print("ipstatus:",status)
	
	if ipstatusind and ipstatus~=status then
		sys.dispatch("IP_STATUS_IND",status=="IP GPRSACT" or status=="IP PROCESSING" or status=="IP STATUS")
	end
	
	if not sim.getstatus() then
		status = "IP INITIAL"
	end

	if ipstatus ~= status or status=="IP START" or status == "IP CONFIG" or status == "IP GPRSACT" or status == "PDP DEACT" then
		if status=="IP GPRSACT" and checkciicrtm then
			--رաAT+CIICRIP糬ʱδɹĶʱ
			print("ciicrerrtmfnc stop")
			sys.timer_stop(ciicrerrtmfnc)
		end
		ipstatus = status
		if ipstatus == "IP PROCESSING" then
		--IP׼
		elseif ipstatus == "IP STATUS" then
			--ִбsocket
			connpend()
		--IPر
		elseif ipstatus == "IP INITIAL" then
			--IPSTART_INTVL¼IP
			sys.timer_start(setupIP,IPSTART_INTVL)
		--IP缤
		elseif ipstatus == "IP CONFIG" or ipstatus == "IP START" then
			--2ӲѯһIP״̬
			sys.timer_start(req,2000,"AT+CIPSTATUS")
		--IP缤ɹ
		elseif ipstatus == "IP GPRSACT" then
			--ȡIPַַȡɹIP״̬лΪ"IP STATUS"
			req("AT+CIFSR")
			--ѯIP״̬
			req("AT+CIPSTATUS")
		else --쳣״̬رIP INITIAL
			shut()
			sys.timer_stop(req,"AT+CIPSTATUS")
		end
	end
end

--[[
shutcnf
  رIP
  
		resultرսַ
ֵ
]]
local function shutcnf(result)
	shuting = false
	if ipstatusind then sys.dispatch("IP_SHUTING_IND",false) end
	--رճɹ
	if result == "SHUT OK" or not sim.getstatus() then
		setIPStatus("IP INITIAL")
		--ϿsocketӣsocketϢ
		for i = 0,MAXLINKS do
			if linklist[i] then
				if linklist[i].state == "CONNECTING" and linklist[i].pending then
					-- δй ʾclose,IPԶ
				elseif linklist[i].state == "INITIAL" then -- δӵҲʾ
				else
					linklist[i].state = "CLOSED"
					linklist[i].notify(i,"STATE","SHUTED")
					usersckntfy(i,false)
				end
				stopconnectingtimer(i)
			end
		end
	else
		--req("AT+CIPSTATUS")
		sys.timer_start(req,10000,"AT+CIPSTATUS")
	end
	if checkciicrtm and result=="SHUT OK" and not ciicrerrcb then
		--رաAT+CIICRIP糬ʱδɹĶʱ
		print("ciicrerrtmfnc stop")
		sys.timer_stop(ciicrerrtmfnc)
	end
end
--[[
local function reconnip(force)
	print("link.reconnip",force,ipstatus,cgatt)
	if force then
		setIPStatus("PDP DEACT")
	else
		if ipstatus == "IP START" or ipstatus == "IP CONFIG" or ipstatus == "IP GPRSACT" or ipstatus == "IP STATUS" or ipstatus == "IP PROCESSING" then
			setIPStatus("PDP DEACT")
		end
		cgatt = "0"
	end
end
]]

--άATͨյһΡĳsocketӷյݡ
--idsocket id
--lenյܳ
--dataѾյ
local rcvd = {id = 0,len = 0,rcvLen = 0,data = {}}

--[[
rcvdfilter
  ATͨȡһ
  
		data
ֵֵһֵʾδݣڶֵʾATͨݹ
]]
local function rcvdfilter(data)
	--ܳΪ0򱾺յݣֱӷ
	if rcvd.len == 0 then
		return data
	end
	--ʣδյݳ
	local restlen = rcvd.len - rcvd.rcvLen
	if  string.len(data) > restlen then -- atͨݱʣδյݶ
		-- ȡ緢
		table.insert(rcvd.data,string.sub(data,1,restlen))
		rcvd.rcvLen = rcvd.rcvLen+restlen
		-- ʣµ԰atк
		data = string.sub(data,restlen+1,-1)
	else
		table.insert(rcvd.data,data)
		rcvd.rcvLen = rcvd.rcvLen+data:len()
		data = ""
	end

	if rcvd.len == rcvd.rcvLen then
		--֪ͨ
		recv(rcvd.id,rcvd.len,table.concat(rcvd.data))
		rcvd.id = 0
		rcvd.len = 0
		rcvd.rcvLen = 0
		rcvd.data = {}
		return data
	else
		return data, rcvdfilter
	end
end

--[[
urc
  ģڡעĵײcoreͨ⴮ϱ֪ͨĴ
  
		dataַ֪ͨϢ
		prefix֪ͨǰ׺
ֵ
]]
function urc(data,prefix)
	--IP״̬֪ͨ
	if prefix == "STATE" then
		setIPStatus(string.sub(data,8,-1))
	elseif prefix == "C" then
		--linkstatus(data)
	--IP类ȥ
	elseif prefix == "+PDP" then
		--req("AT+CIPSTATUS")
		shut()
		sys.timer_stop(req,"AT+CIPSTATUS")
	--socketյ
	elseif prefix == "+RECEIVE" then
		local lid,len = string.match(data,",(%d),(%d+)",string.len("+RECEIVE")+1)
		rcvd.id = tonumber(lid)
		rcvd.len = tonumber(len)
		return rcvdfilter,rcvd.len
	--socket״̬֪ͨ
	else
		local lid,lstate = string.match(data,"(%d), *([%u :%d]+)")

		if lid then
			lid = tonumber(lid)
			statusind(lid,lstate)
		end
	end
end

--[[
shut
  رIP
  
ֵ
]]
function shut()
	--ִԶܻdbgܻntpܣӳٹر
	if updating or dbging or ntping then shutpending = true return end
	--ATر
	req("AT+CIPSHUT")
	--ùرб־
	shuting = true
	if ipstatusind then sys.dispatch("IP_SHUTING_IND",true) end
	shutpending = false
end
reset = shut

--[[
getresult
  socket״ַ̬
  
		str״ַ̬ERROR1, SEND OK1, CLOSE OK
ֵsocket״̬socket id,ERRORSEND OKCLOSE OK
]]
local function getresult(str)
	return str == "ERROR" and str or string.match(str,"%d, *([%u :%d]+)")
end

--[[
rsp
  ģڡͨ⴮ڷ͵ײcoreATӦ
  
		cmdӦӦAT
		successATִнtruefalse
		responseATӦеִнַ
		intermediateATӦемϢ
ֵ
]]
local function rsp(cmd,success,response,intermediate)
	local prefix = string.match(cmd,"AT(%+%u+)")
	local id = tonumber(string.match(cmd,"AT%+%u+=(%d)"))
	--ݵӦ
	if prefix == "+CIPSEND" then
		if response == "+PDP: DEACT" then
			req("AT+CIPSTATUS")
			response = "ERROR"
		end
		if string.match(response,"DATA ACCEPT") then
			sendcnf(id,"SEND OK")
		else
			sendcnf(id,getresult(response))
		end
	--رsocketӦ
	elseif prefix == "+CIPCLOSE" then
		closecnf(id,getresult(response))
	--رIPӦ
	elseif prefix == "+CIPSHUT" then
		shutcnf(response)
	--ӵӦ
	elseif prefix == "+CIPSTART" then
		if response == "ERROR" then
			statusind(id,"ERROR")
		end
	--IPӦ
	elseif prefix == "+CIICR" then
		if success then
			--ɹ󣬵ײȥIP磬luaӦҪAT+CIPSTATUSѯIP״̬
			if checkciicrtm and not sys.timer_is_active(ciicrerrtmfnc) then
				--IP糬ʱʱ
				print("ciicrerrtmfnc start")
				sys.timer_start(ciicrerrtmfnc,checkciicrtm)
			end
		else
			shut()
			sys.timer_stop(req,"AT+CIPSTATUS")
		end
	end
end

--עurc֪ͨĴ
ril.regurc("STATE",urc)
ril.regurc("C",urc)
ril.regurc("+PDP",urc)
ril.regurc("+RECEIVE",urc)
--עATӦ
ril.regrsp("+CIPSTART",rsp)
ril.regrsp("+CIPSEND",rsp)
ril.regrsp("+CIPCLOSE",rsp)
ril.regrsp("+CIPSHUT",rsp)
ril.regrsp("+CIICR",rsp)

--gprsδʱʱѯ״̬ļ
local QUERYTIME = 2000

--[[
cgattrsp
  ѯGPRS總״̬Ӧ
  
		cmdӦӦAT
		successATִнtruefalse
		responseATӦеִнַ
		intermediateATӦемϢ
ֵ
]]
local function cgattrsp(cmd,success,response,intermediate)
	--Ѹ
	if intermediate == "+CGATT: 1" then
		cgatt = "1"
		sys.dispatch("NET_GPRS_READY",true)

		-- ,ôgprsԺԶIP
		if base.next(linklist) then
			if ipstatus == "IP INITIAL" then
				setupIP()
			else
				req("AT+CIPSTATUS")
			end
		end
	--δ
	elseif intermediate == "+CGATT: 0" then
		if cgatt ~= "0" then
			cgatt = "0"
			sys.dispatch("NET_GPRS_READY",false)
		end
		--öʱѯ
		sys.timer_start(querycgatt,QUERYTIME)
	end
end

--[[
querycgatt
  ѯGPRS總״̬
  
ֵ
]]
function querycgatt()
	--Ƿģʽȥѯ
	if not flymode then req("AT+CGATT?",nil,cgattrsp) end
end

-- ýӿ
local qsend = 0
function SetQuickSend(mode)
	--qsend = mode
end

local inited = false
--[[
initial
  ñģ鹦ܵһЩʼ
  
ֵ
]]
local function initial()
	if not inited then
		inited = true
		req("AT+CIICRMODE=2") --ciicr첽
		req("AT+CIPMUX=1") --
		req("AT+CIPHEAD=1")
		req("AT+CIPQSEND=" .. qsend)--ģʽ
	end
end

--[[
netmsg
  GSMע״̬仯Ĵ
  
ֵtrue
]]
local function netmsg(id,data)
	--GSMע
	if data == "REGISTERED" then
		--гʼ
		initial() 
		--ʱѯGPRS總״̬
		sys.timer_start(querycgatt,QUERYTIME)
	end

	return true
end

--simĬapn
local apntable =
{
	["46000"] = DEFAULT_APN,
	["46002"] = DEFAULT_APN,
	["46004"] = DEFAULT_APN,
	["46007"] = DEFAULT_APN,
	["46001"] = "UNINET",
	["46006"] = "UNINET",
	["46011"] = "",
}

--[[
proc
  ģעڲϢĴ
  
		idڲϢid
		paraڲϢ
ֵtrue
]]
local function proc(id,para)
	--IMSIȡɹ
	if id=="IMSI_READY" then
		--ģڲԶȡapnϢ
		if apnflag then
			if apn then
				local temp1,temp2,temp3=apn.get_default_apn(tonumber(sim.getmcc(),16),tonumber(sim.getmnc(),16))
				if temp1 == '' or temp1 == nil then temp1=DEFAULT_APN end
				setapn(temp1,temp2,temp3)
			else
				setapn(apntable[sim.getmcc()..sim.getmnc()] or DEFAULT_APN)
			end
		end
	--ģʽ״̬仯
	elseif id=="FLYMODE_IND" then
		flymode = para
		if para then
			sys.timer_stop(req,"AT+CIPSTATUS")
		else
			req("AT+CGATT?",nil,cgattrsp)
		end
	--Զʼ
	elseif id=="UPDATE_BEGIN_IND" then
		updating = true
	--Զ
	elseif id=="UPDATE_END_IND" then
		updating = false
		if shutpending then shut() end
	--dbgܿʼ
	elseif id=="DBG_BEGIN_IND" then
		dbging = true
	--dbgܽ
	elseif id=="DBG_END_IND" then
		dbging = false
		if shutpending then shut() end
	--NTPͬʼ
	elseif id=="NTP_BEGIN_IND" then
		ntping = true
	--NTPͬ
	elseif id=="NTP_END_IND" then
		ntping = false
		if shutpending then shut() end
	end
	return true
end

--[[
checkciicr
  üIP󣬳ʱδɹĳʱʱ䡣ִAT+CIICRcheckciicrtmcheckciicrtmûмɹ;ִAT+CIPSHUT
  
		tmʱʱ䣬λ
ֵtrue
]]
function checkciicr(tm)
	checkciicrtm = tm
	ril.regrsp("+CIICR",rsp)
end

--[[
setiperrcb
  "IP󣬳ʱδɹ"ûص
  
		cbص
ֵ
]]
function setiperrcb(cb)
	ciicrerrcb = cb
end

--[[
setretrymode
  "ӹ̺ݷ͹TCPЭ"
  
		mdnumber֧ͣ01
			0ΪܻܶܳʱŻ᷵ӻ߷ͽ
			1Ϊʶϲû磬10뷵ʧܽ
ֵ
]]
function setretrymode(md)
	ril.request("AT+TCPUSERPARAM=6,"..(md==0 and 4 or 2)..",7200,"..(md==0 and 16 or 8))
	ril.setDataTimeout(md==0 and 120000 or 60000)
end

--- TCPԶشĲ
-- @number[opt=4] retryCntشȡֵΧ012
-- @number[opt=16] retryMaxTimeoutÿشʱʱ(λ)ȡֵΧ116
-- @return nil
-- @usage
-- setTcpResendPara(3,8)
-- setTcpResendPara(4,16)
function setTcpResendPara(retryCnt, retryMaxTimeout)
    req("AT+TCPUSERPARAM=6," .. (retryCnt or 4) .. ",7200," .. (retryMaxTimeout or 16))
    ril.setDataTimeout(((retryCnt or 4)*(retryMaxTimeout or 16) + 60) * 1000)
end

--ע᱾ģעڲϢĴ
sys.regapp(proc,"IMSI_READY","FLYMODE_IND","UPDATE_BEGIN_IND","UPDATE_END_IND","DBG_BEGIN_IND","DBG_END_IND","NTP_BEGIN_IND","NTP_END_IND")
sys.regapp(netmsg,"NET_STATE_CHANGED")
checkciicr(120000)
setTcpResendPara(4,16)
