No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

1262 líneas
44 KiB

  1. /*******************************************************************************
  2. File Name:
  3. socket.c
  4. Summary:
  5. WINC3400 BSD Compatible Socket Interface
  6. Description:
  7. WINC3400 BSD Compatible Socket Interface
  8. *******************************************************************************/
  9. //DOM-IGNORE-BEGIN
  10. /*******************************************************************************
  11. * Copyright (C) 2021 Microchip Technology Inc. and its subsidiaries.
  12. *
  13. * Subject to your compliance with these terms, you may use Microchip software
  14. * and any derivatives exclusively with Microchip products. It is your
  15. * responsibility to comply with third party license terms applicable to your
  16. * use of third party software (including open source software) that may
  17. * accompany Microchip software.
  18. *
  19. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
  20. * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
  21. * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
  22. * PARTICULAR PURPOSE.
  23. *
  24. * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
  25. * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
  26. * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
  27. * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
  28. * FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
  29. * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  30. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  31. *******************************************************************************/
  32. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  33. INCLUDES
  34. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  35. #include "nm_bsp.h"
  36. #include "socket.h"
  37. #include "m2m_hif.h"
  38. #include "m2m_socket_host_if.h"
  39. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  40. MACROS
  41. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  42. #define TLS_RECORD_HEADER_LENGTH (5)
  43. #define ETHERNET_HEADER_OFFSET (34)
  44. #define ETHERNET_HEADER_LENGTH (14)
  45. #define TCP_IP_HEADER_LENGTH (40)
  46. #define UDP_IP_HEADER_LENGTH (28)
  47. #define IP_PACKET_OFFSET (ETHERNET_HEADER_LENGTH + ETHERNET_HEADER_OFFSET - M2M_HIF_HDR_OFFSET)
  48. #define TCP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + TCP_IP_HEADER_LENGTH)
  49. #define UDP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + UDP_IP_HEADER_LENGTH)
  50. #define SSL_TX_PACKET_OFFSET (TCP_TX_PACKET_OFFSET + TLS_RECORD_HEADER_LENGTH)
  51. #define SOCKET_REQUEST(reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset) \
  52. hif_send(M2M_REQ_GROUP_IP, reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset)
  53. #define SSL_FLAGS_ACTIVE NBIT0
  54. #define SSL_FLAGS_BYPASS_X509 NBIT1
  55. #define SSL_FLAGS_CACHE_SESSION NBIT4
  56. #define SSL_FLAGS_CHECK_CERTNAME NBIT6
  57. #define SSL_FLAGS_DELAY NBIT7
  58. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  59. PRIVATE DATA TYPES
  60. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  61. /*!
  62. * @brief
  63. */
  64. typedef struct {
  65. SOCKET sock;
  66. uint8_t u8Dummy;
  67. uint16_t u16SessionID;
  68. } tstrCloseCmd;
  69. /*!
  70. * @brief
  71. */
  72. typedef struct {
  73. uint8_t *pu8UserBuffer;
  74. uint16_t u16UserBufferSize;
  75. uint16_t u16SessionID;
  76. uint16_t u16DataOffset;
  77. uint8_t bIsUsed;
  78. uint8_t u8SSLFlags;
  79. uint8_t bIsRecvPending;
  80. uint8_t u8AlpnStatus;
  81. uint8_t u8ErrSource;
  82. uint8_t u8ErrCode;
  83. } tstrSocket;
  84. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  85. GLOBALS
  86. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  87. volatile tstrSocket gastrSockets[MAX_SOCKET];
  88. volatile uint16_t gu16SessionID = 0;
  89. volatile tpfAppSocketCb gpfAppSocketCb;
  90. volatile tpfAppResolveCb gpfAppResolveCb;
  91. volatile uint8_t gbSocketInit = 0;
  92. static tpfPingCb gfpPingCb = NULL;
  93. static uint32_t gu32PingId = 0;
  94. /*********************************************************************
  95. Function
  96. Socket_ReadSocketData
  97. Description
  98. Callback function used by the WINC3400 driver to deliver messages
  99. for socket layer.
  100. Return
  101. None.
  102. *********************************************************************/
  103. static void Socket_ReadSocketData(SOCKET sock, tstrSocketRecvMsg *pstrRecv, uint8_t u8SocketMsg,
  104. uint32_t u32StartAddress, uint16_t u16ReadCount)
  105. {
  106. uint32_t u32Address = u32StartAddress;
  107. uint16_t u16Read;
  108. int16_t s16Diff;
  109. pstrRecv->u16RemainingSize = u16ReadCount;
  110. if((u16ReadCount > 0) && (gastrSockets[sock].pu8UserBuffer != NULL) && (gastrSockets[sock].u16UserBufferSize > 0) && (gastrSockets[sock].bIsUsed == 1))
  111. {
  112. u16Read = u16ReadCount;
  113. s16Diff = u16Read - gastrSockets[sock].u16UserBufferSize;
  114. if(s16Diff > 0)
  115. {
  116. /* We don't expect to be here. Firmware only sends data to the driver according to the application's buffer size.
  117. * But it is worth keeping this check, eg in case the application calls recv again with a smaller buffer size, or in case of HIF hacking. */
  118. u16Read = gastrSockets[sock].u16UserBufferSize;
  119. }
  120. if(hif_receive(u32Address, gastrSockets[sock].pu8UserBuffer, u16Read, 1) == M2M_SUCCESS)
  121. {
  122. pstrRecv->pu8Buffer = gastrSockets[sock].pu8UserBuffer;
  123. pstrRecv->s16BufferSize = u16Read;
  124. pstrRecv->u16RemainingSize -= u16Read;
  125. gastrSockets[sock].u16UserBufferSize = 0;
  126. gastrSockets[sock].pu8UserBuffer = NULL;
  127. if(gpfAppSocketCb)
  128. gpfAppSocketCb(sock, u8SocketMsg, pstrRecv);
  129. }
  130. else
  131. {
  132. M2M_ERR("Current <%d>\r\n", u16ReadCount);
  133. }
  134. }
  135. }
  136. /*********************************************************************
  137. Function
  138. m2m_ip_cb
  139. Description
  140. Callback function used by the NMC1000 driver to deliver messages
  141. for socket layer.
  142. Return
  143. None.
  144. *********************************************************************/
  145. static void m2m_ip_cb(uint8_t u8OpCode, uint16_t u16BufferSize, uint32_t u32Address)
  146. {
  147. if(u8OpCode == SOCKET_CMD_BIND)
  148. {
  149. tstrBindReply strBindReply;
  150. tstrSocketBindMsg strBind;
  151. if(hif_receive(u32Address, (uint8_t*)&strBindReply, sizeof(tstrBindReply), 0) == M2M_SUCCESS)
  152. {
  153. strBind.status = strBindReply.s8Status;
  154. if(gpfAppSocketCb)
  155. gpfAppSocketCb(strBindReply.sock, SOCKET_MSG_BIND, &strBind);
  156. }
  157. }
  158. else if(u8OpCode == SOCKET_CMD_LISTEN)
  159. {
  160. tstrListenReply strListenReply;
  161. tstrSocketListenMsg strListen;
  162. if(hif_receive(u32Address, (uint8_t*)&strListenReply, sizeof(tstrListenReply), 0) == M2M_SUCCESS)
  163. {
  164. strListen.status = strListenReply.s8Status;
  165. if(gpfAppSocketCb)
  166. gpfAppSocketCb(strListenReply.sock, SOCKET_MSG_LISTEN, &strListen);
  167. }
  168. }
  169. else if(u8OpCode == SOCKET_CMD_ACCEPT)
  170. {
  171. tstrAcceptReply strAcceptReply;
  172. tstrSocketAcceptMsg strAccept;
  173. if(hif_receive(u32Address, (uint8_t*)&strAcceptReply, sizeof(tstrAcceptReply), 0) == M2M_SUCCESS)
  174. {
  175. if((strAcceptReply.sConnectedSock >= 0) && (strAcceptReply.sConnectedSock < MAX_SOCKET))
  176. {
  177. gastrSockets[strAcceptReply.sConnectedSock].u8SSLFlags = 0;
  178. gastrSockets[strAcceptReply.sConnectedSock].bIsUsed = 1;
  179. /* The session ID is used to distinguish different socket connections
  180. by comparing the assigned session ID to the one reported by the firmware*/
  181. ++gu16SessionID;
  182. if(gu16SessionID == 0)
  183. ++gu16SessionID;
  184. gastrSockets[strAcceptReply.sConnectedSock].u16SessionID = gu16SessionID;
  185. M2M_DBG("Socket %d session ID = %d\r\n", strAcceptReply.sConnectedSock, gu16SessionID);
  186. }
  187. strAccept.sock = strAcceptReply.sConnectedSock;
  188. strAccept.strAddr.sin_family = AF_INET;
  189. strAccept.strAddr.sin_port = strAcceptReply.strAddr.u16Port;
  190. strAccept.strAddr.sin_addr.s_addr = strAcceptReply.strAddr.u32IPAddr;
  191. if(gpfAppSocketCb)
  192. gpfAppSocketCb(strAcceptReply.sListenSock, SOCKET_MSG_ACCEPT, &strAccept);
  193. }
  194. }
  195. else if((u8OpCode == SOCKET_CMD_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT_ALPN))
  196. {
  197. /* Note that for successful connections the fw always sends SOCKET_CMD_CONNECT, even for SSL connections. */
  198. tstrConnectAlpnReply strConnectAlpnReply = {{0}};
  199. tstrSocketConnectMsg strConnMsg;
  200. uint16_t u16HifSz = sizeof(tstrConnectAlpnReply);
  201. if(u8OpCode != SOCKET_CMD_SSL_CONNECT_ALPN)
  202. u16HifSz = sizeof(tstrConnectReply);
  203. if(hif_receive(u32Address, (uint8_t*)&strConnectAlpnReply, u16HifSz, 0) == M2M_SUCCESS)
  204. {
  205. if((strConnectAlpnReply.strConnReply.sock >= 0) && (strConnectAlpnReply.strConnReply.sock < MAX_SOCKET))
  206. {
  207. uint8_t u8Msg = SOCKET_MSG_CONNECT;
  208. strConnMsg.sock = strConnectAlpnReply.strConnReply.sock;
  209. strConnMsg.s8Error = strConnectAlpnReply.strConnReply.s8Error;
  210. /* If the SOCKET_CMD_SSL_CONNECT op code is received and the socket was already connected, then the
  211. callback corresponds to an attempt to make the socket secure. */
  212. if(0 != gastrSockets[strConnMsg.sock].u16DataOffset)
  213. {
  214. u8Msg = SOCKET_MSG_SECURE;
  215. }
  216. if(strConnectAlpnReply.strConnReply.s8Error == SOCK_ERR_NO_ERROR)
  217. {
  218. gastrSockets[strConnMsg.sock].u16DataOffset = strConnectAlpnReply.strConnReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET;
  219. gastrSockets[strConnMsg.sock].u8AlpnStatus = strConnectAlpnReply.u8AppProtocolIdx;
  220. }
  221. else
  222. {
  223. gastrSockets[strConnMsg.sock].u8ErrSource = strConnectAlpnReply.strConnReply.u8ErrSource;
  224. gastrSockets[strConnMsg.sock].u8ErrCode = strConnectAlpnReply.strConnReply.u8ErrCode;
  225. }
  226. if(gpfAppSocketCb)
  227. gpfAppSocketCb(strConnMsg.sock, u8Msg, &strConnMsg);
  228. }
  229. }
  230. }
  231. else if(u8OpCode == SOCKET_CMD_DNS_RESOLVE)
  232. {
  233. tstrDnsReply strDnsReply;
  234. if(hif_receive(u32Address, (uint8_t*)&strDnsReply, sizeof(tstrDnsReply), 0) == M2M_SUCCESS)
  235. {
  236. strDnsReply.u32HostIP = strDnsReply.u32HostIP;
  237. if(gpfAppResolveCb)
  238. gpfAppResolveCb((uint8_t*)strDnsReply.acHostName, strDnsReply.u32HostIP);
  239. }
  240. }
  241. else if((u8OpCode == SOCKET_CMD_RECV) || (u8OpCode == SOCKET_CMD_RECVFROM) || (u8OpCode == SOCKET_CMD_SSL_RECV))
  242. {
  243. SOCKET sock;
  244. int16_t s16RecvStatus;
  245. tstrRecvReply strRecvReply;
  246. uint16_t u16ReadSize;
  247. tstrSocketRecvMsg strRecvMsg;
  248. uint8_t u8CallbackMsgID = SOCKET_MSG_RECV;
  249. uint16_t u16DataOffset;
  250. if(u8OpCode == SOCKET_CMD_RECVFROM)
  251. u8CallbackMsgID = SOCKET_MSG_RECVFROM;
  252. /* Read RECV REPLY data structure.
  253. */
  254. u16ReadSize = sizeof(tstrRecvReply);
  255. if(hif_receive(u32Address, (uint8_t*)&strRecvReply, u16ReadSize, 0) == M2M_SUCCESS)
  256. {
  257. if((strRecvReply.sock >= 0) && (strRecvReply.sock < MAX_SOCKET))
  258. {
  259. uint16_t u16SessionID = 0;
  260. sock = strRecvReply.sock;
  261. u16SessionID = strRecvReply.u16SessionID;
  262. M2M_DBG("recv callback session ID = %d\r\n", u16SessionID);
  263. /* Reset the Socket RX Pending Flag.
  264. */
  265. gastrSockets[sock].bIsRecvPending = 0;
  266. s16RecvStatus = NM_BSP_B_L_16(strRecvReply.s16RecvStatus);
  267. u16DataOffset = NM_BSP_B_L_16(strRecvReply.u16DataOffset);
  268. strRecvMsg.strRemoteAddr.sin_port = strRecvReply.strRemoteAddr.u16Port;
  269. strRecvMsg.strRemoteAddr.sin_addr.s_addr = strRecvReply.strRemoteAddr.u32IPAddr;
  270. if(u16SessionID == gastrSockets[sock].u16SessionID)
  271. {
  272. if((s16RecvStatus > 0) && (s16RecvStatus < u16BufferSize))
  273. {
  274. /* Skip incoming bytes until reaching the Start of Application Data.
  275. */
  276. u32Address += u16DataOffset;
  277. /* Read the Application data and deliver it to the application callback in
  278. the given application buffer. Firmware only sends data up to
  279. the size of the application buffer. For TCP, a new call to recv is needed
  280. in order to retrieve any outstanding data from firmware.
  281. */
  282. u16ReadSize = (uint16_t)s16RecvStatus;
  283. Socket_ReadSocketData(sock, &strRecvMsg, u8CallbackMsgID, u32Address, u16ReadSize);
  284. }
  285. else
  286. {
  287. /* Don't tidy up here. Application must call shutdown().
  288. */
  289. strRecvMsg.s16BufferSize = s16RecvStatus;
  290. strRecvMsg.pu8Buffer = NULL;
  291. if(gpfAppSocketCb)
  292. gpfAppSocketCb(sock, u8CallbackMsgID, &strRecvMsg);
  293. }
  294. }
  295. else
  296. {
  297. M2M_DBG("Discard recv callback %d %d\r\n", u16SessionID, gastrSockets[sock].u16SessionID);
  298. if(u16ReadSize < u16BufferSize)
  299. hif_receive(0, NULL, 0, 1);
  300. }
  301. }
  302. }
  303. }
  304. else if((u8OpCode == SOCKET_CMD_SEND) || (u8OpCode == SOCKET_CMD_SENDTO) || (u8OpCode == SOCKET_CMD_SSL_SEND))
  305. {
  306. SOCKET sock;
  307. int16_t s16Rcvd;
  308. tstrSendReply strReply;
  309. uint8_t u8CallbackMsgID = SOCKET_MSG_SEND;
  310. if(u8OpCode == SOCKET_CMD_SENDTO)
  311. u8CallbackMsgID = SOCKET_MSG_SENDTO;
  312. if(hif_receive(u32Address, (uint8_t*)&strReply, sizeof(tstrSendReply), 0) == M2M_SUCCESS)
  313. {
  314. if((strReply.sock >=0) && (strReply.sock < MAX_SOCKET))
  315. {
  316. uint16_t u16SessionID = 0;
  317. sock = strReply.sock;
  318. u16SessionID = strReply.u16SessionID;
  319. M2M_DBG("send callback session ID = %d\r\n", u16SessionID);
  320. s16Rcvd = NM_BSP_B_L_16(strReply.s16SentBytes);
  321. if(u16SessionID == gastrSockets[sock].u16SessionID)
  322. {
  323. if(gpfAppSocketCb)
  324. gpfAppSocketCb(sock, u8CallbackMsgID, &s16Rcvd);
  325. }
  326. else
  327. {
  328. M2M_DBG("Discard send callback %d %d\r\n", u16SessionID, gastrSockets[sock].u16SessionID);
  329. }
  330. }
  331. }
  332. }
  333. else if(u8OpCode == SOCKET_CMD_PING)
  334. {
  335. tstrPingReply strPingReply;
  336. if(hif_receive(u32Address, (uint8_t*)&strPingReply, sizeof(tstrPingReply), 1) == M2M_SUCCESS)
  337. {
  338. if((gu32PingId == strPingReply.u32CmdPrivate) && (gfpPingCb != NULL))
  339. {
  340. gfpPingCb(strPingReply.u32IPAddr, strPingReply.u32RTT, strPingReply.u8ErrorCode);
  341. }
  342. }
  343. }
  344. }
  345. /*********************************************************************
  346. Function
  347. socketInit
  348. Description
  349. Return
  350. None.
  351. *********************************************************************/
  352. void socketInit(void)
  353. {
  354. if(gbSocketInit==0)
  355. {
  356. memset((uint8_t*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
  357. hif_register_cb(M2M_REQ_GROUP_IP, m2m_ip_cb);
  358. gbSocketInit=1;
  359. gu16SessionID = 0;
  360. }
  361. }
  362. /*********************************************************************
  363. Function
  364. socketDeinit
  365. Description
  366. Return
  367. None.
  368. *********************************************************************/
  369. void socketDeinit(void)
  370. {
  371. memset((uint8_t*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
  372. hif_register_cb(M2M_REQ_GROUP_IP, NULL);
  373. gpfAppSocketCb = NULL;
  374. gpfAppResolveCb = NULL;
  375. gbSocketInit = 0;
  376. }
  377. /*********************************************************************
  378. Function
  379. registerSocketCallback
  380. Description
  381. Return
  382. None.
  383. *********************************************************************/
  384. void registerSocketCallback(tpfAppSocketCb pfAppSocketCb, tpfAppResolveCb pfAppResolveCb)
  385. {
  386. gpfAppSocketCb = pfAppSocketCb;
  387. gpfAppResolveCb = pfAppResolveCb;
  388. }
  389. void registerSocketEventCallback(tpfAppSocketCb pfAppSocketCb)
  390. {
  391. gpfAppSocketCb = pfAppSocketCb;
  392. }
  393. void registerSocketResolveCallback(tpfAppResolveCb pfAppResolveCb)
  394. {
  395. gpfAppResolveCb = pfAppResolveCb;
  396. }
  397. /*********************************************************************
  398. Function
  399. socket
  400. Description
  401. Creates a socket.
  402. Return
  403. - Negative value for error.
  404. - ZERO or positive value as a socket ID if successful.
  405. *********************************************************************/
  406. SOCKET socket(uint16_t u16Domain, uint8_t u8Type, uint8_t u8Config)
  407. {
  408. SOCKET sock = -1;
  409. uint8_t u8SockID;
  410. uint8_t u8Count;
  411. volatile tstrSocket *pstrSock = NULL;
  412. static volatile uint8_t u8NextTcpSock = 0;
  413. static volatile uint8_t u8NextUdpSock = 0;
  414. /* The only supported family is the AF_INET for UDP and TCP transport layer protocols. */
  415. if(u16Domain == AF_INET)
  416. {
  417. if(u8Type == SOCK_STREAM)
  418. {
  419. for(u8Count = 0; u8Count < TCP_SOCK_MAX; u8Count ++)
  420. {
  421. u8SockID = u8NextTcpSock;
  422. pstrSock = &gastrSockets[u8NextTcpSock];
  423. u8NextTcpSock = (u8NextTcpSock + 1) % TCP_SOCK_MAX;
  424. if(!pstrSock->bIsUsed)
  425. {
  426. sock = (SOCKET)u8SockID;
  427. memset((uint8_t*)pstrSock, 0, sizeof(tstrSocket));
  428. /* In the current implementation, SSL flags only have meaning for the TCP socket case. */
  429. if(u8Config != SOCKET_CONFIG_SSL_OFF)
  430. {
  431. tstrSSLSocketCreateCmd strSSLCreate;
  432. strSSLCreate.sslSock = sock;
  433. SOCKET_REQUEST(SOCKET_CMD_SSL_CREATE, (uint8_t*)&strSSLCreate, sizeof(tstrSSLSocketCreateCmd), 0, 0, 0);
  434. pstrSock->u8SSLFlags = SSL_FLAGS_ACTIVE;
  435. if(u8Config == SOCKET_CONFIG_SSL_DELAY)
  436. pstrSock->u8SSLFlags |= SSL_FLAGS_DELAY;
  437. }
  438. break;
  439. }
  440. }
  441. }
  442. else if(u8Type == SOCK_DGRAM)
  443. {
  444. volatile tstrSocket *pastrUDPSockets = &gastrSockets[TCP_SOCK_MAX];
  445. for(u8Count = 0; u8Count < UDP_SOCK_MAX; u8Count ++)
  446. {
  447. u8SockID = u8NextUdpSock;
  448. pstrSock = &pastrUDPSockets[u8NextUdpSock];
  449. u8NextUdpSock = (u8NextUdpSock + 1) % UDP_SOCK_MAX;
  450. if(!pstrSock->bIsUsed)
  451. {
  452. sock = (SOCKET)(u8SockID + TCP_SOCK_MAX);
  453. memset((uint8_t*)pstrSock, 0, sizeof(tstrSocket));
  454. break;
  455. }
  456. }
  457. }
  458. else if(u8Type == SOCK_RAW)
  459. {
  460. /* Only raw IP packets are supported */
  461. if(u8Config == SOCKET_CONFIG_IPPROTO_RAW)
  462. {
  463. pstrSock = &gastrSockets[RAW_SOCK_ID];
  464. if(!pstrSock->bIsUsed)
  465. {
  466. /* Socket identified by RAW_SOCK_ID is reserved */
  467. sock = (SOCKET)RAW_SOCK_ID;
  468. memset((uint8_t*)pstrSock, 0, sizeof(tstrSocket));
  469. }
  470. }
  471. }
  472. if(sock >= 0)
  473. {
  474. pstrSock->bIsUsed = 1;
  475. /* The session ID is used to distinguish different socket connections
  476. by comparing the assigned session ID to the one reported by the firmware*/
  477. ++gu16SessionID;
  478. if(gu16SessionID == 0)
  479. ++gu16SessionID;
  480. pstrSock->u16SessionID = gu16SessionID;
  481. M2M_INFO("Socket %d session ID = %d\r\n", sock, gu16SessionID);
  482. }
  483. }
  484. return sock;
  485. }
  486. /*********************************************************************
  487. Function
  488. bind
  489. Description
  490. Request to bind a socket on a local address.
  491. Return
  492. *********************************************************************/
  493. int8_t bind(SOCKET sock, struct sockaddr *pstrAddr, uint8_t u8AddrLen)
  494. {
  495. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  496. if((pstrAddr != NULL) && (sock >= 0) && (sock < MAX_SOCKET) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0))
  497. {
  498. tstrBindCmd strBind;
  499. /* Build the bind request. */
  500. strBind.sock = sock;
  501. memcpy((uint8_t *)&strBind.strAddr, (uint8_t *)pstrAddr, sizeof(tstrSockAddr));
  502. strBind.strAddr.u16Family = strBind.strAddr.u16Family;
  503. strBind.strAddr.u16Port = strBind.strAddr.u16Port;
  504. strBind.strAddr.u32IPAddr = strBind.strAddr.u32IPAddr;
  505. strBind.u16SessionID = gastrSockets[sock].u16SessionID;
  506. /* Send the request. */
  507. s8Ret = SOCKET_REQUEST(SOCKET_CMD_BIND, (uint8_t*)&strBind, sizeof(tstrBindCmd), NULL, 0, 0);
  508. if(s8Ret != SOCK_ERR_NO_ERROR)
  509. {
  510. s8Ret = SOCK_ERR_INVALID;
  511. }
  512. }
  513. return s8Ret;
  514. }
  515. /*********************************************************************
  516. Function
  517. listen
  518. Description
  519. Return
  520. *********************************************************************/
  521. int8_t listen(SOCKET sock, uint8_t backlog)
  522. {
  523. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  524. if((sock >= 0) && (sock < MAX_SOCKET) && (gastrSockets[sock].bIsUsed == 1))
  525. {
  526. tstrListenCmd strListen;
  527. strListen.sock = sock;
  528. strListen.u8BackLog = backlog;
  529. strListen.u16SessionID = gastrSockets[sock].u16SessionID;
  530. s8Ret = SOCKET_REQUEST(SOCKET_CMD_LISTEN, (uint8_t*)&strListen, sizeof(tstrListenCmd), NULL, 0, 0);
  531. if(s8Ret != SOCK_ERR_NO_ERROR)
  532. {
  533. s8Ret = SOCK_ERR_INVALID;
  534. }
  535. }
  536. return s8Ret;
  537. }
  538. /*********************************************************************
  539. Function
  540. accept
  541. Description
  542. Return
  543. *********************************************************************/
  544. int8_t accept(SOCKET sock, struct sockaddr *addr, uint8_t *addrlen)
  545. {
  546. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  547. if((sock >= 0) && (sock < MAX_SOCKET) && (gastrSockets[sock].bIsUsed == 1))
  548. {
  549. s8Ret = SOCK_ERR_NO_ERROR;
  550. }
  551. return s8Ret;
  552. }
  553. /*********************************************************************
  554. Function
  555. connect
  556. Description
  557. Connect to a remote TCP Server.
  558. Return
  559. *********************************************************************/
  560. int8_t connect(SOCKET sock, struct sockaddr *pstrAddr, uint8_t u8AddrLen)
  561. {
  562. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  563. if((sock >= 0) && (sock < MAX_SOCKET) && (pstrAddr != NULL) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0))
  564. {
  565. tstrConnectCmd strConnect;
  566. uint8_t u8Cmd = SOCKET_CMD_CONNECT;
  567. if((gastrSockets[sock].u8SSLFlags) & SSL_FLAGS_ACTIVE)
  568. {
  569. u8Cmd = SOCKET_CMD_SSL_CONNECT;
  570. strConnect.u8SslFlags = gastrSockets[sock].u8SSLFlags;
  571. }
  572. strConnect.sock = sock;
  573. memcpy((uint8_t *)&strConnect.strAddr, (uint8_t *)pstrAddr, sizeof(tstrSockAddr));
  574. strConnect.u16SessionID = gastrSockets[sock].u16SessionID;
  575. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8_t*)&strConnect, sizeof(tstrConnectCmd), NULL, 0, 0);
  576. if(s8Ret != SOCK_ERR_NO_ERROR)
  577. {
  578. s8Ret = SOCK_ERR_INVALID;
  579. }
  580. }
  581. return s8Ret;
  582. }
  583. /*********************************************************************
  584. Function
  585. secure
  586. Description
  587. Make secure (TLS) an open TCP client connection.
  588. Return
  589. *********************************************************************/
  590. int8_t secure(SOCKET sock)
  591. {
  592. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  593. if((sock >= 0) && (sock < MAX_SOCKET) && (gastrSockets[sock].bIsUsed == 1))
  594. {
  595. if(
  596. (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
  597. && (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_DELAY)
  598. && (gastrSockets[sock].u16DataOffset != 0)
  599. )
  600. {
  601. tstrConnectCmd strConnect = {0};
  602. gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_DELAY;
  603. strConnect.u8SslFlags = gastrSockets[sock].u8SSLFlags;
  604. strConnect.sock = sock;
  605. strConnect.u16SessionID = gastrSockets[sock].u16SessionID;
  606. s8Ret = SOCKET_REQUEST(SOCKET_CMD_SECURE, (uint8_t*)&strConnect, sizeof(tstrConnectCmd), NULL, 0, 0);
  607. if(s8Ret != SOCK_ERR_NO_ERROR)
  608. {
  609. s8Ret = SOCK_ERR_INVALID;
  610. }
  611. }
  612. }
  613. return s8Ret;
  614. }
  615. /*********************************************************************
  616. Function
  617. send
  618. Description
  619. Return
  620. *********************************************************************/
  621. int16_t send(SOCKET sock, void *pvSendBuffer, uint16_t u16SendLength, uint16_t flags)
  622. {
  623. int16_t s16Ret = SOCK_ERR_INVALID_ARG;
  624. if((sock >= 0) && (sock < MAX_SOCKET) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH) && (gastrSockets[sock].bIsUsed == 1))
  625. {
  626. uint16_t u16DataOffset;
  627. tstrSendCmd strSend;
  628. uint8_t u8Cmd;
  629. u8Cmd = SOCKET_CMD_SEND;
  630. u16DataOffset = TCP_TX_PACKET_OFFSET;
  631. strSend.sock = sock;
  632. strSend.u16DataSize = NM_BSP_B_L_16(u16SendLength);
  633. strSend.u16SessionID = gastrSockets[sock].u16SessionID;
  634. if(sock >= TCP_SOCK_MAX)
  635. {
  636. u16DataOffset = UDP_TX_PACKET_OFFSET;
  637. }
  638. if(
  639. (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
  640. && (!(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_DELAY))
  641. )
  642. {
  643. u8Cmd = SOCKET_CMD_SSL_SEND;
  644. u16DataOffset = gastrSockets[sock].u16DataOffset;
  645. }
  646. s16Ret = SOCKET_REQUEST(u8Cmd|M2M_REQ_DATA_PKT, (uint8_t*)&strSend, sizeof(tstrSendCmd), pvSendBuffer, u16SendLength, u16DataOffset);
  647. if(s16Ret != SOCK_ERR_NO_ERROR)
  648. {
  649. s16Ret = SOCK_ERR_BUFFER_FULL;
  650. }
  651. }
  652. return s16Ret;
  653. }
  654. /*********************************************************************
  655. Function
  656. sendto
  657. Description
  658. Return
  659. *********************************************************************/
  660. int16_t sendto(SOCKET sock, void *pvSendBuffer, uint16_t u16SendLength, uint16_t flags, struct sockaddr *pstrDestAddr, uint8_t u8AddrLen)
  661. {
  662. int16_t s16Ret = SOCK_ERR_INVALID_ARG;
  663. uint16_t u16MaxLength = (sock == RAW_SOCK_ID) ? (M2M_HIF_MAX_PACKET_SIZE - M2M_HIF_HDR_OFFSET - sizeof(tstrSendCmd)) : SOCKET_BUFFER_MAX_LENGTH;
  664. if((sock >= 0) && (sock < MAX_SOCKET) && (pvSendBuffer != NULL) && (u16SendLength <= u16MaxLength) && (gastrSockets[sock].bIsUsed == 1))
  665. {
  666. tstrSendCmd strSendTo;
  667. memset((uint8_t*)&strSendTo, 0, sizeof(tstrSendCmd));
  668. strSendTo.sock = sock;
  669. strSendTo.u16DataSize = NM_BSP_B_L_16(u16SendLength);
  670. strSendTo.u16SessionID = gastrSockets[sock].u16SessionID;
  671. if(pstrDestAddr != NULL)
  672. {
  673. struct sockaddr_in *pstrAddr;
  674. pstrAddr = (void*)pstrDestAddr;
  675. strSendTo.strAddr.u16Family = pstrAddr->sin_family;
  676. strSendTo.strAddr.u16Port = pstrAddr->sin_port;
  677. strSendTo.strAddr.u32IPAddr = pstrAddr->sin_addr.s_addr;
  678. }
  679. s16Ret = SOCKET_REQUEST(SOCKET_CMD_SENDTO|M2M_REQ_DATA_PKT, (uint8_t*)&strSendTo, sizeof(tstrSendCmd),
  680. pvSendBuffer, u16SendLength, (sock == RAW_SOCK_ID) ? IP_PACKET_OFFSET: UDP_TX_PACKET_OFFSET);
  681. if(s16Ret != SOCK_ERR_NO_ERROR)
  682. {
  683. s16Ret = SOCK_ERR_BUFFER_FULL;
  684. }
  685. }
  686. return s16Ret;
  687. }
  688. /*********************************************************************
  689. Function
  690. recv
  691. Description
  692. Return
  693. *********************************************************************/
  694. int16_t recv(SOCKET sock, void *pvRecvBuf, uint16_t u16BufLen, uint32_t u32Timeoutmsec)
  695. {
  696. int16_t s16Ret = SOCK_ERR_INVALID_ARG;
  697. if((sock >= 0) && (sock < MAX_SOCKET) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1))
  698. {
  699. s16Ret = SOCK_ERR_NO_ERROR;
  700. gastrSockets[sock].pu8UserBuffer = (uint8_t*)pvRecvBuf;
  701. gastrSockets[sock].u16UserBufferSize = u16BufLen;
  702. if(!gastrSockets[sock].bIsRecvPending)
  703. {
  704. tstrRecvCmd strRecv;
  705. uint8_t u8Cmd = SOCKET_CMD_RECV;
  706. gastrSockets[sock].bIsRecvPending = 1;
  707. if(
  708. (gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
  709. && (!(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_DELAY))
  710. )
  711. {
  712. u8Cmd = SOCKET_CMD_SSL_RECV;
  713. }
  714. /* Check the timeout value. */
  715. if(u32Timeoutmsec == 0)
  716. strRecv.u32Timeoutmsec = 0xFFFFFFFF;
  717. else
  718. strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
  719. strRecv.sock = sock;
  720. strRecv.u16SessionID = gastrSockets[sock].u16SessionID;
  721. strRecv.u16BufLen = u16BufLen;
  722. s16Ret = SOCKET_REQUEST(u8Cmd, (uint8_t*)&strRecv, sizeof(tstrRecvCmd), NULL, 0, 0);
  723. if(s16Ret != SOCK_ERR_NO_ERROR)
  724. {
  725. s16Ret = SOCK_ERR_BUFFER_FULL;
  726. }
  727. }
  728. }
  729. return s16Ret;
  730. }
  731. /*********************************************************************
  732. Function
  733. shutdown
  734. Description
  735. Return
  736. None.
  737. *********************************************************************/
  738. int8_t shutdown(SOCKET sock)
  739. {
  740. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  741. M2M_INFO("Sock to delete <%d> (used %u)\r\n", sock, gastrSockets[sock].bIsUsed);
  742. if((sock >= 0) && (sock < MAX_SOCKET) && (gastrSockets[sock].bIsUsed == 1))
  743. {
  744. uint8_t u8Cmd = SOCKET_CMD_CLOSE;
  745. tstrCloseCmd strclose;
  746. strclose.sock = sock;
  747. strclose.u16SessionID = gastrSockets[sock].u16SessionID;
  748. if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
  749. {
  750. u8Cmd = SOCKET_CMD_SSL_CLOSE;
  751. }
  752. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8_t*)&strclose, sizeof(tstrCloseCmd), NULL, 0, 0);
  753. if(s8Ret != SOCK_ERR_NO_ERROR)
  754. {
  755. s8Ret = SOCK_ERR_INVALID;
  756. }
  757. memset((uint8_t*)&gastrSockets[sock], 0, sizeof(tstrSocket));
  758. }
  759. return s8Ret;
  760. }
  761. /*********************************************************************
  762. Function
  763. recvfrom
  764. Description
  765. Return
  766. *********************************************************************/
  767. int16_t recvfrom(SOCKET sock, void *pvRecvBuf, uint16_t u16BufLen, uint32_t u32Timeoutmsec)
  768. {
  769. int16_t s16Ret = SOCK_ERR_NO_ERROR;
  770. if((sock >= 0) && (sock < MAX_SOCKET) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1))
  771. {
  772. if(gastrSockets[sock].bIsUsed)
  773. {
  774. s16Ret = SOCK_ERR_NO_ERROR;
  775. gastrSockets[sock].pu8UserBuffer = (uint8_t*)pvRecvBuf;
  776. gastrSockets[sock].u16UserBufferSize = u16BufLen;
  777. if(!gastrSockets[sock].bIsRecvPending)
  778. {
  779. tstrRecvCmd strRecv;
  780. gastrSockets[sock].bIsRecvPending = 1;
  781. /* Check the timeout value. */
  782. if(u32Timeoutmsec == 0)
  783. strRecv.u32Timeoutmsec = 0xFFFFFFFF;
  784. else
  785. strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
  786. strRecv.sock = sock;
  787. strRecv.u16SessionID = gastrSockets[sock].u16SessionID;
  788. strRecv.u16BufLen = u16BufLen;
  789. s16Ret = SOCKET_REQUEST(SOCKET_CMD_RECVFROM, (uint8_t*)&strRecv, sizeof(tstrRecvCmd), NULL, 0, 0);
  790. if(s16Ret != SOCK_ERR_NO_ERROR)
  791. {
  792. s16Ret = SOCK_ERR_BUFFER_FULL;
  793. }
  794. }
  795. }
  796. }
  797. else
  798. {
  799. s16Ret = SOCK_ERR_INVALID_ARG;
  800. }
  801. return s16Ret;
  802. }
  803. /*********************************************************************
  804. Function
  805. gethostbyname
  806. Description
  807. Return
  808. None.
  809. *********************************************************************/
  810. int8_t gethostbyname(const char *pcHostName)
  811. {
  812. int8_t s8Err = SOCK_ERR_INVALID_ARG;
  813. uint8_t u8HostNameSize = (uint8_t)strlen(pcHostName);
  814. if(u8HostNameSize <= HOSTNAME_MAX_SIZE)
  815. {
  816. s8Err = SOCKET_REQUEST(SOCKET_CMD_DNS_RESOLVE|M2M_REQ_DATA_PKT, (uint8_t*)pcHostName, u8HostNameSize + 1, NULL, 0, 0);
  817. if(s8Err != SOCK_ERR_NO_ERROR)
  818. {
  819. s8Err = SOCK_ERR_INVALID;
  820. }
  821. }
  822. return s8Err;
  823. }
  824. /*********************************************************************
  825. Function
  826. rawSetSockOpt
  827. Description
  828. Return
  829. None.
  830. *********************************************************************/
  831. static int8_t rawSetSockOpt(SOCKET sock, uint8_t u8Opt, const void *pvOptVal, uint16_t u16OptLen)
  832. {
  833. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  834. if(RAW_SOCK_ID == sock)
  835. {
  836. if(u16OptLen == sizeof(uint32_t))
  837. {
  838. uint8_t u8Cmd = SOCKET_CMD_RAW_SET_SOCK_OPT;
  839. tstrSetSocketOptCmd strSetSockOpt;
  840. strSetSockOpt.u8Option = u8Opt;
  841. strSetSockOpt.sock = sock;
  842. strSetSockOpt.u32OptionValue = *(uint32_t*)pvOptVal;
  843. strSetSockOpt.u16SessionID = gastrSockets[sock].u16SessionID;
  844. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8_t*)&strSetSockOpt, sizeof(tstrSetSocketOptCmd), NULL, 0, 0);
  845. if(s8Ret != SOCK_ERR_NO_ERROR)
  846. {
  847. s8Ret = SOCK_ERR_INVALID;
  848. }
  849. }
  850. }
  851. return s8Ret;
  852. }
  853. /*********************************************************************
  854. Function
  855. sslSetSockOpt
  856. Description
  857. Return
  858. None.
  859. *********************************************************************/
  860. static int8_t sslSetSockOpt(SOCKET sock, uint8_t u8Opt, const void *pvOptVal, uint16_t u16OptLen)
  861. {
  862. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  863. if(sock < TCP_SOCK_MAX)
  864. {
  865. if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
  866. {
  867. uint8_t sslFlag = 0;
  868. s8Ret = SOCK_ERR_NO_ERROR;
  869. if(u16OptLen == sizeof(int))
  870. {
  871. if(u8Opt == SO_SSL_BYPASS_X509_VERIF)
  872. {
  873. sslFlag = SSL_FLAGS_BYPASS_X509;
  874. }
  875. else if(u8Opt == SO_SSL_ENABLE_SESSION_CACHING)
  876. {
  877. sslFlag = SSL_FLAGS_CACHE_SESSION;
  878. }
  879. else if(u8Opt == SO_SSL_ENABLE_CERTNAME_VALIDATION)
  880. {
  881. sslFlag = SSL_FLAGS_CHECK_CERTNAME;
  882. }
  883. }
  884. if(sslFlag)
  885. {
  886. int optVal = *((int*)pvOptVal);
  887. if(optVal)
  888. {
  889. gastrSockets[sock].u8SSLFlags |= sslFlag;
  890. }
  891. else
  892. {
  893. gastrSockets[sock].u8SSLFlags &= ~sslFlag;
  894. }
  895. }
  896. else if(
  897. ((u8Opt == SO_SSL_SNI) && (u16OptLen < HOSTNAME_MAX_SIZE))
  898. || ((u8Opt == SO_SSL_ALPN) && (u16OptLen <= ALPN_LIST_MAX_SIZE))
  899. )
  900. {
  901. tstrSSLSetSockOptCmd strCmd = {0};
  902. strCmd.sock = sock;
  903. strCmd.u16SessionID = gastrSockets[sock].u16SessionID;
  904. strCmd.u8Option = u8Opt;
  905. strCmd.u32OptLen = u16OptLen;
  906. memcpy(strCmd.au8OptVal, (uint8_t*)pvOptVal, u16OptLen);
  907. s8Ret = SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT, (uint8_t*)&strCmd, sizeof(tstrSSLSetSockOptCmd), 0, 0, 0);
  908. if(s8Ret == M2M_ERR_MEM_ALLOC)
  909. {
  910. s8Ret = SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT | M2M_REQ_DATA_PKT,
  911. (uint8_t*)&strCmd, sizeof(tstrSSLSetSockOptCmd), 0, 0, 0);
  912. }
  913. }
  914. else
  915. {
  916. M2M_ERR("Unknown SSL Socket Option %d\r\n",u8Opt);
  917. s8Ret = SOCK_ERR_INVALID_ARG;
  918. }
  919. }
  920. else
  921. {
  922. M2M_ERR("Not SSL Socket\r\n");
  923. }
  924. }
  925. return s8Ret;
  926. }
  927. /*********************************************************************
  928. Function
  929. setsockopt
  930. Description
  931. Return
  932. None.
  933. *********************************************************************/
  934. int8_t setsockopt(SOCKET sock, uint8_t u8Level, uint8_t option_name,
  935. const void *option_value, uint16_t u16OptionLen)
  936. {
  937. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  938. if((sock >= 0) && (sock < MAX_SOCKET) && (option_value != NULL) && (gastrSockets[sock].bIsUsed == 1))
  939. {
  940. if(u8Level == SOL_RAW)
  941. {
  942. s8Ret = rawSetSockOpt(sock, option_name, option_value, u16OptionLen);
  943. }
  944. else if(u8Level == SOL_SSL_SOCKET)
  945. {
  946. s8Ret = sslSetSockOpt(sock, option_name, option_value, u16OptionLen);
  947. }
  948. else if(u8Level == SOL_SOCKET)
  949. {
  950. if(u16OptionLen == sizeof(uint32_t))
  951. {
  952. uint8_t u8Cmd = SOCKET_CMD_SET_SOCKET_OPTION;
  953. tstrSetSocketOptCmd strSetSockOpt;
  954. strSetSockOpt.u8Option=option_name;
  955. strSetSockOpt.sock = sock;
  956. strSetSockOpt.u32OptionValue = *(uint32_t*)option_value;
  957. strSetSockOpt.u16SessionID = gastrSockets[sock].u16SessionID;
  958. s8Ret = SOCKET_REQUEST(u8Cmd, (uint8_t*)&strSetSockOpt, sizeof(tstrSetSocketOptCmd), NULL, 0, 0);
  959. if(s8Ret != SOCK_ERR_NO_ERROR)
  960. {
  961. s8Ret = SOCK_ERR_INVALID;
  962. }
  963. }
  964. }
  965. }
  966. return s8Ret;
  967. }
  968. /*********************************************************************
  969. Function
  970. getsockopt
  971. Description
  972. Return
  973. None.
  974. *********************************************************************/
  975. int8_t getsockopt(SOCKET sock, uint8_t u8Level, uint8_t u8OptName, const void *pvOptValue, uint8_t* pu8OptLen)
  976. {
  977. // This is not implemented so return a value that will cause failure should this be used.
  978. return SOCK_ERR_INVALID_ARG;
  979. }
  980. /*********************************************************************
  981. Function
  982. m2m_ping_req
  983. Description
  984. Send Ping request.
  985. Return
  986. *********************************************************************/
  987. int8_t m2m_ping_req(uint32_t u32DstIP, uint8_t u8TTL, tpfPingCb fpPingCb)
  988. {
  989. int8_t s8Ret = M2M_ERR_INVALID_ARG;
  990. if((u32DstIP != 0) && (fpPingCb != NULL))
  991. {
  992. tstrPingCmd strPingCmd;
  993. strPingCmd.u16PingCount = 1;
  994. strPingCmd.u32DestIPAddr = u32DstIP;
  995. strPingCmd.u32CmdPrivate = ++gu32PingId;
  996. strPingCmd.u8TTL = u8TTL;
  997. gfpPingCb = fpPingCb;
  998. s8Ret = SOCKET_REQUEST(SOCKET_CMD_PING, (uint8_t*)&strPingCmd, sizeof(tstrPingCmd), NULL, 0, 0);
  999. }
  1000. return s8Ret;
  1001. }
  1002. /*********************************************************************
  1003. Function
  1004. set_alpn_protocol_list
  1005. Description
  1006. This function sets the protocol list used for application-layer protocol negotiation (ALPN).
  1007. If used, it must be called after creating a SSL socket (using @ref socket) and before
  1008. connecting/binding (using @ref connect or @ref bind).
  1009. Return
  1010. The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise.
  1011. *********************************************************************/
  1012. int8_t set_alpn_list(SOCKET sock, const char *pcProtocolList)
  1013. {
  1014. int8_t s8Ret = SOCK_ERR_INVALID_ARG;
  1015. if ((sock >= 0) && (sock < TCP_SOCK_MAX) && (pcProtocolList != NULL))
  1016. {
  1017. uint8_t u8Length = strlen(pcProtocolList);
  1018. if ((u8Length > 0) && (u8Length < ALPN_LIST_MAX_APP_LENGTH))
  1019. {
  1020. /*
  1021. ALPN socket option requires Alpn list in this format:
  1022. 0 1 2 3 ... (bytes)
  1023. +-------+-------+-------+ ... +-------+ ... +-------+ ...
  1024. | Length L (BE) | len1 | name1... | len2 | name2... | len3 | name3...
  1025. +-------+-------+-------+ ... +-------+ ... +-------+ ...
  1026. Length fields do not include themselves.
  1027. */
  1028. uint8_t au8AlpnList[ALPN_LIST_MAX_SIZE] = {0};
  1029. uint8_t *pu8Ptr = &au8AlpnList[3] + u8Length;
  1030. uint8_t u8Len = 0;
  1031. memcpy(&au8AlpnList[3], pcProtocolList, u8Length);
  1032. u8Length++;
  1033. au8AlpnList[1] = u8Length;
  1034. au8AlpnList[2] = ' ';
  1035. /* Convert space characters into length fields. */
  1036. while (u8Length--)
  1037. {
  1038. if (*--pu8Ptr == ' ')
  1039. {
  1040. if (u8Len == 0) goto ERR;
  1041. *pu8Ptr = u8Len;
  1042. u8Len = 0;
  1043. }
  1044. else u8Len++;
  1045. }
  1046. s8Ret = setsockopt(sock, SOL_SSL_SOCKET, SO_SSL_ALPN, au8AlpnList, sizeof(au8AlpnList));
  1047. }
  1048. }
  1049. ERR:
  1050. return s8Ret;
  1051. }
  1052. /*********************************************************************
  1053. Function
  1054. get_alpn_protocol_index
  1055. Description
  1056. This function gets the protocol list used for application-layer protocol negotiation (ALPN).
  1057. If used, it must be called after creating a SSL socket (using @ref socket) and before
  1058. connecting/binding (using @ref connect or @ref bind).
  1059. Return
  1060. The function returns the index of the selected application-layer protocol.
  1061. Special values:
  1062. 0: no negotiation has occurred.
  1063. <0: error.
  1064. *********************************************************************/
  1065. int8_t get_alpn_index(SOCKET sock)
  1066. {
  1067. if (sock >= TCP_SOCK_MAX || sock < 0)
  1068. return SOCK_ERR_INVALID_ARG;
  1069. if (!(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) || !gastrSockets[sock].bIsUsed)
  1070. return SOCK_ERR_INVALID_ARG;
  1071. return gastrSockets[sock].u8AlpnStatus;
  1072. }
  1073. /*********************************************************************
  1074. Function
  1075. IsSocketReady
  1076. Description
  1077. Return
  1078. None.
  1079. *********************************************************************/
  1080. uint8_t IsSocketReady(void)
  1081. {
  1082. return gbSocketInit;
  1083. }
  1084. /*********************************************************************
  1085. Function
  1086. get_error_detail
  1087. Description
  1088. This function gets detail about a socket failure.
  1089. The application can call this when notified of a socket failure via
  1090. @ref SOCKET_MSG_CONNECT or @ref SOCKET_MSG_RECV.
  1091. If used, it must be called before @ref shutdown.
  1092. Return
  1093. The function returns @ref SOCK_ERR_NO_ERROR if the request is successful
  1094. and a negative value otherwise.
  1095. *********************************************************************/
  1096. int8_t get_error_detail(SOCKET sock, tstrSockErr *pstrErr)
  1097. {
  1098. if ((sock >= TCP_SOCK_MAX) || (sock < 0) || (pstrErr == NULL))
  1099. return SOCK_ERR_INVALID_ARG;
  1100. if (!gastrSockets[sock].bIsUsed)
  1101. return SOCK_ERR_INVALID_ARG;
  1102. pstrErr->enuErrSource = gastrSockets[sock].u8ErrSource;
  1103. pstrErr->u8ErrCode = gastrSockets[sock].u8ErrCode;
  1104. return SOCK_ERR_NO_ERROR;
  1105. }