+ SilcSocketStream sock = stream;
+ SilcSockaddr remote;
+ int ret;
+
+ SILC_LOG_DEBUG(("Sending data to UDP socket %d", sock->sock));
+
+ /* Set sockaddr */
+ if (!silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port))
+ return -2;
+
+ /* Send */
+ 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 */
+
+typedef struct {
+ SilcNetStatus status;
+ SilcSocketStreamStatus stream_status;
+ SilcStream stream;
+ SilcFSMStruct fsm;
+ SilcFSMEventStruct event;
+ SilcAsyncOperation op;
+ SilcAsyncOperation sop;
+ char *local_ip;
+ char *remote;
+ char ip_addr[64];
+ int sock;
+ SilcNetCallback callback;
+ void *context;
+ unsigned int port : 24;
+ unsigned int retry : 7;
+ unsigned int aborted : 1;
+} *SilcNetConnect;
+
+SILC_FSM_STATE(silc_net_connect_st_start);
+SILC_FSM_STATE(silc_net_connect_st_connected);
+SILC_FSM_STATE(silc_net_connect_st_stream);
+SILC_FSM_STATE(silc_net_connect_st_finish);
+
+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)
+{
+ SilcNetConnect conn = fsm_context;