static long bio_dsk_ctrl (BIO *bio, int cmd, long num, void *ptr) { DskSslStream *stream = DSK_SSL_STREAM (bio->ptr); DSK_UNUSED (stream); DSK_UNUSED (num); DSK_UNUSED (ptr); //DEBUG_BIO("bio_dsk_ctrl: called with cmd=%d", cmd); switch (cmd) { case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: case BIO_CTRL_PENDING: case BIO_CTRL_WPENDING: return 1; } /* -1 seems more appropriate, but this is what bss_fd returns when it doesn't know the cmd. */ return 0; }
static DSK_CMDLINE_CALLBACK_DECLARE(handle_make_maze) { unsigned width, height; unsigned y; Game *game; DSK_UNUSED (arg_name); DSK_UNUSED (callback_data); if (arg_value == NULL) width = height = 10; else { if (sscanf (arg_value, "%ux%u", &width, &height) != 2) { dsk_set_error (error, "error parsing WIDTHxHEIGHT for --make-maze"); return DSK_FALSE; } } game = create_game ("name doesn't matter", width, height); for (y = 0; y < height; y++) { render_hwall_line_ascii (width, game->h_walls + width * y); render_vwall_line_ascii (width, game->v_walls + width * y); } render_hwall_line_ascii (width, game->h_walls); exit (0); return DSK_TRUE; }
static dsk_boolean table_checkpoint_trivial__sync (DskTableCheckpoint *checkpoint, DskError **error) { /* no sync implementation yet */ DSK_UNUSED (checkpoint); DSK_UNUSED (error); return DSK_TRUE; }
static dsk_boolean table_checkpoint_trivial__close(DskTableCheckpoint *checkpoint, DskError **error) { //TrivialTableCheckpoint *cp = (TrivialTableCheckpoint *) checkpoint; DSK_UNUSED (checkpoint); DSK_UNUSED (error); return DSK_TRUE; }
static DSK_CMDLINE_CALLBACK_DECLARE(handle_dsk_log_template) { DSK_UNUSED (arg_name); DSK_UNUSED (callback_data); DSK_UNUSED (error); dsk_daemon_log_template = arg_value; /* TODO: verify it's a valid format string, and verify that log_interval is short enough. */ return DSK_TRUE; }
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; }
static int bio_dsk_create (BIO *bio) { DSK_UNUSED (bio); // DEBUG_BIO("bio_dsk_create (%p)", bio); return 1; }
static dsk_boolean dsk_whitespace_trimmer_process (DskSyncFilter *filter, DskBuffer *out, unsigned in_length, const uint8_t *in_data, DskError **error) { DskWhitespaceTrimmer *trimmer = (DskWhitespaceTrimmer *) filter; uint8_t in_space = trimmer->in_space; DSK_UNUSED (error); while (in_length > 0) { uint8_t c = *in_data++; if (dsk_ascii_isspace (c)) { in_space = DSK_TRUE; } else { if (in_space) { if (trimmer->in_initial_space) trimmer->in_initial_space = DSK_FALSE; else dsk_buffer_append_byte (out, ' '); } in_space = DSK_FALSE; dsk_buffer_append_byte (out, c); } in_length--; } trimmer->in_space = in_space; return DSK_TRUE; }
static int set_password_cb (char *buf, int size, int rwflag, void *userdata) { DskSslContext *ctx = userdata; DSK_UNUSED (rwflag); strncpy (buf, ctx->password, size); return strlen (ctx->password); }
static int bio_dsk_destroy (BIO *bio) { DskSslStream *stream = DSK_SSL_STREAM (bio->ptr); //DEBUG_BIO("bio_dsk_destroy (%p)", bio); DSK_UNUSED (stream); return 1; }
static dsk_boolean dsk_xml_escaper_process (DskOctetFilter *filter, DskBuffer *out, unsigned in_length, const uint8_t *in_data, DskError **error) { DSK_UNUSED (filter); DSK_UNUSED (error); while (in_length > 0) { unsigned n = 0; while (n < in_length && in_data[n] != '<' && in_data[n] != '>' && in_data[n] != '&') n++; if (n) dsk_buffer_append (out, n, in_data); in_data += n; in_length -= n; while (in_length > 0) if (*in_data == '<') { in_data++; in_length--; dsk_buffer_append (out, 4, "<"); } else if (*in_data == '>') { in_data++; in_length--; dsk_buffer_append (out, 4, ">"); } else if (*in_data == '&') { in_data++; in_length--; dsk_buffer_append (out, 5, "&"); } else break; } return DSK_TRUE; }
static dsk_boolean dsk_utf8_fixer_finish (DskOctetFilter *filter, DskBuffer *out, DskError **error) { DskUtf8Fixer *fixer = (DskUtf8Fixer *) filter; unsigned i; DSK_UNUSED (error); for (i = 0; i < fixer->spare_len; i++) handle_bad_char (fixer, out, fixer->spare[i]); return DSK_TRUE; }
static DSK_CMDLINE_CALLBACK_DECLARE(handle_dsk_log_timezone) { char *end; DSK_UNUSED (callback_data); if (!dsk_date_parse_timezone (arg_value, &end, &dsk_daemon_tzoffset)) { dsk_set_error (error, "bad timezone argument '%s' to --%s", arg_value, arg_name); return DSK_FALSE; } dsk_daemon_tzoffset *= 60; return DSK_TRUE; }
static DskIOResult dsk_memory_sink_write_buffer (DskOctetSink *sink, DskBuffer *buffer, DskError **error) { DskMemorySink *msink = DSK_MEMORY_SINK (sink); unsigned max_xfer = msink->max_buffer_size - msink->buffer.size; DSK_UNUSED (error); if (msink->buffer.size >= msink->max_buffer_size) return DSK_IO_RESULT_AGAIN; dsk_buffer_transfer (&msink->buffer, buffer, max_xfer); dsk_hook_set_idle_notify (&msink->buffer_nonempty, DSK_TRUE); return DSK_IO_RESULT_SUCCESS; }
static void handle_fd_events (DskFileDescriptor fd, unsigned events, void *callback_data) { DskClientStream *stream = callback_data; DSK_UNUSED (fd); if ((events & DSK_EVENT_READABLE) != 0 && stream->base_instance.source != NULL) dsk_hook_notify (&stream->base_instance.source->readable_hook); if ((events & DSK_EVENT_WRITABLE) != 0 && stream->base_instance.sink != NULL) dsk_hook_notify (&stream->base_instance.sink->writable_hook); }
static dsk_boolean dsk_hex_decoder_finish(DskOctetFilter *filter, DskBuffer *out, DskError **error) { DskHexDecoder *dec = (DskHexDecoder *) filter; DSK_UNUSED (out); if (dec->has_nibble) { dsk_set_error (error, "stray nibble encountered- incomplete byte in hex-data"); return DSK_FALSE; } return DSK_TRUE; }
static void dump_nfa_node (struct NFA_State *state, void *callback_data) { struct NFA_Transition *trans; DSK_UNUSED (callback_data); if (state->is_match) printf ("%p: [match %u]\n", state, state->pattern_index); else printf ("%p:\n", state); for (trans = state->transitions; trans; trans = trans->next_in_state) { printf (" "); if (trans->char_class == NULL) printf ("[empty]"); else print_char_class (trans->char_class); printf (" -> %p\n", trans->next_state); } }
static DskIOResult dsk_memory_sink_write (DskOctetSink *sink, unsigned max_len, const void *data_out, unsigned *n_written_out, DskError **error) { DskMemorySink *msink = DSK_MEMORY_SINK (sink); DSK_UNUSED (error); if (msink->buffer.size >= msink->max_buffer_size) return DSK_IO_RESULT_AGAIN; if (msink->buffer.size + max_len <= msink->max_buffer_size) *n_written_out = max_len; else *n_written_out = msink->max_buffer_size - msink->buffer.size; dsk_buffer_append (&msink->buffer, *n_written_out, data_out); dsk_hook_set_idle_notify (&msink->buffer_nonempty, DSK_TRUE); return DSK_IO_RESULT_SUCCESS; }
static dsk_boolean dsk_hex_decoder_process (DskOctetFilter *filter, DskBuffer *out, unsigned in_length, const uint8_t *in_data, DskError **error) { DskHexDecoder *hexdec = (DskHexDecoder *) filter; DSK_UNUSED (error); while (in_length) { if (dsk_ascii_isxdigit (*in_data)) { if (hexdec->has_nibble) { dsk_buffer_append_byte (out, (hexdec->nibble << 4) | dsk_ascii_xdigit_value (*in_data)); hexdec->has_nibble = DSK_FALSE; } else { hexdec->nibble = dsk_ascii_xdigit_value (*in_data); hexdec->has_nibble = DSK_TRUE; } in_data++; in_length--; } else if (dsk_ascii_isspace (*in_data)) { in_data++; in_length--; } else { dsk_set_error (error, "bad character %s in hex-data", dsk_ascii_byte_name (*in_data)); return DSK_FALSE; } } return DSK_TRUE; }
static dsk_boolean dsk_utf8_fixer_process (DskOctetFilter *filter, DskBuffer *out, unsigned in_length, const uint8_t *in_data, DskError **error) { DskUtf8Fixer *fixer = (DskUtf8Fixer *) filter; DSK_UNUSED (error); retry_spare: if (fixer->spare_len) { unsigned used = 6 - fixer->spare_len; unsigned u; if (used < in_length) used = in_length; memcpy (fixer->spare + fixer->spare_len, in_data, used); switch (dsk_utf8_validate (fixer->spare_len + used, (char*) fixer->spare, &u)) { case DSK_UTF8_VALIDATION_SUCCESS: dsk_buffer_append (out, fixer->spare_len, fixer->spare); in_length -= used; in_data += used; fixer->spare_len = 0; break; case DSK_UTF8_VALIDATION_PARTIAL: dsk_assert (u > fixer->spare_len); dsk_buffer_append (out, u, fixer->spare); in_length -= u - fixer->spare_len; in_data += u - fixer->spare_len; fixer->spare_len = 0; break; case DSK_UTF8_VALIDATION_INVALID: dsk_buffer_append (out, u, fixer->spare); if (u < fixer->spare_len) { handle_bad_char (fixer, out, fixer->spare[u]); u++; memmove (fixer->spare, fixer->spare + u, fixer->spare_len - u); fixer->spare_len -= u; goto retry_spare; } else { in_length -= u - fixer->spare_len; in_data += u - fixer->spare_len; fixer->spare_len = 0; } break; } } while (in_length) { unsigned used; switch (dsk_utf8_validate (in_length, (char*) in_data, &used)) { case DSK_UTF8_VALIDATION_SUCCESS: dsk_buffer_append (out, used, in_data); return DSK_TRUE; case DSK_UTF8_VALIDATION_PARTIAL: dsk_assert (in_length - used <= 6); dsk_buffer_append (out, used, in_data); fixer->spare_len = in_length - used; memcpy (fixer->spare, in_data, fixer->spare_len); return DSK_TRUE; case DSK_UTF8_VALIDATION_INVALID: if (used > 0) { dsk_buffer_append (out, used, in_data); in_data += used; in_length -= used; } dsk_assert (in_length > 0); dsk_assert (*in_data >= 128); handle_bad_char (fixer, out, *in_data); in_length--; in_data++; break; } } return DSK_TRUE; }
static DskTableCheckpoint * table_checkpoint_trivial__create (DskTableCheckpointInterface *iface, DskDir *dir, const char *basename, unsigned cp_data_len, const uint8_t *cp_data, DskTableCheckpoint *prior, /* optional */ DskError **error) { unsigned mmapped_size; int fd; void *mmapped; TrivialTableCheckpoint *rv; DSK_UNUSED (iface); if (prior == NULL) mmapped_size = DEFAULT_MMAP_SIZE; else { dsk_assert (prior->add == table_checkpoint_trivial__add); mmapped_size = ((TrivialTableCheckpoint *) prior)->mmapped_size; } if (mmapped_size < cp_data_len + 32) { mmapped_size = cp_data_len + 32; mmapped_size += MMAP_MIN_RESIZE_GROW; mmapped_size += MMAP_GRANULARITY - 1; mmapped_size /= MMAP_GRANULARITY; mmapped_size *= MMAP_GRANULARITY; } /* create fd */ fd = dsk_dir_openfd (dir, basename, DSK_DIR_OPENFD_WRITABLE|DSK_DIR_OPENFD_TRUNCATE|DSK_DIR_OPENFD_MAY_CREATE, 0666, error); if (fd < 0) return NULL; /* truncate / fallocate */ if (ftruncate (fd, mmapped_size) < 0) { dsk_set_error (error, "error expanding file %s to %u bytes: %s", basename, mmapped_size, strerror (errno)); close (fd); return NULL; } /* mmap */ mmapped = mmap (NULL, mmapped_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (mmapped == MAP_FAILED) { dsk_set_error (error, "mmap of %u bytes failed: %s", mmapped_size, strerror (errno)); return DSK_FALSE; } rv = DSK_NEW (TrivialTableCheckpoint); rv->base = table_checkpoint_trivial__vfuncs; rv->fd = fd; rv->mmapped = mmapped; rv->mmapped_size = mmapped_size; rv->cur_size = (12 + cp_data_len + 3) / 4 * 4; ((uint32_t *) (mmapped))[0] = UINT32_TO_LE (TRIVIAL_CP_MAGIC); ((uint32_t *) (mmapped))[1] = UINT32_TO_LE (1); /* version */ ((uint32_t *) (mmapped))[2] = UINT32_TO_LE (cp_data_len); /* version */ memcpy (mmapped + 12, cp_data, cp_data_len); if (cp_data_len % 4 != 0) memset (mmapped + 12 + cp_data_len, 0, 4 - cp_data_len % 4); * ((uint32_t *) (mmapped+rv->cur_size)) = 0xffffffff; /* end-marker */ return &rv->base; }
static DskTableCheckpoint * table_checkpoint_trivial__open (DskTableCheckpointInterface *iface, DskDir *dir, const char *basename, unsigned *cp_data_len_out, uint8_t **cp_data_out, DskTableCheckpointReplayFunc func, void *func_data, DskError **error) { int fd = -1; struct stat stat_buf; void *mmapped = NULL; TrivialTableCheckpoint *rv; unsigned version, cp_data_len; unsigned at; DSK_UNUSED (iface); /* open fd */ fd = dsk_dir_openfd (dir, basename, DSK_DIR_OPENFD_WRITABLE, 0, error); if (fd < 0) return NULL; /* fstat */ if (fstat (fd, &stat_buf) < 0) { dsk_set_error (error, "fstat of %s failed: %s", basename, strerror (errno)); goto error_cleanup; } /* mmap */ mmapped = mmap (NULL, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (mmapped == MAP_FAILED) { dsk_set_error (error, "mmap of %u bytes (file %s) failed: %s", (unsigned) stat_buf.st_size, basename, strerror (errno)); goto error_cleanup; } /* check format */ if (((uint32_t*)mmapped)[0] != UINT32_TO_LE (TRIVIAL_CP_MAGIC)) { dsk_set_error (error, "checkpoint file %s has bad magic", basename); goto error_cleanup; } version = UINT32_FROM_LE (((uint32_t*)mmapped)[1]); if (version != 1) { dsk_set_error (error, "checkpoint file %s has bad version %u", basename, version); goto error_cleanup; } cp_data_len = UINT32_FROM_LE (((uint32_t*)mmapped)[2]); /* replay */ at = 12 + (cp_data_len + 3) / 4 * 4; if (at + 4 > stat_buf.st_size) { dsk_set_error (error, "checkpoint data length (%u) too big for file's length (%u)", cp_data_len, (unsigned) stat_buf.st_size); goto error_cleanup; } while (* (uint32_t*) (mmapped+at) != 0xffffffff) { uint32_t key_len, value_len; uint32_t kv_len, kvp_len; if (at + 8 > stat_buf.st_size) { dsk_set_error (error, "checkpoint entry header too long"); goto error_cleanup; } key_len = UINT32_FROM_LE (((uint32_t *) (mmapped+at))[0]); value_len = UINT32_FROM_LE (((uint32_t *) (mmapped+at))[1]); kv_len = key_len + value_len; if (kv_len < key_len) { dsk_set_error (error, "key+value length greater than 4G"); goto error_cleanup; } kvp_len = (kv_len + 3) / 4 * 4; if (at + 8 + kvp_len + 4 > stat_buf.st_size) { dsk_set_error (error, "checkpoint entry data too long"); goto error_cleanup; } if (!func (key_len, mmapped + at + 8, value_len, mmapped + at + 8 + key_len, func_data, error)) { if (error && !*error) dsk_set_error (error, "replay handler returned false but didn't set error"); goto error_cleanup; } at += 8 + kvp_len; } /* copy cp_data */ if (cp_data_len_out != NULL) *cp_data_len_out = cp_data_len; if (cp_data_out != NULL) { *cp_data_out = dsk_malloc (cp_data_len); memcpy (*cp_data_out, mmapped + 12, cp_data_len); } rv = DSK_NEW (TrivialTableCheckpoint); rv->base = table_checkpoint_trivial__vfuncs; rv->fd = fd; rv->mmapped = mmapped; rv->mmapped_size = stat_buf.st_size; rv->cur_size = at; return &rv->base; error_cleanup: if (mmapped != NULL && munmap ((void*) mmapped, stat_buf.st_size) < 0) dsk_warning ("error calling munmap(): %s", strerror (errno)); if (fd >= 0) close (fd); return NULL; }