1 /**
2  *
3  * \file
4  *
5  * \brief BSD compatible socket interface.
6  *
7  * Copyright (c) 2016-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 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
43 INCLUDES
44 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
45 
46 #include "bsp/include/nm_bsp.h"
47 #include "socket/include/socket.h"
48 #include "driver/source/m2m_hif.h"
49 #include "socket/source/socket_internal.h"
50 #include "driver/include/m2m_types.h"
51 
52 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
53 MACROS
54 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
55 
56 
57 #define TLS_RECORD_HEADER_LENGTH			(5)
58 #define ETHERNET_HEADER_OFFSET				(34)
59 #define ETHERNET_HEADER_LENGTH				(14)
60 #define TCP_IP_HEADER_LENGTH				(40)
61 #define UDP_IP_HEADER_LENGTH				(28)
62 
63 #define IP_PACKET_OFFSET					(ETHERNET_HEADER_LENGTH + ETHERNET_HEADER_OFFSET - M2M_HIF_HDR_OFFSET)
64 
65 #define TCP_TX_PACKET_OFFSET				(IP_PACKET_OFFSET + TCP_IP_HEADER_LENGTH)
66 #define UDP_TX_PACKET_OFFSET				(IP_PACKET_OFFSET + UDP_IP_HEADER_LENGTH)
67 #define SSL_TX_PACKET_OFFSET				(TCP_TX_PACKET_OFFSET + TLS_RECORD_HEADER_LENGTH)
68 
69 #define SOCKET_REQUEST(reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset)		\
70 	hif_send(M2M_REQ_GROUP_IP, reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset)
71 
72 
73 #define SSL_FLAGS_ACTIVE					NBIT0
74 #define SSL_FLAGS_BYPASS_X509				NBIT1
75 #define SSL_FLAGS_2_RESERVD					NBIT2
76 #define SSL_FLAGS_3_RESERVD					NBIT3
77 #define SSL_FLAGS_CACHE_SESSION				NBIT4
78 #define SSL_FLAGS_NO_TX_COPY				NBIT5
79 #define SSL_FLAGS_CHECK_SNI					NBIT6
80 
81 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
82 PRIVATE DATA TYPES
83 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
84 
85 
86 /*!
87 *  @brief
88 */
89 typedef struct{
90 	SOCKET		sock;
91 	uint8		u8Dummy;
92 	uint16		u16SessionID;
93 }tstrCloseCmd;
94 
95 
96 /*!
97 *  @brief
98 */
99 typedef struct{
100 	uint8				*pu8UserBuffer;
101 	uint16				u16UserBufferSize;
102 	uint16				u16SessionID;
103 	uint16				u16DataOffset;
104 	uint8				bIsUsed;
105 	uint8				u8SSLFlags;
106 	uint8				bIsRecvPending;
107 }tstrSocket;
108 
109 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
110 GLOBALS
111 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
112 
113 volatile sint8					gsockerrno;
114 volatile tstrSocket				gastrSockets[MAX_SOCKET];
115 volatile uint8					gu8OpCode;
116 volatile uint16					gu16BufferSize;
117 volatile uint16					gu16SessionID = 0;
118 
119 volatile tpfAppSocketCb		    gpfAppSocketCb;
120 volatile tpfAppResolveCb		gpfAppResolveCb;
121 volatile uint8					gbSocketInit = 0;
122 volatile tpfPingCb				gfpPingCb;
123 
124 /*********************************************************************
125 Function
126 		Socket_ReadSocketData
127 
128 Description
129 		Callback function used by the NMC1500 driver to deliver messages
130 		for socket layer.
131 
132 Return
133 		None.
134 
135 Author
136 		Ahmed Ezzat
137 
138 Version
139 		1.0
140 
141 Date
142 		17 July 2012
143 *********************************************************************/
Socket_ReadSocketData(SOCKET sock,tstrSocketRecvMsg * pstrRecv,uint8 u8SocketMsg,uint32 u32StartAddress,uint16 u16ReadCount)144 NMI_API void Socket_ReadSocketData(SOCKET sock, tstrSocketRecvMsg *pstrRecv,uint8 u8SocketMsg,
145 								  uint32 u32StartAddress,uint16 u16ReadCount)
146 {
147 	if((u16ReadCount > 0) && (gastrSockets[sock].pu8UserBuffer != NULL) && (gastrSockets[sock].u16UserBufferSize > 0) && (gastrSockets[sock].bIsUsed == 1))
148 	{
149 		uint32	u32Address = u32StartAddress;
150 		uint16	u16Read;
151 		sint16	s16Diff;
152 		uint8	u8SetRxDone;
153 
154 		pstrRecv->u16RemainingSize = u16ReadCount;
155 		do
156 		{
157 			u8SetRxDone = 1;
158 			u16Read = u16ReadCount;
159 			s16Diff	= u16Read - gastrSockets[sock].u16UserBufferSize;
160 			if(s16Diff > 0)
161 			{
162 				u8SetRxDone = 0;
163 				u16Read		= gastrSockets[sock].u16UserBufferSize;
164 			}
165 
166 			if(hif_receive(u32Address, gastrSockets[sock].pu8UserBuffer, u16Read, u8SetRxDone) == M2M_SUCCESS)
167 			{
168 				pstrRecv->pu8Buffer			= gastrSockets[sock].pu8UserBuffer;
169 				pstrRecv->s16BufferSize		= u16Read;
170 				pstrRecv->u16RemainingSize	-= u16Read;
171 
172 				if (gpfAppSocketCb)
173 					gpfAppSocketCb(sock,u8SocketMsg, pstrRecv);
174 
175 				u16ReadCount -= u16Read;
176 				u32Address += u16Read;
177 
178 				if((!gastrSockets[sock].bIsUsed) && (u16ReadCount))
179 				{
180 					M2M_DBG("Application Closed Socket While Rx Is not Complete\n");
181 					if(hif_receive(0, NULL, 0, 1) == M2M_SUCCESS)
182 						M2M_DBG("hif_receive Success\n");
183 					else
184 						M2M_DBG("hif_receive Fail\n");
185 					break;
186 				}
187 			}
188 			else
189 			{
190 				M2M_INFO("(ERRR)Current <%d>\n", u16ReadCount);
191 				break;
192 			}
193 		}while(u16ReadCount != 0);
194 	}
195 }
196 /*********************************************************************
197 Function
198 		m2m_ip_cb
199 
200 Description
201 		Callback function used by the NMC1000 driver to deliver messages
202 		for socket layer.
203 
204 Return
205 		None.
206 
207 Author
208 		Ahmed Ezzat
209 
210 Version
211 		1.0
212 
213 Date
214 		17 July 2012
215 *********************************************************************/
m2m_ip_cb(uint8 u8OpCode,uint16 u16BufferSize,uint32 u32Address)216 static void m2m_ip_cb(uint8 u8OpCode, uint16 u16BufferSize,uint32 u32Address)
217 {
218 	if((u8OpCode == SOCKET_CMD_BIND) || (u8OpCode == SOCKET_CMD_SSL_BIND))
219 	{
220 		tstrBindReply		strBindReply;
221 		tstrSocketBindMsg	strBind;
222 
223 		if(hif_receive(u32Address, (uint8*)&strBindReply, sizeof(tstrBindReply), 0) == M2M_SUCCESS)
224 		{
225 			strBind.status = strBindReply.s8Status;
226 			if(gpfAppSocketCb)
227 				gpfAppSocketCb(strBindReply.sock,SOCKET_MSG_BIND,&strBind);
228 		}
229 	}
230 	else if(u8OpCode == SOCKET_CMD_LISTEN)
231 	{
232 		tstrListenReply			strListenReply;
233 		tstrSocketListenMsg		strListen;
234 		if(hif_receive(u32Address, (uint8*)&strListenReply, sizeof(tstrListenReply), 0) == M2M_SUCCESS)
235 		{
236 			strListen.status = strListenReply.s8Status;
237 			if(gpfAppSocketCb)
238 				gpfAppSocketCb(strListenReply.sock,SOCKET_MSG_LISTEN, &strListen);
239 		}
240 	}
241 	else if(u8OpCode == SOCKET_CMD_ACCEPT)
242 	{
243 		tstrAcceptReply			strAcceptReply;
244 		tstrSocketAcceptMsg		strAccept;
245 		if(hif_receive(u32Address, (uint8*)&strAcceptReply, sizeof(tstrAcceptReply), 0) == M2M_SUCCESS)
246 		{
247 			if(strAcceptReply.sConnectedSock >= 0)
248 			{
249 				gastrSockets[strAcceptReply.sConnectedSock].u8SSLFlags 		= gastrSockets[strAcceptReply.sListenSock].u8SSLFlags;
250 				gastrSockets[strAcceptReply.sConnectedSock].bIsUsed 		= 1;
251 				gastrSockets[strAcceptReply.sConnectedSock].u16DataOffset 	= strAcceptReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET;
252 
253 				/* The session ID is used to distinguish different socket connections
254 					by comparing the assigned session ID to the one reported by the firmware*/
255 				++gu16SessionID;
256 				if(gu16SessionID == 0)
257 					++gu16SessionID;
258 
259 				gastrSockets[strAcceptReply.sConnectedSock].u16SessionID = gu16SessionID;
260 				M2M_DBG("Socket %d session ID = %d\r\n",strAcceptReply.sConnectedSock , gu16SessionID );
261 			}
262 			strAccept.sock = strAcceptReply.sConnectedSock;
263 			strAccept.strAddr.sin_family		= AF_INET;
264 			strAccept.strAddr.sin_port = strAcceptReply.strAddr.u16Port;
265 			strAccept.strAddr.sin_addr.s_addr = strAcceptReply.strAddr.u32IPAddr;
266 			if(gpfAppSocketCb)
267 				gpfAppSocketCb(strAcceptReply.sListenSock, SOCKET_MSG_ACCEPT, &strAccept);
268 		}
269 	}
270 	else if((u8OpCode == SOCKET_CMD_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT))
271 	{
272 		tstrConnectReply		strConnectReply;
273 		tstrSocketConnectMsg	strConnMsg;
274 		if(hif_receive(u32Address, (uint8*)&strConnectReply, sizeof(tstrConnectReply), 0) == M2M_SUCCESS)
275 		{
276 			strConnMsg.sock		= strConnectReply.sock;
277 			strConnMsg.s8Error	= strConnectReply.s8Error;
278 			if(strConnectReply.s8Error == SOCK_ERR_NO_ERROR)
279 			{
280 				gastrSockets[strConnectReply.sock].u16DataOffset = strConnectReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET;
281 			}
282 			if(gpfAppSocketCb)
283 				gpfAppSocketCb(strConnectReply.sock,SOCKET_MSG_CONNECT, &strConnMsg);
284 		}
285 	}
286 	else if(u8OpCode == SOCKET_CMD_DNS_RESOLVE)
287 	{
288 		tstrDnsReply	strDnsReply;
289 		if(hif_receive(u32Address, (uint8*)&strDnsReply, sizeof(tstrDnsReply), 0) == M2M_SUCCESS)
290 		{
291 			if(gpfAppResolveCb)
292 				gpfAppResolveCb((uint8*)strDnsReply.acHostName, strDnsReply.u32HostIP);
293 		}
294 	}
295 	else if((u8OpCode == SOCKET_CMD_RECV) || (u8OpCode == SOCKET_CMD_RECVFROM) || (u8OpCode == SOCKET_CMD_SSL_RECV))
296 	{
297 		SOCKET				sock;
298 		sint16				s16RecvStatus;
299 		tstrRecvReply		strRecvReply;
300 		uint16				u16ReadSize;
301 		tstrSocketRecvMsg	strRecvMsg;
302 		uint8				u8CallbackMsgID = SOCKET_MSG_RECV;
303 		uint16				u16DataOffset;
304 
305 		if(u8OpCode == SOCKET_CMD_RECVFROM)
306 			u8CallbackMsgID = SOCKET_MSG_RECVFROM;
307 
308 		/* Read RECV REPLY data structure.
309 		*/
310 		u16ReadSize = sizeof(tstrRecvReply);
311 		if(hif_receive(u32Address, (uint8*)&strRecvReply, u16ReadSize, 0) == M2M_SUCCESS)
312 		{
313 			uint16 u16SessionID = 0;
314 
315 			sock			= strRecvReply.sock;
316 			u16SessionID = strRecvReply.u16SessionID;
317 			M2M_DBG("recv callback session ID = %d\r\n",u16SessionID);
318 
319 			/* Reset the Socket RX Pending Flag.
320 			*/
321 			gastrSockets[sock].bIsRecvPending = 0;
322 
323 			s16RecvStatus	= NM_BSP_B_L_16(strRecvReply.s16RecvStatus);
324 			u16DataOffset	= NM_BSP_B_L_16(strRecvReply.u16DataOffset);
325 			strRecvMsg.strRemoteAddr.sin_port 			= strRecvReply.strRemoteAddr.u16Port;
326 			strRecvMsg.strRemoteAddr.sin_addr.s_addr 	= strRecvReply.strRemoteAddr.u32IPAddr;
327 
328 			if(u16SessionID == gastrSockets[sock].u16SessionID)
329 			{
330 				if((s16RecvStatus > 0) && (s16RecvStatus < u16BufferSize))
331 				{
332 					/* Skip incoming bytes until reaching the Start of Application Data.
333 					*/
334 					u32Address += u16DataOffset;
335 
336 					/* Read the Application data and deliver it to the application callback in
337 					the given application buffer. If the buffer is smaller than the received data,
338 					the data is passed to the application in chunks according to its buffer size.
339 					*/
340 					u16ReadSize = (uint16)s16RecvStatus;
341 					Socket_ReadSocketData(sock, &strRecvMsg, u8CallbackMsgID, u32Address, u16ReadSize);
342 				}
343 				else
344 				{
345 					strRecvMsg.s16BufferSize	= s16RecvStatus;
346 					strRecvMsg.pu8Buffer		= NULL;
347 					if(gpfAppSocketCb)
348 						gpfAppSocketCb(sock,u8CallbackMsgID, &strRecvMsg);
349 				}
350 			}
351 			else
352 			{
353 				M2M_DBG("Discard recv callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID);
354 				if(u16ReadSize < u16BufferSize)
355 				{
356 					if(hif_receive(0, NULL, 0, 1) == M2M_SUCCESS)
357 						M2M_DBG("hif_receive Success\n");
358 					else
359 						M2M_DBG("hif_receive Fail\n");
360 				}
361 			}
362 		}
363 	}
364 	else if((u8OpCode == SOCKET_CMD_SEND) || (u8OpCode == SOCKET_CMD_SENDTO) || (u8OpCode == SOCKET_CMD_SSL_SEND))
365 	{
366 		SOCKET			sock;
367 		sint16			s16Rcvd;
368 		tstrSendReply	strReply;
369 		uint8			u8CallbackMsgID = SOCKET_MSG_SEND;
370 
371 		if(u8OpCode == SOCKET_CMD_SENDTO)
372 			u8CallbackMsgID = SOCKET_MSG_SENDTO;
373 
374 		if(hif_receive(u32Address, (uint8*)&strReply, sizeof(tstrSendReply), 0) == M2M_SUCCESS)
375 		{
376 			uint16 u16SessionID = 0;
377 
378 			sock = strReply.sock;
379 			u16SessionID = strReply.u16SessionID;
380 			M2M_DBG("send callback session ID = %d\r\n",u16SessionID);
381 
382 			s16Rcvd = NM_BSP_B_L_16(strReply.s16SentBytes);
383 
384 			if(u16SessionID == gastrSockets[sock].u16SessionID)
385 			{
386 				if(gpfAppSocketCb)
387 					gpfAppSocketCb(sock,u8CallbackMsgID, &s16Rcvd);
388 			}
389 			else
390 			{
391 				M2M_DBG("Discard send callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID);
392 			}
393 		}
394 	}
395 	else if(u8OpCode == SOCKET_CMD_PING)
396 	{
397 		tstrPingReply	strPingReply;
398 		if(hif_receive(u32Address, (uint8*)&strPingReply, sizeof(tstrPingReply), 1) == M2M_SUCCESS)
399 		{
400 			gfpPingCb = (void (*)(uint32 , uint32 , uint8))strPingReply.u32CmdPrivate;
401 			if(gfpPingCb != NULL)
402 			{
403 				gfpPingCb(strPingReply.u32IPAddr, strPingReply.u32RTT, strPingReply.u8ErrorCode);
404 			}
405 		}
406 	}
407 }
408 /*********************************************************************
409 Function
410 		socketInit
411 
412 Description
413 
414 Return
415 		None.
416 
417 Author
418 		Ahmed Ezzat
419 
420 Version
421 		1.0
422 
423 Date
424 		4 June 2012
425 *********************************************************************/
socketInit(void)426 void socketInit(void)
427 {
428 	if(gbSocketInit == 0)
429 	{
430 		m2m_memset((uint8*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
431 		hif_register_cb(M2M_REQ_GROUP_IP,m2m_ip_cb);
432 		gbSocketInit	= 1;
433 		gu16SessionID	= 0;
434 	}
435 }
436 /*********************************************************************
437 Function
438 		socketDeinit
439 
440 Description
441 
442 Return
443 		None.
444 
445 Author
446 		Samer Sarhan
447 
448 Version
449 		1.0
450 
451 Date
452 		27 Feb 2015
453 *********************************************************************/
socketDeinit(void)454 void socketDeinit(void)
455 {
456 	m2m_memset((uint8*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket));
457 	hif_register_cb(M2M_REQ_GROUP_IP, NULL);
458 	gpfAppSocketCb	= NULL;
459 	gpfAppResolveCb	= NULL;
460 	gbSocketInit	= 0;
461 }
462 /*********************************************************************
463 Function
464 		registerSocketCallback
465 
466 Description
467 
468 Return
469 		None.
470 
471 Author
472 		Ahmed Ezzat
473 
474 Versio
475 		1.0
476 
477 Date
478 		4 June 2012
479 *********************************************************************/
registerSocketCallback(tpfAppSocketCb pfAppSocketCb,tpfAppResolveCb pfAppResolveCb)480 void registerSocketCallback(tpfAppSocketCb pfAppSocketCb, tpfAppResolveCb pfAppResolveCb)
481 {
482 	gpfAppSocketCb = pfAppSocketCb;
483 	gpfAppResolveCb = pfAppResolveCb;
484 }
485 
486 /*********************************************************************
487 Function
488 		socket
489 
490 Description
491 		Creates a socket.
492 
493 Return
494 		- Negative value for error.
495 		- ZERO or positive value as a socket ID if successful.
496 
497 Author
498 		Ahmed Ezzat
499 
500 Version
501 		1.0
502 
503 Date
504 		4 June 2012
505 *********************************************************************/
socket(uint16 u16Domain,uint8 u8Type,uint8 u8Flags)506 SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags)
507 {
508 	SOCKET					sock = -1;
509 	uint8					u8SockID;
510 	uint8					u8Count;
511 	volatile tstrSocket		*pstrSock;
512 	static volatile uint8	u8NextTcpSock	= 0;
513 	static volatile uint8	u8NextUdpSock	= 0;
514 
515 	/* The only supported family is the AF_INET for UDP and TCP transport layer protocols. */
516 	if(u16Domain == AF_INET)
517 	{
518 		if(u8Type == SOCK_STREAM)
519 		{
520 			for(u8Count = 0; u8Count < TCP_SOCK_MAX; u8Count ++)
521 			{
522 				u8SockID	= u8NextTcpSock;
523 				pstrSock	= &gastrSockets[u8NextTcpSock];
524 				u8NextTcpSock = (u8NextTcpSock + 1) % TCP_SOCK_MAX;
525 				if(!pstrSock->bIsUsed)
526 				{
527 					sock = (SOCKET)u8SockID;
528 					break;
529 				}
530 			}
531 		}
532 		else if(u8Type == SOCK_DGRAM)
533 		{
534 			volatile tstrSocket	*pastrUDPSockets = &gastrSockets[TCP_SOCK_MAX];
535 			for(u8Count = 0; u8Count < UDP_SOCK_MAX; u8Count ++)
536 			{
537 				u8SockID		= u8NextUdpSock;
538 				pstrSock		= &pastrUDPSockets[u8NextUdpSock];
539 				u8NextUdpSock	= (u8NextUdpSock + 1) % UDP_SOCK_MAX;
540 				if(!pstrSock->bIsUsed)
541 				{
542 					sock = (SOCKET)(u8SockID + TCP_SOCK_MAX);
543 					break;
544 				}
545 			}
546 		}
547 
548 		if(sock >= 0)
549 		{
550 			m2m_memset((uint8*)pstrSock, 0, sizeof(tstrSocket));
551 			pstrSock->bIsUsed = 1;
552 
553 			/* The session ID is used to distinguish different socket connections
554 				by comparing the assigned session ID to the one reported by the firmware*/
555 			++gu16SessionID;
556 			if(gu16SessionID == 0)
557 				++gu16SessionID;
558 
559 			pstrSock->u16SessionID = gu16SessionID;
560             M2M_INFO("Socket %d session ID = %d\r\n",sock, gu16SessionID );
561 
562 			if(u8Flags & SOCKET_FLAGS_SSL)
563 			{
564 				tstrSSLSocketCreateCmd	strSSLCreate;
565 				strSSLCreate.sslSock = sock;
566 				pstrSock->u8SSLFlags = SSL_FLAGS_ACTIVE | SSL_FLAGS_NO_TX_COPY;
567 				SOCKET_REQUEST(SOCKET_CMD_SSL_CREATE, (uint8*)&strSSLCreate, sizeof(tstrSSLSocketCreateCmd), 0, 0, 0);
568 			}
569 		}
570 	}
571 	return sock;
572 }
573 /*********************************************************************
574 Function
575 		bind
576 
577 Description
578 		Request to bind a socket on a local address.
579 
580 Return
581 
582 
583 Author
584 		Ahmed Ezzat
585 
586 Version
587 		1.0
588 
589 Date
590 		5 June 2012
591 *********************************************************************/
bind(SOCKET sock,struct sockaddr * pstrAddr,uint8 u8AddrLen)592 sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen)
593 {
594 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
595 	if((pstrAddr != NULL) && (sock >= 0) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0))
596 	{
597 		tstrBindCmd			strBind;
598 		uint8				u8CMD = SOCKET_CMD_BIND;
599 		if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
600 		{
601 			u8CMD = SOCKET_CMD_SSL_BIND;
602 		}
603 
604 		/* Build the bind request. */
605 		strBind.sock = sock;
606 		m2m_memcpy((uint8 *)&strBind.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr));
607 		strBind.u16SessionID		= gastrSockets[sock].u16SessionID;
608 
609 		/* Send the request. */
610 		s8Ret = SOCKET_REQUEST(u8CMD, (uint8*)&strBind,sizeof(tstrBindCmd) , NULL , 0, 0);
611 		if(s8Ret != SOCK_ERR_NO_ERROR)
612 		{
613 			s8Ret = SOCK_ERR_INVALID;
614 		}
615 	}
616 	return s8Ret;
617 }
618 /*********************************************************************
619 Function
620 		listen
621 
622 Description
623 
624 
625 Return
626 
627 
628 Author
629 		Ahmed Ezzat
630 
631 Version
632 		1.0
633 
634 Date
635 		5 June 2012
636 *********************************************************************/
listen(SOCKET sock,uint8 backlog)637 sint8 listen(SOCKET sock, uint8 backlog)
638 {
639 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
640 
641 	if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1))
642 	{
643 		tstrListenCmd		strListen;
644 
645 		strListen.sock = sock;
646 		strListen.u8BackLog = backlog;
647 		strListen.u16SessionID		= gastrSockets[sock].u16SessionID;
648 
649 		s8Ret = SOCKET_REQUEST(SOCKET_CMD_LISTEN, (uint8*)&strListen, sizeof(tstrListenCmd), NULL, 0, 0);
650 		if(s8Ret != SOCK_ERR_NO_ERROR)
651 		{
652 			s8Ret = SOCK_ERR_INVALID;
653 		}
654 	}
655 	return s8Ret;
656 }
657 /*********************************************************************
658 Function
659 		accept
660 
661 Description
662 
663 Return
664 
665 
666 Author
667 		Ahmed Ezzat
668 
669 Version
670 		1.0
671 
672 Date
673 		5 June 2012
674 *********************************************************************/
accept(SOCKET sock,struct sockaddr * addr,uint8 * addrlen)675 sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen)
676 {
677 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
678 
679 	if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1) )
680 	{
681 		s8Ret = SOCK_ERR_NO_ERROR;
682 	}
683 	return s8Ret;
684 }
685 /*********************************************************************
686 Function
687 		connect
688 
689 Description
690 		Connect to a remote TCP Server.
691 
692 Return
693 
694 
695 Author
696 		Ahmed Ezzat
697 
698 Version
699 		1.0
700 
701 Date
702 		5 June 2012
703 *********************************************************************/
connect(SOCKET sock,struct sockaddr * pstrAddr,uint8 u8AddrLen)704 sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen)
705 {
706 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
707 	if((sock >= 0) && (pstrAddr != NULL) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0))
708 	{
709 		tstrConnectCmd	strConnect;
710 		uint8			u8Cmd = SOCKET_CMD_CONNECT;
711 		if((gastrSockets[sock].u8SSLFlags) & SSL_FLAGS_ACTIVE)
712 		{
713 			u8Cmd = SOCKET_CMD_SSL_CONNECT;
714 			strConnect.u8SslFlags = gastrSockets[sock].u8SSLFlags;
715 		}
716 		strConnect.sock = sock;
717 		m2m_memcpy((uint8 *)&strConnect.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr));
718 
719 		strConnect.u16SessionID		= gastrSockets[sock].u16SessionID;
720 		s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strConnect,sizeof(tstrConnectCmd), NULL, 0, 0);
721 		if(s8Ret != SOCK_ERR_NO_ERROR)
722 		{
723 			s8Ret = SOCK_ERR_INVALID;
724 		}
725 	}
726 	return s8Ret;
727 }
728 /*********************************************************************
729 Function
730 		send
731 
732 Description
733 
734 Return
735 
736 Author
737 		Ahmed Ezzat
738 
739 Version
740 		1.0
741 
742 Date
743 		5 June 2012
744 *********************************************************************/
send(SOCKET sock,void * pvSendBuffer,uint16 u16SendLength,uint16 flags)745 sint16 send(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags)
746 {
747 	sint16	s16Ret = SOCK_ERR_INVALID_ARG;
748 
749 	if((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH) && (gastrSockets[sock].bIsUsed == 1))
750 	{
751 		uint16			u16DataOffset;
752 		tstrSendCmd		strSend;
753 		uint8			u8Cmd;
754 
755 		u8Cmd			= SOCKET_CMD_SEND;
756 		u16DataOffset	= TCP_TX_PACKET_OFFSET;
757 
758 		strSend.sock			= sock;
759 		strSend.u16DataSize		= NM_BSP_B_L_16(u16SendLength);
760 		strSend.u16SessionID	= gastrSockets[sock].u16SessionID;
761 
762 		if(sock >= TCP_SOCK_MAX)
763 		{
764 			u16DataOffset = UDP_TX_PACKET_OFFSET;
765 		}
766 		if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
767 		{
768 			u8Cmd			= SOCKET_CMD_SSL_SEND;
769 			u16DataOffset	= gastrSockets[sock].u16DataOffset;
770 		}
771 
772 		s16Ret =  SOCKET_REQUEST(u8Cmd|M2M_REQ_DATA_PKT, (uint8*)&strSend, sizeof(tstrSendCmd), pvSendBuffer, u16SendLength, u16DataOffset);
773 		if(s16Ret != SOCK_ERR_NO_ERROR)
774 		{
775 			s16Ret = SOCK_ERR_BUFFER_FULL;
776 		}
777 	}
778 	return s16Ret;
779 }
780 /*********************************************************************
781 Function
782 		sendto
783 
784 Description
785 
786 Return
787 
788 Author
789 		Ahmed Ezzat
790 
791 Version
792 		1.0
793 
794 Date
795 		4 June 2012
796 *********************************************************************/
sendto(SOCKET sock,void * pvSendBuffer,uint16 u16SendLength,uint16 flags,struct sockaddr * pstrDestAddr,uint8 u8AddrLen)797 sint16 sendto(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags, struct sockaddr *pstrDestAddr, uint8 u8AddrLen)
798 {
799 	sint16	s16Ret = SOCK_ERR_INVALID_ARG;
800 
801 	if((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH) && (gastrSockets[sock].bIsUsed == 1))
802 	{
803 		if(gastrSockets[sock].bIsUsed)
804 		{
805 			tstrSendCmd	strSendTo;
806 
807 			m2m_memset((uint8*)&strSendTo, 0, sizeof(tstrSendCmd));
808 
809 			strSendTo.sock			= sock;
810 			strSendTo.u16DataSize	= NM_BSP_B_L_16(u16SendLength);
811 			strSendTo.u16SessionID	= gastrSockets[sock].u16SessionID;
812 
813 			if(pstrDestAddr != NULL)
814 			{
815 				struct sockaddr_in	*pstrAddr;
816 				pstrAddr = (void*)pstrDestAddr;
817 
818 				strSendTo.strAddr.u16Family	= pstrAddr->sin_family;
819 				strSendTo.strAddr.u16Port	= pstrAddr->sin_port;
820 				strSendTo.strAddr.u32IPAddr	= pstrAddr->sin_addr.s_addr;
821 			}
822 			s16Ret = SOCKET_REQUEST(SOCKET_CMD_SENDTO|M2M_REQ_DATA_PKT, (uint8*)&strSendTo,  sizeof(tstrSendCmd),
823 				pvSendBuffer, u16SendLength, UDP_TX_PACKET_OFFSET);
824 
825 			if(s16Ret != SOCK_ERR_NO_ERROR)
826 			{
827 				s16Ret = SOCK_ERR_BUFFER_FULL;
828 			}
829 		}
830 	}
831 	return s16Ret;
832 }
833 /*********************************************************************
834 Function
835 		recv
836 
837 Description
838 
839 Return
840 
841 
842 Author
843 		Ahmed Ezzat
844 
845 Version
846 		1.0
847 		2.0  9 April 2013 --> Add timeout for recv operation.
848 
849 Date
850 		5 June 2012
851 *********************************************************************/
recv(SOCKET sock,void * pvRecvBuf,uint16 u16BufLen,uint32 u32Timeoutmsec)852 sint16 recv(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec)
853 {
854 	sint16	s16Ret = SOCK_ERR_INVALID_ARG;
855 
856 	if((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1))
857 	{
858 		s16Ret = SOCK_ERR_NO_ERROR;
859 		gastrSockets[sock].pu8UserBuffer 		= (uint8*)pvRecvBuf;
860 		gastrSockets[sock].u16UserBufferSize 	= u16BufLen;
861 
862 		if(!gastrSockets[sock].bIsRecvPending)
863 		{
864 			tstrRecvCmd	strRecv;
865 			uint8		u8Cmd = SOCKET_CMD_RECV;
866 
867 			gastrSockets[sock].bIsRecvPending = 1;
868 			if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
869 			{
870 				u8Cmd = SOCKET_CMD_SSL_RECV;
871 			}
872 
873 			/* Check the timeout value. */
874 			if(u32Timeoutmsec == 0)
875 				strRecv.u32Timeoutmsec = 0xFFFFFFFF;
876 			else
877 				strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
878 			strRecv.sock = sock;
879 			strRecv.u16SessionID		= gastrSockets[sock].u16SessionID;
880 
881 			s16Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strRecv, sizeof(tstrRecvCmd), NULL , 0, 0);
882 			if(s16Ret != SOCK_ERR_NO_ERROR)
883 			{
884 				s16Ret = SOCK_ERR_BUFFER_FULL;
885 			}
886 		}
887 	}
888 	return s16Ret;
889 }
890 /*********************************************************************
891 Function
892 		close
893 
894 Description
895 
896 Return
897 		None.
898 
899 Author
900 		Ahmed Ezzat
901 
902 Version
903 		1.0
904 
905 Date
906 		4 June 2012
907 *********************************************************************/
winc1500_close(SOCKET sock)908 sint8 winc1500_close(SOCKET sock)
909 {
910 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
911     M2M_INFO("Sock to delete <%d>\n", sock);
912 	if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1))
913 	{
914 		uint8	u8Cmd = SOCKET_CMD_CLOSE;
915 		tstrCloseCmd strclose;
916 		strclose.sock = sock;
917 		strclose.u16SessionID		= gastrSockets[sock].u16SessionID;
918 
919 		gastrSockets[sock].bIsUsed = 0;
920 		gastrSockets[sock].u16SessionID =0;
921 
922 		if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
923 		{
924 			u8Cmd = SOCKET_CMD_SSL_CLOSE;
925 		}
926 		s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strclose, sizeof(tstrCloseCmd), NULL,0, 0);
927 		if(s8Ret != SOCK_ERR_NO_ERROR)
928 		{
929 			s8Ret = SOCK_ERR_INVALID;
930 		}
931 		m2m_memset((uint8*)&gastrSockets[sock], 0, sizeof(tstrSocket));
932 	}
933 	return s8Ret;
934 }
935 /*********************************************************************
936 Function
937 		recvfrom
938 
939 Description
940 
941 Return
942 
943 
944 Author
945 		Ahmed Ezzat
946 
947 Version
948 		1.0
949 		2.0  9 April 2013 --> Add timeout for recv operation.
950 
951 Date
952 		5 June 2012
953 *********************************************************************/
recvfrom(SOCKET sock,void * pvRecvBuf,uint16 u16BufLen,uint32 u32Timeoutmsec)954 sint16 recvfrom(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec)
955 {
956 	sint16	s16Ret = SOCK_ERR_NO_ERROR;
957 	if((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1))
958 	{
959 		if(gastrSockets[sock].bIsUsed)
960 		{
961 			s16Ret = SOCK_ERR_NO_ERROR;
962 			gastrSockets[sock].pu8UserBuffer = (uint8*)pvRecvBuf;
963 			gastrSockets[sock].u16UserBufferSize = u16BufLen;
964 
965 			if(!gastrSockets[sock].bIsRecvPending)
966 			{
967 				tstrRecvCmd	strRecv;
968 
969 				gastrSockets[sock].bIsRecvPending = 1;
970 
971 				/* Check the timeout value. */
972 				if(u32Timeoutmsec == 0)
973 					strRecv.u32Timeoutmsec = 0xFFFFFFFF;
974 				else
975 					strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec);
976 				strRecv.sock = sock;
977 				strRecv.u16SessionID		= gastrSockets[sock].u16SessionID;
978 
979 				s16Ret = SOCKET_REQUEST(SOCKET_CMD_RECVFROM, (uint8*)&strRecv, sizeof(tstrRecvCmd), NULL , 0, 0);
980 				if(s16Ret != SOCK_ERR_NO_ERROR)
981 				{
982 					s16Ret = SOCK_ERR_BUFFER_FULL;
983 				}
984 			}
985 		}
986 	}
987 	else
988 	{
989 		s16Ret = SOCK_ERR_INVALID_ARG;
990 	}
991 	return s16Ret;
992 }
993 /*********************************************************************
994 Function
995 		nmi_inet_addr
996 
997 Description
998 
999 Return
1000 		Unsigned 32-bit integer representing the IP address in Network
1001 		byte order.
1002 
1003 Author
1004 		Ahmed Ezzat
1005 
1006 Version
1007 		1.0
1008 
1009 Date
1010 		4 June 2012
1011 *********************************************************************/
nmi_inet_addr(char * pcIpAddr)1012 uint32 nmi_inet_addr(char *pcIpAddr)
1013 {
1014 	uint8	tmp;
1015 	uint32	u32IP = 0;
1016 	uint8	au8IP[4];
1017 	uint8 	c;
1018 	uint8	i, j;
1019 
1020 	tmp = 0;
1021 
1022 	for(i = 0; i < 4; ++i)
1023 	{
1024 		j = 0;
1025 		do
1026 		{
1027 			c = *pcIpAddr;
1028 			++j;
1029 			if(j > 4)
1030 			{
1031 				return 0;
1032 			}
1033 			if(c == '.' || c == 0)
1034 			{
1035 				au8IP[i] = tmp;
1036 				tmp = 0;
1037 			}
1038 			else if(c >= '0' && c <= '9')
1039 			{
1040 				tmp = (tmp * 10) + (c - '0');
1041 			}
1042 			else
1043 			{
1044 				return 0;
1045 			}
1046 			++pcIpAddr;
1047 		} while(c != '.' && c != 0);
1048 	}
1049 	m2m_memcpy((uint8*)&u32IP, au8IP, 4);
1050 	return u32IP;
1051 }
1052 /*********************************************************************
1053 Function
1054 		gethostbyname
1055 
1056 Description
1057 
1058 Return
1059 		None.
1060 
1061 Author
1062 		Ahmed Ezzat
1063 
1064 Version
1065 		1.0
1066 
1067 Date
1068 		4 June 2012
1069 *********************************************************************/
gethostbyname(uint8 * pcHostName)1070 sint8 gethostbyname(uint8 * pcHostName)
1071 {
1072 	sint8	s8Err = SOCK_ERR_INVALID_ARG;
1073 	uint8	u8HostNameSize = (uint8)m2m_strlen(pcHostName);
1074 	if(u8HostNameSize <= HOSTNAME_MAX_SIZE)
1075 	{
1076 		s8Err = SOCKET_REQUEST(SOCKET_CMD_DNS_RESOLVE, (uint8*)pcHostName, u8HostNameSize + 1, NULL,0, 0);
1077 	}
1078 	return s8Err;
1079 }
1080 /*********************************************************************
1081 Function
1082 		setsockopt
1083 
1084 Description
1085 
1086 Return
1087 		None.
1088 
1089 Author
1090 		Abdelrahman Diab
1091 
1092 Version
1093 		1.0
1094 
1095 Date
1096 		9 September 2014
1097 *********************************************************************/
sslSetSockOpt(SOCKET sock,uint8 u8Opt,const void * pvOptVal,uint16 u16OptLen)1098 static sint8 sslSetSockOpt(SOCKET sock, uint8  u8Opt, const void *pvOptVal, uint16 u16OptLen)
1099 {
1100 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
1101 	if(sock < TCP_SOCK_MAX)
1102 	{
1103 		if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE)
1104 		{
1105 			if(u8Opt == SO_SSL_BYPASS_X509_VERIF)
1106 			{
1107 				int	optVal = *((int*)pvOptVal);
1108 				if(optVal)
1109 				{
1110 					gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_BYPASS_X509;
1111 				}
1112 				else
1113 				{
1114 					gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_BYPASS_X509;
1115 				}
1116 				s8Ret = SOCK_ERR_NO_ERROR;
1117 			}
1118 			else if(u8Opt == SO_SSL_ENABLE_SESSION_CACHING)
1119 			{
1120 				int	optVal = *((int*)pvOptVal);
1121 				if(optVal)
1122 				{
1123 					gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CACHE_SESSION;
1124 				}
1125 				else
1126 				{
1127 					gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CACHE_SESSION;
1128 				}
1129 				s8Ret = SOCK_ERR_NO_ERROR;
1130 			}
1131 			else if(u8Opt == SO_SSL_ENABLE_SNI_VALIDATION)
1132 			{
1133 				int	optVal = *((int*)pvOptVal);
1134 				if(optVal)
1135 				{
1136 					gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CHECK_SNI;
1137 				}
1138 				else
1139 				{
1140 					gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CHECK_SNI;
1141 				}
1142 				s8Ret = SOCK_ERR_NO_ERROR;
1143 			}
1144 			else if(u8Opt == SO_SSL_SNI)
1145 			{
1146 				if(u16OptLen < HOSTNAME_MAX_SIZE)
1147 				{
1148 					uint8					*pu8SNI = (uint8*)pvOptVal;
1149 					tstrSSLSetSockOptCmd	strCmd;
1150 
1151 					strCmd.sock			= sock;
1152 					strCmd.u16SessionID	= gastrSockets[sock].u16SessionID;
1153 					strCmd.u8Option		= u8Opt;
1154 					strCmd.u32OptLen	= u16OptLen;
1155 					m2m_memcpy(strCmd.au8OptVal, pu8SNI, HOSTNAME_MAX_SIZE);
1156 
1157 					if(SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT, (uint8*)&strCmd, sizeof(tstrSSLSetSockOptCmd),
1158 						0, 0, 0) == M2M_ERR_MEM_ALLOC)
1159 					{
1160 						s8Ret = SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT | M2M_REQ_DATA_PKT,
1161 							(uint8*)&strCmd, sizeof(tstrSSLSetSockOptCmd), 0, 0, 0);
1162 					}
1163 					s8Ret = SOCK_ERR_NO_ERROR;
1164 				}
1165 				else
1166 				{
1167 					M2M_ERR("SNI Exceeds Max Length\n");
1168 				}
1169 			}
1170 			else
1171 			{
1172 				M2M_ERR("Unknown SSL Socket Option %d\n",u8Opt);
1173 			}
1174 		}
1175 		else
1176 		{
1177 			M2M_ERR("Not SSL Socket\n");
1178 		}
1179 	}
1180 	return s8Ret;
1181 }
1182 /*********************************************************************
1183 Function
1184 		setsockopt
1185 
1186 Description
1187 
1188 Return
1189 		None.
1190 
1191 Author
1192 		Abdelrahman Diab
1193 
1194 Version
1195 		1.0
1196 
1197 Date
1198 		9 September 2014
1199 *********************************************************************/
setsockopt(SOCKET sock,uint8 u8Level,uint8 option_name,const void * option_value,uint16 u16OptionLen)1200 sint8 setsockopt(SOCKET sock, uint8  u8Level, uint8  option_name,
1201        const void *option_value, uint16 u16OptionLen)
1202 {
1203 	sint8	s8Ret = SOCK_ERR_INVALID_ARG;
1204 	if((sock >= 0)  && (option_value != NULL)  && (gastrSockets[sock].bIsUsed == 1))
1205 	{
1206 		if(u8Level == SOL_SSL_SOCKET)
1207 		{
1208 			s8Ret = sslSetSockOpt(sock, option_name, option_value, u16OptionLen);
1209 		}
1210 		else
1211 		{
1212 			uint8	u8Cmd = SOCKET_CMD_SET_SOCKET_OPTION;
1213 			tstrSetSocketOptCmd strSetSockOpt;
1214 			strSetSockOpt.u8Option=option_name;
1215 			strSetSockOpt.sock = sock;
1216 			strSetSockOpt.u32OptionValue = *(uint32*)option_value;
1217 			strSetSockOpt.u16SessionID		= gastrSockets[sock].u16SessionID;
1218 
1219 			s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strSetSockOpt, sizeof(tstrSetSocketOptCmd), NULL,0, 0);
1220 			if(s8Ret != SOCK_ERR_NO_ERROR)
1221 			{
1222 				s8Ret = SOCK_ERR_INVALID;
1223 			}
1224 		}
1225 	}
1226 	return s8Ret;
1227 }
1228 /*********************************************************************
1229 Function
1230 		getsockopt
1231 
1232 Description
1233 
1234 Return
1235 		None.
1236 
1237 Author
1238 		Ahmed Ezzat
1239 
1240 Version
1241 		1.0
1242 
1243 Date
1244 		24 August 2014
1245 *********************************************************************/
getsockopt(SOCKET sock,uint8 u8Level,uint8 u8OptName,const void * pvOptValue,uint8 * pu8OptLen)1246 sint8 getsockopt(SOCKET sock, uint8 u8Level, uint8 u8OptName, const void *pvOptValue, uint8* pu8OptLen)
1247 {
1248 	/* TBD */
1249 	return M2M_SUCCESS;
1250 }
1251 /*********************************************************************
1252 Function
1253 	m2m_ping_req
1254 
1255 Description
1256 	Send Ping request.
1257 
1258 Return
1259 
1260 Author
1261 	Ahmed Ezzat
1262 
1263 Version
1264 	1.0
1265 
1266 Date
1267 	4 June 2015
1268 *********************************************************************/
m2m_ping_req(uint32 u32DstIP,uint8 u8TTL,tpfPingCb fpPingCb)1269 sint8 m2m_ping_req(uint32 u32DstIP, uint8 u8TTL, tpfPingCb fpPingCb)
1270 {
1271 	sint8	s8Ret = M2M_ERR_INVALID_ARG;
1272 
1273 	if((u32DstIP != 0) && (fpPingCb != NULL))
1274 	{
1275 		tstrPingCmd	strPingCmd;
1276 
1277 		strPingCmd.u16PingCount		= 1;
1278 		strPingCmd.u32DestIPAddr	= u32DstIP;
1279 		strPingCmd.u32CmdPrivate	= (uint32)fpPingCb;
1280 		strPingCmd.u8TTL			= u8TTL;
1281 
1282 		s8Ret = SOCKET_REQUEST(SOCKET_CMD_PING, (uint8*)&strPingCmd, sizeof(tstrPingCmd), NULL, 0, 0);
1283 	}
1284 	return s8Ret;
1285 }
1286 /*********************************************************************
1287 Function
1288 	sslEnableCertExpirationCheck
1289 
1290 Description
1291 	Enable/Disable TLS Certificate Expiration Check.
1292 
1293 Return
1294 
1295 Author
1296 	Ahmed Ezzat
1297 
1298 Version
1299 	1.0
1300 
1301 Date
1302 
1303 *********************************************************************/
sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting)1304 sint8 sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting)
1305 {
1306 	tstrSslCertExpSettings	strSettings;
1307 	strSettings.u32CertExpValidationOpt = (uint32)enuValidationSetting;
1308 	return SOCKET_REQUEST(SOCKET_CMD_SSL_EXP_CHECK, (uint8*)&strSettings, sizeof(tstrSslCertExpSettings), NULL, 0, 0);
1309 }