Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

1267 рядки
31 KiB

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