ref: e09ff804102de75826409b6043619d2668d9cef8
parent: 99aaa335c1a504b5210fd9e354a49749cec5c88b
author: libredev <libredev@ircforever.org>
date: Sun Nov 20 17:37:18 EST 2022
optimized and added timeout
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
#include <poll.h>
+#include <time.h>
#include <unistd.h>
#include "htable.h"
@@ -17,17 +18,14 @@
#define BUFFER_LEN 1024
#define MAX_NICK_LEN 16
-#define FD_ADDEND 100
#define POLLFD_ADDEND 100
#define NET_ADDEND 10
#define USER_ADDEND 100
-#define FIFO_FD 1
-#define LINKER_FD 2
-#define CLONE_FD 3
+#define TIME_OUT 180
typedef struct {
- int fd; /* fd of linker */
+ int id; /* fd of linker */
int join; /* is joined */
char *name; /* name */
char *symb; /* symbol */
@@ -37,18 +35,17 @@
} Network;
/* user defined data for each fd */
-struct fdData {
- int netid; /* net index */
- int type; /* fd type */
- int suffix; /* fd suffix count */
+struct FdData {
+ int netid; /* net index */
+ int suffix; /* suffix count */
+ char *user; /* user nick */
+ time_t time;
};
-static struct pollfd *pfdset; /* pollfd set */
-static struct fdData *fddata; /* fd user data set */
-static int pfdlen; /* pollfd length */
-static int pfdcap; /* pollfd capacity */
-static int *fdtoid; /* fd to pfdset index */
-static int fdscap; /* fds capacity */
+static struct pollfd *fdset; /* pollfd set */
+static struct FdData *fddata; /* user data set */
+static int fdslen; /* fdset length */
+static int fdscap; /* fdset capacity */
static Network *networks; /* linked list of networks */
static int netlen; /* current network length */
@@ -67,10 +64,11 @@
void net_update(int);
void user_add(char *, int);
void user_del(char *, char *);
-int *user_fds(char *, int);
-int clone_add(int, char *);
-void fd_add(int, int, int, int);
-void fd_del(int);
+int *user_ids(char *, int);
+int *euserids(char *);
+int clone_add(char *, int);
+int fdset_add(int, int, int, char *);
+void fdset_del(int);
void nick_add_symb(char *, int);
void privmsg_update(char *, char *, int);
void terminate(int);
@@ -82,7 +80,8 @@
int
main(int argc, char *argv[])
{
- int i, n;
+ int i, n, timeout_id;
+ time_t last_time, timeout;
/* set stdout to unbufferd */
setvbuf(stdout, NULL, _IONBF, 0);
@@ -94,11 +93,9 @@
}
/* init global variables */
- pfdcap = POLLFD_ADDEND;
- pfdset = ecalloc((size_t)pfdcap, sizeof(struct pollfd));
- fddata = ecalloc((size_t)pfdcap, sizeof(struct fdData));
- fdscap = FD_ADDEND;
- fdtoid = ecalloc((size_t)fdscap, sizeof(int));
+ fdscap = POLLFD_ADDEND;
+ fdset = ecalloc((size_t)fdscap, sizeof(struct pollfd));
+ fddata = ecalloc((size_t)fdscap, sizeof(struct FdData));
netcap = NET_ADDEND;
networks = ecalloc((size_t)netcap, sizeof(Network));
/*
@@ -110,22 +107,44 @@
users = htcreate((KeyLenFn *)strlen, (KeyCmpFn *)strcmp, free, free, USER_ADDEND);
/* add fifo_fd */
- fd_add(fifo_open(argv[1]), 0, FIFO_FD, 0);
+ fdset_add(fifo_open(argv[1]), -1, -1, NULL);
/* select loop */
while (isrunning) {
- if ((n = poll(pfdset, (nfds_t)pfdlen, -1)) == -1) {
+ /* calculate timeout from fdset */
+ last_time = time(NULL);
+ for (i = 0; i < fdslen; i++) {
+ if ((fddata[i].netid != -1) /* ignore fifo */
+ && (fddata[i].time < last_time)) {
+ last_time = fddata[i].time;
+ timeout_id = i;
+ }
+ }
+ timeout = TIME_OUT - (time(NULL) - last_time);
+ if (timeout < 0)
+ timeout = 0;
+
+ n = poll(fdset, (nfds_t)fdslen, (int)timeout * 1000);
+ if (n == -1) {
printf("error: poll: %s\n", strerror(errno));
terminate(1);
+ } else if (n == 0) {
+ snprintf(msg, sizeof(msg), "PING :%s\r\n",
+ networks[fddata[timeout_id].netid].host);
+ writeall(fdset[timeout_id].fd, msg);
+ fddata[timeout_id].time = time(NULL);
+ continue;
}
- for (i = 0; i < pfdlen; i++) {
- if (!(pfdset[i].revents & (POLLIN|POLLHUP)))
+ for (i = 0; i < fdslen; i++) {
+ if (!(fdset[i].revents & (POLLIN|POLLHUP)))
continue;
- /* printf("poll: %d\n", pfdset[i].fd); */
- if (fddata[i].type == FIFO_FD)
+ if (fddata[i].netid == -1)
handle_fifo_input(i, argv[1]);
else
handle_server_output(i);
+
+ fddata[i].time = time(NULL);
+
/*
* handle one ready fd at one time because if we
* close upcoming ready fd, it cause infinite loop.
@@ -146,12 +165,12 @@
ssize_t n;
/* if failed to read data */
- if ((n = readline(pfdset[id].fd, buffer, sizeof(buffer))) < 1) {
+ if ((n = readline(fdset[id].fd, buffer, sizeof(buffer))) < 1) {
if (n == 0) { /* restart again */
- fd_del(pfdset[id].fd);
- fd_add(fifo_open(path), 0, FIFO_FD, 0);
+ fdset_del(id);
+ fdset_add(fifo_open(path), -1, -1, NULL);
} else if ((errno != EAGAIN) && (errno != EINTR)) {
- printf("error: read: %s\n", strerror(errno));
+ printf("error: %d: read: %s\n", fdset[id].fd, strerror(errno));
}
return;
}
@@ -201,13 +220,15 @@
ssize_t n;
/* if failed to read data */
- if ((n = readline(pfdset[id].fd, buffer, sizeof(buffer))) < 1) {
+ if ((n = readline(fdset[id].fd, buffer, sizeof(buffer))) < 1) {
if (n == 0) {
- printf("error: remote host closed connection: %s\n", strerror(errno));
+ printf("error: %d: connection closed\n", fdset[id].fd);
+ printf("ping: %d : %ld\n", fdset[id].fd, time(0) - fddata[id].time);
terminate(1);
- /* fd_del(pfdset[id].fd); */
+ /* fdset_del(fdset[id].fd); */
} else if ((errno != EAGAIN) && (errno != EINTR)) {
- printf("error: read: %s\n", strerror(errno));
+ printf("error: %d: read: %s\n", fdset[id].fd, strerror(errno));
+ printf("ping: %d : %ld\n", fdset[id].fd, time(0) - fddata[id].time);
terminate(1);
}
return;
@@ -239,7 +260,7 @@
goto printbuffer;
} else if (strcmp(cmd, "PING") == 0) {
snprintf(msg, sizeof(msg), "PONG %s\r\n", buf);
- writeall(pfdset[id].fd, msg);
+ writeall(fdset[id].fd, msg);
return;
}
/* strip nick from first column */
@@ -287,28 +308,28 @@
strcat(nick, "_");
fddata[id].suffix++;
snprintf(msg, sizeof(msg), "NICK %s\r\n", nick);
- writeall(pfdset[id].fd, msg);
+ writeall(fdset[id].fd, msg);
}
return;
} else if (strcmp(cmd, "001") == 0) {
snprintf(msg, sizeof(msg), "JOIN %s\r\n", networks[netid].chan);
- writeall(pfdset[id].fd, msg);
+ writeall(fdset[id].fd, msg);
return;
} else if (strcmp(cmd, "PRIVMSG") == 0) {
char privmsg[BUFFER_LEN] = "";
- int *fds;
+ int *ids;
- if (fddata[id].type == LINKER_FD) {
+ if (fddata[id].user == NULL) { /* if linker */
nick_add_symb(nick, netid);
- if ((fds = htsearch(users, nick)) == NULL)
+ if ((ids = htsearch(users, nick)) == NULL)
return;
split(&buf, ':'); /* set buf to msg */
privmsg_update(privmsg, buf, netid);
for (i = 0; i < netlen; i++) {
- if (fds[i] > 0) {
+ if (ids[i] > 0) {
snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", networks[i].chan, privmsg);
- writeall(fds[i], msg);
+ writeall(fdset[ids[i]].fd, msg);
}
}
} else {
@@ -320,7 +341,7 @@
return;
nick_add_symb(nick, netid);
- if ((fds = htsearch(users, nick)) == NULL)
+ if ((ids = htsearch(users, nick)) == NULL)
return;
/* split user nick and network symbol */
@@ -337,12 +358,12 @@
split(&buf, ':'); /* set buf to msg */
privmsg_update(privmsg, buf, netid);
snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", user, privmsg);
- writeall(fds[i], msg);
+ writeall(fdset[ids[i]].fd, msg);
}
return;
}
/* these messages are handled by linker */
- if (fddata[id].type == CLONE_FD) {
+ if (fddata[id].user != NULL) { /* if clone */
if ((strcmp(cmd, "353") == 0)
|| (strcmp(cmd, "JOIN") == 0)
|| (strcmp(cmd, "QUIT") == 0)
@@ -369,21 +390,22 @@
return;
} else if (strcmp(cmd, "JOIN") == 0) {
if ((strcmp(nick, linker_nick) != 0)
- && (user_fds(nick, netid) == NULL)) /* if not clone */
+ && (user_ids(nick, netid) == NULL)) /* if not clone */
user_add(nick, netid);
return;
} else if ((strcmp(cmd, "QUIT") == 0)
|| (strcmp(cmd, "PART") == 0)) {
- nick_add_symb(nick, netid);
snprintf(msg, sizeof(msg), "QUIT :%s\r\n", buf);
- user_del(nick, msg);
+ nick_add_symb(nick, netid);
+ if (htsearch(users, nick) != NULL)
+ user_del(nick, msg);
return;
} else if (strcmp(cmd, "NICK") == 0) {
- int *fds, i;
+ int *ids, i;
char *newnick;
nick_add_symb(nick, netid);
- if ((fds = htsearch(users, nick)) == NULL)
+ if ((ids = htsearch(users, nick)) == NULL)
return;
/* set buf to new nick */
@@ -395,13 +417,13 @@
snprintf(msg, sizeof(msg), "NICK %s\r\n", newnick);
for (i = 0; i < netlen; i++) {
- if (fds[i] > 0)
- writeall(fds[i], msg);
+ if (ids[i] > 0)
+ writeall(fdset[ids[i]].fd, msg);
}
return;
} else if (strcmp(cmd, "KICK") == 0) {
/* :<nick_which_is_kicking>!~user@host KICK <channel> <nick_which_has_been_kicked> :<kick_msg> */
- int *fds;
+ int *ids;
char *chan = split(&buf, ' ');
char *user = split(&buf, ' ');
@@ -415,7 +437,7 @@
}
/* delete the user if the message from the same network */
- if ((fds = user_fds(user, netid)) == NULL) {
+ if ((ids = user_ids(user, netid)) == NULL) {
nick_add_symb(user, netid);
user_del(user, msg);
return;
@@ -422,9 +444,8 @@
}
/* close the kicked fd */
- writeall(fds[netid], msg);
- fd_del(fds[netid]);
- fds[netid] = -2;
+ writeall(fdset[ids[netid]].fd, msg);
+ fdset_del(id);
/*
* send notice in the channel through linker
@@ -431,7 +452,7 @@
*/
/* get the original user netid */
for (i = 0; i < netlen; i++) {
- if (fds[i] == -1)
+ if (ids[i] == -1)
break;
}
/* set buf to msg */
@@ -442,11 +463,11 @@
snprintf(msg, sizeof(msg),
"PRIVMSG %s :%s was kicked out by %s from network %s %s [%s]\r\n",
networks[i].chan, user, nick, networks[netid].name, chan, buf);
- writeall(networks[i].fd, msg);
+ writeall(fdset[networks[i].id].fd, msg);
return;
}
printbuffer:
- printf("%d: %s\n", pfdset[id].fd, backup);
+ printf("%d: %s\n", fdset[id].fd, backup);
}
void
@@ -485,7 +506,6 @@
/* connect */
if ((fd = dial(host, port)) == -1)
return;
- fd_add(fd, netlen, LINKER_FD, 0);
/* send NICK and USER commands */
snprintf(msg, sizeof(msg), "NICK linker\r\n");
writeall(fd, msg);
@@ -493,7 +513,7 @@
writeall(fd, msg);
/* add a network */
n = &networks[netlen];
- n->fd = fd;
+ n->id = fdset_add(fd, netlen, 0, NULL);
n->join = 0;
n->name = strdup(name);
n->symb = strdup(symb);
@@ -507,7 +527,7 @@
void
net_del(char *name)
{
- int i, netid, *fds;
+ int i, netid, *ids;
Htiter it = {0}; /* current iterator */
Htiter lastit = {0}; /* last iterator */
@@ -530,34 +550,34 @@
/* reconstruct the user-clones table */
while (htiterate(users, &it)) {
- fds = (int *)it.node->val;
+ ids = (int *)it.node->val;
/* delete all the users of deleting network */
- if (fds[netid] == -1) {
+ if (ids[netid] == -1) {
user_del(it.node->key, msg);
/* this node is deleted */
it = lastit;
/* delete the clones */
} else {
- if (fds[netid] > 0) {
- writeall(fds[netid], msg);
- fd_del(fds[netid]);
+ if (ids[netid] > 0) {
+ writeall(fdset[ids[netid]].fd, msg);
+ fdset_del(ids[netid]);
}
/* swap last with current one */
- fds[netid] = fds[netlen-1];
+ ids[netid] = ids[netlen-1];
}
lastit = it;
}
- /* set pollfds netid with last netid to current netid. */
- for (i = 0; i < pfdlen; i++) {
+ /* set netid of fds with last netid to current netid. */
+ for (i = 0; i < fdslen; i++) {
if (fddata[i].netid == netlen-1)
fddata[i].netid = netid;
}
- writeall(networks[netid].fd, msg);
- fd_del(networks[netid].fd);
+ writeall(fdset[networks[netid].id].fd, msg);
+ fdset_del(networks[netid].id);
net_del_raw(netid);
- printf("%d: network '%s' deleted\n", networks[netid].fd, name);
+ printf("%d: network '%s' deleted\n", fdset[networks[netid].id].fd, name);
/* swap the network with the last */
networks[netid] = networks[netlen-1];
netlen--;
@@ -577,19 +597,15 @@
void
net_update(int netid)
{
- int *fds;
- Htiter it = {0};
-
- while (htiterate(users, &it)) {
- fds = (int *)it.node->val;
- fds[netid] = clone_add(netid, it.node->key);
- }
+ Htiter it = {0};
+ while (htiterate(users, &it))
+ ((int *)it.node->val)[netid] = clone_add(it.node->key, netid);
}
void
user_add(char *unick, int netid)
{
- int i, *fds;
+ int i, *ids;
size_t len;
char *nick;
@@ -609,7 +625,7 @@
/* allocate a new user */
nick = ecalloc(len, sizeof(char));
- fds = ecalloc((size_t)netcap, sizeof(int));
+ ids = ecalloc((size_t)netcap, sizeof(int));
sprintf(nick, "%s[%s]", unick, networks[netid].symb);
/* clone the user on all other network */
@@ -617,13 +633,13 @@
if (networks[i].join == 0)
continue;
if (i == netid) {
- fds[i] = -1;
+ ids[i] = -1;
} else {
- fds[i] = clone_add(i, nick);
+ ids[i] = clone_add(nick, i);
}
}
/* insert it to the users hash table */
- if (htinsert(users, nick, fds) == -1) {
+ if (htinsert(users, nick, ids) == -1) {
/* this shouldn't happen as it was already checked */
printf("error: user '%s' already exists\n", nick);
terminate(1);
@@ -633,16 +649,12 @@
void
user_del(char *nick, char *msg)
{
- int *fds, i;
- if ((fds = htsearch(users, nick)) == NULL) {
- printf("error: user '%s' doesn't exists\n", nick);
- return;
- }
-
+ int i;
+ int *ids = euserids(nick);
for (i = 0; i < netlen; i++) {
- if (fds[i] > 0) {
- writeall(fds[i], msg);
- fd_del(fds[i]);
+ if (ids[i] > 0) {
+ writeall(fdset[ids[i]].fd, msg);
+ fdset_del(ids[i]);
}
}
htremove(users, nick);
@@ -649,10 +661,10 @@
}
int *
-user_fds(char *nick, int netid)
+user_ids(char *nick, int netid)
{
unsigned int suffix;
- int *fds = NULL;
+ int *ids = NULL;
/* count suffix */
for (suffix = 0; nick[strlen(nick)-suffix-1] == '_'; suffix++);
@@ -660,65 +672,80 @@
if (suffix > 0)
nick[strlen(nick)-suffix] = '\0';
- fds = htsearch(users, nick);
+ ids = htsearch(users, nick);
/* if match but suffix doesn't match */
- if ((fds != NULL) && (fddata[fdtoid[fds[netid]]].suffix != (int)suffix))
- fds = NULL;
+ if ((ids != NULL) && (fddata[ids[netid]].suffix != (int)suffix))
+ ids = NULL;
/* add suffix back */
if (suffix > 0)
nick[strlen(nick)] = '_';
- return fds;
+ return ids;
}
+/* get user ids */
+int *
+euserids(char *user)
+{
+ int *ids;
+ if ((ids = htsearch(users, user)) == NULL) {
+ printf("error: cannot find user '%s'\n", user);
+ terminate(1);
+ }
+ return ids;
+}
+
int
-clone_add(int netid, char *nick)
+clone_add(char *nick, int netid)
{
int fd;
Network *n = &networks[netid];
-
if ((fd = dial(n->host, n->port)) == -1)
return -1;
- fd_add(fd, netid, CLONE_FD, 0);
/* send NICK and USER commands */
snprintf(msg, sizeof(msg), "NICK %s\r\n", nick);
writeall(fd, msg);
snprintf(msg, sizeof(msg), "USER user 0 * :user\r\n");
writeall(fd, msg);
- return fd;
+ return fdset_add(fd, netid, 0, nick);
}
-void
-fd_add(int fd, int netid, int type, int suffix)
+int
+fdset_add(int fd, int netid, int suffix, char *user)
{
- /* resize if full */
- if (fd+1 == fdscap) {
- fdtoid = erecalloc(fdtoid, (size_t)fdscap, FD_ADDEND, sizeof(int));
- fdscap += FD_ADDEND;
+ if (fdslen == fdscap) {
+ fdset = erecalloc(fdset, (size_t)fdscap, POLLFD_ADDEND, sizeof(struct pollfd));
+ fddata = erecalloc(fddata, (size_t)fdscap, POLLFD_ADDEND, sizeof(struct FdData));
+ fdscap += POLLFD_ADDEND;
}
- if (pfdlen == pfdcap) {
- pfdset = erecalloc(pfdset, (size_t)pfdcap, POLLFD_ADDEND, sizeof(struct pollfd));
- fddata = erecalloc(fddata, (size_t)pfdcap, POLLFD_ADDEND, sizeof(struct fdData));
- pfdcap += POLLFD_ADDEND;
- }
- pfdset[pfdlen].fd = fd;
- pfdset[pfdlen].events = POLLIN;
- fddata[pfdlen].netid = netid;
- fddata[pfdlen].type = type;
- fddata[pfdlen].suffix = suffix;
- fdtoid[fd] = pfdlen;
- pfdlen++;
+ fdset[fdslen].fd = fd;
+ fdset[fdslen].events = POLLIN;
+ fddata[fdslen].netid = netid;
+ fddata[fdslen].suffix = suffix;
+ fddata[fdslen].user = user;
+ fddata[fdslen].time = time(NULL);
+ return fdslen++;
}
void
-fd_del(int fd)
+fdset_del(int id)
{
- close(fd);
- pfdset[fdtoid[fd]] = pfdset[pfdlen-1];
- fddata[fdtoid[fd]] = fddata[pfdlen-1];
- fdtoid[fd] = pfdlen-1;
- pfdlen--;
+ /* set id of last fd to current id */
+ if (fddata[fdslen-1].user != NULL)
+ euserids(fddata[fdslen-1].user)[fddata[fdslen-1].netid] = id;
+ else if ((fddata[fdslen-1].user == NULL) && (fddata[fdslen-1].netid != -1))
+ networks[fddata[fdslen-1].netid].id = id;
+ /* set id of removing fd to -2 */
+ if (fddata[id].user != NULL)
+ euserids(fddata[id].user)[fddata[id].netid] = -2;
+ else if ((fddata[id].user == NULL) && (fddata[id].netid != -1))
+ networks[fddata[id].netid].id = -2;
+
+ close(fdset[id].fd);
+ fdset[id] = fdset[fdslen-1];
+ fddata[id] = fddata[fdslen-1];
+ fdslen--;
}
void
@@ -750,7 +777,7 @@
}
/* check if the word is nick */
- if (user_fds(src, netid) != NULL)
+ if (user_ids(src, netid) != NULL)
*strrchr(src, '[') = '\0';
strcat(dst, src);
@@ -765,10 +792,10 @@
{
int i;
snprintf(msg, sizeof(msg), "QUIT :linker shutting down\r\n");
- for (i = 0; i < pfdlen; i++) {
- if (fddata[i].type != FIFO_FD)
- writeall(pfdset[i].fd, msg);
- fd_del(pfdset[i].fd);
+ for (i = 0; i < fdslen; i++) {
+ if (fddata[i].netid != -1)
+ writeall(fdset[i].fd, msg);
+ fdset_del(i);
}
/* delete all the users */
htdestroy(users);
@@ -776,11 +803,10 @@
/* delete all the networks */
for (i = 0; i < netlen; i++)
net_del_raw(i);
- free(networks);
- free(pfdset);
+ free(networks);
+ free(fdset);
free(fddata);
- free(fdtoid);
if (status == 0) {
printf("exit successfully\n");
@@ -794,7 +820,7 @@
void
print_table(void)
{
- int i, *fds, diff, tabs;
+ int i, *ids, diff, tabs;
Htiter it = {0};
char *nick;
@@ -805,11 +831,11 @@
/* print networks */
printf("Networks\t\t");
for (i = 0; i < netlen; i++)
- printf("%s(%d)\t", networks[i].symb, networks[i].fd);
+ printf("%s(%d)\t", networks[i].symb, fdset[networks[i].id].fd);
printf("\n");
while (htiterate(users, &it)) {
- fds = (int *)it.node->val;
+ ids = (int *)it.node->val;
nick = (char *)it.node->key;
/* print tabbed user nick */
printf("%s", nick);
@@ -816,12 +842,12 @@
diff = 24 - (int)strlen(nick);
tabs = ((diff / 8) + (diff % 8 > 0));
printf("%.*s", tabs, "\t\t\t");
- /* print tabbed clones fds */
+ /* print tabbed clones ids */
for (i = 0; i < netlen; i++) {
- printf("%d", fds[i]);
+ printf("%d", ids[i]);
/* print suffix */
- if ((fds[i] > 0) && (fddata[fdtoid[fds[i]]].suffix > 0))
- printf("(%d)", fddata[fdtoid[fds[i]]].suffix);
+ if ((ids[i] > 0) && (fddata[ids[i]].suffix > 0))
+ printf("(%d)", fddata[ids[i]].suffix);
printf("\t");
}
printf("\n");
--- a/util.c
+++ b/util.c
@@ -112,6 +112,27 @@
}
int
+connect_wait(int s)
+{
+ struct pollfd pfd[1];
+ int error = 0;
+ socklen_t len = sizeof(error);
+
+ pfd[0].fd = s;
+ pfd[0].events = POLLOUT;
+
+ if (poll(pfd, 1, -1) == -1)
+ return -1;
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1)
+ return -1;
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+int
dial(char *host, char *port)
{
static struct addrinfo hints, *res = NULL, *res0;
@@ -126,14 +147,19 @@
return -1;
}
for (res = res0; res != NULL; res = res->ai_next) {
- if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
+ if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
continue;
- if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) {
- close(fd);
- fd = -1;
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+ printf("error: fcntl: %s\n", strerror(errno));
continue;
}
- break;
+ if (connect(fd, res->ai_addr, res->ai_addrlen) == 0)
+ break;
+ else if ((errno == EINPROGRESS) && (connect_wait(fd) == 0))
+ break;
+ printf("error: connect: %s\n", strerror(errno));
+ close(fd);
+ fd = -1;
}
if (fd == -1)
printf("error: cannot connect to host '%s'\n", host);