PageRenderTime 64ms CodeModel.GetById 18ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 1ms

/src/Arduino/libraries/CC3000/utility/socket.cpp

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