示例#1
0
文件: utils.c 项目: UIKit0/libgrss
gboolean
address_seems_public (GInetAddress *addr)
{
	return (g_inet_address_get_is_loopback (addr) == FALSE &&
	        g_inet_address_get_is_site_local (addr) == FALSE &&
	        g_inet_address_get_is_multicast (addr) == FALSE &&
	        g_inet_address_get_is_mc_link_local (addr) == FALSE &&
	        g_inet_address_get_is_mc_node_local (addr) == FALSE &&
	        g_inet_address_get_is_mc_site_local (addr) == FALSE &&
	        g_inet_address_get_is_mc_org_local (addr) == FALSE &&
	        g_inet_address_get_is_mc_global (addr) == FALSE);
}
示例#2
0
static gboolean
on_socket_input (GSocket *socket,
                 GIOCondition condition,
                 gpointer user_data)
{
  CockpitRequest *request = user_data;
  guchar first_byte;
  GInputVector vector[1] = { { &first_byte, 1 } };
  gint flags = G_SOCKET_MSG_PEEK;
  gboolean redirect_tls;
  gboolean is_tls;
  GSocketAddress *addr;
  GInetAddress *inet;
  GError *error = NULL;
  GIOStream *tls_stream;
  gssize num_read;

  num_read = g_socket_receive_message (socket,
                                       NULL, /* out GSocketAddress */
                                       vector,
                                       1,
                                       NULL, /* out GSocketControlMessage */
                                       NULL, /* out num_messages */
                                       &flags,
                                       NULL, /* GCancellable* */
                                       &error);
  if (num_read < 0)
    {
      /* Just wait and try again */
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
        {
          g_error_free (error);
          return TRUE;
        }

      if (!should_suppress_request_error (error))
        g_warning ("couldn't read from socket: %s", error->message);

      cockpit_request_finish (request);
      g_error_free (error);
      return FALSE;
    }

  is_tls = TRUE;
  redirect_tls = FALSE;

  /*
   * TLS streams are guaranteed to start with octet 22.. this way we can distinguish them
   * from regular HTTP requests
   */
  if (first_byte != 22 && first_byte != 0x80)
    {
      is_tls = FALSE;
      redirect_tls = TRUE;
      addr = g_socket_connection_get_remote_address (G_SOCKET_CONNECTION (request->io), NULL);
      if (G_IS_INET_SOCKET_ADDRESS (addr))
        {
          inet = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
          redirect_tls = !g_inet_address_get_is_loopback (inet);
        }
      g_clear_object (&addr);
    }

  if (is_tls)
    {
      tls_stream = g_tls_server_connection_new (request->io,
                                                request->web_server->certificate,
                                                &error);
      if (tls_stream == NULL)
        {
          g_warning ("couldn't create new TLS stream: %s", error->message);
          cockpit_request_finish (request);
          g_error_free (error);
          return FALSE;
        }

      g_object_unref (request->io);
      request->io = G_IO_STREAM (tls_stream);
    }
  else if (redirect_tls)
    {
      request->delayed_reply = 301;
    }

  start_request_input (request);

  /* No longer run *this* source */
  return FALSE;
}
示例#3
0
static gboolean
handler (GThreadedSocketService *service,
         GSocketConnection      *connection,
         GSocketListener        *listener,
         gpointer                user_data)
{
  GLibJsonRpcServerPrivate *jsonrpc_server = (GLibJsonRpcServerPrivate*)user_data;
  GError *error = NULL;
  
  // Check if it is a local connection. - This doesn't work!
  GSocketAddress *sockaddr
    = g_socket_connection_get_remote_address(connection,
                                             &error);
  GInetAddress *addr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(sockaddr));

  if (!jsonrpc_server->allow_non_loopback_connections)
    {
#if 0
      // Why doesn't this work?
      if (!g_inet_address_get_is_loopback(addr))
        return TRUE; // just fail
#endif
      
      gchar *addr_string = g_inet_address_to_string(addr);
      gboolean is_local = g_strstr_len(addr_string, -1, "127.0.0.1") != NULL;
      g_free(addr_string);
      if (!is_local) 
        return TRUE; // silently fail
    }

  GOutputStream *out;
  GInputStream *in;
  char buffer[1024];
  gssize size;

  out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
  in = g_io_stream_get_input_stream (G_IO_STREAM (connection));

  // Read the http header
  gboolean skip_header = TRUE;
  JsonParser *parser = json_parser_new();
  GString *json_string = g_string_new("");
  while (0 < (size = g_input_stream_read (in, buffer,
                                          sizeof buffer, NULL, NULL)))
    {
      int header_size = 0;
      
      if (skip_header)
        {
          gchar *head_end = g_strstr_len(buffer, size,
                                         "\r\n\r\n");
          if (head_end > 0)
            header_size = head_end - buffer;
          else
            continue;
        }
      
      g_string_append_len(json_string, buffer+header_size, size-header_size);
      if (json_parser_load_from_data(parser, json_string->str, -1, &error))
        break;
      else
        g_error_free(error);
    }

  // TBD:   raise error if there was a syntax error
  g_string_free(json_string, TRUE);

  // Get params object without the reader 
  JsonNode *root = json_parser_get_root(parser);
  JsonObject *root_object = json_node_get_object(root);
  JsonNode* params = json_object_get_member(root_object, "params");

  // Use reader for method and id
  JsonReader *reader = json_reader_new(json_parser_get_root(parser));
  json_reader_read_member (reader, "method");
  const gchar *method = json_reader_get_string_value (reader);
  json_reader_end_member (reader);
  
  json_reader_read_member (reader, "id");
  gint64 id = json_reader_get_int_value(reader);
  json_reader_end_member (reader);

  // Build the response which is either a response object or an error object
  JsonNode *response = NULL;
  
  /* Call the callback */
  command_hash_value_t *command_val = NULL;
  if (method)
    command_val = g_hash_table_lookup(jsonrpc_server->command_hash,
                                      method);
  if (!command_val)
    response = create_fault_msg_response(-2, "No such method!",id);
  else if (command_val->async_callback)
    {
      if (jsonrpc_server->async_busy)
        response = create_fault_msg_response(-2, "Busy!",id);
      else
        {
          // With the embedding of the mutex in the query we should
          // be able to handle more than one connection, so there
          // is no need to protect against a busy state.
          // jsonrpc_server->async_busy = TRUE;
          GLibJsonRpcAsyncQueryPrivate *query = glib_jsonrpc_server_query_new((GLibJsonRpcServer*)jsonrpc_server);
          
          // Create a secondary main loop
          (*command_val->async_callback)((GLibJsonRpcServer*)jsonrpc_server,
                                         (GLibJsonRpcAsyncQuery*)query,
                                         method,
                                         params,
                                         command_val->user_data);
          
          // Lock on a mutex
          g_mutex_lock(&query->mutex);
          g_cond_wait(&query->cond, &query->mutex);
          g_mutex_unlock(&query->mutex);

          if (query->error_num != 0)
            response = create_fault_value_response(query->error_num,query->reply,id);
          else
            response = create_response(query->reply, id);
          jsonrpc_server->async_busy = FALSE;

          // Erase the query
          glib_jsonrpc_async_query_free(query);
        }
    }
  else
    {
      JsonNode *reply;

      int ret = (*command_val->callback)((GLibJsonRpcServer*)jsonrpc_server,
                                         method,
                                         params,
                                         &reply,
                                         command_val->user_data);

      if (ret == 0)
        response = create_response(reply,id);
      else
        // For faults expect a string response containing the error
        response = create_fault_value_response(ret, reply,id);

      if (reply)
        json_node_free(reply);
    }

  if (response)
    {
      GString *response_string = g_string_new("");
  
      // Serialize response into content_string
      JsonGenerator *gen = json_generator_new ();
      gsize len;
      json_generator_set_root (gen, response);
      json_node_free(response);
      gchar *content_string = json_generator_to_data(gen, &len);
      g_object_unref (gen);

      g_string_append_printf(response_string,
                             "HTTP/1.1 200 OK\r\n"
                             "Connection: close\r\n"
                             "Content-Length: %d\r\n"
                             "Content-Type: text/xml\r\n"
                             "Date: Fri, 1 Jan 2000 00:00:00 GMT\r\n"
                             "Server: GlibJsonRPC server\r\n"
                             "\r\n"
                             "%s",
                             (int)len,
                             content_string
                             );
      g_free(content_string);
  
      g_output_stream_write (out,
                             response_string->str,
                             response_string->len,
                             NULL,NULL);
      g_string_free(response_string, TRUE);
    }

  g_object_unref(parser);

  return TRUE;
}