static void handle_fd_connecting (DskFileDescriptor fd, unsigned events, void *callback_data) { int err = dsk_errno_from_fd (fd); DskClientStream *stream = callback_data; DSK_UNUSED (events); if (err == 0) { stream->is_connecting = DSK_FALSE; stream->is_connected = DSK_TRUE; handle_fd_connected (stream); /* sets the watch on the fd */ return; } if (err != EINTR && err != EAGAIN) { dsk_octet_stream_set_last_error (&stream->base_instance, "error finishing connection to %s: %s", stream->name, strerror (err)); dsk_dispatch_close_fd (dsk_dispatch_default (), stream->fd); stream->fd = -1; stream->is_connecting = DSK_FALSE; maybe_set_autoreconnect_timer (stream); return; } /* wait for another notification */ return; }
DskDispatchSignal*dsk_main_add_signal (int signal_number, DskSignalHandler func, void *func_data) { return dsk_dispatch_add_signal (dsk_dispatch_default (), signal_number, func, func_data); }
DskDispatchChild *dsk_main_add_child (int process_id, DskChildHandler func, void *func_data) { return dsk_dispatch_add_child (dsk_dispatch_default (), process_id, func, func_data); }
/* --- Creating a user in a game --- */ static User * create_user (Game *game, const char *name, unsigned width, unsigned height) { User *user = dsk_malloc (sizeof (User)); Cell *cell; user->name = dsk_strdup (name); user->base.type = OBJECT_TYPE_USER; user->base.game = game; /* pick random unoccupied position */ teleport_object (&user->base); cell = game->cells + (user->base.x / CELL_SIZE) + (user->base.y / CELL_SIZE) * game->universe_width; add_object_to_game_list (&user->base); add_object_to_cell_list (&user->base); user->bullet_block = 0; user->bullet_x = user->bullet_y = 0; user->width = width; user->height = height; user->dead_count = 0; user->last_seen_time = dsk_dispatch_default ()->last_dispatch_secs; user->move_x = user->move_y = 0; user->last_update = (unsigned)(-1); return user; }
DskDispatchTimer *dsk_main_add_timer_millis(unsigned milliseconds, DskTimerFunc func, void *func_data) { return dsk_dispatch_add_timer_millis (dsk_dispatch_default (), milliseconds, func, func_data); }
DskDispatchTimer *dsk_main_add_timer (unsigned timeout_secs, unsigned timeout_usecs, DskTimerFunc func, void *func_data) { return dsk_dispatch_add_timer (dsk_dispatch_default (), timeout_secs, timeout_usecs, func, func_data); }
int dsk_main_run (void) { DskDispatch *d = dsk_dispatch_default (); while (main_exit_status < 0) dsk_dispatch_run (d); return main_exit_status; }
void dsk_main_watch_fd (DskFileDescriptor fd, unsigned events, DskFDFunc callback, void *callback_data) { dsk_assert (fd >= 0); dsk_dispatch_watch_fd (dsk_dispatch_default (), fd, events, callback, callback_data); }
static void maybe_set_autoreconnect_timer (DskClientStream *stream) { dsk_assert (stream->reconnect_timer == NULL); if (stream->reconnect_time_ms >= 0) stream->reconnect_timer = dsk_dispatch_add_timer_millis (dsk_dispatch_default (), stream->reconnect_time_ms, handle_reconnect_timer_expired, stream); }
static void handle_fd_connected (DskClientStream *stream) { stream_do_watch_fd (stream); dsk_assert (stream->idle_disconnect_timer == NULL); if (stream->idle_disconnect_time_ms >= 0) stream->idle_disconnect_timer = dsk_dispatch_add_timer_millis (dsk_dispatch_default (), stream->idle_disconnect_time_ms, handle_idle_too_long, stream); }
/* use -1 to disable these timeouts */ void dsk_client_stream_set_reconnect_time (DskClientStream *client, int millis) { /* short-circuit no-op cases */ if (millis < 0) { if (client->reconnect_time_ms == -1) return; millis = -1; } else if (client->reconnect_time_ms == millis) return; /* if we have a valid file-descriptor or we are resolving the name, there then the reconnect_time_ms is not currently relevant: set it and go */ if (client->fd != -1 || client->is_resolving_name) { client->reconnect_time_ms = millis; return; } if (millis == -1) { /* handle timer removal */ if (client->reconnect_timer) { dsk_dispatch_remove_timer (client->reconnect_timer); client->reconnect_timer = NULL; } else dsk_warn_if_reached ("no reconnect timer?"); } else { if (client->reconnect_time_ms >= 0) dsk_dispatch_remove_timer (client->reconnect_timer); else dsk_assert (client->reconnect_timer == NULL); client->reconnect_time_ms = millis; /* TODO: subtract elapsed time from last disconnect / failed to connect */ client->reconnect_timer = dsk_dispatch_add_timer_millis (dsk_dispatch_default (), millis, handle_reconnect_timer_expired, client); } }
static void add_maybe_redirect_timer (void) { if (dsk_daemon_log_template == NULL) return; maybe_redirect_stdouterr (); unsigned time = dsk_dispatch_default ()->last_dispatch_secs; time -= time % dsk_daemon_log_interval; time += dsk_daemon_log_interval; dsk_main_add_timer (time, 0, (DskTimerFunc) add_maybe_redirect_timer, NULL); }
static void stream_do_watch_fd (DskClientStream *stream) { if (stream->is_connected) { int events = 0; if (stream->base_instance.source != NULL && dsk_hook_is_trapped (&stream->base_instance.source->readable_hook)) events |= DSK_EVENT_READABLE; if (stream->base_instance.sink != NULL && dsk_hook_is_trapped (&stream->base_instance.sink->writable_hook)) events |= DSK_EVENT_WRITABLE; dsk_dispatch_watch_fd (dsk_dispatch_default (), stream->fd, events, handle_fd_events, stream); } }
void dsk_client_stream_set_max_idle_time (DskClientStream *client, int millis) { if (millis < 0) millis = -1; if (millis == client->idle_disconnect_time_ms) return; if (client->idle_disconnect_timer != NULL) { dsk_dispatch_remove_timer (client->idle_disconnect_timer); client->idle_disconnect_timer = NULL; } if (millis >= 0 && client->is_connected) client->idle_disconnect_timer = dsk_dispatch_add_timer_millis (dsk_dispatch_default (), millis, handle_idle_too_long, client); client->idle_disconnect_time_ms = millis; }
void dsk_main_fd_closed (DskFileDescriptor fd) { dsk_dispatch_fd_closed (dsk_dispatch_default (), fd); }
static void begin_connecting_sockaddr (DskClientStream *stream, unsigned addr_len, struct sockaddr *addr) { int fd; dsk_assert (stream->fd == -1); dsk_assert (!stream->is_connecting); dsk_assert (!stream->is_connected); retry_sys_socket: fd = socket (addr->sa_family, SOCK_STREAM, 0); if (fd < 0) { int e = errno; if (e == EINTR) goto retry_sys_socket; if (dsk_fd_creation_failed (e)) goto retry_sys_socket; /* set error */ dsk_octet_stream_set_last_error (&stream->base_instance, "error invoking socket(2) system-call: %s", strerror (e)); goto handle_error; } /* set non-blocking */ dsk_fd_set_nonblocking (fd); dsk_fd_set_close_on_exec (fd); /* call connect() */ retry_sys_connect: if (connect (fd, addr, addr_len) < 0) { int e = errno; if (e == EINTR) goto retry_sys_connect; if (e == EAGAIN || e == EINPROGRESS) { stream->is_connecting = DSK_TRUE; stream->fd = fd; dsk_dispatch_watch_fd (dsk_dispatch_default (), fd, DSK_EVENT_WRITABLE|DSK_EVENT_READABLE, handle_fd_connecting, stream); return; } /* set error */ close (fd); dsk_octet_stream_set_last_error (&stream->base_instance, "error connecting to %s: %s", stream->name, strerror (e)); goto handle_error; } stream->is_connected = DSK_TRUE; stream->fd = fd; handle_fd_connected (stream); return; handle_error: maybe_set_autoreconnect_timer (stream); return; }
DskDispatchIdle *dsk_main_add_idle (DskIdleFunc func, void *func_data) { return dsk_dispatch_add_idle (dsk_dispatch_default (), func, func_data); }