authNew.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include "includes.h"
  2. /*文件描述
  3. 1、本文件主要处理终端向服务器授权的功能,DTU作为中间的网络桥梁
  4. 2、主要通讯链路包括两部分:终端<-->DTU, DTU<-->服务器
  5. 3、终端到DTU之间的通讯是自定义协议,带加密
  6. 4、DTU到服务器之间使用部标协议,自定义消息ID
  7. 5、支持多串口通道授权操作,每个串口要独立配置好外设
  8. */
  9. CHANNEL_DEF channel[CHANNEL_NUM];
  10. void authSendCmd(unsigned char cmd, unsigned char *data, unsigned char len);
  11. unsigned char authSocketStatus;
  12. //授权初始化
  13. void authNewInit(void)
  14. {
  15. unsigned char i;
  16. for(i=0;i<CHL_TOTAL;i++) memset((unsigned char *)&channel[i], 0, sizeof(CHANNEL_DEF));
  17. authSocketStatus=0;
  18. }
  19. //DTU处理终端发过来的协议包
  20. char authHandleData(char uartType,unsigned char *data, unsigned short len)
  21. {
  22. unsigned short i;
  23. unsigned char sum=0;
  24. unsigned char temp[3];
  25. unsigned char *dataPtr=data+3;
  26. unsigned char id[UNIQUE_ID_BYTES];
  27. unsigned char queuebuf[4];//
  28. if(data[0] != PRO_HEADER) return 1;
  29. if((data[2]+3) != len) return 2;
  30. for(i=0;i<len-1;i++) sum ^= data[i];
  31. if(sum != data[len-1]) return 3;
  32. temp[0]=len;
  33. temp[1]=data[0];
  34. temp[2]=data[1];
  35. for(i=0;i<data[2]-1;i++){
  36. dataPtr[i] ^= temp[i % 3];
  37. dataPtr[i] ^= TX_RX_SEED;
  38. }
  39. memcpy(id, dataPtr+2, UNIQUE_ID_BYTES);
  40. if(data[1]==PRO_AUTH_REQ){//终端请求鉴权
  41. //请求信息压进队列去
  42. if(channel[uartType].root==0){//此通道还没有发起来鉴权请求
  43. NEED_AUTH:
  44. channel[uartType].root=1;
  45. channel[uartType].reqTime=0;
  46. memcpy(channel[uartType].id, id, UNIQUE_ID_BYTES);
  47. channel[uartType].result=SER_AUTH_BUSY;
  48. }else{//已经有数据了
  49. if(0 != memcmp(id, channel[uartType].id,sizeof(id))) goto NEED_AUTH;//不相等,表示是新设备请求鉴权
  50. else{//已存在,如果是已经失败的状态下,也要允许重新请求鉴权
  51. goto NEED_AUTH;
  52. }
  53. }
  54. }else if(data[1]==PRO_AUTH_OK){//终端鉴权码与服务器给的一致
  55. if(channel[uartType].root != 0){
  56. channel[uartType].result=SER_AUTH_DEV_OK_DLY;
  57. channel[uartType].waitTime=os_time_get()+50;
  58. }
  59. //显示成功状态
  60. }else if(data[1]==PRO_AUTH_FAI){//终端鉴权码与服务器给的不一致
  61. if(channel[uartType].root != 0){
  62. channel[uartType].result=SER_AUTH_DEV_FAI;
  63. }
  64. }
  65. }
  66. //多通道授权状态机处理接口
  67. void AuthIndicator(void)
  68. {
  69. CHANNEL_TYPEENUM scanChannel;
  70. for(scanChannel=CHL_UART1;scanChannel<CHL_TOTAL;scanChannel++){
  71. if(channel[scanChannel].root != 0){
  72. switch(channel[scanChannel].result){
  73. case SER_AUTH_IDLE://通道空闲,没有终端鉴权请求
  74. break;
  75. case SER_AUTH_BUSY://通道忙,表示正在处理终端鉴权请求
  76. break;
  77. case SER_AUTH_OK://鉴权成功,可以显示状态,但不清除结构体,通知终端成功了
  78. authSendCmd(PRO_AUTH_SUC,(unsigned char *)&channel[scanChannel].encodeValue,4);
  79. channel[scanChannel].result=SER_AUTH_WAIT;
  80. channel[scanChannel].waitTime=os_time_get()+200;
  81. break;
  82. case SER_AUTH_WAIT:
  83. if(os_time_get()>channel[scanChannel].waitTime){
  84. //两秒超时终端没响应,则清掉本结构体
  85. memset((unsigned char *)&channel[scanChannel], 0, sizeof(CHANNEL_DEF));
  86. channel[scanChannel].result=SER_AUTH_IDLE;
  87. }
  88. break;
  89. case SER_AUTH_FAILED:break;//鉴权失败,可以显示状态,但不清除结构体
  90. case SER_AUTH_DEV_OK_DLY://防止由于鉴权太快了,灯看不到灭的瞬间而作出的一小会灭延时
  91. if(os_time_get()>channel[scanChannel].waitTime){
  92. channel[scanChannel].result=SER_AUTH_DEV_OK;
  93. }
  94. break;
  95. }
  96. }
  97. }
  98. }
  99. void ModemTryAuthNow(unsigned char *id);
  100. //应用发起向服务器请求授权的入口
  101. void ModemSendAuthReqHandle(void)
  102. {
  103. static CHANNEL_TYPEENUM scanChannel=CHL_UART1;
  104. static unsigned int tick=0;
  105. unsigned char reReqNum;
  106. AuthIndicator();
  107. if(sutModemStatus.PDPStatus != OPENED) return;
  108. if(authSocketStatus==0) return;
  109. if(os_time_get()<tick) return;
  110. tick=os_time_get()+50;//0.5秒一次
  111. reReqNum=300/(50*CHL_TOTAL);//3秒重新发一次鉴权请求(超时请求)
  112. if(channel[scanChannel].root != 0){//有要请求的通道数据
  113. if(channel[scanChannel].result==SER_AUTH_BUSY){
  114. if(channel[scanChannel].reqTime==0) ModemTryAuthNow(channel[scanChannel].id);
  115. if(++channel[scanChannel].reqTime >= reReqNum) channel[scanChannel].reqTime=0;
  116. }
  117. }
  118. if(++scanChannel >= CHL_TOTAL) scanChannel=CHL_UART1;
  119. }
  120. void testMakeReqAck(unsigned char *id);
  121. //模块通过部标向服务器请示某终端鉴权请求接口
  122. void ModemTryAuthNow(unsigned char *id)
  123. {//打包并通过UDP发送数据
  124. unsigned char sendbuf[128];
  125. unsigned short i,j;
  126. unsigned char *ptr=sendbuf;
  127. unsigned char th,tl,sum=0;
  128. char temp[20];
  129. static unsigned short liushui=0;
  130. j=0;
  131. //header
  132. //sms type 2bytes
  133. ptr[j++]=AUTH_REQ_ID>>8;
  134. ptr[j++]=AUTH_REQ_ID&0xff;
  135. //sms property 2bytes
  136. i=45;//only low 10bits are define as sms length
  137. ptr[j++]=i>>8;//no sub packets,no encrypt
  138. ptr[j++]=i;//sms length
  139. //device SN 6bytes
  140. snprintf(temp, sizeof(temp),"%012d",sutProductPara.PSN);
  141. for(i=0;i<6;i++){
  142. th=temp[2*i];
  143. tl=temp[2*i+1];
  144. th <<= 4;th &= 0xF0;
  145. tl &= 0x0F;
  146. ptr[j++]=th | tl;
  147. }
  148. //serial nuber 2bytes
  149. ptr[j++]=(liushui>>8)&0xFF;
  150. ptr[j++]=liushui&0xFF;
  151. liushui++;
  152. //sms info
  153. //生厂产家标识
  154. i=sizeof(sutProductPara.proName);
  155. memset(&ptr[j], 0, i);
  156. memcpy(&ptr[j], sutProductPara.proName, i);
  157. j += i;
  158. //产品型号
  159. i=sizeof(sutProductPara.devName);
  160. memset(&ptr[j], 0, i);
  161. memcpy(&ptr[j], sutProductPara.devName, i);
  162. j += i;
  163. //id len
  164. ptr[j++]=UNIQUE_ID_BYTES;
  165. //id data
  166. memcpy(ptr+j, id, UNIQUE_ID_BYTES);
  167. j += UNIQUE_ID_BYTES;
  168. //verify code
  169. for(i=0;i<j;i++) sum ^= sendbuf[i];
  170. ptr[j++]=sum;
  171. //translate
  172. j=PacketConvert(sendbuf,sizeof(sendbuf),j);
  173. ModemSendToUdpSocket(AUTH_UDP_SOCKET,sendbuf, j);
  174. }
  175. //DTU与终端之间的通讯发送函数接口,为了不让别人容易监听串口数据,协议对数据内容作了加密处理
  176. void authSendCmd(unsigned char cmd, unsigned char *data, unsigned char len)
  177. {
  178. //协议格式
  179. //head cmd len data
  180. //data:liushui[2] id[12] 均经过cmd和长度加密
  181. static unsigned short liushui=0;
  182. unsigned char sendbuf[64];
  183. unsigned char i,k;
  184. unsigned char *dataPtr=sendbuf+3;
  185. unsigned char datalen=2+len+1;//加上sum
  186. unsigned char temp[3],sum;
  187. i=0;
  188. sendbuf[i++]=PRO_HEADER;
  189. sendbuf[i++]=cmd;
  190. sendbuf[i++]=datalen;
  191. sendbuf[i++]=liushui>>8;
  192. sendbuf[i++]=liushui;
  193. for(k=0;k<len;k++)
  194. sendbuf[i++]=data[k];
  195. temp[0]=3+datalen;//总长度,包括sum
  196. temp[1]=sendbuf[0];
  197. temp[2]=sendbuf[1];
  198. for(k=0;k<datalen-1;k++){
  199. dataPtr[k] ^= temp[k % 3];
  200. dataPtr[k] ^= TX_RX_SEED;
  201. }
  202. sum=0;
  203. for(k=0;k<i;k++) sum ^= sendbuf[k];
  204. sendbuf[i++]=sum;
  205. Uart1Send(sendbuf, i);
  206. // printf("Data:%d\r\n", i);
  207. // {
  208. // int j;
  209. // for(j=0;j<i;j++) printf("%02x",sendbuf[j]);
  210. // }
  211. // printf("\r\nEnd\r\n");
  212. }
  213. //显示多通道串口灯的显示状态
  214. //每个通道有两个灯,一个是表示DTU是否有鉴权能力的红灯
  215. //一个是表示DTU的授权状态
  216. void authLedShow()
  217. {//这里只做显示,不做任何跟逻辑有关
  218. //红灯:
  219. //灭 表示本设备正常使用
  220. //亮 表示本设备无权向服务器鉴权,需要向我们反馈
  221. //蓝/绿灯:
  222. //灭 表示没有终端请求鉴权操作
  223. //亮 表示终端鉴权成功了
  224. //均匀闪 表示正在忙于鉴权操作
  225. //快闪1次 表示终端鉴权失败了
  226. CHANNEL_TYPEENUM scanChannel;
  227. for(scanChannel=CHL_UART1;scanChannel<CHL_TOTAL;scanChannel++){
  228. if(channel[scanChannel].root != 0){
  229. switch(channel[scanChannel].result){
  230. case SER_AUTH_IDLE://通道空闲,没有终端鉴权请求
  231. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  232. SetLedStatus(2*scanChannel+1,NotBright);//非红灯灭,表示设备空闲
  233. break;
  234. case SER_AUTH_BUSY://通道忙,表示正在处理终端鉴权请求
  235. case SER_AUTH_OK://鉴权成功,可以显示状态,但不清除结构体,通知终端成功了
  236. case SER_AUTH_WAIT://正在等待终端响应结果
  237. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  238. SetLedStatus(2*scanChannel+1,Flash);//非红灯均匀闪烁,表示设备忙于鉴权
  239. break;
  240. case SER_AUTH_FAILED://鉴权失败,设备无权
  241. SetLedStatus(2*scanChannel,Bright);//红灯灭,表示设备正常
  242. SetLedStatus(2*scanChannel+1,Flash);//非红灯均匀闪烁,表示设备忙于鉴权
  243. break;
  244. case SER_AUTH_DEV_FAI://终端鉴权失败
  245. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  246. SetLedStatus(2*scanChannel+1,OneFlashFast);//非红灯快闪1次,表示鉴权失败了
  247. break;
  248. case SER_AUTH_DEV_OK_DLY://终端鉴权成功延时
  249. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  250. SetLedStatus(2*scanChannel+1,NotBright);//非红灯常亮,用于给用户能看到变化
  251. break;
  252. case SER_AUTH_DEV_OK://终端鉴权成功
  253. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  254. SetLedStatus(2*scanChannel+1,Bright);//非红灯常亮,表示鉴权成功了
  255. break;
  256. }
  257. }else{//此通道收到任何终端请求
  258. SetLedStatus(2*scanChannel,NotBright);//红灯灭,表示设备正常
  259. SetLedStatus(2*scanChannel+1,NotBright);//非红灯灭,表示设备空闲
  260. }
  261. }
  262. }
  263. //接收到从服务器响应的部标数据包且包正确,处理接收到的数据
  264. void authBubiaoHandleRecv(unsigned char *msg)
  265. {//37ffd6054b543335504302430000000000000000000000000000000000000000 00 1f 04 6735d710 40
  266. unsigned char id[UNIQUE_ID_BYTES];
  267. unsigned char result;
  268. unsigned char factor;
  269. unsigned char len,i;
  270. unsigned int code;
  271. CHANNEL_TYPEENUM scanChannel;
  272. memcpy(id, msg, UNIQUE_ID_BYTES);
  273. result=msg[32];
  274. factor=msg[33];
  275. len=msg[34];
  276. if(result!=0) {
  277. for(scanChannel=CHL_UART1;scanChannel<CHL_TOTAL;scanChannel++){
  278. if(0==memcmp(id,channel[scanChannel].id,UNIQUE_ID_BYTES))
  279. channel[scanChannel].result=SER_AUTH_FAILED;
  280. }
  281. return;
  282. }
  283. //服务器授权成功
  284. //检测ID是否还存在
  285. for(i=CHL_UART1;i<CHL_TOTAL;i++){
  286. if(channel[i].root != 0){
  287. if(0==memcmp(id, channel[i].id, UNIQUE_ID_BYTES)){//存在
  288. goto GO_ON;
  289. }
  290. }
  291. }
  292. return;
  293. GO_ON:
  294. //printf("Code1:%02x,%02x%02x%02x%02x\r\n", factor, msg[35],msg[36],msg[37],msg[38]);
  295. code=msg[38]^factor;code <<= 8;code &= 0xff00;
  296. code |= msg[37]^factor;code <<= 8;code &= 0xffff00;
  297. code |= msg[36]^factor;code <<= 8;code &= 0xffffff00;
  298. code |= msg[35]^factor;
  299. channel[i].encodeValue=code;
  300. channel[i].result=SER_AUTH_OK;
  301. //printf("Code2:%08x\r\n", code);
  302. }
  303. //以下只是用来模拟服务器产生ACK的包的函数
  304. void testMakeReqAck(unsigned char *id)
  305. {
  306. unsigned char sendbuf[128];
  307. unsigned short i,j;
  308. unsigned char *ptr=sendbuf;
  309. unsigned char th,tl,sum=0;
  310. char temp[20];
  311. static unsigned short liushui=0;
  312. #define ENCODE_VALUE 0x1f
  313. j=0;
  314. //header
  315. //sms type 2bytes
  316. ptr[j++]=AUTH_ACK_ID>>8;
  317. ptr[j++]=AUTH_ACK_ID&0xff;
  318. //sms property 2bytes
  319. i=39;//授权成功长度 36 授权失败长度
  320. ptr[j++]=i>>8;//no sub packets,no encrypt
  321. ptr[j++]=i;//sms length
  322. //device SN 6bytes
  323. snprintf(temp, sizeof(temp),"%012d",sutProductPara.PSN);
  324. for(i=0;i<6;i++){
  325. th=temp[2*i];
  326. tl=temp[2*i+1];
  327. th <<= 4;th &= 0xF0;
  328. tl &= 0x0F;
  329. ptr[j++]=th | tl;
  330. }
  331. //serial nuber 2bytes
  332. ptr[j++]=(liushui>>8)&0xFF;
  333. ptr[j++]=liushui&0xFF;
  334. liushui++;
  335. //sms info
  336. memset(ptr+j, 0, 32);
  337. memcpy(ptr+j, id, UNIQUE_ID_BYTES);
  338. j += 32;
  339. ptr[j++]=0;
  340. ptr[j++]=ENCODE_VALUE;
  341. ptr[j++]=4;
  342. ptr[j++]=0x78^ENCODE_VALUE;
  343. ptr[j++]=0x2a^ENCODE_VALUE;
  344. ptr[j++]=0xc8^ENCODE_VALUE;
  345. ptr[j++]=0x0f^ENCODE_VALUE;
  346. //verify code
  347. for(i=0;i<j;i++) sum ^= sendbuf[i];
  348. ptr[j++]=sum;
  349. //translate
  350. j=PacketConvert(sendbuf,sizeof(sendbuf),j);
  351. printf("Data:");
  352. for(i=0;i<j;i++){
  353. printf("%02x",sendbuf[i]);
  354. }
  355. printf("\r\n");
  356. }