/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*----------------------------------------------------------------------------*/
/*! @file c_net_socket.h
 * $RCSfile: $
 * $Revision: #1 $
 * $Date: 2015/05/29 $
 * $Author: brianpc.huang $
 *
 * @par Description:
 *      network socket APIs
 */
/*----------------------------------------------------------------------------*/
/*!
* @addtogroup  groupMW_INET
* @{
*/

#ifndef C_NET_SOCKET_H
#define C_NET_SOCKET_H

#include "u_net_socket.h"
#ifdef MT8520
#include "u_time.h"
#else
#ifndef LINUX_TURNKEY_SOLUTION
#include "time.h"
#else
#include <time.h>
#endif
#endif

#ifndef LINUX_TURNKEY_SOLUTION

/*-----------------------------------------------------------------------------
 * Name: socket
 *
 * Description: Create a new unnamed socket within a specified communication 
 *              domain
 *
 * Inputs:      AF_INET     : internet protocol version 4
 *              AF_INET6    : internet protocol version 6
 * Outputs:     NA
 * Returns:     -1 is returned if an error occurs; 
 *              otherwise the return value is a descriptor referencing the socket
 ----------------------------------------------------------------------------*/
int socket  (int domain, int type, int protocol);

/*-----------------------------------------------------------------------------
 * Name: connect
 *
 * Description: The connect function is used by a TCP client to establish 
 *              a connect with a TCP server.
 *
 * Inputs:      sockfd      :   socket descriptor
 *              servaddr    :   server address
 *              addrlen     :   sizeof servaddr
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int connect (int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

/*-----------------------------------------------------------------------------
 * Name: bind
 *
 * Description: The bind function assigns a local protocol address to a socket
 *
 * Inputs:      sockfd      :   socket descriptor
 *              myaddr      :   myaddr address
 *              addrlen     :   sizeof myaddr
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int bind    (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

/*-----------------------------------------------------------------------------
 * Name: listen
 *
 * Description: The listen function prepare a socket to accept incoming connections
 *
 * Inputs:      sockfd      :   socket descriptor
 *              backlog     :   maximum number of connections
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int listen(int sockfd, int backlog);

/*-----------------------------------------------------------------------------
 * Name: accept
 *
 * Description: The accept function is called by a TCP server to return 
 *              the next completed connection 
 *
 * Inputs:      sockfd      :   socket descriptor
 *              cliaddr     :   client address
 *              addrlen     :   size of address
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

/*-----------------------------------------------------------------------------
 * Name: recv
 *
 * Description: recv data from client (TCP)
 *
 * Inputs:      sockfd      :   socket descriptor
 *              buff        :   buffer to save received data
 *              nbytes      :   buffer size
 *              flags       :   
 *                              MSG_OOB, MSG_PEEK, MSG_DONTROUTE, MSG_DONTWAIT
 *                              MSG_WAITALL  
 * Outputs:     NA              
 * Returns:     the bytes of data has received
 *             -1 on error      
 ----------------------------------------------------------------------------*/
ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);

/*-----------------------------------------------------------------------------
 * Name: send
 *
 * Description: send data to client (TCP)
 * Inputs:      sockfd      :   socket descriptor
 *              buff        :   the data to be send
 *              nbytes      :   data size
 *              flags       :   
 *                              MSG_OOB, MSG_PEEK, MSG_DONTROUTE, MSG_DONTWAIT
 *                              MSG_WAITALL  
 *
 * Outputs:     NA
 * Returns:     the bytes of data has send
 *             -1 on error
 ----------------------------------------------------------------------------*/
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);

/*-----------------------------------------------------------------------------
 * Name: recvfrom
 *
 * Description: receive data to client (UDP)
 * Inputs:      sockfd      :   socket descriptor
 *              buff        :   the data to be send
 *              nbytes      :   data size
 *              flags       :   
 *                              MSG_OOB, MSG_PEEK, MSG_DONTROUTE, MSG_DONTWAIT
 *                              MSG_WAITALL  
 *              from        :   the address which data come from
 *              addrlen     :   the size of from   
 *
 * Outputs:     NA
 * Returns:     the bytes of data has send
 *             -1 on error
 ----------------------------------------------------------------------------*/
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);

/*-----------------------------------------------------------------------------
 * Name: sendto
 *
 * Description: send data to client (UDP)
 * Inputs:      sockfd      :   socket descriptor
 *              buff        :   the data to be send
 *              nbytes      :   data size
 *              flags       :   
 *                              MSG_OOB, MSG_PEEK, MSG_DONTROUTE, MSG_DONTWAIT
 *                              MSG_WAITALL  
 *              to          :   the address to send data out
 *              addrlen     :   the size of to 
 *
 * Outputs:     NA
 * Returns:     the bytes of data has send
 *             -1 on error
 ----------------------------------------------------------------------------*/
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen);

/*-----------------------------------------------------------------------------
 * Name: close
 *
 * Description: terminate connection and release socket
 *
 * Inputs:      sockfd      :   socket descriptor
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int close(int sockfd);

/*-----------------------------------------------------------------------------
 * Name: getsockname
 *
 * Description: get local protocol address
 *
 * Inputs:      sockfd      :   socket descriptor
 *              localaddr   :   localaddr address
 *              addrlen     :   size of localaddr
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);

/*-----------------------------------------------------------------------------
 * Name: getpeername
 *
 * Description: get peer protocol address
 *
 * Inputs:      sockfd      :   socket descriptor
 *              peername    :   peername address
 *              addrlen     :   size of peername
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int getpeername(int sockfd, struct sockaddr *peername, socklen_t *addrlen);

/*-----------------------------------------------------------------------------
 * Name: getsockopt
 *
 * Description: set socket option
 *
 * Inputs:      sockfd      :   socket descriptor
 *              level       :   option level 
 *              optname     :   option nanme
 *              optval      :   buffer to store return value    
 *              optlen      :   return value size
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

/*-----------------------------------------------------------------------------
 * Name: setsockopt
 *
 * Description: get socket option
 *
 * Inputs:      sockfd      :   socket descriptor
 *              level       :   option level 
 *              optname     :   option nanme
 *              optval      :   data to set    
 *              optlen      :   data size
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

/*-----------------------------------------------------------------------------
 * Name: select
 *
 * Description: get socket option
 *
 * Inputs:      maxfdp1      :   socket descriptor
 *              readset      :   option level 
 *              writeset     :   option nanme
 *              exceptset    :   data to set    
 *              timeout      :   data size
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
struct timeval
{
    long tv_sec;     /* seconds */
    long tv_usec;    /* and microseconds */
};

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);

/*-----------------------------------------------------------------------------
 * Name: shutdown
 *
 * Description: terminate connection in one or both direction
 *
 * Inputs:      sockfd       :   socket descriptor
 *              howto        :   shutdown method (SHUT_RD, SHUT_WR, SHUT_RDWR)
 * Outputs:     NA
 * Returns:     0 if OK
 *             -1 on error
 ----------------------------------------------------------------------------*/
int shutdown(int sockfd, int howto);

/**
 * gethostbyname
 * 
 * resolve host name to ip address
 * 
 * @param hostname, user specify name
 * 
 * @return struct hostent*
 *        nonnull pointer if OK
 *        NULL on error
 */
struct hostent *gethostbyname(const char *hostname);

/**
 * 
 * @param addr
 * @param len
 * @param family
 * 
 * @return struct hostent*
 */
struct hostent *gethostbyaddr(const char *addr, size_t len, int family);

/**
 * This function return the name of the current host
 * @param name, the space to save hostname
 * @param namlen, the space size
 * 
 * @return int
 * 0: ok
 * -1: error
 */
int gethostname(char *name, size_t namlen);

/* utility API 
 * inet_aton
 * inet_ntoa
*/
/**
 * inet_aton
 * 
 * convert address string to 32bits network order byte value
 * @param strptr, input
 * @param addrptr, result
 * 
 * @return int
 *  1: ok
 *  0: failed
 */
int inet_aton(const char *strptr, struct in_addr *addrptr);

/**
 * inet_ntoa
 * 
 * convert a 32bits network byte address into dot string format
 * user must release memory after this return is unused.
 * 
 * @param inaddr
 * 
 * @return char*
 *     NULL, faile
 *     others, ok
 */
char *inet_ntoa(struct in_addr inaddr);
in_addr_t inet_addr(const char *strptr);
int inet_pton(int family, const char *strptr, void *addrptr);
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

#endif
/**
 * c_net_socket_nonblocking
 * 
 * configure socket as nonblocking mode
 * 
 * @param sock, socket to config
 * 
 * @return int
 * 0: ok
 * -1: failed
 */
/*!
 * @brief configure socket as nonblocking mode
 * @param in sock - socket file-description to config
 * @return return the error code
 * @retval NET_OK - ok
 * @retval else   - failed
 */
int c_net_socket_nonblocking(int sock);

/**
 * c_net_socket_blocking
 * 
 * configure socket as blocking mode
 * 
 * @param sock, socket to config
 * 
 * @return int
 * 0: ok
 * -1: failed
 */
/*!
 * @brief configure socket as blocking mode
 * @param in sock - socket file-description to config
 * @return return the error code
 * @retval NET_OK - ok
 * @retval else   - failed
 */
int c_net_socket_blocking(int sock);

/**
 * c_net_get_socket_mode
 * 
 * query current socket mode
 * 
 * @param sock
 * 
 * @return int
 * 0: blocking
 * 1: nonblocking
 */
/*!
 * @brief query current socket mode
 * @param in sock - socket file-description to query
 * @return return the error code
 * @retval NET_OK - ok
 * @retval else   - failed
 */
int c_net_get_socket_mode(int sock);

/*!
 * @brief free network host database storage return by calling gethostbyname
 * @see gethostbyname
 * @param in ptr   - the host database pointer
 */
void c_net_free_hostent(struct hostent *ptr);


/* only FIONREAD */
/*!
 * @brief control a STREAMS device (socket file-description, FIONREAD only so far)
 * @param in i4_sockfd  - socket fd
 * @param in i4_cmd     - request command
 * @param in pv_data    - request data pointer
 * @return return the error code
 * @retval NET_OK    - OK
 * @retval others    - failed
 */
int c_net_ioctl(int i4_sockfd, int i4_cmd, void *pv_data);

extern int x_net_socket_nonblocking(int sock);
extern int x_net_socket_blocking(int sock);
extern int x_net_get_socket_mode(int sock);
extern void x_net_free_hostent(struct hostent *ptr);
extern int x_net_ioctl(int i4_sockfd, int i4_cmd, void *pv_data);

#endif

/*! @} */

