Example #1
0
static void
handle_dns_result  (DskDnsLookupResult *result,
                    void               *callback_data)
{
  const char *name = callback_data;
  char *str;
  switch (result->type)
    {
    case DSK_DNS_LOOKUP_RESULT_FOUND:
      str = dsk_ip_address_to_string (result->addr);
      printf ("%s: %s\n", name, str);
      dsk_free (str);
      break;
    case DSK_DNS_LOOKUP_RESULT_NOT_FOUND:
      printf ("%s: not found\n", name);
      break;
    case DSK_DNS_LOOKUP_RESULT_TIMEOUT:
      printf ("%s: timeout\n", name);
      break;
    case DSK_DNS_LOOKUP_RESULT_BAD_RESPONSE:
      printf ("%s: bad response: %s\n", name, result->message);
      break;
    default:
      dsk_assert_not_reached ();
    }
  if (result->type != DSK_DNS_LOOKUP_RESULT_FOUND)
    {
      exit_status = 1;
      if (fatal_errors)
        exit (1);
    }
  --n_running;
}
Example #2
0
static dsk_boolean
handle_incoming_connection (DskOctetListener *listener)
{
  DskHttpServerStream *stream;

  /* accept connection */
  switch (dsk_octet_listener_accept (listener, NULL,
                                     &source, &sink, &error))
    {
    case DSK_IO_RESULT_SUCCESS:
      /* create http-server stream */
      stream = dsk_http_server_stream_new (sink, source, &server_stream_options);
      dsk_assert (stream != NULL);
      dsk_hook_trap (&stream->request_available,
                     (DskHookFunc) handle_http_stream_request_available,
                     stream,
                     dsk_object_unref);
      break;
    case DSK_IO_RESULT_AGAIN:
      break;
    case DSK_IO_RESULT_ERROR:
      dsk_main_exit (1);
      dsk_warning ("cannot accept a new socket: %s",
                   error->message);
      dsk_error_unref (error);
      error = NULL;
      return DSK_FALSE;
    case DSK_IO_RESULT_EOF:
      dsk_assert_not_reached ();
    }

  /* invoke this handler when the next incoming connection is available. */
  return DSK_TRUE;
}
Example #3
0
static void
handle_expected_subvalue (DskJsonParser *parser,
                          JsonTokenType  token)
{
  switch (token)
    {
    case JSON_TOKEN_LBRACE:
      push_stack (parser, STACK_NODE_OBJECT);
      parser->parse_state = PARSE_EXPECTING_MEMBER;
      break;
    case JSON_TOKEN_STRING:
      handle_subvalue (parser, dsk_json_value_new_string (parser->str_len,
                                                          parser->str));
      break;
    case JSON_TOKEN_LBRACKET:
      push_stack (parser, STACK_NODE_ARRAY);
      parser->parse_state = PARSE_EXPECTING_ELEMENT;
      break;
    case JSON_TOKEN_NUMBER:
      {
      /* parse number */
      double value;
      append_char_to_string_buffer (parser, 0);
      value = strtod (parser->str, NULL);

      handle_subvalue (parser, dsk_json_value_new_number (value));
      break;
      }

    case JSON_TOKEN_TRUE:
      handle_subvalue (parser, dsk_json_value_new_boolean (DSK_TRUE));
      break;
    case JSON_TOKEN_FALSE:
      handle_subvalue (parser, dsk_json_value_new_boolean (DSK_FALSE));
      break;
    case JSON_TOKEN_NULL:
      handle_subvalue (parser, dsk_json_value_new_null ());
      break;

    default:
      dsk_assert_not_reached ();
    }
}
Example #4
0
static void
handle_dns_done (DskDnsLookupResult *result,
                 void               *callback_data)
{
  DskClientStream *stream = callback_data;

  stream->is_resolving_name = 0;
  switch (result->type)
    {
    case DSK_DNS_LOOKUP_RESULT_FOUND:
      {
        struct sockaddr_storage addr;
        unsigned addr_len;
        dsk_ip_address_to_sockaddr (result->addr, stream->port, &addr, &addr_len);
        begin_connecting_sockaddr (stream, addr_len, (struct sockaddr *) &addr);
      }
      break;
    case DSK_DNS_LOOKUP_RESULT_NOT_FOUND:
      dsk_octet_stream_set_last_error (&stream->base_instance,
                             "dns entry for %s not found",
                             stream->name);
      maybe_set_autoreconnect_timer (stream);
      break;
    case DSK_DNS_LOOKUP_RESULT_TIMEOUT:
      dsk_octet_stream_set_last_error (&stream->base_instance,
                                       "dns lookup for %s timed out",
                                       stream->name);
      maybe_set_autoreconnect_timer (stream);
      break;
    case DSK_DNS_LOOKUP_RESULT_BAD_RESPONSE:
      dsk_octet_stream_set_last_error (&stream->base_instance,
                                       "dns lookup for %s failed: %s",
                                       stream->name, result->message);
      maybe_set_autoreconnect_timer (stream);
      break;
    default:
      dsk_assert_not_reached ();
    }

  dsk_object_unref (stream);
}
Example #5
0
DskIOResult
dsk_websocket_receive  (DskWebsocket *websocket,
                        unsigned     *length_out,
                        uint8_t     **data_out,
                        DskError    **error)
{
  uint8_t header[9];
  uint64_t length;
restart:
  maybe_discard_data (websocket);
  if (websocket->incoming.size < 9)
    return DSK_IO_RESULT_AGAIN;
  dsk_buffer_peek (&websocket->incoming, 9, header);
  length = dsk_uint64be_parse (header + 1);
  if (length > websocket->max_length)
    {
      switch (websocket->too_long_mode)
        {
        case DSK_WEBSOCKET_MODE_DROP:
          websocket->to_discard = length + 9;
          goto restart;
        case DSK_WEBSOCKET_MODE_SHUTDOWN:
          do_deferred_shutdown (websocket);
          return DSK_IO_RESULT_ERROR;
        case DSK_WEBSOCKET_MODE_RETURN_ERROR:
          websocket->to_discard = length + 9;
          maybe_discard_data (websocket);
          dsk_set_error (error, "packet too long (%"PRIu64" bytes)", length);
          return DSK_IO_RESULT_ERROR;
        }
    }
  switch (header[0])
    {
    case 0x00:
      /* uh oh - shutdown packet */
      dsk_buffer_discard (&websocket->incoming, 9 + length);
      do_deferred_shutdown (websocket);
      return DSK_IO_RESULT_EOF;
    case 0xff:
      if (websocket->incoming.size - 9 < length)
        return DSK_IO_RESULT_AGAIN;
      *length_out = length;
      *data_out = dsk_malloc (length);
      dsk_buffer_discard (&websocket->incoming, 9);
      *data_out = dsk_malloc (length);
      dsk_buffer_read (&websocket->incoming, length, *data_out);
      update_hooks_with_buffer (websocket);
      return DSK_IO_RESULT_SUCCESS;
    default:
      /* error */
      switch (websocket->bad_packet_type_mode)
        {
        case DSK_WEBSOCKET_MODE_SHUTDOWN:
          do_deferred_shutdown (websocket);
          break;
        case DSK_WEBSOCKET_MODE_RETURN_ERROR:
          dsk_set_error (error, "packet had bad type: 0x%02x", header[0]);
          websocket->to_discard = length + 9;
          maybe_discard_data (websocket);
          return DSK_IO_RESULT_ERROR;
        case DSK_WEBSOCKET_MODE_DROP:
          websocket->to_discard = length + 9;
          goto restart;
        }
    }
  dsk_assert_not_reached ();
  return DSK_IO_RESULT_ERROR;
}
Example #6
0
/* Converting pattern to NFS_State, allowing transitions that
   don't consume characters */
static struct NFA_State *
pattern_to_nfa_state (struct Pattern *pattern,
                      unsigned pattern_index,
                      struct NFA_State *result,
                      DskMemPool *pool)
{
  struct NFA_State *b, *rv;
  struct NFA_Transition *trans;
tail_recurse:
  switch (pattern->type)
    {
    case PATTERN_LITERAL:
      /* Allocate state with one transition */
      rv = dsk_mem_pool_alloc (pool, sizeof (struct NFA_State));
      rv->pattern_index = pattern_index;
      rv->pattern = pattern;
      rv->transitions = NULL;
      rv->flag = 0;
      rv->is_match = DSK_FALSE;
      prepend_transition (&rv->transitions, pattern->info.literal, result, pool);
      break;
      
    case PATTERN_ALT:
      rv = pattern_to_nfa_state (pattern->info.alternation.a, pattern_index, result, pool);
      b = pattern_to_nfa_state (pattern->info.alternation.b, pattern_index, result, pool);
      for (trans = b->transitions; trans; trans = trans->next_in_state)
        prepend_transition (&rv->transitions, trans->char_class, trans->next_state, pool);
      break;
    case PATTERN_CONCAT:
      /* NOTE: we handle tail_recursion to benefit long strings of concatenation
             (((('a' . 'b') . 'c') . 'd') . 'e')
         thus, the parser should be careful to arrange the concat patterns thusly */
      b = pattern_to_nfa_state (pattern->info.concat.b, pattern_index, result, pool);
      pattern = pattern->info.concat.a;
      result = b;
      goto tail_recurse;
    case PATTERN_OPTIONAL:
      rv = pattern_to_nfa_state (pattern->info.optional, pattern_index, result, pool);
      prepend_transition (&rv->transitions, NULL, result, pool);
      break;
    case PATTERN_PLUS:
      rv = pattern_to_nfa_state (pattern->info.plus, pattern_index, result, pool);
      prepend_transition (&result->transitions, NULL, rv, pool);
      break;
    case PATTERN_STAR:
      {
        struct NFA_State *new_result;
        new_result = dsk_mem_pool_alloc0 (pool, sizeof (struct NFA_State));
        new_result->pattern = pattern;
        new_result->pattern_index = pattern_index;
        prepend_transition (&new_result->transitions, NULL, result, pool);
      
        rv = pattern_to_nfa_state (pattern->info.star, pattern_index, new_result, pool);
        prepend_transition (&rv->transitions, NULL, new_result, pool);
        prepend_transition (&new_result->transitions, NULL, rv, pool);
        break;
      }
    default:
      dsk_assert_not_reached ();
    }
  return rv;
}
Example #7
0
static struct Pattern *
parse_pattern (unsigned      pattern_index,
               struct Token *token_list,
               DskMemPool   *pool,
               DskError    **error)
{
  dsk_boolean last_was_alter;
  dsk_boolean accept_empty;

  /* Handle parens */
  struct Token *token;
  for (token = token_list; token; token = token->next)
    if (token->type == TOKEN_LPAREN)
      {
        /* find matching rparen (or error) */
        struct Token *rparen = token->next;
        int balance = 1;
        struct Pattern *subpattern;
        while (rparen)
          {
            if (rparen->type == TOKEN_LPAREN)
              balance++;
            else if (rparen->type == TOKEN_RPAREN)
              {
                balance--;
                if (balance == 0)
                  break;
              }
            rparen = rparen->next;
          }
        if (balance)
          {
            /* missing right-paren */
            dsk_set_error (error, "missing right-paren in regex");
            return NULL;
          }

        /* recurse */
        rparen->prev->next = NULL;
        subpattern = parse_pattern (pattern_index, token->next, pool, error);
        if (subpattern == NULL)
          return NULL;

        /* replace parenthesized expr with subpattern; slice out remainder of list */
        token->type = TOKEN_PATTERN;
        token->pattern = subpattern;
        token->next = rparen->next;
        if (rparen->next)
          token->next->prev = token;
      }
    else if (token->type == TOKEN_RPAREN)
      {
        dsk_set_error (error, "unexpected right-paren in regex");
        return NULL;
      }

  /* Handle star/plus/qm */
  for (token = token_list; token; token = token->next)
    if (token->type == TOKEN_QUESTION_MARK
     || token->type == TOKEN_STAR
     || token->type == TOKEN_PLUS)
      {
        struct Pattern *new_pattern;
        if (token->prev == NULL || token->prev->type != TOKEN_PATTERN)
          {
            dsk_set_error (error, "'%c' must be precede by pattern",
                           token->type == TOKEN_QUESTION_MARK ? '?' 
                           : token->type == TOKEN_STAR ? '*'
                           : '+');
            return NULL;
          }
        new_pattern = dsk_mem_pool_alloc (pool, sizeof (struct Pattern));
        switch (token->type)
          {
          case TOKEN_QUESTION_MARK:
            new_pattern->type = PATTERN_OPTIONAL;
            new_pattern->info.optional = token->prev->pattern;
            break;
          case TOKEN_STAR:
            new_pattern->type = PATTERN_STAR;
            new_pattern->info.star = token->prev->pattern;
            break;
          case TOKEN_PLUS:
            new_pattern->type = PATTERN_PLUS;
            new_pattern->info.plus = token->prev->pattern;
            break;
          default:
            dsk_assert_not_reached ();
          }
        token->prev->pattern = new_pattern;

        /* remove token */
        if (token->prev)
          token->prev->next = token->next;
        else
          token_list = token->next;
        if (token->next)
          token->next->prev = token->prev;
        /* token isn't in the list now!  but it doesn't matter b/c token->next is still correct */
      }

  /* Handle concatenation */
  for (token = token_list; token && token->next; )
    {
      if (token->type == TOKEN_PATTERN
       && token->next->type == TOKEN_PATTERN)
        {
          /* concat */
          struct Pattern *new_pattern = dsk_mem_pool_alloc (pool, sizeof (struct Pattern));
          struct Token *kill;
          new_pattern->type = PATTERN_CONCAT;
          new_pattern->info.concat.a = token->pattern;
          new_pattern->info.concat.b = token->next->pattern;
          token->pattern = new_pattern;

          /* remove token->next */
          kill = token->next;
          token->next = kill->next;
          if (kill->next)
            kill->next->prev = token;
        }
      else
        token = token->next;
    }

  /* At this point we consist of nothing but alternations and
     patterns.  Scan through, discarding TOKEN_ALTER,
     and keeping track of whether the empty pattern matches */
  last_was_alter = DSK_TRUE;     /* trick the empty pattern detector
                                    into triggering on initial '|' */
  accept_empty = DSK_FALSE;
  for (token = token_list; token; token = token->next)
    if (token->type == TOKEN_ALTER)
      {
        if (last_was_alter)
          accept_empty = DSK_TRUE;
        last_was_alter = DSK_TRUE;

        /* remove token from list */
        if (token->prev)
          token->prev->next = token->next;
        else
          token_list = token->next;
        if (token->next)
          token->next->prev = token->prev;
      }
    else
      {
        last_was_alter = DSK_FALSE;
      }
  if (last_was_alter)
    accept_empty = DSK_TRUE;

  /* if we accept an empty token, toss a PATTERN_EMPTY onto the list of patterns
     in the alternation. */
  if (accept_empty || token_list == NULL)
    {
      struct Token *t = dsk_mem_pool_alloc (pool, sizeof (struct Token));
      t->next = token_list;
      t->prev = NULL;
      if (t->next)
        t->next->prev = t;
      token_list = t;

      t->type = TOKEN_PATTERN;
      t->pattern = dsk_mem_pool_alloc (pool, sizeof (struct Pattern));
    }

  /* At this point, token_list!=NULL,
     and it consists entirely of patterns.
     Reduce it to a singleton with the alternation pattern. */
  while (token_list->next != NULL)
    {
      /* create alternation pattern */
      struct Pattern *new_pattern = dsk_mem_pool_alloc (pool, sizeof (struct Pattern));
      new_pattern->type = PATTERN_ALT;
      new_pattern->info.alternation.a = token_list->pattern;
      new_pattern->info.alternation.b = token_list->next->pattern;
      token_list->pattern = new_pattern;

      /* remove token->next */
      {
        struct Token *kill = token_list->next;
        token_list->next = kill->next;
        if (kill->next)
          kill->next->prev = token_list;
      }
    }

  /* Return value consists of merely a single token-list. */
  dsk_assert (token_list != NULL && token_list->next == NULL);
  return token_list->pattern;
}