nonblocking connect() - part 1
This commit is contained in:
parent
48f18df080
commit
7edf765697
27
connection.c
27
connection.c
@ -44,6 +44,8 @@ static struct connection * create_connection()
|
|||||||
|
|
||||||
static int destroy_connection(struct connection *con)
|
static int destroy_connection(struct connection *con)
|
||||||
{
|
{
|
||||||
|
// TODO: detroy connect-timeout?
|
||||||
|
|
||||||
if (con->src_fd != -1) {
|
if (con->src_fd != -1) {
|
||||||
close(con->src_fd);
|
close(con->src_fd);
|
||||||
event_remove_fd(con->src_fd);
|
event_remove_fd(con->src_fd);
|
||||||
@ -81,6 +83,24 @@ static int forward_handler(int fd, void *privdata)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int connect_handler(int fd, void *privdata)
|
||||||
|
{
|
||||||
|
struct connection *con = (struct connection *)privdata;
|
||||||
|
|
||||||
|
if (tcp_connect_error(fd)) {
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr));
|
||||||
|
event_add_readfd(con->dst_fd, forward_handler, con);
|
||||||
|
event_add_readfd(con->src_fd, forward_handler, con);
|
||||||
|
|
||||||
|
/* dismiss connect_handler */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int client_handler(int fd, void *privdata)
|
static int client_handler(int fd, void *privdata)
|
||||||
{
|
{
|
||||||
struct connection *con = (struct connection *)privdata;
|
struct connection *con = (struct connection *)privdata;
|
||||||
@ -107,9 +127,10 @@ static int client_handler(int fd, void *privdata)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr));
|
// TODO: start connect timeout, callback destroys connection
|
||||||
event_add_readfd(con->dst_fd, forward_handler, con);
|
|
||||||
event_add_readfd(con->src_fd, forward_handler, con);
|
log_print(LOG_INFO, "connecting to %s", get_sockaddr_buf(&con->dst_addr));
|
||||||
|
event_add_writefd(con->dst_fd, connect_handler, con);
|
||||||
|
|
||||||
/* dismiss client_handler */
|
/* dismiss client_handler */
|
||||||
return -1;
|
return -1;
|
||||||
|
50
network.c
50
network.c
@ -4,6 +4,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ int tcp_listen_socket(struct sockaddr_in *sa)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) {
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) {
|
||||||
log_print(LOG_ERROR, "tcp_listen_socket(): setsockopt(SO_REUSEADDR)");
|
log_print(LOG_ERROR, "tcp_listen_socket(): setsockopt(SO_REUSEADDR)");
|
||||||
close(sock);
|
close(sock);
|
||||||
@ -85,10 +87,54 @@ int tcp_connect_socket(struct sockaddr_in *sa)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr *)sa, sizeof(*sa))) {
|
int flags = fcntl(sock, F_GETFL, 0);
|
||||||
|
if (flags < 0) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_GETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-blocking */
|
||||||
|
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = connect(sock, (struct sockaddr *)sa, sizeof(*sa));
|
||||||
|
if (ret && errno != EINPROGRESS) {
|
||||||
log_print(LOG_ERROR, "tcp_connect_socket(): bind(%s)", get_sockaddr_buf(sa));
|
log_print(LOG_ERROR, "tcp_connect_socket(): bind(%s)", get_sockaddr_buf(sa));
|
||||||
close(sock);
|
close(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reset EINPROGRESS */
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* blocking */
|
||||||
|
if (fcntl(sock, F_SETFL, flags)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tcp_connect_error(int fd)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int err_size = sizeof(err);
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_size)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_error(): getsockopt(SO_ERROR)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
errno = err;
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_error()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
int parse_saddr(const char *addr, struct sockaddr_in *sa);
|
int parse_saddr(const char *addr, struct sockaddr_in *sa);
|
||||||
int tcp_listen_socket(struct sockaddr_in *sa);
|
int tcp_listen_socket(struct sockaddr_in *sa);
|
||||||
int tcp_connect_socket(struct sockaddr_in *sa);
|
int tcp_connect_socket(struct sockaddr_in *sa);
|
||||||
|
int tcp_connect_error(int fd);
|
||||||
|
|
||||||
int get_sockaddr(struct sockaddr_in *sa, char *buf, int size);
|
int get_sockaddr(struct sockaddr_in *sa, char *buf, int size);
|
||||||
char * get_sockaddr_buf(struct sockaddr_in *sa);
|
char * get_sockaddr_buf(struct sockaddr_in *sa);
|
||||||
|
Loading…
Reference in New Issue
Block a user