aboutsummaryrefslogtreecommitdiffstats
path: root/sock_conn.c
diff options
context:
space:
mode:
authorFreeArtMan <dos21h@gmail.com>2017-05-11 16:45:00 +0100
committerFreeArtMan <dos21h@gmail.com>2017-05-11 16:45:00 +0100
commit1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53 (patch)
tree878d3d9a46db60a156935c41307b83c39c0d42c8 /sock_conn.c
parent6a377350d63fc2dd470e9bd25008e8e827c011f2 (diff)
downloadagni-1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53.tar.gz
agni-1e8e7cf72de6ca97b8e8cd3ba4266788ba9fec53.zip
Update socket connection functions. Now reconnection is possible
Diffstat (limited to 'sock_conn.c')
-rw-r--r--sock_conn.c247
1 files changed, 246 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);
+}
+