Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions src/libguac/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
Expand All @@ -50,7 +51,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
if ((retval = getaddrinfo(hostname, port, &hints, &addresses))) {
guac_error = GUAC_STATUS_INVALID_ARGUMENT;
guac_error_message = "Error parsing address or port.";
return retval;
return -1;
}

/* Attempt connection to each address until success */
Expand Down Expand Up @@ -83,6 +84,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
guac_error = GUAC_STATUS_INVALID_ARGUMENT;
guac_error_message = "Failed to retrieve socket options.";
close(fd);
fd = -1;
continue;
}

Expand All @@ -91,6 +93,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
guac_error = GUAC_STATUS_INVALID_ARGUMENT;
guac_error_message = "Failed to set non-blocking socket.";
close(fd);
fd = -1;
continue;
}

Expand All @@ -108,12 +111,46 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
FD_SET(fd, &fdset);

retval = select(fd + 1, NULL, &fdset, NULL, &tv);

if (retval > 0) {
int so_error = 0;
socklen_t so_error_len = sizeof(so_error);
retval = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);

/* Error occurs retrieving the socket status, so we set it
and move on. */
if (retval < 0) {
guac_error = GUAC_STATUS_INVALID_ARGUMENT;
guac_error_message = "Failed to retrieve socket status.";
close(fd);
fd = -1;
continue;
}

/* This indicates that the connection is successful, so we
break so that the socket can be immediately returned. */
if (so_error == 0) {
break;
}

/* There's a socket error, so we retrieve it and move to
the next address. */
else {
guac_error = GUAC_STATUS_REFUSED;
guac_error_message = strerror(so_error);
close(fd);
fd = -1;
continue;
}
}

}

else {
guac_error = GUAC_STATUS_REFUSED;
guac_error_message = "Unable to connect via socket.";
close(fd);
fd = -1;
continue;
}
}
Expand All @@ -125,6 +162,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
guac_error = GUAC_STATUS_INVALID_ARGUMENT;
guac_error_message = "Failed to reset socket options.";
close(fd);
fd = -1;
continue;
}

Expand All @@ -142,7 +180,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)

/* Some error has occurred - free resources before next iteration. */
close(fd);

fd = -1;
}

/* Free addrinfo */
Expand All @@ -152,6 +190,7 @@ int guac_tcp_connect(const char* hostname, const char* port, const int timeout)
if (current_address == NULL) {
guac_error = GUAC_STATUS_REFUSED;
guac_error_message = "Unable to connect to remote host.";
fd = -1;
}

/* Return the fd, or the error message if the socket connection failed. */
Expand Down