/* Copyright 2017-present Renesas Electronics Corporation and other contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef POSIX4MBED_AUX_INCL
#define POSIX4MBED_AUX_INCL

#include <stddef.h>
#include <stdint.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/utime.h>
#include <sys/syscall.h>
#include <sys/syslimits.h>
#include <sys/types.h>
//#include <sys/stat.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef uint8_t		u8_t;
typedef int8_t		s8_t;
typedef uint16_t	u16_t;
typedef int16_t		s16_t;
typedef uint32_t	u32_t;
typedef int32_t		s32_t;
typedef uint64_t	u64_t;
typedef int64_t		s64_t;

typedef struct stat	stat_t;

#define P4(name) p4_ ## name

#define p4_timespec		timespec
#define p4_timeval		timeval
#define p4_utimbuf		utimbuf

#define NAME_MAX 255	// Maximum size of a name in a file path

enum { CLOCK_MONOTONIC = 1 };		// clockid_t 
enum { PTHREAD_ONCE_INIT = 1234 };	// pthread_once_t

enum { SOCK_STREAM, SOCK_DGRAM, SOCK_RAW };	// Socket protocol types (TCP/UDP/RAW)
enum {										// Option flags per-socket
	SOL_SOCKET,
	SO_REUSEADDR, SO_KEEPALIVE, SO_BROADCAST,
	SO_TYPE, SO_ERROR,
};

enum {
	IPPROTO_IP		= 0,
	IPPROTO_TCP		= 6,
	IPPROTO_UDP		= 17,
	IPPROTO_IPV6	= 41,
	IPPROTO_RAW		= 255,
};
enum {
	// Options for level IPPROTO_IP
	IP_TOS,
	IP_TTL,
	// Options for level IPPROTO_TCP
	TCP_NODELAY,
	TCP_KEEPALIVE,
	TCP_KEEPIDLE,
	TCP_KEEPINTVL,
	TCP_KEEPCNT,
	// Options and types related to multicast membership
	IP_ADD_MEMBERSHIP,
	IP_DROP_MEMBERSHIP,
	// Options and types for UDP multicast traffic handling
	IP_MULTICAST_IF,
	IP_MULTICAST_LOOP,
	IP_MULTICAST_TTL,
	// Options and types related to multicast membership
	IPV6_ADD_MEMBERSHIP,
	IPV6_DROP_MEMBERSHIP,
	// Options and types for UDP multicast traffic handling
	IPV6_MULTICAST_HOPS,
	IPV6_MULTICAST_IF,
	IPV6_MULTICAST_LOOP,
	IPV6_UNICAST_HOPS,
};

enum { AF_UNSPEC, AF_INET, AF_INET6, AF_UNIX = AF_UNSPEC };

#define IPADDR_NONE			((u32_t)0xffffffffUL)	// 255.255.255.255
#define IPADDR_LOOPBACK		((u32_t)0x7f000001UL)	// 127.0.0.1
#define IPADDR_ANY			((u32_t)0x00000000UL)	// 0.0.0.0
#define IPADDR_BROADCAST	((u32_t)0xffffffffUL)	// 255.255.255.255

#define IP6ADDR_STRLEN_MAX	(46)
#define IP4ADDR_STRLEN_MAX	(16)
#define IPADDR_STRLEN_MAX	IP6ADDR_STRLEN_MAX

#define INET_ADDRSTRLEN		IP4ADDR_STRLEN_MAX
#define INET6_ADDRSTRLEN	IP6ADDR_STRLEN_MAX

#define INADDR_NONE			IPADDR_NONE			// 255.255.255.255
#define INADDR_LOOPBACK		IPADDR_LOOPBACK		// 127.0.0.1
#define INADDR_ANY			IPADDR_ANY			// 0.0.0.0
#define INADDR_BROADCAST	IPADDR_BROADCAST	// 255.255.255.255
extern const struct P4(in6_addr) in6addr_any;

enum {
	AI_PASSIVE		= 0x01,
	AI_V4MAPPED		= 0x08,
	AI_ADDRCONFIG	= 0x20,
};

enum {
	EAI_NONAME		= 200,
	EAI_SERVICE,
	EAI_FAIL,
	EAI_MEMORY,
	EAI_FAMILY,
};

enum { MSG_TRUNC };						// msghdr.msg_flags
enum { SCM_RIGHTS, SCM_CREDENTIALS };	// cmsghdr.cmsg_type
enum { SHUT_RD, SHUT_WR, SHUT_RDWR };	// shutdown().how

enum POLL_OPCODES { POLL_CTL_ADD=1, POLL_CTL_DEL, POLL_CTL_MOD };	// epoll_ctl().op

#if !defined(POLLIN)
enum POLL_EVENTS {
	POLLIN	= 0x0001,	// see <mbed-os/platform/mbed_poll.h>
	POLLOUT	= 0x0010,	// see <mbed-os/platform/mbed_poll.h>
	POLLERR	= 0x1000,	// see <mbed-os/platform/mbed_poll.h>
	POLLHUP	= 0x2000,	// see <mbed-os/platform/mbed_poll.h>
	POLLNVAL= 0x4000,	// see <mbed-os/platform/mbed_poll.h>

	POLLPRI	= 0x0100,
};
#endif

enum { FIONREAD, FIONBIO, FIOCLEX, FIONCLEX };	// ioctl().request
enum { RTLD_LAZY, RTLD_NOW };					// dlopen().flag


typedef clockid_t	P4(clockid_t);
typedef u32_t		P4(in_addr_t);
typedef u16_t		P4(in_port_t);
typedef mode_t		P4(mode_t);
typedef off_t		P4(off_t);
typedef int			P4(pthread_attr_t);
typedef void*		P4(pthread_cond_t);
typedef void*		P4(pthread_condattr_t);
typedef int			P4(pthread_key_t);
typedef void*		P4(pthread_mutex_t);
typedef int			P4(pthread_mutexattr_t);
typedef int			P4(pthread_once_t);
typedef int			P4(pthread_rwlock_t);
typedef int			P4(pthread_rwlockattr_t);
typedef void*		P4(pthread_t);
typedef u8_t		P4(sa_family_t);
typedef int			P4(sem_t);
typedef sigset_t	P4(sigset_t);
typedef size_t		P4(size_t);
typedef u32_t		P4(socklen_t);
typedef ssize_t		P4(ssize_t);
typedef stat_t		P4(stat_t);

struct P4(addrinfo);
struct P4(cmsghdr);
struct P4(dirent);
struct P4(in6_addr);
struct P4(in_addr);
struct P4(iovec);
struct P4(msghdr);
struct P4(poll_event);
struct P4(sockaddr);
struct P4(sockaddr_in);
struct P4(sockaddr_in6);
struct P4(sockaddr_storage);
struct P4(termios);
struct P4(timespec);
struct P4(timeval);
struct P4(utimbuf);


struct P4(addrinfo) {
	int						ai_flags;		// Input flags
	int						ai_family;		// Address family of socket
	int						ai_socktype;	// Socket type
	int						ai_protocol;	// Protocol of socket
	P4(socklen_t)			ai_addrlen;		// Length of socket address
	struct P4(sockaddr)*	ai_addr;		// Socket address of socket
	char*					ai_canonname;	// Canonical name of service location
	struct P4(addrinfo)*	ai_next;		// Pointer to next in list
};

struct P4(cmsghdr) {
	int cmsg_type;
	int cmsg_len;
	int cmsg_level;
};

struct P4(dirent) {
	char d_name[NAME_MAX+1];
	u8_t d_type;
};

struct P4(in6_addr) {
	u8_t s6_addr[16];
};

struct P4(in_addr) {
	P4(in_addr_t) s_addr;
};

struct P4(iovec) {
	void* iov_base;
	P4(size_t) iov_len;
};

struct P4(msghdr) {
	void*				msg_name;
	P4(socklen_t)		msg_namelen;
	struct P4(iovec)*	msg_iov;
	int					msg_iovlen;
	void*				msg_control;
	P4(socklen_t)		msg_controllen;
	int					msg_flags;
};

struct P4(poll_event) {
	u32_t events;	// Poll events
	union {
		void* ptr;
		int fd;
		u32_t u32;
		u64_t u64;
	} data;			// User data variable
};

struct P4(sockaddr) {
	u8_t				sa_len;
	P4(sa_family_t)		sa_family;
	char				sa_data[14];
};

struct P4(sockaddr_in) {
	u8_t				sin_len;
	P4(sa_family_t)		sin_family;
	P4(in_port_t)		sin_port;
	struct P4(in_addr)	sin_addr;
	char				sin_zero[8];
};

struct P4(sockaddr_in6) {
	u8_t				sin6_len;
	P4(sa_family_t)		sin6_family;
	P4(in_port_t)		sin6_port;
	u32_t				sin6_flowinfo;
	struct P4(in6_addr)	sin6_addr;
	u32_t				sin6_scope_id;
};

struct P4(sockaddr_storage) {
	u8_t				s2_len;
	P4(sa_family_t)		ss_family;
	char				s2_data1[2];
	u32_t				s2_data2[3];
	u32_t				s2_data3[3];
};

struct P4(termios) {};

typedef struct P4(ip_mreq) {
	struct P4(in_addr)	imr_multiaddr;
	struct P4(in_addr)	imr_interface;
} P4(ip_mreq);

typedef struct P4(ipv6_mreq) {
	struct P4(in6_addr)	ipv6mr_multiaddr;
	unsigned int		ipv6mr_interface;
} P4(ipv6_mreq);

#ifdef __cplusplus
}
#endif

#endif	// #ifndef POSIX4MBED_AUX_INCL
