/********************************************************************************
|
* Copyright: (C) 2020 LingYun IoT System Studio
|
* All rights reserved.
|
*
|
* Filename: socket.h
|
* Description: This head file is for socket API
|
*
|
* Version: 1.0.0(2020年04月16日)
|
* Author: Guo Wenxue <guowenxue@gmail.com>
|
* ChangeLog: 1, Release initial version on "2020年04月16日 13时45分33秒"
|
*
|
********************************************************************************/
|
#ifndef _SOCKET_H_
|
#define _SOCKET_H_
|
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdint.h>
|
#include <netdb.h>
|
#include <fcntl.h>
|
#include <unistd.h>
|
#include <sys/un.h>
|
#include <poll.h>
|
#include <errno.h>
|
|
#include <sys/types.h>
|
#include <sys/socket.h>
|
#include <linux/sockios.h>
|
#include <sys/ioctl.h>
|
#include <sys/socket.h>
|
#include <netinet/in.h>
|
#include <netinet/tcp.h>
|
#include <arpa/inet.h>
|
|
#include <sys/epoll.h>
|
#include <sys/resource.h>
|
|
#include "list.h"
|
|
#define HOSTNAME_LEN 128
|
|
enum
|
{
|
SOCK_TYPE_LISTEN, /* listen socket */
|
SOCK_TYPE_ACCEPT, /* accept socket */
|
SOCK_TYPE_CONNECT, /* connect socket */
|
};
|
|
enum
|
{
|
SOCK_STAT_UNINIT = 0, /* socket not initial */
|
SOCK_STAT_INIT = 1, /* socket initialed */
|
|
SOCK_STAT_CONNECTING = 2, /* socket connecting in non-block mode */
|
|
SOCK_STAT_CONNECTED = 3, /* socket connected in client mdoe */
|
SOCK_STAT_LISTENED = 3, /* socket listened in server mode */
|
SOCK_STAT_ACCEPTED = 3, /* socket already accepted */
|
};
|
|
typedef struct socket_s
|
{
|
int fd; /* socket fd */
|
uint8_t type; /* socket type: listen, accept or accept */
|
uint8_t status; /* socket status: SOCK_STAT_INIT,SOCK_STAT_CONNECTED... */
|
|
/* socket server/client IP address and port */
|
char raddr[HOSTNAME_LEN]; /* remote IP address or domain name */
|
char laddr[HOSTNAME_LEN]; /* local IP address */
|
uint16_t lport; /* local listen port */
|
uint16_t rport; /* remote connected port */
|
|
/* socket heartbeat settings */
|
int keepintvl; /* keepalive detect interval */
|
int keepcnt; /* keepalive count */
|
|
struct sockaddr saddr; /* sockaddr for connect */
|
|
struct list_head list; /* socket server manage client link list */
|
} socket_t;
|
|
|
/*+-------------------------------------------------------------------+
|
*| client/server socket API functions |
|
*+-------------------------------------------------------------------+*/
|
|
/* description: initialise socket context and create socket fd if sepecified
|
* input args: $sock: socket context
|
* $type: SOCK_TYPE_LISTEN, SOCK_TYPE_ACCEPT or SOCK_TYPE_CONNEC
|
* $create: call socket() create or not
|
* return value: <0: failure 0: successfully
|
*/
|
enum
|
{
|
SOCK_NOT_CREATE,
|
SOCK_CREATE,
|
};
|
int socket_init(socket_t *sock, uint8_t type, int create);
|
|
|
/* description: close socket and set socket status as SOCK_STAT_INIT
|
* input args: $sock: socket context
|
* return value: <0: failure 0: successfully
|
*/
|
int socket_close(socket_t *sock);
|
|
|
/* description: close socket
|
* input args: $sock: socket context
|
* $lport: specify use local port $lport to connect remote server
|
* $host: IP address and port, format as "host:port", such as "127.0.0.1:8000"
|
* $block: block mode(1) or none-block(0)
|
*return value: <0: error 0: connecing in non-block mode 1:connected
|
*/
|
enum
|
{
|
MODE_NONBLOCK,
|
MODE_BLOCK,
|
};
|
int socket_connect(socket_t *sock, int lport, char *host, int block);
|
|
|
/* description: create socket and listen on port $port
|
* input args: $sock: socket context
|
* $ip: listen IP address, NULL for any address
|
* $port: listen port
|
* return value: <0: failure 0: successfully
|
*/
|
int socket_listen(socket_t *sock, char *ipaddr, int port);
|
|
|
/* description: accept a new client socket
|
* input args: $sock: socket context
|
* $listenfd: listen socket fd
|
* return value: <0: failure 0: successfully
|
*/
|
int socket_accept(socket_t *sock, int listenfd);
|
|
/* description: send data to the socket, make sure all data send over.
|
* input args: $sock: socket context
|
* $data: send data
|
* $bytes: data size
|
* return value: <0: failure 0: successfully
|
*/
|
int socket_send(socket_t *sock, char *data, int bytes);
|
|
|
/* description: receive data from the socket in some time
|
* input args: $sock: socket context
|
* $data: send data
|
* $bytes: data size
|
* $timeout: receive data time, <=0 will don't timeout
|
* return value: <0: error >=0: receive data bytes;
|
*/
|
int socket_recv(socket_t *sock, char *buf, int size, int timeout);
|
|
|
/* description: create epoll for socket server and add listenfd into it
|
* input args: $max_evts: max events for epoll_create()
|
* $listenfd: listen socket fd
|
* return value: <0: failure >=0: epollfd
|
*/
|
int epoll_init(int max_evts, int listenfd);
|
|
/* description: add new fd into epoll to monitor
|
* input args: $epollfd: epoll fd
|
* $fd: socket fd need added into epoll
|
* return value: <0: failure 0: successfully
|
*/
|
inline int epoll_add(int epollfd, int fd);
|
|
static inline int epoll_del(int epollfd, int fd)
|
{
|
return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
|
}
|
|
/*+-------------------------------------------------------------------+
|
*| socket utils function |
|
*+-------------------------------------------------------------------+*/
|
|
/* description: parser hostname and port from $host and set it into $sock
|
* input args: $sock: socket context
|
* $host: connect hostname, format as "hostname:port"
|
*/
|
int parser_host_port(socket_t *sock, char *host);
|
|
|
/* description: set socket listen port as reusable, fix port already used bug */
|
int socket_set_reuseaddr(int sockfd);
|
|
/* set socket as non-block mode, common socket default work as block mode */
|
int socket_set_nonblock(int sockfd);
|
|
/* set socket receive and send buffer size in linux kernel space */
|
int socket_set_buffer(int sockfd, int rsize, int ssize);
|
|
/* set heartbeat keepalive */
|
int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt);
|
|
/* Set open file description count to max */
|
void set_socket_rlimit(void);
|
|
#endif /* ----- #ifndef _SOCKET_H_ ----- */
|