diff options
Diffstat (limited to 'sock_conn.c')
-rw-r--r-- | sock_conn.c | 247 |
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); +} + |