25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1195 lines
33 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief BSD compatible socket interface.
  6. *
  7. * Copyright (c) 2015 - 2017 Atmel Corporation. All rights reserved.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * 1. Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. *
  19. * 2. Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. *
  23. * 3. The name of Atmel may not be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  27. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  28. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  29. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  30. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  34. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  35. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * \asf_license_stop
  39. *
  40. */
  41. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  42. INCLUDES
  43. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  44. #include "bsp/include/nm_bsp.h"
  45. #include "socket/include/socket.h"
  46. #include "driver/source/m2m_hif.h"
  47. #include "socket/source/socket_internal.h"
  48. #include "driver/include/m2m_types.h"
  49. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  50. MACROS
  51. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  52. #define TLS_RECORD_HEADER_LENGTH (5)
  53. #define ETHERNET_HEADER_OFFSET (34)
  54. #define ETHERNET_HEADER_LENGTH (14)
  55. #define TCP_IP_HEADER_LENGTH (40)
  56. #define UDP_IP_HEADER_LENGTH (28)
  57. #define IP_PACKET_OFFSET (ETHERNET_HEADER_LENGTH + ETHERNET_HEADER_OFFSET - M2M_HIF_HDR_OFFSET)
  58. #define TCP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + TCP_IP_HEADER_LENGTH)
  59. #define UDP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + UDP_IP_HEADER_LENGTH)
  60. #define SSL_TX_PACKET_OFFSET (TCP_TX_PACKET_OFFSET + TLS_RECORD_HEADER_LENGTH)
  61. #define SOCKET_REQUEST(reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset) \
  62. hif_send(M2M_REQ_GROUP_IP, reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset)
  63. #define SSL_FLAGS_ACTIVE NBIT0
  64. #define SSL_FLAGS_BYPASS_X509 NBIT1
  65. #define SSL_FLAGS_2_RESERVD NBIT2
  66. #define SSL_FLAGS_3_RESERVD NBIT3
  67. #define SSL_FLAGS_CACHE_SESSION NBIT4
  68. #define SSL_FLAGS_NO_TX_COPY NBIT5
  69. #define SSL_FLAGS_CHECK_SNI NBIT6
  70. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  71. PRIVATE DATA TYPES
  72. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  73. /*!
  74. * @brief
  75. */
  76. typedef struct {
  77. SOCKET sock;
  78. uint8 u8Dummy;
  79. uint16 u16SessionID;
  80. } tstrCloseCmd;
  81. /*!
  82. * @brief
  83. */
  84. typedef struct {
  85. uint8 *pu8UserBuffer;
  86. uint16 u16UserBufferSize;
  87. uint16 u16SessionID;
  88. uint16 u16DataOffset;
  89. uint8 bIsUsed;
  90. uint8 u8SSLFlags;
  91. uint8 bIsRecvPending;
  92. } tstrSocket;
  93. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  94. GLOBALS
  95. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  96. volatile sint8 gsockerrno;
  97. volatile tstrSocket gastrSockets[MAX_SOCKET];
  98. volatile uint8 gu8OpCode;
  99. volatile uint16 gu16BufferSize;
  100. volatile uint16 gu16SessionID = 0;
  101. volatile tpfAppSocketCb gpfAppSocketCb;
  102. volatile tpfAppResolveCb gpfAppResolveCb;
  103. volatile uint8 gbSocketInit = 0;
  104. volatile tpfPingCb gfpPingCb;
  105. /*********************************************************************
  106. Function
  107. Socket_ReadSocketData
  108. Description
  109. Callback function used by the NMC1500 driver to deliver messages
  110. for socket layer.
  111. Return
  112. None.
  113. Author
  114. Ahmed Ezzat
  115. Version
  116. 1.0
  117. Date
  118. 17 July 2012
  119. *********************************************************************/
  120. NMI_API void Socket_ReadSocketData(SOCKET sock, tstrSocketRecvMsg *pstrRecv, uint8 u8SocketMsg, uint32 u32StartAddress,
  121. uint16 u16ReadCount)
  122. {
  123. if ((u16ReadCount > 0) && (gastrSockets[sock].pu8UserBuffer != NULL) && (gastrSockets[sock].u16UserBufferSize > 0)
  124. && (gastrSockets[sock].bIsUsed == 1)) {
  125. uint32 u32Address = u32StartAddress;
  126. uint16 u16Read;
  127. sint16 s16Diff;
  128. uint8 u8SetRxDone;
  129. pstrRecv->u16RemainingSize = u16ReadCount;
  130. do {
  131. u8SetRxDone = 1;
  132. u16Read = u16ReadCount;
  133. s16Diff = u16Read - gastrSockets[sock].u16UserBufferSize;
  134. if (s16Diff > 0) {
  135. u8SetRxDone = 0;
  136. u16Read = gastrSockets[sock].u16UserBufferSize;
  137. }
  138. if (hif_receive(u32Address, gastrSockets[sock].pu8UserBuffer, u16Read, u8SetRxDone) == M2M_SUCCESS) {
  139. pstrRecv->pu8Buffer = gastrSockets[sock].pu8UserBuffer;
  140. pstrRecv->s16BufferSize = u16Read;
  141. pstrRecv->u16RemainingSize -= u16Read;
  142. if (gpfAppSocketCb)
  143. gpfAppSocketCb(sock, u8SocketMsg, pstrRecv);
  144. u16ReadCount -= u16Read;
  145. u32Address += u16Read;
  146. if ((!gastrSockets[sock].bIsUsed) && (u16ReadCount)) {
  147. M2M_DBG("Application Closed Socket While Rx Is not Complete\n");
  148. if (hif_receive(0, NULL, 0, 1) == M2M_SUCCESS)
  149. M2M_DBG("hif_receive Success\n");
  150. else
  151. M2M_DBG("hif_receive Fail\n");
  152. break;
  153. }
  154. } else {
  155. M2M_INFO("(ERRR)Current <%d>\n", u16ReadCount);
  156. break;
  157. }
  158. } while (u16ReadCount != 0);
  159. }
  160. }
  161. /*********************************************************************
  162. Function
  163. m2m_ip_cb
  164. Description
  165. Callback function used by the NMC1000 driver to deliver messages
  166. for socket layer.
  167. Return
  168. None.
  169. Author
  170. Ahmed Ezzat
  171. Version
  172. 1.0
  173. Date
  174. 17 July 2012
  175. *********************************************************************/
  176. static void m2m_ip_cb(uint8 u8OpCode, uint16 u16BufferSize, uint32 u32Address)
  177. {
  178. if ((u8OpCode == SOCKET_CMD_BIND) || (u8OpCode == SOCKET_CMD_SSL_BIND)) {
  179. tstrBindReply strBindReply;
  180. tstrSocketBindMsg strBind;
  181. if (hif_receive(u32Address, (uint8 *)&strBindReply, sizeof(tstrBindReply), 0) == M2M_SUCCESS) {
  182. strBind.status = strBindReply.s8Status;
  183. if (gpfAppSocketCb)
  184. gpfAppSocketCb(strBindReply.sock, SOCKET_MSG_BIND, &strBind);
  185. }
  186. } else if (u8OpCode == SOCKET_CMD_LISTEN) {
  187. tstrListenReply strListenReply;
  188. tstrSocketListenMsg strListen;
  189. if (hif_receive(u32Address, (uint8 *)&strListenReply, sizeof(tstrListenReply), 0) == M2M_SUCCESS) {
  190. strListen.status = strListenReply.s8Status;
  191. if (gpfAppSocketCb)
  192. gpfAppSocketCb(strListenReply.sock, SOCKET_MSG_LISTEN, &strListen);
  193. }
  194. } else if (u8OpCode == SOCKET_CMD_ACCEPT) {
  195. tstrAcceptReply strAcceptReply;
  196. tstrSocketAcceptMsg strAccept;
  197. if (hif_receive(u32Address, (uint8 *)&strAcceptReply, sizeof(tstrAcceptReply), 0) == M2M_SUCCESS) {
  198. if (strAcceptReply.sConnectedSock >= 0) {
  199. gastrSockets[strAcceptReply.sConnectedSock].u8SSLFlags
  200. = gastrSockets[strAcceptReply.sListenSock].u8SSLFlags;
  201. gastrSockets[strAcceptReply.sConnectedSock].bIsUsed = 1;
  202. gastrSockets[strAcceptReply.sConnectedSock].u16DataOffset
  203. = strAcceptReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET;
  204. /* The session ID is used to distinguish different socket connections
  205. by comparing the assigned session ID to the one reported by the firmware*/
  206. ++gu16SessionID;
  207. if (gu16SessionID == 0)
  208. ++gu16SessionID;
  209. gastrSockets[strAcceptReply.sConnectedSock].u16SessionID = gu16SessionID;
  210. M2M_DBG("Socket %d session ID = %d\r\n", strAcceptReply.sConnectedSock, gu16SessionID);
  211. }
  212. strAccept.sock = strAcceptReply.sConnectedSock;
  213. strAccept.strAddr.sin_family = AF_INET;
  214. strAccept.strAddr.sin_port = strAcceptReply.strAddr.u16Port;
  215. strAccept.strAddr.sin_addr.s_addr = strAcceptReply.strAddr.u32IPAddr;
  216. if (gpfAppSocketCb)
  217. gpfAppSocketCb(strAcceptReply.sListenSock, SOCKET_MSG_ACCEPT, &strAccept);
  218. }
  219. } else if ((u8OpCode == SOCKET_CMD_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT)) {
  220. tstrConnectReply strConnectReply;
  221. tstrSocketConnectMsg strConnMsg;
  222. if (hif_receive(u32Address, (uint8 *)&strConnectReply, sizeof(tstrConnectReply), 0) == M2M_SUCCESS) {
  223. strConnMsg.sock = strConnectReply.sock;
  224. strConnMsg.s8Error = strConnectReply.s8Error;
  225. if (strConnectReply.s8Error == SOCK_ERR_NO_ERROR) {
  226. gastrSockets[strConnectReply.sock].u16DataOffset
  227. = strConnectReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET;
  228. }
  229. if (gpfAppSocketCb)
  230. gpfAppSocketCb(strConnectReply.sock, SOCKET_MSG_CONNECT, &strConnMsg);
  231. }
  232. } else if (u8OpCode == SOCKET_CMD_DNS_RESOLVE) {
  233. tstrDnsReply strDnsReply;
  234. if (hif_receive(u32Address, (uint8 *)&strDnsReply, sizeof(tstrDnsReply), 0) == M2M_SUCCESS) {
  235. if (gpfAppResolveCb)
  236. gpfAppResolveCb((uint8 *)strDnsReply.acHostName, strDnsReply.u32HostIP);
  237. }
  238. } else if ((u8OpCode == SOCKET_CMD_RECV) || (u8OpCode == SOCKET_CMD_RECVFROM)
  239. || (u8OpCode == SOCKET_CMD_SSL_RECV)) {
  240. SOCKET sock;
  241. sint16 s16RecvStatus;
  242. tstrRecvReply strRecvReply;
  243. uint16 u16ReadSize;
  244. tstrSocketRecvMsg strRecvMsg;
  245. uint8 u8CallbackMsgID = SOCKET_MSG_RECV;
  246. uint16 u16DataOffset;
  247. if (u8OpCode == SOCKET_CMD_RECVFROM)
  248. u8CallbackMsgID = SOCKET_MSG_RECVFROM;
  249. /* Read RECV REPLY data structure.
  250. */
  251. u16ReadSize = sizeof(tstrRecvReply);
  252. if (hif_receive(u32Address, (uint8 *)&strRecvReply, u16ReadSize, 0) == M2M_SUCCESS) {
  253. uint16 u16SessionID = 0;
  254. sock = strRecvReply.sock;
  255. u16SessionID = strRecvReply.u16SessionID;
  256. M2M_DBG("recv callback session ID = %d\r\n", u16SessionID);
  257. /* Reset the Socket RX Pending Flag.
  258. */
  259. gastrSockets[sock].bIsRecvPending = 0;
  260. s16RecvStatus = NM_BSP_B_L_16(strRecvReply.s16RecvStatus);
  261. u16DataOffset = NM_BSP_B_L_16(strRecvReply.u16DataOffset);
  262. strRecvMsg.strRemoteAddr.sin_port = strRecvReply.strRemoteAddr.u16Port;
  263. strRecvMsg.strRemoteAddr.sin_addr.s_addr = strRecvReply.strRemoteAddr.u32IPAddr;
  264. if (u16SessionID == gastrSockets[sock].u16SessionID) {
  265. if ((s16RecvStatus > 0) && (s16RecvStatus < u16BufferSize)) {
  266. /* Skip incoming bytes until reaching the Start of Application Data.
  267. */
  268. u32Address += u16DataOffset;
  269. /* Read the Application data and deliver it to the application callback in
  270. the given application buffer. If the buffer is smaller than the received data,
  271. the data is passed to the application in chunks according to its buffer size.
  272. */
  273. u16ReadSize = (uint16)s16RecvStatus;
  274. Socket_ReadSocketData(sock, &strRecvMsg, u8CallbackMsgID, u32Address, u16ReadSize);
  275. } else {
  276. strRecvMsg.s16BufferSize = s16RecvStatus;
  277. strRecvMsg.pu8Buffer = NULL;
  278. if (gpfAppSocketCb)
  279. gpfAppSocketCb(sock, u8CallbackMsgID, &strRecvMsg);
  280. }
  281. } else {
  282. M2M_DBG("Discard recv callback %d %d \r\n", u16SessionID, gastrSockets[sock].u16SessionID);
  283. if (u16ReadSize < u16BufferSize) {
  284. if (hif_receive(0, NULL, 0, 1) == M2M_SUCCESS)
  285. M2M_DBG("hif_receive Success\n");
  286. else
  287. M2M_DBG("hif_receive Fail\n");
  288. }
  289. }
  290. }
  291. } else if ((u8OpCode == SOCKET_CMD_SEND) || (u8OpCode == SOCKET_CMD_SENDTO) || (u8OpCode == SOCKET_CMD_SSL_SEND)) {
  292. SOCKET sock;
  293. sint16 s16Rcvd;
  294. tstrSendReply strReply;
  295. uint8 u8CallbackMsgID = SOCKET_MSG_SEND;
  296. if (u8OpCode == SOCKET_CMD_SENDTO)
  297. u8CallbackMsgID = SOCKET_MSG_SENDTO;
  298. if (hif_receive(u32Address, (uint8 *)&strReply, sizeof(tstrSendReply), 0) == M2M_SUCCESS) {
  299. uint16 u16SessionID = 0;
  300. sock = strReply.sock;
  301. u16SessionID = strReply.u16SessionID;
  302. M2M_DBG("send callback session ID = %d\r\n", u16SessionID);
  303. s16Rcvd = NM_BSP_B_L_16(strReply.s16SentBytes);
  304. if (u16SessionID == gastrSockets[sock].u16SessionID) {
  305. if (gpfAppSocketCb)
  306. gpfAppSocketCb(sock, u8CallbackMsgID, &s16Rcvd);
  307. } else {
  308. M2M_DBG("Discard send callback %d %d \r\n", u16SessionID, gastrSockets[sock].u16SessionID);
  309. }
  310. }
  311. } else if (u8OpCode == SOCKET_CMD_PING) {
  312. tstrPingReply strPingReply;
  313. if (hif_receive(u32Address, (uint8 *)&strPingReply, sizeof(tstrPingReply), 1) == M2M_SUCCESS) {
  314. gfpPingCb = (void (*)(uint32, uint32, uint8))strPingReply.u32CmdPrivate;
  315. if (gfpPingCb != NULL) {
  316. gfpPingCb(strPingReply.u32IPAddr, strPingReply.u32RTT, strPingReply.u8ErrorCode);
  317. }
  318. }
  319. }
  320. }
  321. /*********************************************************************
  322. Function
  323. socketInit
  324. Description
  325. Return
  326. None.
  327. Author
  328. Ahmed Ezzat
  329. Version
  330. 1.0
  331. Date
  332. 4 June 2012
  333. *********************************************************************/
  334. void socketInit(void)
  335. {
  336. if (gbSocketInit == 0) {
  337. m2m_memset((uint8 *)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
  338. hif_register_cb(M2M_REQ_GROUP_IP, m2m_ip_cb);
  339. gbSocketInit = 1;
  340. gu16SessionID = 0;
  341. }
  342. }
  343. /*********************************************************************
  344. Function
  345. socketDeinit
  346. Description
  347. Return
  348. None.
  349. Author
  350. Samer Sarhan
  351. Version
  352. 1.0
  353. Date
  354. 27 Feb 2015
  355. *********************************************************************/
  356. void socketDeinit(void)
  357. {
  358. m2m_memset((uint8 *)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
  359. hif_register_cb(M2M_REQ_GROUP_IP, NULL);
  360. gpfAppSocketCb = NULL;
  361. gpfAppResolveCb = NULL;
  362. gbSocketInit = 0;
  363. }
  364. /*********************************************************************
  365. Function
  366. registerSocketCallback
  367. Description
  368. Return
  369. None.
  370. Author
  371. Ahmed Ezzat
  372. Versio
  373. 1.0
  374. Date
  375. 4 June 2012
  376. *********************************************************************/
  377. void registerSocketCallback(tpfAppSocketCb pfAppSocketCb, tpfAppResolveCb pfAppResolveCb)
  378. {
  379. gpfAppSocketCb = pfAppSocketCb;
  380. gpfAppResolveCb = pfAppResolveCb;
  381. }
  382. /*********************************************************************
  383. Function
  384. socket
  385. Description
  386. Creates a socket.
  387. Return
  388. - Negative value for error.
  389. - ZERO or positive value as a socket ID if successful.
  390. Author
  391. Ahmed Ezzat
  392. Version
  393. 1.0
  394. Date
  395. 4 June 2012
  396. *********************************************************************/
  397. SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags)
  398. {
  399. SOCKET sock = -1;
  400. uint8 u8SockID;
  401. uint8 u8Count;
  402. volatile tstrSocket * pstrSock;
  403. static volatile uint8 u8NextTcpSock = 0;
  404. static volatile uint8 u8NextUdpSock = 0;
  405. /* The only supported family is the AF_INET for UDP and TCP transport layer protocols. */
  406. if (u16Domain == AF_INET) {
  407. if (u8Type == SOCK_STREAM) {
  408. for (u8Count = 0; u8Count < TCP_SOCK_MAX; u8Count++) {
  409. u8SockID = u8NextTcpSock;
  410. pstrSock = &gastrSockets[u8NextTcpSock];
  411. u8NextTcpSock = (u8NextTcpSock + 1) % TCP_SOCK_MAX;
  412. if (!pstrSock->bIsUsed) {
  413. sock = (SOCKET)u8SockID;
  414. break;
  415. }
  416. }
  417. } else if (u8Type == SOCK_DGRAM) {
  418. volatile tstrSocket *pastrUDPSockets = &gastrSockets[TCP_SOCK_MAX];
  419. for (u8Count = 0; u8Count < UDP_SOCK_MAX; u8Count++) {
  420. u8SockID = u8NextUdpSock;
  421. pstrSock = &pastrUDPSockets[u8NextUdpSock];
  422. u8NextUdpSock = (u8NextUdpSock + 1) % UDP_SOCK_MAX;
  423. if (!pstrSock->bIsUsed) {
  424. sock = (SOCKET)(u8SockID + TCP_SOCK_MAX);
  425. break;
  426. }
  427. }
  428. }
  429. if (sock >= 0) {
  430. m2m_memset((uint8 *)pstrSock, 0, sizeof(tstrSocket));
  431. pstrSock->bIsUsed = 1;
  432. /* The session ID is used to distinguish different socket connections
  433. by comparing the assigned session ID to the one reported by the firmware*/
  434. ++gu16SessionID;
  435. if (gu16SessionID == 0)
  436. ++gu16SessionID;
  437. pstrSock->u16SessionID = gu16SessionID;
  438. M2M_INFO("Socket %d session ID = %d\r\n", sock, gu16SessionID);
  439. if (u8Flags & SOCKET_FLAGS_SSL) {
  440. tstrSSLSocketCreateCmd strSSLCreate;
  441. strSSLCreate.sslSock = sock;
  442. pstrSock->u8SSLFlags = SSL_FLAGS_ACTIVE | SSL_FLAGS_NO_TX_COPY;
  443. SOCKET_REQUEST(SOCKET_CMD_SSL_CREATE, (uint8 *)&strSSLCreate, sizeof(tstrSSLSocketCreateCmd), 0, 0, 0);
  444. }
  445. }
  446. }
  447. return sock;
  448. }
  449. /*********************************************************************
  450. Function
  451. bind
  452. Description
  453. Request to bind a socket on a local address.
  454. Return
  455. Author
  456. Ahmed Ezzat
  457. Version
  458. 1.0
  459. Date
  460. 5 June 2012
  461. *********************************************************************/
  462. sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen)
  463. {
  464. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  465. if ((pstrAddr != NULL) && (sock >= 0) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0)) {
  466. tstrBindCmd strBind;
  467. uint8 u8CMD = SOCKET_CMD_BIND;
  468. if (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) {
  469. u8CMD = SOCKET_CMD_SSL_BIND;
  470. }
  471. /* Build the bind request. */
  472. strBind.sock = sock;
  473. m2m_memcpy((uint8 *)&strBind.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr));
  474. strBind.u16SessionID = gastrSockets[sock].u16SessionID;
  475. /* Send the request. */
  476. s8Ret = SOCKET_REQUEST(u8CMD, (uint8 *)&strBind, sizeof(tstrBindCmd), NULL, 0, 0);
  477. if (s8Ret != SOCK_ERR_NO_ERROR) {
  478. s8Ret = SOCK_ERR_INVALID;
  479. }
  480. }
  481. return s8Ret;
  482. }
  483. /*********************************************************************
  484. Function
  485. listen
  486. Description
  487. Return
  488. Author
  489. Ahmed Ezzat
  490. Version
  491. 1.0
  492. Date
  493. 5 June 2012
  494. *********************************************************************/
  495. sint8 listen(SOCKET sock, uint8 backlog)
  496. {
  497. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  498. if (sock >= 0 && (gastrSockets[sock].bIsUsed == 1)) {
  499. tstrListenCmd strListen;
  500. strListen.sock = sock;
  501. strListen.u8BackLog = backlog;
  502. strListen.u16SessionID = gastrSockets[sock].u16SessionID;
  503. s8Ret = SOCKET_REQUEST(SOCKET_CMD_LISTEN, (uint8 *)&strListen, sizeof(tstrListenCmd), NULL, 0, 0);
  504. if (s8Ret != SOCK_ERR_NO_ERROR) {
  505. s8Ret = SOCK_ERR_INVALID;
  506. }
  507. }
  508. return s8Ret;
  509. }
  510. /*********************************************************************
  511. Function
  512. accept
  513. Description
  514. Return
  515. Author
  516. Ahmed Ezzat
  517. Version
  518. 1.0
  519. Date
  520. 5 June 2012
  521. *********************************************************************/
  522. sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen)
  523. {
  524. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  525. if (sock >= 0 && (gastrSockets[sock].bIsUsed == 1)) {
  526. s8Ret = SOCK_ERR_NO_ERROR;
  527. }
  528. return s8Ret;
  529. }
  530. /*********************************************************************
  531. Function
  532. connect
  533. Description
  534. Connect to a remote TCP Server.
  535. Return
  536. Author
  537. Ahmed Ezzat
  538. Version
  539. 1.0
  540. Date
  541. 5 June 2012
  542. *********************************************************************/
  543. sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen)
  544. {
  545. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  546. if ((sock >= 0) && (pstrAddr != NULL) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0)) {
  547. tstrConnectCmd strConnect;
  548. uint8 u8Cmd = SOCKET_CMD_CONNECT;
  549. if ((gastrSockets[sock].u8SSLFlags) & SSL_FLAGS_ACTIVE) {
  550. u8Cmd = SOCKET_CMD_SSL_CONNECT;
  551. strConnect.u8SslFlags = gastrSockets[sock].u8SSLFlags;
  552. }
  553. strConnect.sock = sock;
  554. m2m_memcpy((uint8 *)&strConnect.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr));
  555. strConnect.u16SessionID = gastrSockets[sock].u16SessionID;
  556. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8 *)&strConnect, sizeof(tstrConnectCmd), NULL, 0, 0);
  557. if (s8Ret != SOCK_ERR_NO_ERROR) {
  558. s8Ret = SOCK_ERR_INVALID;
  559. }
  560. }
  561. return s8Ret;
  562. }
  563. /*********************************************************************
  564. Function
  565. send
  566. Description
  567. Return
  568. Author
  569. Ahmed Ezzat
  570. Version
  571. 1.0
  572. Date
  573. 5 June 2012
  574. *********************************************************************/
  575. sint16 send(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags)
  576. {
  577. sint16 s16Ret = SOCK_ERR_INVALID_ARG;
  578. if ((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH)
  579. && (gastrSockets[sock].bIsUsed == 1)) {
  580. uint16 u16DataOffset;
  581. tstrSendCmd strSend;
  582. uint8 u8Cmd;
  583. u8Cmd = SOCKET_CMD_SEND;
  584. u16DataOffset = TCP_TX_PACKET_OFFSET;
  585. strSend.sock = sock;
  586. strSend.u16DataSize = NM_BSP_B_L_16(u16SendLength);
  587. strSend.u16SessionID = gastrSockets[sock].u16SessionID;
  588. if (sock >= TCP_SOCK_MAX) {
  589. u16DataOffset = UDP_TX_PACKET_OFFSET;
  590. }
  591. if (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) {
  592. u8Cmd = SOCKET_CMD_SSL_SEND;
  593. u16DataOffset = gastrSockets[sock].u16DataOffset;
  594. }
  595. s16Ret = SOCKET_REQUEST(u8Cmd | M2M_REQ_DATA_PKT,
  596. (uint8 *)&strSend,
  597. sizeof(tstrSendCmd),
  598. pvSendBuffer,
  599. u16SendLength,
  600. u16DataOffset);
  601. if (s16Ret != SOCK_ERR_NO_ERROR) {
  602. s16Ret = SOCK_ERR_BUFFER_FULL;
  603. }
  604. }
  605. return s16Ret;
  606. }
  607. /*********************************************************************
  608. Function
  609. sendto
  610. Description
  611. Return
  612. Author
  613. Ahmed Ezzat
  614. Version
  615. 1.0
  616. Date
  617. 4 June 2012
  618. *********************************************************************/
  619. sint16 sendto(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags, struct sockaddr *pstrDestAddr,
  620. uint8 u8AddrLen)
  621. {
  622. sint16 s16Ret = SOCK_ERR_INVALID_ARG;
  623. if ((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH)
  624. && (gastrSockets[sock].bIsUsed == 1)) {
  625. if (gastrSockets[sock].bIsUsed) {
  626. tstrSendCmd strSendTo;
  627. m2m_memset((uint8 *)&strSendTo, 0, sizeof(tstrSendCmd));
  628. strSendTo.sock = sock;
  629. strSendTo.u16DataSize = NM_BSP_B_L_16(u16SendLength);
  630. strSendTo.u16SessionID = gastrSockets[sock].u16SessionID;
  631. if (pstrDestAddr != NULL) {
  632. struct sockaddr_in *pstrAddr;
  633. pstrAddr = (void *)pstrDestAddr;
  634. strSendTo.strAddr.u16Family = pstrAddr->sin_family;
  635. strSendTo.strAddr.u16Port = pstrAddr->sin_port;
  636. strSendTo.strAddr.u32IPAddr = pstrAddr->sin_addr.s_addr;
  637. }
  638. s16Ret = SOCKET_REQUEST(SOCKET_CMD_SENDTO | M2M_REQ_DATA_PKT,
  639. (uint8 *)&strSendTo,
  640. sizeof(tstrSendCmd),
  641. pvSendBuffer,
  642. u16SendLength,
  643. UDP_TX_PACKET_OFFSET);
  644. if (s16Ret != SOCK_ERR_NO_ERROR) {
  645. s16Ret = SOCK_ERR_BUFFER_FULL;
  646. }
  647. }
  648. }
  649. return s16Ret;
  650. }
  651. /*********************************************************************
  652. Function
  653. recv
  654. Description
  655. Return
  656. Author
  657. Ahmed Ezzat
  658. Version
  659. 1.0
  660. 2.0 9 April 2013 --> Add timeout for recv operation.
  661. Date
  662. 5 June 2012
  663. *********************************************************************/
  664. sint16 recv(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec)
  665. {
  666. sint16 s16Ret = SOCK_ERR_INVALID_ARG;
  667. if ((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1)) {
  668. s16Ret = SOCK_ERR_NO_ERROR;
  669. gastrSockets[sock].pu8UserBuffer = (uint8 *)pvRecvBuf;
  670. gastrSockets[sock].u16UserBufferSize = u16BufLen;
  671. if (!gastrSockets[sock].bIsRecvPending) {
  672. tstrRecvCmd strRecv;
  673. uint8 u8Cmd = SOCKET_CMD_RECV;
  674. gastrSockets[sock].bIsRecvPending = 1;
  675. if (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) {
  676. u8Cmd = SOCKET_CMD_SSL_RECV;
  677. }
  678. /* Check the timeout value. */
  679. if (u32Timeoutmsec == 0)
  680. strRecv.u32Timeoutmsec = 0xFFFFFFFF;
  681. else
  682. strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
  683. strRecv.sock = sock;
  684. strRecv.u16SessionID = gastrSockets[sock].u16SessionID;
  685. s16Ret = SOCKET_REQUEST(u8Cmd, (uint8 *)&strRecv, sizeof(tstrRecvCmd), NULL, 0, 0);
  686. if (s16Ret != SOCK_ERR_NO_ERROR) {
  687. s16Ret = SOCK_ERR_BUFFER_FULL;
  688. }
  689. }
  690. }
  691. return s16Ret;
  692. }
  693. /*********************************************************************
  694. Function
  695. close
  696. Description
  697. Return
  698. None.
  699. Author
  700. Ahmed Ezzat
  701. Version
  702. 1.0
  703. Date
  704. 4 June 2012
  705. *********************************************************************/
  706. sint8 close(SOCKET sock)
  707. {
  708. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  709. M2M_INFO("Sock to delete <%d>\n", sock);
  710. if (sock >= 0 && (gastrSockets[sock].bIsUsed == 1)) {
  711. uint8 u8Cmd = SOCKET_CMD_CLOSE;
  712. tstrCloseCmd strclose;
  713. strclose.sock = sock;
  714. strclose.u16SessionID = gastrSockets[sock].u16SessionID;
  715. gastrSockets[sock].bIsUsed = 0;
  716. gastrSockets[sock].u16SessionID = 0;
  717. if (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) {
  718. u8Cmd = SOCKET_CMD_SSL_CLOSE;
  719. }
  720. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8 *)&strclose, sizeof(tstrCloseCmd), NULL, 0, 0);
  721. if (s8Ret != SOCK_ERR_NO_ERROR) {
  722. s8Ret = SOCK_ERR_INVALID;
  723. }
  724. m2m_memset((uint8 *)&gastrSockets[sock], 0, sizeof(tstrSocket));
  725. }
  726. return s8Ret;
  727. }
  728. /*********************************************************************
  729. Function
  730. recvfrom
  731. Description
  732. Return
  733. Author
  734. Ahmed Ezzat
  735. Version
  736. 1.0
  737. 2.0 9 April 2013 --> Add timeout for recv operation.
  738. Date
  739. 5 June 2012
  740. *********************************************************************/
  741. sint16 recvfrom(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec)
  742. {
  743. sint16 s16Ret = SOCK_ERR_NO_ERROR;
  744. if ((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1)) {
  745. if (gastrSockets[sock].bIsUsed) {
  746. s16Ret = SOCK_ERR_NO_ERROR;
  747. gastrSockets[sock].pu8UserBuffer = (uint8 *)pvRecvBuf;
  748. gastrSockets[sock].u16UserBufferSize = u16BufLen;
  749. if (!gastrSockets[sock].bIsRecvPending) {
  750. tstrRecvCmd strRecv;
  751. gastrSockets[sock].bIsRecvPending = 1;
  752. /* Check the timeout value. */
  753. if (u32Timeoutmsec == 0)
  754. strRecv.u32Timeoutmsec = 0xFFFFFFFF;
  755. else
  756. strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
  757. strRecv.sock = sock;
  758. strRecv.u16SessionID = gastrSockets[sock].u16SessionID;
  759. s16Ret = SOCKET_REQUEST(SOCKET_CMD_RECVFROM, (uint8 *)&strRecv, sizeof(tstrRecvCmd), NULL, 0, 0);
  760. if (s16Ret != SOCK_ERR_NO_ERROR) {
  761. s16Ret = SOCK_ERR_BUFFER_FULL;
  762. }
  763. }
  764. }
  765. } else {
  766. s16Ret = SOCK_ERR_INVALID_ARG;
  767. }
  768. return s16Ret;
  769. }
  770. /*********************************************************************
  771. Function
  772. nmi_inet_addr
  773. Description
  774. Return
  775. Unsigned 32-bit integer representing the IP address in Network
  776. byte order.
  777. Author
  778. Ahmed Ezzat
  779. Version
  780. 1.0
  781. Date
  782. 4 June 2012
  783. *********************************************************************/
  784. uint32 nmi_inet_addr(char *pcIpAddr)
  785. {
  786. uint8 tmp;
  787. uint32 u32IP = 0;
  788. uint8 au8IP[4];
  789. uint8 c;
  790. uint8 i, j;
  791. tmp = 0;
  792. for (i = 0; i < 4; ++i) {
  793. j = 0;
  794. do {
  795. c = *pcIpAddr;
  796. ++j;
  797. if (j > 4) {
  798. return 0;
  799. }
  800. if (c == '.' || c == 0) {
  801. au8IP[i] = tmp;
  802. tmp = 0;
  803. } else if (c >= '0' && c <= '9') {
  804. tmp = (tmp * 10) + (c - '0');
  805. } else {
  806. return 0;
  807. }
  808. ++pcIpAddr;
  809. } while (c != '.' && c != 0);
  810. }
  811. m2m_memcpy((uint8 *)&u32IP, au8IP, 4);
  812. return u32IP;
  813. }
  814. /*********************************************************************
  815. Function
  816. gethostbyname
  817. Description
  818. Return
  819. None.
  820. Author
  821. Ahmed Ezzat
  822. Version
  823. 1.0
  824. Date
  825. 4 June 2012
  826. *********************************************************************/
  827. sint8 gethostbyname(uint8 *pcHostName)
  828. {
  829. sint8 s8Err = SOCK_ERR_INVALID_ARG;
  830. uint8 u8HostNameSize = (uint8)m2m_strlen(pcHostName);
  831. if (u8HostNameSize <= HOSTNAME_MAX_SIZE) {
  832. s8Err = SOCKET_REQUEST(SOCKET_CMD_DNS_RESOLVE, (uint8 *)pcHostName, u8HostNameSize + 1, NULL, 0, 0);
  833. }
  834. return s8Err;
  835. }
  836. /*********************************************************************
  837. Function
  838. setsockopt
  839. Description
  840. Return
  841. None.
  842. Author
  843. Abdelrahman Diab
  844. Version
  845. 1.0
  846. Date
  847. 9 September 2014
  848. *********************************************************************/
  849. static sint8 sslSetSockOpt(SOCKET sock, uint8 u8Opt, const void *pvOptVal, uint16 u16OptLen)
  850. {
  851. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  852. if (sock < TCP_SOCK_MAX) {
  853. if (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) {
  854. if (u8Opt == SO_SSL_BYPASS_X509_VERIF) {
  855. int optVal = *((int *)pvOptVal);
  856. if (optVal) {
  857. gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_BYPASS_X509;
  858. } else {
  859. gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_BYPASS_X509;
  860. }
  861. s8Ret = SOCK_ERR_NO_ERROR;
  862. } else if (u8Opt == SO_SSL_ENABLE_SESSION_CACHING) {
  863. int optVal = *((int *)pvOptVal);
  864. if (optVal) {
  865. gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CACHE_SESSION;
  866. } else {
  867. gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CACHE_SESSION;
  868. }
  869. s8Ret = SOCK_ERR_NO_ERROR;
  870. } else if (u8Opt == SO_SSL_ENABLE_SNI_VALIDATION) {
  871. int optVal = *((int *)pvOptVal);
  872. if (optVal) {
  873. gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CHECK_SNI;
  874. } else {
  875. gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CHECK_SNI;
  876. }
  877. s8Ret = SOCK_ERR_NO_ERROR;
  878. } else if (u8Opt == SO_SSL_SNI) {
  879. if (u16OptLen < HOSTNAME_MAX_SIZE) {
  880. uint8 * pu8SNI = (uint8 *)pvOptVal;
  881. tstrSSLSetSockOptCmd strCmd;
  882. strCmd.sock = sock;
  883. strCmd.u16SessionID = gastrSockets[sock].u16SessionID;
  884. strCmd.u8Option = u8Opt;
  885. strCmd.u32OptLen = u16OptLen;
  886. m2m_memcpy(strCmd.au8OptVal, pu8SNI, HOSTNAME_MAX_SIZE);
  887. if (SOCKET_REQUEST(
  888. SOCKET_CMD_SSL_SET_SOCK_OPT, (uint8 *)&strCmd, sizeof(tstrSSLSetSockOptCmd), 0, 0, 0)
  889. == M2M_ERR_MEM_ALLOC) {
  890. s8Ret = SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT | M2M_REQ_DATA_PKT,
  891. (uint8 *)&strCmd,
  892. sizeof(tstrSSLSetSockOptCmd),
  893. 0,
  894. 0,
  895. 0);
  896. }
  897. s8Ret = SOCK_ERR_NO_ERROR;
  898. } else {
  899. M2M_ERR("SNI Exceeds Max Length\n");
  900. }
  901. } else {
  902. M2M_ERR("Unknown SSL Socket Option %d\n", u8Opt);
  903. }
  904. } else {
  905. M2M_ERR("Not SSL Socket\n");
  906. }
  907. }
  908. return s8Ret;
  909. }
  910. /*********************************************************************
  911. Function
  912. setsockopt
  913. Description
  914. Return
  915. None.
  916. Author
  917. Abdelrahman Diab
  918. Version
  919. 1.0
  920. Date
  921. 9 September 2014
  922. *********************************************************************/
  923. sint8 setsockopt(SOCKET sock, uint8 u8Level, uint8 option_name, const void *option_value, uint16 u16OptionLen)
  924. {
  925. sint8 s8Ret = SOCK_ERR_INVALID_ARG;
  926. if ((sock >= 0) && (option_value != NULL) && (gastrSockets[sock].bIsUsed == 1)) {
  927. if (u8Level == SOL_SSL_SOCKET) {
  928. s8Ret = sslSetSockOpt(sock, option_name, option_value, u16OptionLen);
  929. } else {
  930. uint8 u8Cmd = SOCKET_CMD_SET_SOCKET_OPTION;
  931. tstrSetSocketOptCmd strSetSockOpt;
  932. strSetSockOpt.u8Option = option_name;
  933. strSetSockOpt.sock = sock;
  934. strSetSockOpt.u32OptionValue = *(uint32 *)option_value;
  935. strSetSockOpt.u16SessionID = gastrSockets[sock].u16SessionID;
  936. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8 *)&strSetSockOpt, sizeof(tstrSetSocketOptCmd), NULL, 0, 0);
  937. if (s8Ret != SOCK_ERR_NO_ERROR) {
  938. s8Ret = SOCK_ERR_INVALID;
  939. }
  940. }
  941. }
  942. return s8Ret;
  943. }
  944. /*********************************************************************
  945. Function
  946. getsockopt
  947. Description
  948. Return
  949. None.
  950. Author
  951. Ahmed Ezzat
  952. Version
  953. 1.0
  954. Date
  955. 24 August 2014
  956. *********************************************************************/
  957. sint8 getsockopt(SOCKET sock, uint8 u8Level, uint8 u8OptName, const void *pvOptValue, uint8 *pu8OptLen)
  958. {
  959. /* TBD */
  960. return M2M_SUCCESS;
  961. }
  962. /*********************************************************************
  963. Function
  964. m2m_ping_req
  965. Description
  966. Send Ping request.
  967. Return
  968. Author
  969. Ahmed Ezzat
  970. Version
  971. 1.0
  972. Date
  973. 4 June 2015
  974. *********************************************************************/
  975. sint8 m2m_ping_req(uint32 u32DstIP, uint8 u8TTL, tpfPingCb fpPingCb)
  976. {
  977. sint8 s8Ret = M2M_ERR_INVALID_ARG;
  978. if ((u32DstIP != 0) && (fpPingCb != NULL)) {
  979. tstrPingCmd strPingCmd;
  980. strPingCmd.u16PingCount = 1;
  981. strPingCmd.u32DestIPAddr = u32DstIP;
  982. strPingCmd.u32CmdPrivate = (uint32)fpPingCb;
  983. strPingCmd.u8TTL = u8TTL;
  984. s8Ret = SOCKET_REQUEST(SOCKET_CMD_PING, (uint8 *)&strPingCmd, sizeof(tstrPingCmd), NULL, 0, 0);
  985. }
  986. return s8Ret;
  987. }
  988. /*********************************************************************
  989. Function
  990. sslEnableCertExpirationCheck
  991. Description
  992. Enable/Disable TLS Certificate Expiration Check.
  993. Return
  994. Author
  995. Ahmed Ezzat
  996. Version
  997. 1.0
  998. Date
  999. *********************************************************************/
  1000. sint8 sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting)
  1001. {
  1002. tstrSslCertExpSettings strSettings;
  1003. strSettings.u32CertExpValidationOpt = (uint32)enuValidationSetting;
  1004. return SOCKET_REQUEST(SOCKET_CMD_SSL_EXP_CHECK, (uint8 *)&strSettings, sizeof(tstrSslCertExpSettings), NULL, 0, 0);
  1005. }