PageRenderTime 77ms CodeModel.GetById 3ms app.highlight 66ms RepoModel.GetById 1ms app.codeStats 0ms

/utility/socket.cpp

https://github.com/zrecommerce/Adafruit_CC3000_Library
C++ | 1190 lines | 455 code | 153 blank | 582 comment | 37 complexity | 1c6036ad52d0fbe46dd068928b84737a MD5 | raw file
   1/*****************************************************************************
   2*
   3*  socket.c  - CC3000 Host Driver Implementation.
   4*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   5*
   6* Adapted for use with the Arduino/AVR by KTOWN (Kevin Townsend) 
   7* & Limor Fried for Adafruit Industries
   8* This library works with the Adafruit CC3000 breakout 
   9*	----> https://www.adafruit.com/products/1469
  10* Adafruit invests time and resources providing this open source code,
  11* please support Adafruit and open-source hardware by purchasing
  12* products from Adafruit!
  13*
  14*  Redistribution and use in source and binary forms, with or without
  15*  modification, are permitted provided that the following conditions
  16*  are met:
  17*
  18*    Redistributions of source code must retain the above copyright
  19*    notice, this list of conditions and the following disclaimer.
  20*
  21*    Redistributions in binary form must reproduce the above copyright
  22*    notice, this list of conditions and the following disclaimer in the
  23*    documentation and/or other materials provided with the   
  24*    distribution.
  25*
  26*    Neither the name of Texas Instruments Incorporated nor the names of
  27*    its contributors may be used to endorse or promote products derived
  28*    from this software without specific prior written permission.
  29*
  30*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  31*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  32*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  33*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
  34*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  35*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
  36*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  37*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  38*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  39*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  40*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41*
  42*****************************************************************************/
  43
  44//*****************************************************************************
  45//
  46//! \addtogroup socket_api
  47//! @{
  48//
  49//*****************************************************************************
  50
  51#include <stdio.h>
  52#include <string.h>
  53#include <stdlib.h>
  54#include "hci.h"
  55#include "socket.h"
  56#include "evnt_handler.h"
  57#include "netapp.h"
  58#include "debug.h"
  59
  60
  61
  62//Enable this flag if and only if you must comply with BSD socket 
  63//close() function
  64#ifdef _API_USE_BSD_CLOSE
  65   #define close(sd) closesocket(sd)
  66#endif
  67
  68//Enable this flag if and only if you must comply with BSD socket read() and 
  69//write() functions
  70#ifdef _API_USE_BSD_READ_WRITE
  71              #define read(sd, buf, len, flags) recv(sd, buf, len, flags)
  72              #define write(sd, buf, len, flags) send(sd, buf, len, flags)
  73#endif
  74
  75#define SOCKET_OPEN_PARAMS_LEN				(12)
  76#define SOCKET_CLOSE_PARAMS_LEN				(4)
  77#define SOCKET_ACCEPT_PARAMS_LEN			(4)
  78#define SOCKET_BIND_PARAMS_LEN				(20)
  79#define SOCKET_LISTEN_PARAMS_LEN			(8)
  80#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN	(9)
  81#define SOCKET_CONNECT_PARAMS_LEN			(20)
  82#define SOCKET_SELECT_PARAMS_LEN			(44)
  83#define SOCKET_SET_SOCK_OPT_PARAMS_LEN		(20)
  84#define SOCKET_GET_SOCK_OPT_PARAMS_LEN		(12)
  85#define SOCKET_RECV_FROM_PARAMS_LEN			(12)
  86#define SOCKET_SENDTO_PARAMS_LEN			(24)
  87#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN	(12)
  88
  89
  90// The legnth of arguments for the SEND command: sd + buff_offset + len + flags, 
  91// while size of each parameter is 32 bit - so the total length is 16 bytes;
  92
  93#define HCI_CMND_SEND_ARG_LENGTH	(16)
  94
  95
  96#define SELECT_TIMEOUT_MIN_MICRO_SECONDS  5000
  97
  98#define HEADERS_SIZE_DATA       (SPI_HEADER_SIZE + 5)
  99
 100#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE  (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
 101
 102#define MDNS_DEVICE_SERVICE_MAX_LENGTH 	(32)
 103
 104
 105//*****************************************************************************
 106//
 107//! HostFlowControlConsumeBuff
 108//!
 109//!  @param  sd  socket descriptor
 110//!
 111//!  @return 0 in case there are buffers available, 
 112//!          -1 in case of bad socket
 113//!          -2 if there are no free buffers present (only when 
 114//!          SEND_NON_BLOCKING is enabled)
 115//!
 116//!  @brief  if SEND_NON_BLOCKING not define - block until have free buffer 
 117//!          becomes available, else return immediately  with correct status 
 118//!          regarding the buffers available.
 119//
 120//*****************************************************************************
 121int
 122HostFlowControlConsumeBuff(int sd)
 123{
 124#ifndef SEND_NON_BLOCKING
 125	/* wait in busy loop */
 126	do
 127	{
 128		// In case last transmission failed then we will return the last failure 
 129		// reason here.
 130		// Note that the buffer will not be allocated in this case
 131		if (tSLInformation.slTransmitDataError != 0)
 132		{
 133			errno = tSLInformation.slTransmitDataError;
 134			tSLInformation.slTransmitDataError = 0;
 135			return errno;
 136		}
 137		
 138		if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
 139			return -1;
 140	} while(0 == tSLInformation.usNumberOfFreeBuffers);
 141	
 142	tSLInformation.usNumberOfFreeBuffers--;
 143	
 144	return 0;
 145#else
 146	
 147	// In case last transmission failed then we will return the last failure 
 148	// reason here.
 149	// Note that the buffer will not be allocated in this case
 150	if (tSLInformation.slTransmitDataError != 0)
 151	{
 152		errno = tSLInformation.slTransmitDataError;
 153		tSLInformation.slTransmitDataError = 0;
 154		return errno;
 155	}
 156	if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
 157		return -1;
 158	
 159	//If there are no available buffers, return -2. It is recommended to use  
 160	// select or receive to see if there is any buffer occupied with received data
 161	// If so, call receive() to release the buffer.
 162	if(0 == tSLInformation.usNumberOfFreeBuffers)
 163	{
 164		return -2;
 165	}
 166	else
 167	{
 168		tSLInformation.usNumberOfFreeBuffers--;
 169		return 0;
 170	}
 171#endif
 172}
 173
 174//*****************************************************************************
 175//
 176//! socket
 177//!
 178//!  @param  domain    selects the protocol family which will be used for 
 179//!                    communication. On this version only AF_INET is supported
 180//!  @param  type      specifies the communication semantics. On this version 
 181//!                    only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
 182//!  @param  protocol  specifies a particular protocol to be used with the 
 183//!                    socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are 
 184//!                    supported.
 185//!
 186//!  @return  On success, socket handle that is used for consequent socket 
 187//!           operations. On error, -1 is returned.
 188//!
 189//!  @brief  create an endpoint for communication
 190//!          The socket function creates a socket that is bound to a specific 
 191//!          transport service provider. This function is called by the 
 192//!          application layer to obtain a socket handle.
 193//
 194//*****************************************************************************
 195
 196int
 197socket(long domain, long type, long protocol)
 198{
 199	long ret;
 200	unsigned char *ptr, *args;
 201	
 202	ret = EFAIL;
 203	ptr = tSLInformation.pucTxCommandBuffer;
 204	args = (ptr + HEADERS_SIZE_CMD);
 205	
 206	// Fill in HCI packet structure
 207	args = UINT32_TO_STREAM(args, domain);
 208	args = UINT32_TO_STREAM(args, type);
 209	args = UINT32_TO_STREAM(args, protocol);
 210	
 211	// Initiate a HCI command
 212	hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
 213	
 214	// Since we are in blocking state - wait for event complete
 215	SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
 216	
 217	// Process the event 
 218	errno = ret;
 219	
 220	set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
 221	
 222	return(ret);
 223}
 224
 225//*****************************************************************************
 226//
 227//! closesocket
 228//!
 229//!  @param  sd    socket handle.
 230//!
 231//!  @return  On success, zero is returned. On error, -1 is returned.
 232//!
 233//!  @brief  The socket function closes a created socket.
 234//
 235//*****************************************************************************
 236
 237long
 238closesocket(long sd)
 239{
 240	long ret;
 241	unsigned char *ptr, *args;
 242	
 243	ret = EFAIL;
 244	ptr = tSLInformation.pucTxCommandBuffer;
 245	args = (ptr + HEADERS_SIZE_CMD);
 246	
 247	// Fill in HCI packet structure
 248	args = UINT32_TO_STREAM(args, sd);
 249	
 250	// Initiate a HCI command
 251	hci_command_send(HCI_CMND_CLOSE_SOCKET, ptr, SOCKET_CLOSE_PARAMS_LEN);
 252	
 253	// Since we are in blocking state - wait for event complete
 254	SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
 255	errno = ret;
 256	
 257	// since 'close' call may result in either OK (and then it closed) or error 
 258	// mark this socket as invalid 
 259	set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
 260	
 261	return(ret);
 262}
 263
 264//*****************************************************************************
 265//
 266//! accept
 267//!
 268//!  @param[in]   sd      socket descriptor (handle)              
 269//!  @param[out]  addr    the argument addr is a pointer to a sockaddr structure
 270//!                       This structure is filled in with the address of the  
 271//!                       peer socket, as known to the communications layer.        
 272//!                       determined. The exact format of the address returned             
 273//!                       addr is by the socket's address sockaddr. 
 274//!                       On this version only AF_INET is supported.
 275//!                       This argument returns in network order.
 276//!  @param[out] addrlen  the addrlen argument is a value-result argument: 
 277//!                       it should initially contain the size of the structure
 278//!                       pointed to by addr.
 279//!
 280//!  @return  For socket in blocking mode:
 281//!				      On success, socket handle. on failure negative
 282//!			      For socket in non-blocking mode:
 283//!				     - On connection establishment, socket handle
 284//!				     - On connection pending, SOC_IN_PROGRESS (-2)
 285//!			       - On failure, SOC_ERROR	(-1)
 286//!
 287//!  @brief  accept a connection on a socket:
 288//!          This function is used with connection-based socket types 
 289//!          (SOCK_STREAM). It extracts the first connection request on the 
 290//!          queue of pending connections, creates a new connected socket, and
 291//!          returns a new file descriptor referring to that socket.
 292//!          The newly created socket is not in the listening state. 
 293//!          The original socket sd is unaffected by this call. 
 294//!          The argument sd is a socket that has been created with socket(),
 295//!          bound to a local address with bind(), and is  listening for 
 296//!          connections after a listen(). The argument addr is a pointer 
 297//!          to a sockaddr structure. This structure is filled in with the 
 298//!          address of the peer socket, as known to the communications layer.
 299//!          The exact format of the address returned addr is determined by the 
 300//!          socket's address family. The addrlen argument is a value-result
 301//!          argument: it should initially contain the size of the structure
 302//!          pointed to by addr, on return it will contain the actual 
 303//!          length (in bytes) of the address returned.
 304//!
 305//! @sa     socket ; bind ; listen
 306//
 307//*****************************************************************************
 308
 309long
 310accept(long sd, sockaddr *addr, socklen_t *addrlen)
 311{
 312	long ret;
 313	unsigned char *ptr, *args;
 314	tBsdReturnParams tAcceptReturnArguments;
 315	
 316	ret = EFAIL;
 317	ptr = tSLInformation.pucTxCommandBuffer;
 318	args = (ptr + HEADERS_SIZE_CMD);
 319	
 320	// Fill in temporary command buffer
 321	args = UINT32_TO_STREAM(args, sd);
 322	
 323	// Initiate a HCI command
 324	hci_command_send(HCI_CMND_ACCEPT,
 325									 ptr, SOCKET_ACCEPT_PARAMS_LEN);
 326	
 327	// Since we are in blocking state - wait for event complete
 328	SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
 329	
 330	
 331	// need specify return parameters!!!
 332	memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
 333	*addrlen = ASIC_ADDR_LEN;
 334	errno = tAcceptReturnArguments.iStatus; 
 335	ret = errno;
 336	
 337	// if succeeded, iStatus = new socket descriptor. otherwise - error number 
 338	if(M_IS_VALID_SD(ret))
 339	{
 340		set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
 341	}
 342	else
 343	{
 344		set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
 345	}
 346	
 347	return(ret);
 348}
 349
 350//*****************************************************************************
 351//
 352//! bind
 353//!
 354//!  @param[in]   sd      socket descriptor (handle)              
 355//!  @param[out]  addr    specifies the destination address. On this version 
 356//!                       only AF_INET is supported.
 357//!  @param[out] addrlen  contains the size of the structure pointed to by addr.
 358//!
 359//!  @return  	On success, zero is returned. On error, -1 is returned.
 360//!
 361//!  @brief  assign a name to a socket
 362//!          This function gives the socket the local address addr.
 363//!          addr is addrlen bytes long. Traditionally, this is called when a 
 364//!          socket is created with socket, it exists in a name space (address 
 365//!          family) but has no name assigned.
 366//!          It is necessary to assign a local address before a SOCK_STREAM
 367//!          socket may receive connections.
 368//!
 369//! @sa     socket ; accept ; listen
 370//
 371//*****************************************************************************
 372
 373long
 374bind(long sd, const sockaddr *addr, long addrlen)
 375{
 376	long ret;
 377	unsigned char *ptr, *args;
 378	
 379	ret = EFAIL;
 380	ptr = tSLInformation.pucTxCommandBuffer;
 381	args = (ptr + HEADERS_SIZE_CMD);
 382	
 383	addrlen = ASIC_ADDR_LEN;
 384	
 385	// Fill in temporary command buffer
 386	args = UINT32_TO_STREAM(args, sd);
 387	args = UINT32_TO_STREAM(args, 0x00000008);
 388	args = UINT32_TO_STREAM(args, addrlen);
 389	ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);
 390	
 391	// Initiate a HCI command
 392	hci_command_send(HCI_CMND_BIND,
 393									 ptr, SOCKET_BIND_PARAMS_LEN);
 394	
 395	// Since we are in blocking state - wait for event complete
 396	SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
 397	
 398	errno = ret;
 399  
 400	return(ret);
 401}
 402
 403//*****************************************************************************
 404//
 405//! listen
 406//!
 407//!  @param[in]   sd      socket descriptor (handle)              
 408//!  @param[in]  backlog  specifies the listen queue depth. On this version
 409//!                       backlog is not supported.
 410//!  @return  	On success, zero is returned. On error, -1 is returned.
 411//!
 412//!  @brief  listen for connections on a socket
 413//!          The willingness to accept incoming connections and a queue
 414//!          limit for incoming connections are specified with listen(),
 415//!          and then the connections are accepted with accept.
 416//!          The listen() call applies only to sockets of type SOCK_STREAM
 417//!          The backlog parameter defines the maximum length the queue of
 418//!          pending connections may grow to. 
 419//!
 420//! @sa     socket ; accept ; bind
 421//!
 422//! @note   On this version, backlog is not supported
 423//
 424//*****************************************************************************
 425
 426long
 427listen(long sd, long backlog)
 428{
 429	long ret;
 430	unsigned char *ptr, *args;
 431	
 432	ret = EFAIL;
 433	ptr = tSLInformation.pucTxCommandBuffer;
 434	args = (ptr + HEADERS_SIZE_CMD);
 435	
 436	// Fill in temporary command buffer
 437	args = UINT32_TO_STREAM(args, sd);
 438	args = UINT32_TO_STREAM(args, backlog);
 439	
 440	// Initiate a HCI command
 441	hci_command_send(HCI_CMND_LISTEN,
 442									 ptr, SOCKET_LISTEN_PARAMS_LEN);
 443	
 444	// Since we are in blocking state - wait for event complete
 445	SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
 446	errno = ret;
 447	
 448	return(ret);
 449}
 450
 451//*****************************************************************************
 452//
 453//! gethostbyname
 454//!
 455//!  @param[in]   hostname     host name              
 456//!  @param[in]   usNameLen    name length 
 457//!  @param[out]  out_ip_addr  This parameter is filled in with host IP address. 
 458//!                            In case that host name is not resolved, 
 459//!                            out_ip_addr is zero.                  
 460//!  @return  	On success, positive is returned. On error, negative is returned
 461//!
 462//!  @brief  Get host IP by name. Obtain the IP Address of machine on network, 
 463//!          by its name.
 464//!
 465//!  @note  On this version, only blocking mode is supported. Also note that
 466//!		     the function requires DNS server to be configured prior to its usage.
 467//
 468//*****************************************************************************
 469
 470#ifndef CC3000_TINY_DRIVER
 471int 
 472gethostbyname(char * hostname, uint8_t usNameLen, uint32_t * out_ip_addr)
 473{
 474	tBsdGethostbynameParams ret;
 475	unsigned char *ptr, *args;
 476	
 477	errno = EFAIL;
 478	
 479	if (usNameLen > HOSTNAME_MAX_LENGTH)
 480	{
 481		return errno;
 482	}
 483	
 484	ptr = tSLInformation.pucTxCommandBuffer;
 485	args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
 486	
 487	// Fill in HCI packet structure
 488	args = UINT32_TO_STREAM(args, 8);
 489	args = UINT32_TO_STREAM(args, usNameLen);
 490	ARRAY_TO_STREAM(args, hostname, usNameLen);
 491	
 492	// Initiate a HCI command
 493	hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
 494									 + usNameLen - 1);
 495	
 496	// Since we are in blocking state - wait for event complete
 497	SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
 498	
 499	errno = ret.retVal;
 500	//Serial.print("errno: "); Serial.println(errno);
 501	(*((uint32_t *)out_ip_addr)) = ret.outputAddress;
 502	
 503	return (errno);
 504	
 505}
 506#endif
 507
 508//*****************************************************************************
 509//
 510//! connect
 511//!
 512//!  @param[in]   sd       socket descriptor (handle)         
 513//!  @param[in]   addr     specifies the destination addr. On this version
 514//!                        only AF_INET is supported.
 515//!  @param[out]  addrlen  contains the size of the structure pointed to by addr    
 516//!  @return  	On success, zero is returned. On error, -1 is returned
 517//!
 518//!  @brief  initiate a connection on a socket 
 519//!          Function connects the socket referred to by the socket descriptor 
 520//!          sd, to the address specified by addr. The addrlen argument 
 521//!          specifies the size of addr. The format of the address in addr is 
 522//!          determined by the address space of the socket. If it is of type 
 523//!          SOCK_DGRAM, this call specifies the peer with which the socket is 
 524//!          to be associated; this address is that to which datagrams are to be
 525//!          sent, and the only address from which datagrams are to be received.  
 526//!          If the socket is of type SOCK_STREAM, this call attempts to make a 
 527//!          connection to another socket. The other socket is specified  by 
 528//!          address, which is an address in the communications space of the
 529//!          socket. Note that the function implements only blocking behavior 
 530//!          thus the caller will be waiting either for the connection 
 531//!          establishment or for the connection establishment failure.
 532//!
 533//!  @sa socket
 534//
 535//*****************************************************************************
 536
 537long
 538connect(long sd, const sockaddr *addr, long addrlen)
 539{
 540	long int ret;
 541	unsigned char *ptr, *args;
 542	
 543	ret = EFAIL;
 544	ptr = tSLInformation.pucTxCommandBuffer;
 545	args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
 546	addrlen = 8;
 547	
 548	// Fill in temporary command buffer
 549	args = UINT32_TO_STREAM(args, sd);
 550	args = UINT32_TO_STREAM(args, 0x00000008);
 551	args = UINT32_TO_STREAM(args, addrlen);
 552	ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);
 553	
 554	// Initiate a HCI command
 555	hci_command_send(HCI_CMND_CONNECT,
 556									 ptr, SOCKET_CONNECT_PARAMS_LEN);
 557	
 558	// Since we are in blocking state - wait for event complete
 559	SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
 560	
 561	errno = ret;
 562	
 563	return((long)ret);
 564}
 565
 566
 567//*****************************************************************************
 568//
 569//! select
 570//!
 571//!  @param[in]   nfds       the highest-numbered file descriptor in any of the
 572//!                           three sets, plus 1.     
 573//!  @param[out]   writesds   socket descriptors list for write monitoring
 574//!  @param[out]   readsds    socket descriptors list for read monitoring  
 575//!  @param[out]   exceptsds  socket descriptors list for exception monitoring
 576//!  @param[in]   timeout     is an upper bound on the amount of time elapsed
 577//!                           before select() returns. Null means infinity 
 578//!                           timeout. The minimum timeout is 5 milliseconds,
 579//!                          less than 5 milliseconds will be set
 580//!                           automatically to 5 milliseconds.
 581//!  @return  	On success, select() returns the number of file descriptors
 582//!             contained in the three returned descriptor sets (that is, the
 583//!             total number of bits that are set in readfds, writefds,
 584//!             exceptfds) which may be zero if the timeout expires before
 585//!             anything interesting  happens.
 586//!             On error, -1 is returned.
 587//!                   *readsds - return the sockets on which Read request will
 588//!                              return without delay with valid data.
 589//!                   *writesds - return the sockets on which Write request 
 590//!                                 will return without delay.
 591//!                   *exceptsds - return the sockets which closed recently.
 592//!
 593//!  @brief  Monitor socket activity  
 594//!          Select allow a program to monitor multiple file descriptors,
 595//!          waiting until one or more of the file descriptors become 
 596//!         "ready" for some class of I/O operation 
 597//!
 598//!  @Note   If the timeout value set to less than 5ms it will automatically set
 599//!          to 5ms to prevent overload of the system
 600//!
 601//!  @sa socket
 602//
 603//*****************************************************************************
 604
 605int
 606select(long nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 
 607       struct timeval *timeout)
 608{
 609	unsigned char *ptr, *args;
 610	tBsdSelectRecvParams tParams;
 611	unsigned long is_blocking;
 612	
 613	if( timeout == NULL)
 614	{
 615		is_blocking = 1; /* blocking , infinity timeout */
 616	}
 617	else
 618	{
 619		is_blocking = 0; /* no blocking, timeout */
 620	}
 621	
 622	// Fill in HCI packet structure
 623	ptr = tSLInformation.pucTxCommandBuffer;
 624	args = (ptr + HEADERS_SIZE_CMD);
 625	
 626	// Fill in temporary command buffer
 627	args = UINT32_TO_STREAM(args, nfds);
 628	args = UINT32_TO_STREAM(args, 0x00000014);
 629	args = UINT32_TO_STREAM(args, 0x00000014);
 630	args = UINT32_TO_STREAM(args, 0x00000014);
 631	args = UINT32_TO_STREAM(args, 0x00000014);
 632	args = UINT32_TO_STREAM(args, is_blocking);
 633	args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0));
 634	args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0));
 635	args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0));
 636	
 637	if (timeout)
 638	{
 639		if ( 0 == timeout->tv_sec && timeout->tv_usec < 
 640				SELECT_TIMEOUT_MIN_MICRO_SECONDS)
 641		{
 642			timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
 643		}
 644		args = UINT32_TO_STREAM(args, timeout->tv_sec);
 645		args = UINT32_TO_STREAM(args, timeout->tv_usec);
 646	}
 647	
 648	// Initiate a HCI command
 649	hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);
 650	
 651	// Since we are in blocking state - wait for event complete
 652	SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);
 653	
 654	// Update actually read FD
 655	if (tParams.iStatus >= 0)
 656	{
 657		if (readsds)
 658		{
 659			memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
 660		}
 661		
 662		if (writesds)
 663		{
 664			memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 
 665		}
 666		
 667		if (exceptsds)
 668		{
 669			memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 
 670		}
 671		
 672		return(tParams.iStatus);
 673		
 674	}
 675	else
 676	{
 677		errno = tParams.iStatus;
 678		return(-1);
 679	}
 680}
 681
 682//*****************************************************************************
 683//
 684//! setsockopt
 685//!
 686//!  @param[in]   sd          socket handle
 687//!  @param[in]   level       defines the protocol level for this option
 688//!  @param[in]   optname     defines the option name to Interrogate
 689//!  @param[in]   optval      specifies a value for the option
 690//!  @param[in]   optlen      specifies the length of the option value
 691//!  @return  	On success, zero is returned. On error, -1 is returned
 692//!
 693//!  @brief  set socket options
 694//!          This function manipulate the options associated with a socket.
 695//!          Options may exist at multiple protocol levels; they are always
 696//!          present at the uppermost socket level.
 697//!          When manipulating socket options the level at which the option 
 698//!          resides and the name of the option must be specified.  
 699//!          To manipulate options at the socket level, level is specified as 
 700//!          SOL_SOCKET. To manipulate options at any other level the protocol 
 701//!          number of the appropriate protocol controlling the option is 
 702//!          supplied. For example, to indicate that an option is to be 
 703//!          interpreted by the TCP protocol, level should be set to the 
 704//!          protocol number of TCP; 
 705//!          The parameters optval and optlen are used to access optval - 
 706//!          use for setsockopt(). For getsockopt() they identify a buffer
 707//!          in which the value for the requested option(s) are to 
 708//!          be returned. For getsockopt(), optlen is a value-result 
 709//!          parameter, initially containing the size of the buffer 
 710//!          pointed to by option_value, and modified on return to 
 711//!          indicate the actual size of the value returned. If no option 
 712//!          value is to be supplied or returned, option_value may be NULL.
 713//!
 714//!  @Note   On this version the following two socket options are enabled:
 715//!    			 The only protocol level supported in this version
 716//!          is SOL_SOCKET (level).
 717//!		       1. SOCKOPT_RECV_TIMEOUT (optname)
 718//!			      SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
 719//!           in milliseconds.
 720//!		        In that case optval should be pointer to unsigned long.
 721//!		       2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
 722//!           or off.
 723//!		        In that case optval should be SOCK_ON or SOCK_OFF (optval).
 724//!
 725//!  @sa getsockopt
 726//
 727//*****************************************************************************
 728
 729#ifndef CC3000_TINY_DRIVER
 730int
 731setsockopt(long sd, long level, long optname, const void *optval,
 732					 socklen_t optlen)
 733{
 734	int ret;
 735	unsigned char *ptr, *args;
 736	
 737	ptr = tSLInformation.pucTxCommandBuffer;
 738	args = (ptr + HEADERS_SIZE_CMD);
 739	
 740	// Fill in temporary command buffer
 741	args = UINT32_TO_STREAM(args, sd);
 742	args = UINT32_TO_STREAM(args, level);
 743	args = UINT32_TO_STREAM(args, optname);
 744	args = UINT32_TO_STREAM(args, 0x00000008);
 745	args = UINT32_TO_STREAM(args, optlen);
 746	ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen);
 747	
 748	// Initiate a HCI command
 749	hci_command_send(HCI_CMND_SETSOCKOPT,
 750									 ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN  + optlen);
 751	
 752	// Since we are in blocking state - wait for event complete
 753	SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
 754	
 755	if (ret >= 0)
 756	{
 757		return (0);
 758	}
 759	else
 760	{
 761		errno = ret;
 762		return (-1);
 763	}
 764}
 765#endif
 766
 767//*****************************************************************************
 768//
 769//! getsockopt
 770//!
 771//!  @param[in]   sd          socket handle
 772//!  @param[in]   level       defines the protocol level for this option
 773//!  @param[in]   optname     defines the option name to Interrogate
 774//!  @param[out]   optval      specifies a value for the option
 775//!  @param[out]   optlen      specifies the length of the option value
 776//!  @return  	On success, zero is returned. On error, -1 is returned
 777//!
 778//!  @brief  set socket options
 779//!          This function manipulate the options associated with a socket.
 780//!          Options may exist at multiple protocol levels; they are always
 781//!          present at the uppermost socket level.
 782//!          When manipulating socket options the level at which the option 
 783//!          resides and the name of the option must be specified.  
 784//!          To manipulate options at the socket level, level is specified as 
 785//!          SOL_SOCKET. To manipulate options at any other level the protocol 
 786//!          number of the appropriate protocol controlling the option is 
 787//!          supplied. For example, to indicate that an option is to be 
 788//!          interpreted by the TCP protocol, level should be set to the 
 789//!          protocol number of TCP; 
 790//!          The parameters optval and optlen are used to access optval - 
 791//!          use for setsockopt(). For getsockopt() they identify a buffer
 792//!          in which the value for the requested option(s) are to 
 793//!          be returned. For getsockopt(), optlen is a value-result 
 794//!          parameter, initially containing the size of the buffer 
 795//!          pointed to by option_value, and modified on return to 
 796//!          indicate the actual size of the value returned. If no option 
 797//!          value is to be supplied or returned, option_value may be NULL.
 798//!
 799//!  @Note   On this version the following two socket options are enabled:
 800//!    			 The only protocol level supported in this version
 801//!          is SOL_SOCKET (level).
 802//!		       1. SOCKOPT_RECV_TIMEOUT (optname)
 803//!			      SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
 804//!           in milliseconds.
 805//!		        In that case optval should be pointer to unsigned long.
 806//!		       2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
 807//!           or off.
 808//!		        In that case optval should be SOCK_ON or SOCK_OFF (optval).
 809//!
 810//!  @sa setsockopt
 811//
 812//*****************************************************************************
 813
 814int
 815getsockopt (long sd, long level, long optname, void *optval, socklen_t *optlen)
 816{
 817	unsigned char *ptr, *args;
 818	tBsdGetSockOptReturnParams  tRetParams;
 819	
 820	ptr = tSLInformation.pucTxCommandBuffer;
 821	args = (ptr + HEADERS_SIZE_CMD);
 822	
 823	// Fill in temporary command buffer
 824	args = UINT32_TO_STREAM(args, sd);
 825	args = UINT32_TO_STREAM(args, level);
 826	args = UINT32_TO_STREAM(args, optname);
 827	
 828	// Initiate a HCI command
 829	hci_command_send(HCI_CMND_GETSOCKOPT,
 830									 ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
 831	
 832	// Since we are in blocking state - wait for event complete
 833	SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
 834	
 835	if (((signed char)tRetParams.iStatus) >= 0)
 836	{
 837		*optlen = 4;
 838		memcpy(optval, tRetParams.ucOptValue, 4);
 839		return (0);
 840	}
 841	else
 842	{
 843		errno = tRetParams.iStatus;
 844		return (-1);
 845	}
 846}
 847
 848//*****************************************************************************
 849//
 850//!  simple_link_recv
 851//!
 852//!  @param sd       socket handle
 853//!  @param buf      read buffer
 854//!  @param len      buffer length
 855//!  @param flags    indicates blocking or non-blocking operation
 856//!  @param from     pointer to an address structure indicating source address
 857//!  @param fromlen  source address structure size
 858//!
 859//!  @return         Return the number of bytes received, or -1 if an error
 860//!                  occurred
 861//!
 862//!  @brief          Read data from socket
 863//!                  Return the length of the message on successful completion.
 864//!                  If a message is too long to fit in the supplied buffer,
 865//!                  excess bytes may be discarded depending on the type of
 866//!                  socket the message is received from
 867//
 868//*****************************************************************************
 869int
 870simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from,
 871                socklen_t *fromlen, long opcode)
 872{
 873	unsigned char *ptr, *args;
 874	tBsdReadReturnParams tSocketReadEvent;
 875	
 876	ptr = tSLInformation.pucTxCommandBuffer;
 877	args = (ptr + HEADERS_SIZE_CMD);
 878	
 879	// Fill in HCI packet structure
 880	args = UINT32_TO_STREAM(args, sd);
 881	args = UINT32_TO_STREAM(args, len);
 882	args = UINT32_TO_STREAM(args, flags);
 883
 884	// Generate the read command, and wait for the 
 885	hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);
 886	
 887	// Since we are in blocking state - wait for event complete
 888	SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
 889
 890	DEBUGPRINT_F("\n\r\tRecv'd data... Socket #");
 891	DEBUGPRINT_DEC(tSocketReadEvent.iSocketDescriptor);
 892	DEBUGPRINT_F(" Bytes: 0x");
 893	DEBUGPRINT_HEX(tSocketReadEvent.iNumberOfBytes);
 894	DEBUGPRINT_F(" Flags: 0x");
 895	DEBUGPRINT_HEX(tSocketReadEvent.uiFlags);
 896	DEBUGPRINT_F("\n\r");
 897
 898	// In case the number of bytes is more then zero - read data
 899	if (tSocketReadEvent.iNumberOfBytes > 0)
 900	{
 901		// Wait for the data in a synchronous way. Here we assume that the bug is 
 902		// big enough to store also parameters of receive from too....
 903	  SimpleLinkWaitData((unsigned char *)buf, (unsigned char *)from, (unsigned char *)fromlen);
 904	}
 905	
 906	errno = tSocketReadEvent.iNumberOfBytes;
 907
 908#if (DEBUG_MODE == 1)
 909	for (uint8_t i=0; i<errno; i++) {
 910	  uart_putchar(((unsigned char *)buf)[i]);
 911	}
 912#endif
 913	
 914	return(tSocketReadEvent.iNumberOfBytes);
 915}
 916
 917//*****************************************************************************
 918//
 919//!  recv
 920//!
 921//!  @param[in]  sd     socket handle
 922//!  @param[out] buf    Points to the buffer where the message should be stored
 923//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
 924//!                     by the buffer argument.
 925//!  @param[in] flags   Specifies the type of message reception. 
 926//!                     On this version, this parameter is not supported.
 927//!
 928//!  @return         Return the number of bytes received, or -1 if an error
 929//!                  occurred
 930//!
 931//!  @brief          function receives a message from a connection-mode socket
 932//!
 933//!  @sa recvfrom
 934//!
 935//!  @Note On this version, only blocking mode is supported.
 936//
 937//*****************************************************************************
 938
 939int
 940recv(long sd, void *buf, long len, long flags)
 941{
 942	return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
 943}
 944
 945//*****************************************************************************
 946//
 947//!  recvfrom
 948//!
 949//!  @param[in]  sd     socket handle
 950//!  @param[out] buf    Points to the buffer where the message should be stored
 951//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
 952//!                     by the buffer argument.
 953//!  @param[in] flags   Specifies the type of message reception. 
 954//!                     On this version, this parameter is not supported.
 955//!  @param[in] from   pointer to an address structure indicating the source
 956//!                    address: sockaddr. On this version only AF_INET is
 957//!                    supported.
 958//!  @param[in] fromlen   source address tructure size
 959//!
 960//!  @return         Return the number of bytes received, or -1 if an error
 961//!                  occurred
 962//!
 963//!  @brief         read data from socket
 964//!                 function receives a message from a connection-mode or
 965//!                 connectionless-mode socket. Note that raw sockets are not
 966//!                 supported.
 967//!
 968//!  @sa recv
 969//!
 970//!  @Note On this version, only blocking mode is supported.
 971//
 972//*****************************************************************************
 973int
 974recvfrom(long sd, void *buf, long len, long flags, sockaddr *from,
 975         socklen_t *fromlen)
 976{
 977	return(simple_link_recv(sd, buf, len, flags, from, fromlen,
 978													HCI_CMND_RECVFROM));
 979}
 980
 981//*****************************************************************************
 982//
 983//!  simple_link_send
 984//!
 985//!  @param sd       socket handle
 986//!  @param buf      write buffer
 987//!  @param len      buffer length
 988//!  @param flags    On this version, this parameter is not supported
 989//!  @param to       pointer to an address structure indicating destination
 990//!                  address
 991//!  @param tolen    destination address structure size
 992//!
 993//!  @return         Return the number of bytes transmitted, or -1 if an error
 994//!                  occurred, or -2 in case there are no free buffers available
 995//!                 (only when SEND_NON_BLOCKING is enabled)
 996//!
 997//!  @brief          This function is used to transmit a message to another
 998//!                  socket
 999//
1000//*****************************************************************************
1001int
1002simple_link_send(long sd, const void *buf, long len, long flags,
1003              const sockaddr *to, long tolen, long opcode)
1004{    
1005	unsigned char uArgSize,  addrlen;
1006	unsigned char *ptr, *pDataPtr, *args;
1007	unsigned long addr_offset;
1008	int res;
1009        tBsdReadReturnParams tSocketSendEvent;
1010	
1011	// Check the bsd_arguments
1012	if (0 != (res = HostFlowControlConsumeBuff(sd)))
1013	{
1014		return res;
1015	}
1016	
1017	//Update the number of sent packets
1018	tSLInformation.NumberOfSentPackets++;
1019	
1020	// Allocate a buffer and construct a packet and send it over spi
1021	ptr = tSLInformation.pucTxCommandBuffer;
1022	args = (ptr + HEADERS_SIZE_DATA);
1023	
1024	// Update the offset of data and parameters according to the command
1025	switch(opcode)
1026	{ 
1027	case HCI_CMND_SENDTO:
1028		{
1029			addr_offset = len + sizeof(len) + sizeof(len);
1030			addrlen = 8;
1031			uArgSize = SOCKET_SENDTO_PARAMS_LEN;
1032			pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
1033			break;
1034		}
1035		
1036	case HCI_CMND_SEND:
1037		{
1038			tolen = 0;
1039			to = NULL;
1040			uArgSize = HCI_CMND_SEND_ARG_LENGTH;
1041			pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
1042			break;
1043		}
1044		
1045	default:
1046		{
1047			break;
1048		}
1049	}
1050	
1051	// Fill in temporary command buffer
1052	args = UINT32_TO_STREAM(args, sd);
1053	args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
1054	args = UINT32_TO_STREAM(args, len);
1055	args = UINT32_TO_STREAM(args, flags);
1056	
1057	if (opcode == HCI_CMND_SENDTO)
1058	{
1059		args = UINT32_TO_STREAM(args, addr_offset);
1060		args = UINT32_TO_STREAM(args, addrlen);
1061	}
1062	
1063	// Copy the data received from user into the TX Buffer
1064	ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)buf), len);
1065	
1066	// In case we are using SendTo, copy the to parameters
1067	if (opcode == HCI_CMND_SENDTO)
1068	{	
1069		ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)to), tolen);
1070	}
1071	
1072	// Initiate a HCI command
1073	hci_data_send(opcode, ptr, uArgSize, len,(unsigned char*)to, tolen);
1074        
1075         if (opcode == HCI_CMND_SENDTO)
1076            SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
1077         else
1078            SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);
1079	
1080	return	(len);
1081}
1082
1083
1084//*****************************************************************************
1085//
1086//!  send
1087//!
1088//!  @param sd       socket handle
1089//!  @param buf      Points to a buffer containing the message to be sent
1090//!  @param len      message size in bytes
1091//!  @param flags    On this version, this parameter is not supported
1092//!
1093//!  @return         Return the number of bytes transmitted, or -1 if an
1094//!                  error occurred
1095//!
1096//!  @brief          Write data to TCP socket
1097//!                  This function is used to transmit a message to another 
1098//!                  socket.
1099//!
1100//!  @Note           On this version, only blocking mode is supported.
1101//!
1102//!  @sa             sendto
1103//
1104//*****************************************************************************
1105
1106int
1107send(long sd, const void *buf, long len, long flags)
1108{
1109	return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
1110}
1111
1112//*****************************************************************************
1113//
1114//!  sendto
1115//!
1116//!  @param sd       socket handle
1117//!  @param buf      Points to a buffer containing the message to be sent
1118//!  @param len      message size in bytes
1119//!  @param flags    On this version, this parameter is not supported
1120//!  @param to       pointer to an address structure indicating the destination
1121//!                  address: sockaddr. On this version only AF_INET is
1122//!                  supported.
1123//!  @param tolen    destination address structure size
1124//!
1125//!  @return         Return the number of bytes transmitted, or -1 if an
1126//!                  error occurred
1127//!
1128//!  @brief          Write data to TCP socket
1129//!                  This function is used to transmit a message to another 
1130//!                  socket.
1131//!
1132//!  @Note           On this version, only blocking mode is supported.
1133//!
1134//!  @sa             send
1135//
1136//*****************************************************************************
1137
1138int
1139sendto(long sd, const void *buf, long len, long flags, const sockaddr *to,
1140       socklen_t tolen)
1141{
1142	return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
1143}
1144
1145//*****************************************************************************
1146//
1147//!  mdnsAdvertiser
1148//!
1149//!  @param[in] mdnsEnabled         flag to enable/disable the mDNS feature
1150//!  @param[in] deviceServiceName   Service name as part of the published
1151//!                                 canonical domain name
1152//!  @param[in] deviceServiceNameLength   Length of the service name
1153//!  
1154//!
1155//!  @return   On success, zero is returned, return SOC_ERROR if socket was not 
1156//!            opened successfully, or if an error occurred.
1157//!
1158//!  @brief    Set CC3000 in mDNS advertiser mode in order to advertise itself.
1159//
1160//*****************************************************************************
1161
1162int
1163mdnsAdvertiser(unsigned short mdnsEnabled, char * deviceServiceName, unsigned short deviceServiceNameLength)
1164{
1165	int ret;
1166 	unsigned char *pTxBuffer, *pArgs;
1167	
1168	if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
1169	{
1170		return EFAIL;
1171	}
1172	
1173	pTxBuffer = tSLInformation.pucTxCommandBuffer;
1174	pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
1175	
1176	// Fill in HCI packet structure
1177	pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
1178	pArgs = UINT32_TO_STREAM(pArgs, 8);
1179	pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
1180	ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
1181	
1182	// Initiate a HCI command
1183	hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
1184	
1185	// Since we are in blocking state - wait for event complete
1186	SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
1187	
1188	return ret;
1189	
1190}