/*
 * UosSylph -- E-Mail client library
 * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd.
 *
 * Author:     shuiqucheng<shuiqucheng@uniontech.com>
 *
 * Maintainer: shuiqucheng<shuiqucheng@uniontech.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef __UOSSOCKET_H__
#define __UOSSOCKET_H__

#include "libsylph/socket.h"
typedef SockInfo UosSockInfo;

#if USE_SSL
#include "uosssl.h"
#endif

typedef ConnectionState UosConnectionState;
typedef SockFlags UosSockFlags;

#define UOSSOCK_SET_FLAGS(flags, set) SOCK_SET_FLAGS(flags, set)
#define UOSSOCK_UNSET_FLAGS(flags, set) SOCK_UNSET_FLAGS(flags, set)
#define UOSSOCK_IS_NONBLOCK(flags) SOCK_IS_NONBLOCK(flags)
#define UOSSOCK_IS_CHECK_IO(flags) SOCK_IS_CHECK_IO(flags)

typedef SockConnectFunc UosSockConnectFunc;
typedef SockFunc UosSockFunc;

gint uos_sock_init(void);
gint uos_sock_cleanup(void);

gint uos_sock_set_io_timeout(guint sec);

SockInfo *uos_sock_new(const gchar *hostname, gushort port);

gint uos_sock_set_nonblocking_mode(UosSockInfo *sock, gboolean nonblock);
gboolean uos_sock_is_nonblocking_mode(UosSockInfo *sock);

gboolean uos_sock_has_read_data(UosSockInfo *sock);

guint uos_sock_add_watch(UosSockInfo *sock, GIOCondition condition,
                     UosSockFunc func, gpointer data);
guint uos_sock_add_watch_poll(UosSockInfo *sock, GIOCondition condition,
                          UosSockFunc func, gpointer data);

struct hostent *uos_my_gethostbyname(const gchar *hostname, gchar **errorchar);

UosSockInfo *uos_sock_connect(const gchar *hostname, gushort port, gchar **errorchar);
#ifdef G_OS_UNIX
gint uos_sock_connect_async(const gchar *hostname, gushort port,
                        UosSockConnectFunc func, gpointer data);
gint uos_sock_connect_async_cancel(gint id);
#endif
#if USE_THREADS
gint uos_sock_connect_async_thread(const gchar *hostname, gushort port);
gint uos_sock_connect_async_thread_wait(gint id, UosSockInfo **sock);
#endif

gint uos_sock_info_connect(UosSockInfo *sock, gchar **errorchar);
#ifdef G_OS_UNIX
gint uos_sock_info_connect_async(UosSockInfo *sock,
                             UosSockConnectFunc func, gpointer data);
#endif
#if USE_THREADS
gint uos_sock_info_connect_async_thread(UosSockInfo *sock);
gint uos_sock_info_connect_async_thread_wait(gint id, UosSockInfo **sock);
#endif

/* Basic I/O functions */
gint uos_sock_printf(UosSockInfo *sock, const gchar *format, ...);
gint uos_sock_read(UosSockInfo *sock, gchar *buf, gint len, gchar **errorchar);
gint uos_sock_write(UosSockInfo *sock, const gchar *buf, gint len);
gint uos_sock_write_all(UosSockInfo *sock, const gchar *buf, gint len, char **errorchar);
gint uos_sock_gets(UosSockInfo *sock, gchar *buf, gint len);
gint uos_sock_getline(UosSockInfo *sock, gchar **line);
gint uos_sock_puts(UosSockInfo *sock, const gchar *buf);
gint uos_sock_peek(UosSockInfo *sock, gchar *buf, gint len);
gint uos_sock_close(UosSockInfo *sock);

/* Functions to directly work on FD.  They are needed for pipes */
gint uos_fd_connect_inet(gushort port);
gint uos_fd_open_inet(gushort port);
gint uos_fd_connect_unix(const gchar *path);
gint uos_fd_open_unix(const gchar *path);
gint uos_fd_accept(gint sock);

gint uos_fd_read(gint sock, gchar *buf, gint len, gboolean *accneedexit, gboolean canexitimmediately, gchar **errorchar);
gint uos_fd_write(gint sock, const gchar *buf, gint len, gboolean *accneedexit, gchar **errorchar);
gint uos_fd_write_all(gint sock, const gchar *buf, gint len, gboolean *accneedexit, gchar **errorchar);
gint uos_fd_gets(gint sock, gchar *buf, gint len, gboolean *accneedexit, gboolean canexitimediately);
gint uos_fd_gets_canexit(gint sock, gchar *buf, gint len, gboolean canexit, gboolean *accneedexit);
gint uos_fd_getline(gint sock, gchar **line, gboolean *accneedexit);
gint uos_fd_getline_canexit(gint sock, gchar **line, gboolean canexit, gboolean *accneedexit); // add by shui
gint uos_fd_close(gint sock);

/* Functions for SSL */
#if USE_SSL
gint uos_ssl_read(SSL *ssl, gchar *buf, gint len, gboolean *accneedexit, gchar **errorname, gboolean canexitimmediately);
gint uos_ssl_write(SSL *ssl, const gchar *buf, gint len, gchar **errorchar);
gint uos_ssl_write_all(SSL *ssl, const gchar *buf, gint len, gboolean *accneedexit, char **errorchar);
gint uos_ssl_gets(SSL *ssl, gchar *buf, gint len, gboolean *accneedexit, gboolean canexitimmediately);
gint uos_ssl_gets_canexit(SSL *ssl, gchar *buf, gint len, gboolean canexit, gboolean *accneedexit); //add by shui
gint uos_ssl_getline(SSL *ssl, gchar **line, gboolean *accneedexit);
gint uos_ssl_getline_canexit(SSL *ssl, gchar **line, gboolean canexit, gboolean *accneedexit); //add by shui
gint uos_ssl_peek(SSL *ssl, gchar *buf, gint len, gboolean *accneedexit, gboolean canexitimmediately);
#endif

#endif /* __UOSSOCKET_H__ */
