X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Funix%2Fsilcunixnet.c;h=e0befdc19979ca325a83cd39b6da9015e34a28f8;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=f7ddb18db0449e86f623301246c150b295856dc2;hpb=9781db929f51eec844277fbe28780faaea35e53f;p=silc.git diff --git a/lib/silcutil/unix/silcunixnet.c b/lib/silcutil/unix/silcunixnet.c index f7ddb18d..e0befdc1 100644 --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@ -21,6 +21,8 @@ #include "silc.h" #include "silcnet.h" +/************************** Types and definitions ***************************/ + #ifdef HAVE_IPV6 #define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \ sizeof(so.sin6) : sizeof(so.sin)) @@ -36,6 +38,8 @@ typedef union { #endif } SilcSockaddr; +/************************ Static utility functions **************************/ + static SilcBool silc_net_set_sockaddr(SilcSockaddr *addr, const char *ip_addr, int port) { @@ -81,6 +85,8 @@ static SilcBool silc_net_set_sockaddr(SilcSockaddr *addr, const char *ip_addr, return TRUE; } +/****************************** TCP Listener ********************************/ + /* Deliver new stream to upper layer */ static void silc_net_accept_stream(SilcSocketStreamStatus status, @@ -108,7 +114,6 @@ SILC_TASK_CALLBACK(silc_net_accept) return; /* Set socket options */ - silc_net_set_socket_nonblock(sock); silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); /* Create socket stream */ @@ -137,10 +142,8 @@ silc_net_tcp_create_listener(const char **local_ip_addr, goto err; listener = silc_calloc(1, sizeof(*listener)); - if (!listener) { - callback(SILC_NET_NO_MEMORY, NULL, context); + if (!listener) return NULL; - } listener->schedule = schedule; listener->callback = callback; listener->context = context; @@ -149,24 +152,20 @@ silc_net_tcp_create_listener(const char **local_ip_addr, if (local_ip_count > 0) { listener->socks = silc_calloc(local_ip_count, sizeof(*listener->socks)); - if (!listener->socks) { - callback(SILC_NET_NO_MEMORY, NULL, context); + if (!listener->socks) return NULL; - } } else { listener->socks = silc_calloc(1, sizeof(*listener->socks)); - if (!listener->socks) { - callback(SILC_NET_NO_MEMORY, NULL, context); + if (!listener->socks) return NULL; - } local_ip_count = 1; } /* Bind to local addresses */ for (i = 0; i < local_ip_count; i++) { - SILC_LOG_DEBUG(("Binding to local address %s", - local_ip_addr ? local_ip_addr[i] : ipany)); + SILC_LOG_DEBUG(("Binding to local address %s:%d", + local_ip_addr ? local_ip_addr[i] : ipany, port)); /* Set sockaddr for server */ if (!silc_net_set_sockaddr(&server, @@ -185,13 +184,15 @@ silc_net_tcp_create_listener(const char **local_ip_addr, rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); + close(sock); goto err; } /* Bind the listener socket */ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { - SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno))); + SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno))); + close(sock); goto err; } @@ -199,6 +200,7 @@ silc_net_tcp_create_listener(const char **local_ip_addr, rval = listen(sock, 64); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno))); + close(sock); goto err; } @@ -216,8 +218,6 @@ silc_net_tcp_create_listener(const char **local_ip_addr, return listener; err: - if (callback) - callback(SILC_NET_ERROR, NULL, context); if (listener) silc_net_close_listener(listener); return NULL; @@ -241,6 +241,8 @@ void silc_net_close_listener(SilcNetListener listener) silc_free(listener); } +/******************************* UDP Stream *********************************/ + /* Create UDP stream */ SilcStream @@ -295,9 +297,6 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, goto err; } - /* Set socket to non-blocking mode */ - silc_net_set_socket_nonblock(sock); - /* Set to connected state if remote address is provided. */ if (remote_ip_addr && remote_port) { if (!silc_net_set_sockaddr(&server, remote_ip_addr, remote_port)) @@ -312,17 +311,23 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, /* Set send and receive buffer size */ #ifdef SO_SNDBUF - rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_SNDBUF, 65535); + rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_SNDBUF, 765535); if (rval < 0) { - SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); - goto err; + rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_SNDBUF, 65535); + if (rval < 0) { + SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); + goto err; + } } #endif /* SO_SNDBUF */ #ifdef SO_RCVBUF - rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_RCVBUF, 65535); + rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_RCVBUF, 765535); if (rval < 0) { - SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); - goto err; + rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_RCVBUF, 65535); + if (rval < 0) { + SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); + goto err; + } } #endif /* SO_RCVBUF */ @@ -446,6 +451,8 @@ int silc_net_udp_send(SilcStream stream, return ret; } +/******************************* TCP Stream *********************************/ + /* Asynchronous TCP/IP connecting */ typedef struct { @@ -476,7 +483,6 @@ SILC_TASK_CALLBACK(silc_net_connect_wait) { SilcNetConnect conn = context; SILC_FSM_EVENT_SIGNAL(&conn->event); - silc_schedule_task_del_by_fd(schedule, conn->sock); } SILC_FSM_STATE(silc_net_connect_st_start) @@ -544,18 +550,15 @@ SILC_FSM_STATE(silc_net_connect_st_start) rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost)); if (rval < 0) { if (errno != EINPROGRESS) { - /* retry using an IPv4 adress, if IPv6 didn't work */ - if (prefer_ipv6 && silc_net_is_ip6(conn->ip_addr)) { - shutdown(sock, 2); - close(sock); + shutdown(sock, 2); + close(sock); + /* Retry using an IPv4 adress, if IPv6 didn't work */ + if (prefer_ipv6 && silc_net_is_ip6(conn->ip_addr)) { prefer_ipv6 = FALSE; goto retry; } - shutdown(sock, 2); - close(sock); - /** Cannot connect to remote host */ SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno))); silc_fsm_next(fsm, silc_net_connect_st_finish); @@ -588,6 +591,7 @@ static void silc_net_connect_wait_stream(SilcSocketStreamStatus status, SilcStream stream, void *context) { SilcNetConnect conn = context; + conn->sop = NULL; conn->stream_status = status; conn->stream = stream; SILC_FSM_CALL_CONTINUE(&conn->fsm); @@ -601,6 +605,8 @@ SILC_FSM_STATE(silc_net_connect_st_connected) if (conn->aborted) { /** Aborted */ + silc_schedule_unset_listen_fd(schedule, conn->sock); + silc_schedule_task_del_by_fd(schedule, conn->sock); silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } @@ -608,8 +614,8 @@ SILC_FSM_STATE(silc_net_connect_st_connected) ret = silc_net_get_socket_opt(conn->sock, SOL_SOCKET, SO_ERROR, &opt, &optlen); - silc_schedule_task_del_by_fd(schedule, conn->sock); silc_schedule_unset_listen_fd(schedule, conn->sock); + silc_schedule_task_del_by_fd(schedule, conn->sock); if (ret != 0 || opt != 0) { if (conn->retry) { @@ -622,29 +628,30 @@ SILC_FSM_STATE(silc_net_connect_st_connected) } #if defined(ECONNREFUSED) - if (errno == ECONNREFUSED) + if (opt == ECONNREFUSED) conn->status = SILC_NET_CONNECTION_REFUSED; #endif /* ECONNREFUSED */ #if defined(ETIMEDOUT) - if (errno == ETIMEDOUT) + if (opt == ETIMEDOUT) conn->status = SILC_NET_CONNECTION_TIMEOUT; #endif /* ETIMEDOUT */ #if defined(ENETUNREACH) - if (errno == ENETUNREACH) + if (opt == ENETUNREACH) conn->status = SILC_NET_HOST_UNREACHABLE; #endif /* ENETUNREACH */ /** Connecting failed */ - SILC_LOG_DEBUG(("Connecting failed")); + SILC_LOG_DEBUG(("Connecting failed, error %s", strerror(opt))); silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } + SILC_LOG_DEBUG(("TCP connection established")); + /** Connection created */ silc_fsm_next(fsm, silc_net_connect_st_stream); SILC_FSM_CALL((conn->sop = silc_socket_tcp_stream_create( - conn->sock, FALSE, FALSE, - schedule, + conn->sock, TRUE, FALSE, schedule, silc_net_connect_wait_stream, conn))); } @@ -670,11 +677,6 @@ SILC_FSM_STATE(silc_net_connect_st_stream) return SILC_FSM_CONTINUE; } - /* Set stream information */ - silc_socket_stream_set_info(conn->stream, - !silc_net_is_ip(conn->remote) ? conn->remote : - conn->ip_addr, conn->ip_addr, conn->port); - /** Stream created successfully */ SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock)); conn->status = SILC_NET_OK; @@ -691,8 +693,6 @@ SILC_FSM_STATE(silc_net_connect_st_finish) conn->callback(conn->status, conn->stream, conn->context); if (conn->op) silc_async_free(conn->op); - if (conn->sop) - silc_async_free(conn->sop); } return SILC_FSM_FINISH; @@ -704,8 +704,10 @@ static void silc_net_connect_abort(SilcAsyncOperation op, void *context) conn->aborted = TRUE; /* Abort underlaying stream creation too */ - if (conn->sop) - silc_async_abort(conn->op, NULL, NULL); + if (conn->sop) { + silc_async_abort(conn->sop, NULL, NULL); + conn->sop = NULL; + } } static void silc_net_connect_destructor(SilcFSM fsm, void *fsm_context,