X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Funix%2Fsilcunixnet.c;h=1ce203811c0c249b5a8baa33915391abac663d8a;hp=929ecf38ce3d5e80be811393258fc4b3bfffb873;hb=9905799a86c606304fd7df2cd401de1740a272a1;hpb=e9f2575973091102bedbd22ebf243122b4b25ed8 diff --git a/lib/silcutil/unix/silcunixnet.c b/lib/silcutil/unix/silcunixnet.c index 929ecf38..1ce20381 100644 --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@ -133,7 +133,7 @@ silc_net_tcp_create_listener(const char **local_ip_addr, SILC_LOG_DEBUG(("Creating TCP listener")); - if (port < 1 || !schedule || !callback) + if (port < 0 || !schedule || !callback) goto err; listener = silc_calloc(1, sizeof(*listener)); @@ -196,7 +196,7 @@ silc_net_tcp_create_listener(const char **local_ip_addr, } /* Specify that we are listenning */ - rval = listen(sock, 5); + rval = listen(sock, 64); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno))); goto err; @@ -330,7 +330,7 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, stream = silc_socket_udp_stream_create(sock, local_ip_addr ? silc_net_is_ip6(local_ip_addr) : FALSE, - schedule); + remote_ip_addr ? TRUE : FALSE, schedule); if (!stream) goto err; @@ -398,6 +398,8 @@ int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr, inet_ntop(AF_INET, &s.sin.sin_addr, remote_ip_addr, remote_ip_addr_size); } + + SILC_LOG_DEBUG(("UDP packet from %s:%d", remote_ip_addr, *remote_port)); } return len; @@ -405,21 +407,43 @@ int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr, /* Send UDP packet */ -void silc_net_udp_send(SilcStream stream, - const char *remote_ip_addr, int remote_port, - const unsigned char *data, SilcUInt32 data_len) +int silc_net_udp_send(SilcStream stream, + const char *remote_ip_addr, int remote_port, + const unsigned char *data, SilcUInt32 data_len) { SilcSocketStream sock = stream; SilcSockaddr remote; + int ret; - SILC_LOG_DEBUG(("Writing data to UDP socket %d", sock->sock)); + SILC_LOG_DEBUG(("Sending data to UDP socket %d", sock->sock)); - /* Set sockaddr for server */ + /* Set sockaddr */ if (!silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port)) - return; + return -2; /* Send */ - sendto(sock->sock, data, data_len, 0, &remote.sa, SIZEOF_SOCKADDR(remote)); + ret = sendto(sock->sock, data, data_len, 0, &remote.sa, + SIZEOF_SOCKADDR(remote)); + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) { + SILC_LOG_DEBUG(("Could not send immediately, will do it later")); + silc_schedule_set_listen_fd(sock->schedule, sock->sock, + SILC_TASK_READ | SILC_TASK_WRITE, FALSE); + return -1; + } + SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno))); + silc_schedule_unset_listen_fd(sock->schedule, sock->sock); + sock->sock_error = errno; + return -2; + } + + SILC_LOG_DEBUG(("Sent data %d bytes", ret)); + if (silc_schedule_get_fd_events(sock->schedule, sock->sock) & + SILC_TASK_WRITE) + silc_schedule_set_listen_fd(sock->schedule, sock->sock, + SILC_TASK_READ, FALSE); + + return ret; } /* Asynchronous TCP/IP connecting */ @@ -429,7 +453,7 @@ typedef struct { SilcSocketStreamStatus stream_status; SilcStream stream; SilcFSMStruct fsm; - SilcFSMSemaStruct sema; + SilcFSMEventStruct event; SilcAsyncOperation op; SilcAsyncOperation sop; char *local_ip; @@ -451,7 +475,8 @@ SILC_FSM_STATE(silc_net_connect_st_finish); SILC_TASK_CALLBACK(silc_net_connect_wait) { SilcNetConnect conn = context; - SILC_FSM_SEMA_POST(&conn->sema); + SILC_FSM_EVENT_SIGNAL(&conn->event); + silc_schedule_task_del_by_fd(schedule, conn->sock); } SILC_FSM_STATE(silc_net_connect_st_start) @@ -464,7 +489,7 @@ SILC_FSM_STATE(silc_net_connect_st_start) if (conn->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /* Do host lookup */ @@ -477,14 +502,14 @@ SILC_FSM_STATE(silc_net_connect_st_start) /** Network unreachable */ conn->status = SILC_NET_HOST_UNREACHABLE; silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /* Set sockaddr for this connection */ if (!silc_net_set_sockaddr(&desthost, conn->ip_addr, conn->port)) { /** Sockaddr failed */ silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /* Create the connection socket */ @@ -500,7 +525,7 @@ SILC_FSM_STATE(silc_net_connect_st_start) /** Cannot create socket */ SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno))); silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /* Bind to the local address if provided */ @@ -534,7 +559,7 @@ SILC_FSM_STATE(silc_net_connect_st_start) /** 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); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } } @@ -550,13 +575,13 @@ SILC_FSM_STATE(silc_net_connect_st_start) /** Wait for connection */ silc_fsm_next(fsm, silc_net_connect_st_connected); - silc_fsm_sema_init(&conn->sema, fsm, 0); + silc_fsm_event_init(&conn->event, fsm); silc_schedule_task_add_fd(silc_fsm_get_schedule(fsm), sock, silc_net_connect_wait, conn); silc_schedule_set_listen_fd(silc_fsm_get_schedule(fsm), sock, SILC_TASK_WRITE, FALSE); - SILC_FSM_SEMA_WAIT(&conn->sema); - return SILC_FSM_CONTINUE; + SILC_FSM_EVENT_WAIT(&conn->event); + SILC_FSM_CONTINUE; } static void silc_net_connect_wait_stream(SilcSocketStreamStatus status, @@ -577,7 +602,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected) if (conn->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } ret = silc_net_get_socket_opt(conn->sock, SOL_SOCKET, SO_ERROR, @@ -593,7 +618,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected) conn->retry--; silc_net_close_connection(conn->sock); silc_fsm_next(fsm, silc_net_connect_st_start); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } #if defined(ECONNREFUSED) @@ -612,7 +637,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected) /** Connecting failed */ SILC_LOG_DEBUG(("Connecting failed")); silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /** Connection created */ @@ -630,7 +655,7 @@ SILC_FSM_STATE(silc_net_connect_st_stream) if (conn->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } if (conn->stream_status != SILC_SOCKET_OK) { @@ -642,7 +667,7 @@ SILC_FSM_STATE(silc_net_connect_st_stream) else conn->status = SILC_NET_ERROR; silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } /* Set stream information */ @@ -654,7 +679,7 @@ SILC_FSM_STATE(silc_net_connect_st_stream) SILC_LOG_DEBUG(("Connected successfully")); conn->status = SILC_NET_OK; silc_fsm_next(fsm, silc_net_connect_st_finish); - return SILC_FSM_CONTINUE; + SILC_FSM_CONTINUE; } SILC_FSM_STATE(silc_net_connect_st_finish) @@ -670,7 +695,7 @@ SILC_FSM_STATE(silc_net_connect_st_finish) silc_async_free(conn->sop); } - return SILC_FSM_FINISH; + SILC_FSM_FINISH; } static void silc_net_connect_abort(SilcAsyncOperation op, void *context) @@ -718,6 +743,7 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, /* Start async operation */ conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn); if (!conn->op) { + silc_free(conn); callback(SILC_NET_NO_MEMORY, NULL, context); return NULL; } @@ -726,6 +752,9 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, conn->local_ip = strdup(local_ip_addr); conn->remote = strdup(remote_ip_addr); if (!conn->remote) { + silc_async_free(conn->op); + silc_free(conn->local_ip); + silc_free(conn); callback(SILC_NET_NO_MEMORY, NULL, context); return NULL; } @@ -750,9 +779,9 @@ void silc_net_close_connection(int sock) /* Set's the socket to non-blocking mode. */ -int silc_net_set_socket_nonblock(int sock) +int silc_net_set_socket_nonblock(SilcSocket sock) { - return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK); + return fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK); } /* Converts the IP number string from numbers-and-dots notation to