Browse Source

Add a public tor_api.h with an implementation in tor_api.c

The main effect of this change is to commit to an extensible
long-term API.

Closes ticket 23684.
Nick Mathewson 6 years ago
parent
commit
fa02ea102e
7 changed files with 210 additions and 8 deletions
  1. 5 0
      changes/ticket23845
  2. 7 2
      src/or/include.am
  3. 8 4
      src/or/main.c
  4. 0 2
      src/or/main.h
  5. 88 0
      src/or/tor_api.c
  6. 82 0
      src/or/tor_api.h
  7. 20 0
      src/or/tor_api_internal.h

+ 5 - 0
changes/ticket23845

@@ -1,3 +1,8 @@
+  o Major features (embedding):
+    - There is now a documented stable API for programs that need to
+      embed Tor. See tor_api.h for full documentation and known bugs.
+      Closes ticket 23684.
+
   o Code simplification and refactoring:
   o Code simplification and refactoring:
     - The tor_git_revision[] constant no longer needs to be redeclared
     - The tor_git_revision[] constant no longer needs to be redeclared
       by everything that links against the rest of Tor.  Done as part
       by everything that links against the rest of Tor.  Done as part

+ 7 - 2
src/or/include.am

@@ -105,6 +105,7 @@ LIBTOR_A_SOURCES = \
 	src/or/statefile.c				\
 	src/or/statefile.c				\
 	src/or/status.c					\
 	src/or/status.c					\
 	src/or/torcert.c				\
 	src/or/torcert.c				\
+	src/or/tor_api.c				\
 	src/or/onion_ntor.c				\
 	src/or/onion_ntor.c				\
 	$(tor_platform_source)
 	$(tor_platform_source)
 
 
@@ -245,9 +246,13 @@ ORHEADERS = \
 	src/or/scheduler.h				\
 	src/or/scheduler.h				\
 	src/or/statefile.h				\
 	src/or/statefile.h				\
 	src/or/status.h					\
 	src/or/status.h					\
-	src/or/torcert.h
+	src/or/torcert.h				\
+	src/or/tor_api_internal.h
 
 
-noinst_HEADERS+= $(ORHEADERS) micro-revision.i
+# This may someday want to be an installed file?
+noinst_HEADERS += src/or/tor_api.h
+
+noinst_HEADERS += $(ORHEADERS) micro-revision.i
 
 
 micro-revision.i: FORCE
 micro-revision.i: FORCE
 	$(AM_V_at)rm -f micro-revision.tmp; \
 	$(AM_V_at)rm -f micro-revision.tmp; \

+ 8 - 4
src/or/main.c

@@ -106,6 +106,8 @@
 #include "shared_random.h"
 #include "shared_random.h"
 #include "statefile.h"
 #include "statefile.h"
 #include "status.h"
 #include "status.h"
+#include "tor_api.h"
+#include "tor_api_internal.h"
 #include "util_process.h"
 #include "util_process.h"
 #include "ext_orport.h"
 #include "ext_orport.h"
 #ifdef USE_DMALLOC
 #ifdef USE_DMALLOC
@@ -3703,14 +3705,16 @@ sandbox_init_filter(void)
   return cfg;
   return cfg;
 }
 }
 
 
-/** Main entry point for the Tor process.  Called from main(). */
-/* This function is distinct from main() only so we can link main.c into
- * the unittest binary without conflicting with the unittests' main. */
+/* Main entry point for the Tor process.  Called from tor_main(), and by
+ * anybody embedding Tor. */
 int
 int
-tor_main(int argc, char *argv[])
+tor_run_main(const tor_main_configuration_t *tor_cfg)
 {
 {
   int result = 0;
   int result = 0;
 
 
+  int argc = tor_cfg->argc;
+  char **argv = tor_cfg->argv;
+
 #ifdef _WIN32
 #ifdef _WIN32
 #ifndef HeapEnableTerminationOnCorruption
 #ifndef HeapEnableTerminationOnCorruption
 #define HeapEnableTerminationOnCorruption 1
 #define HeapEnableTerminationOnCorruption 1

+ 0 - 2
src/or/main.h

@@ -74,8 +74,6 @@ void release_lockfile(void);
 void tor_cleanup(void);
 void tor_cleanup(void);
 void tor_free_all(int postfork);
 void tor_free_all(int postfork);
 
 
-int tor_main(int argc, char *argv[]);
-
 int do_main_loop(void);
 int do_main_loop(void);
 int tor_init(int argc, char **argv);
 int tor_init(int argc, char **argv);
 
 

+ 88 - 0
src/or/tor_api.c

@@ -0,0 +1,88 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor_api.c
+ **/
+
+#include "tor_api.h"
+#include "tor_api_internal.h"
+
+// Include this after the above headers, to insure that they don't
+// depend on anything else.
+#include "orconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// We don't want to use tor_malloc and tor_free here, since this needs
+// to run before anything is initialized at all, and ought to run when
+// we're not linked to anything at all.
+
+#define raw_malloc malloc
+#define raw_free free
+
+tor_main_configuration_t *
+tor_main_configuration_new(void)
+{
+  static const char *fake_argv[] = { "tor" };
+  tor_main_configuration_t *cfg = raw_malloc(sizeof(*cfg));
+  if (cfg == NULL)
+    return NULL;
+
+  memset(cfg, 0, sizeof(*cfg));
+
+  cfg->argc = 1;
+  cfg->argv = (char **) fake_argv;
+
+  return cfg;
+}
+
+int
+tor_main_configuration_set_command_line(tor_main_configuration_t *cfg,
+                                        int argc, char *argv[])
+{
+  if (cfg == NULL)
+    return -1;
+  cfg->argc = argc;
+  cfg->argv = argv;
+  return 0;
+}
+
+void
+tor_main_configuration_free(tor_main_configuration_t *cfg)
+{
+  if (cfg == NULL)
+    return;
+  raw_free(cfg);
+}
+
+/* Main entry point for the Tor process.  Called from main().
+ *
+ * This function is distinct from main() only so we can link main.c into
+ * the unittest binary without conflicting with the unittests' main.
+ *
+ * Some embedders have historically called this function; but that usage is
+ * deprecated: they should use tor_run_main() instead.
+ */
+int
+tor_main(int argc, char *argv[])
+{
+  tor_main_configuration_t *cfg = tor_main_configuration_new();
+  if (!cfg) {
+    puts("INTERNAL ERROR: Allocation failure. Cannot proceed");
+    return 1;
+  }
+  if (tor_main_configuration_set_command_line(cfg, argc, argv) < 0) {
+    puts("INTERNAL ERROR: Can't set command line. Cannot proceed.");
+    return 1;
+  }
+  int rv = tor_run_main(cfg);
+  tor_main_configuration_free(cfg);
+  return rv;
+}
+

+ 82 - 0
src/or/tor_api.h

@@ -0,0 +1,82 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor_api.h
+ * \brief Public C API for the Tor network service.
+ *
+ * This interface is intended for use by programs that need to link Tor as
+ * a library, and launch it in a separate thread.  If you have the ability
+ * to run Tor as a separate executable, you should probably do that instead
+ * of embedding it as a library.
+ **/
+
+#ifndef TOR_API_H
+#define TOR_API_H
+
+typedef struct tor_main_configuration_t tor_main_configuration_t;
+
+/**
+ * Create and return a new tor_main_configuration().
+ */
+tor_main_configuration_t *tor_main_configuration_new(void);
+
+/**
+ * Set the command-line arguments in <b>cfg</b>.
+ *
+ * The <b>argc</b> and <b>argv</b> values here are as for main().  The
+ * contents of the argv pointer must remain unchanged until tor_run_main() has
+ * finished and you call tor_main_configuration_free().
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int tor_main_configuration_set_command_line(tor_main_configuration_t *cfg,
+                                            int argc, char *argv[]);
+/**
+ * Release all storage held in <b>cfg</b>.
+ *
+ * Once you have passed a tor_main_configuration_t to tor_run_main(), you
+ * must not free it until tor_run_main() has finished.
+ */
+void tor_main_configuration_free(tor_main_configuration_t *cfg);
+
+/**
+ * Run the tor process, as if from the command line.
+ *
+ * The command line arguments from tor_main_configuration_set_command_line()
+ * are taken as if they had been passed to main().
+ *
+ * This function will not return until Tor is done running.  It returns zero
+ * on success, and nonzero on failure.
+ *
+ * BUG 23848: In many cases, tor_main will call exit() or abort() instead of
+ * returning.  This is not the intended long-term behavior; we are trying to
+ * fix it.
+ *
+ * BUG 23847: You can only call tor_main() once in a single process; if it
+ * returns and you call it again, you may crash. This is not intended
+ * long-term behavior; we are trying to fix it.
+ *
+ * LIMITATION: You cannot run more than one instance of Tor in the same
+ * process at the same time. Concurrent calls will cause undefined behavior.
+ * We do not currently have plans to change this.
+ */
+int tor_run_main(const tor_main_configuration_t *);
+
+/**
+ * Run the tor process, as if from the command line.
+ *
+ * @deprecated Using this function from outside Tor is deprecated; you should
+ * use use tor_run_main() instead.
+ *
+ * BUGS: This function has all the same bugs as tor_run_main().
+ *
+ * LIMITATIONS: This function has all the limitations of tor_run_main().
+ */
+int tor_main(int argc, char **argv);
+
+#endif /* !defined(TOR_API_H) */
+

+ 20 - 0
src/or/tor_api_internal.h

@@ -0,0 +1,20 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_API_INTERNAL_H
+#define TOR_API_INTERNAL_H
+
+/* The contents of this type are private; don't mess with them from outside
+ * Tor. */
+struct tor_main_configuration_t {
+  /** As in main() */
+  int argc;
+  /** As in main(). This pointer is owned by the caller */
+  char **argv;
+};
+
+#endif
+