diff options
author | FreeArtMan <dos21h@gmail.com> | 2017-05-11 16:45:00 +0100 |
---|---|---|
committer | FreeArtMan <dos21h@gmail.com> | 2017-05-11 16:45:00 +0100 |
commit | 1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53 (patch) | |
tree | 878d3d9a46db60a156935c41307b83c39c0d42c8 | |
parent | 6a377350d63fc2dd470e9bd25008e8e827c011f2 (diff) | |
download | agni-1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53.tar.gz agni-1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53.zip |
Update socket connection functions. Now reconnection is possible
-rw-r--r-- | sock_conn.c | 247 | ||||
-rw-r--r-- | sock_conn.h | 41 |
2 files changed, 287 insertions, 1 deletions
diff --git a/sock_conn.c b/sock_conn.c index bc7dfff..57a3acd 100644 --- a/sock_conn.c +++ b/sock_conn.c @@ -281,7 +281,7 @@ int irc_connect( char *hostname, char *port ) if (0 != getaddrinfo(hostname, port, &serv, &res)) { PERM(); - perror("Couldnt get addr info"); + perror("CONNECT: Couldnt get addr info"); return -1; } fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); @@ -300,3 +300,248 @@ int irc_connect( char *hostname, char *port ) +int irc_open(char *hostname, char *port, irc_conn *conn) +{ + int fd, fret; + struct addrinfo serv, *res; + + struct timespec tv; + tv.tv_sec = 10; + tv.tv_nsec = 0; + + if (conn == NULL) + { + PERM(); + return -1; + } + + if (hostname == NULL) + { + PERM(); + conn->err = ERR_SC_PARAM; + return -1; + } + + if (port == NULL) + { + PERM(); + conn->err = ERR_SC_PARAM; + return -1; + } + + memset(conn, 0, sizeof(irc_conn)); + conn->hostname = alloc_new_str(hostname); + conn->port = alloc_new_str(port); + conn->timeout = 0; + + memset(&serv, 0, sizeof(struct addrinfo)); + serv.ai_family = AF_INET; + serv.ai_socktype = SOCK_STREAM; + + if (0 != getaddrinfo(conn->hostname, conn->port, &serv, &res)) + { + perror("OPEN: Couldnt get addr info"); + PNL(); + conn->liberr = errno; + conn->err = ERR_SC_CONN; + ERROR("%s:%s\n",conn->hostname, conn->port); + return -1; + } + + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (fd < 0) + { + conn->liberr = errno; + conn->err = ERR_SC_CONN; + perror("OPEN: Couldnt get socket"); + return -1; + } + + fret = connect(fd, res->ai_addr, res->ai_addrlen); + if (fret!=0) + { + conn->err = ERR_SC_CONN; + conn->liberr = errno; + perror("OPEN: Cant connect"); + PERM(); + return -1; + } + + //set non blocking + fcntl(fd, F_SETFL, O_NONBLOCK); + + conn->conn_fd = fd; + + conn->err = ERR_SC_NONE; + conn->liberr = 0; + + return 0; +} + +int irc_read_timeout(irc_conn *conn, int timeout) +{ + if (conn == NULL) + { + PERM(); + return -1; + } + + if (timeout<=0) + { + conn->timeout = 0; + return 0; + } + + //woop woop i dont belive you whant 2 hours + if (timeout>(60*60*2)) + { + PERM(); + return -1; + } + + /* + CHECK PREDIFINED MACROSES IF SUCH FUNCTIONALITY EXCISTS OR NOT + */ + #if _POSIX_C_SOURCE < 199309L + ERROR("Dont have clock_gettime functionality\n"); + #endif + + conn->timeout = timeout; + if (-1 == clock_gettime(CLOCK_REALTIME, &conn->last_read)) + { + conn->err = ERR_SC_LIBC; + conn->liberr = errno; + return -1; + } + + conn->err = ERR_SC_NONE; + conn->liberr = 0; + + + return 0; +} + +int irc_read(irc_conn *conn, char *buf, size_t sz) +{ + int fret; + int save_err; + + //PNL(); + fret = read(conn->conn_fd, buf, sz); + save_err = errno; + //PNL(); + if (fret<0) + { + //PNL(); + if (save_err == EAGAIN) + { + //PNL(); + uint64_t proc_sec; + struct timespec cur_clock; + + //PRINT("%d\n", conn->err); + //if last time was without error then lets update last error clock + if (conn->err == ERR_SC_NONE) + { + //PNL(); + clock_gettime(CLOCK_REALTIME, &conn->last_read); + } + + if (conn->timeout > 0) + { + PNL(); + //first read of clock is in irc_read_timeout_function + if (-1 == clock_gettime(CLOCK_REALTIME, &cur_clock)) + { + conn->err = ERR_SC_LIBC; + conn->liberr = errno; + ENL(); + return -1; + } else + { + //who cares about precision + //fix if needed more precision + proc_sec = cur_clock.tv_sec - conn->last_read.tv_sec; + if (proc_sec > conn->timeout) + { + conn->err = ERR_SC_TIMEOUT; + conn->liberr = errno; + return -1; + } + } + } + conn->err = ERR_SC_AGAIN; + conn->liberr = 0; + return -1; + } else + { + conn->err = ERR_SC_ANY; + conn->liberr = errno; + perror("READ: Cant read"); //dont loose errno value + return -1; + } + } + + conn->err = ERR_SC_NONE; + conn->liberr = 0; + + //return number of written bytes + return fret; +} + +int irc_reconnect(irc_conn *conn) +{ + int fret; + int fd; + char *hostname=NULL; + char *port=NULL; + int timeout=-1; + + irc_conn reconn; + + if (conn == NULL) + { + PERM(); + return -1; + } + + //close connection + close(conn->conn_fd); + fd = conn->conn_fd; //do we need that to restore connection? + + hostname = conn->hostname; + port = conn->port; + timeout = timeout; + + fret = irc_open(hostname, port, &reconn); + if (fret==-1) + { + PERM(); + return -1; + } + + if (-1 == irc_read_timeout(&reconn, timeout)) + { + PERM(); + } + + //BUG lets think about this case deeper + //free(hostname); + //free(port); + + return 0; +} + +int irc_close(irc_conn *conn) +{ + if (conn == NULL) + { + PERM(); + return -1; + } + + close(conn->conn_fd); + free(conn->hostname); + free(conn->port); +} + diff --git a/sock_conn.h b/sock_conn.h index 55ef8e0..8cf64be 100644 --- a/sock_conn.h +++ b/sock_conn.h @@ -3,9 +3,15 @@ #include <stdlib.h> #include <stdio.h> +#include <stdint.h> #include <unistd.h> #include <netdb.h> #include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> #include "util.h" @@ -38,7 +44,42 @@ int irc_buf_ready(irc_buf *ib); char *irc_buf_line(irc_buf *ib); int irc_buf_destroy(irc_buf *ib); +//connecto to irc +typedef struct irc_conn +{ + int conn_fd; //save connection fd + char *hostname; + char *port; + struct timespec last_read; //when last read where happening + int timeout; + int err; //local error type + int liberr; //save error from libc +} irc_conn; + int irc_connect(char *hostname, char *port); +//list of errors that will give more precise error description, if there is -1 returned one of this errors happened +#define ERR_SC_NONE 0 //no errors +#define ERR_SC_LIBC 1 //error from libc, dont have our own error +#define ERR_SC_PARAM 2 //something wrong with given params +#define ERR_SC_TIMEOUT 3 //timeout +#define ERR_SC_ALLOC 4 //memory allocation error +#define ERR_SC_CONN 5 //somethign with network connection +#define ERR_SC_RXTX 6 //read/write issue +#define ERR_SC_AGAIN 7 //async stuff try read later +#define ERR_SC_ANY 8 //any other error + +//irc_conn preallocated, artifacts can stay if something whent wrong +int irc_open(char *hostname, char *port, irc_conn *conn); +//if havent readed for more then [timeout] seconds then assume no connection +int irc_read_timeout(irc_conn *conn, int timeout); +//wrapped up usual read, read non blocking, count how long there was no data, +//and asks to reconnect, use err/liberr to diagnose error +int irc_read(irc_conn *conn, char *buf, size_t sz); +//no extra errors +int irc_reconnect(irc_conn *conn); +//clean dont free +int irc_close(irc_conn *conn); + #endif |