Skip to content

Commit d1820c1

Browse files
chelseakomlonmathewson
authored andcommitted
rust implementation of protover
1 parent 5418aa8 commit d1820c1

29 files changed

+1913
-4
lines changed

Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ endif
2727

2828
if USE_RUST
2929
rust_ldadd=$(top_builddir)/src/rust/target/release/@TOR_RUST_UTIL_STATIC_NAME@
30+
rust_ldadd+=$(top_builddir)/src/rust/target/release/@TOR_RUST_PROTOVER_STATIC_NAME@
31+
rust_ldadd+=$(top_builddir)/src/rust/target/release/@TOR_RUST_C_STRING_STATIC_NAME@
3032
else
3133
rust_ldadd=
3234
endif

configure.ac

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,17 @@ if test "x$enable_rust" = "xyes"; then
440440
dnl the MSVC naming convention.
441441
if test "$bwin32" = "true"; then
442442
TOR_RUST_UTIL_STATIC_NAME=tor_util.lib
443+
TOR_RUST_PROTOVER_STATIC_NAME=libprotover.lib
444+
TOR_RUST_C_STRING_STATIC_NAME=libc_string.lib
443445
else
444446
TOR_RUST_UTIL_STATIC_NAME=libtor_util.a
447+
TOR_RUST_PROTOVER_STATIC_NAME=libprotover.a
448+
TOR_RUST_C_STRING_STATIC_NAME=libc_string.a
445449
fi
446450

447451
AC_SUBST(TOR_RUST_UTIL_STATIC_NAME)
452+
AC_SUBST(TOR_RUST_PROTOVER_STATIC_NAME)
453+
AC_SUBST(TOR_RUST_C_STRING_STATIC_NAME)
448454
AC_SUBST(CARGO_ONLINE)
449455
AC_SUBST(RUST_DL)
450456

src/common/include.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ LIBOR_A_SRC = \
9494
src/common/util_bug.c \
9595
src/common/util_format.c \
9696
src/common/util_process.c \
97+
src/common/rust_types.c \
9798
src/common/sandbox.c \
9899
src/common/storagedir.c \
99100
src/common/workqueue.c \
@@ -179,6 +180,7 @@ COMMONHEADERS = \
179180
src/common/procmon.h \
180181
src/common/pubsub.h \
181182
src/common/sandbox.h \
183+
src/common/rust_types.h \
182184
src/common/storagedir.h \
183185
src/common/testsupport.h \
184186
src/common/timers.h \

src/common/rust_types.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* Copyright (c) 2017, The Tor Project, Inc. */
2+
/* See LICENSE for licensing information */
3+
4+
/**
5+
* \file rust_types.c
6+
* \brief This file is used for handling types returned from Rust to C.
7+
**/
8+
9+
#include "or.h"
10+
#include "rust_types.h"
11+
12+
#ifdef HAVE_RUST
13+
14+
void free_rust_str(char *ret);
15+
16+
/* Because Rust strings can only be freed from Rust, we first copy the string's
17+
* contents to a c pointer, and then free the Rust string.
18+
* This function can be extended to return a success/error value if needed.
19+
*/
20+
void
21+
move_rust_str_to_c_and_free(rust_str_ref_t src, char **dest)
22+
{
23+
if (!src) {
24+
log_warn(LD_BUG, "Received a null pointer from protover rust.");
25+
return;
26+
}
27+
28+
if (!dest) {
29+
log_warn(LD_BUG, "Received a null pointer from caller to protover rust. "
30+
"This results in a memory leak due to not freeing the rust "
31+
"string that was meant to be copied..");
32+
return;
33+
}
34+
35+
*dest = tor_strdup(src);
36+
free_rust_str(src);
37+
return;
38+
}
39+
40+
#else
41+
42+
/* When Rust is not enabled, this function should never be used. Log a warning
43+
* in the case that it is ever called when Rust is not enabled.
44+
*/
45+
void
46+
move_rust_str_to_c_and_free(rust_str_ref_t src, char **dest)
47+
{
48+
(void) src;
49+
(void) dest;
50+
log_warn(LD_BUG, "Received a call to free a Rust string when we are "
51+
" not running with Rust enabled.");
52+
return;
53+
}
54+
#endif /* defined(HAVE_RUST) */
55+

src/common/rust_types.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* Copyright (c) 2017, The Tor Project, Inc. */
2+
/* See LICENSE for licensing information */
3+
4+
/**
5+
* \file rust_types.h
6+
* \brief Headers for rust_types.c
7+
**/
8+
9+
#include "or.h"
10+
11+
#ifndef TOR_RUST_TYPES_H
12+
#define TOR_RUST_TYPES_H
13+
14+
/* This type is used to clearly mark strings that have been allocated in Rust,
15+
* and therefore strictly need to use the free_rust_str method to free.
16+
*/
17+
typedef char *rust_str_ref_t;
18+
19+
void move_rust_str_to_c_and_free(rust_str_ref_t src, char **dest);
20+
21+
#endif
22+

src/or/include.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ LIBTOR_A_SOURCES = \
7878
src/or/parsecommon.c \
7979
src/or/periodic.c \
8080
src/or/protover.c \
81+
src/or/protover_rust.c \
8182
src/or/proto_cell.c \
8283
src/or/proto_control0.c \
8384
src/or/proto_ext_or.c \

src/or/protover.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "protover.h"
2828
#include "routerparse.h"
2929

30+
#ifndef HAVE_RUST
31+
3032
static const smartlist_t *get_supported_protocol_list(void);
3133
static int protocol_list_contains(const smartlist_t *protos,
3234
protocol_type_t pr, uint32_t ver);
@@ -735,3 +737,5 @@ protover_free_all(void)
735737
}
736738
}
737739

740+
#endif
741+

src/or/protover.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,15 @@ typedef struct proto_entry_t {
7070
smartlist_t *ranges;
7171
} proto_entry_t;
7272

73+
#if !defined(HAVE_RUST) && defined(TOR_UNIT_TESTS)
7374
STATIC smartlist_t *parse_protocol_list(const char *s);
74-
STATIC void proto_entry_free(proto_entry_t *entry);
7575
STATIC char *encode_protocol_list(const smartlist_t *sl);
7676
STATIC const char *protocol_type_to_str(protocol_type_t pr);
7777
STATIC int str_to_protocol_type(const char *s, protocol_type_t *pr_out);
78+
STATIC void proto_entry_free(proto_entry_t *entry);
79+
80+
#endif
81+
7882
#endif /* defined(PROTOVER_PRIVATE) */
7983

8084
#endif /* !defined(TOR_PROTOVER_H) */

src/or/protover_rust.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* Copyright (c) 2016-2017, The Tor Project, Inc. */
2+
/* See LICENSE for licensing information */
3+
4+
/*
5+
* \file protover_rust.c
6+
* \brief Provide a C wrapper for functions exposed in /src/rust/protover,
7+
* and safe translation/handling between the Rust/C boundary.
8+
*/
9+
10+
#include "or.h"
11+
#include "protover.h"
12+
#include "rust_types.h"
13+
14+
#ifdef HAVE_RUST
15+
16+
int rust_protover_all_supported(const char *s, char **missing);
17+
rust_str_ref_t rust_protover_compute_for_old_tor(const char *version);
18+
rust_str_ref_t rust_protover_compute_vote(const smartlist_t *proto_votes,
19+
int threshold);
20+
rust_str_ref_t rust_protover_get_supported_protocols(void);
21+
int rust_protocol_list_supports_protocol(const char *list, protocol_type_t tp,
22+
uint32_t version);
23+
int rust_protover_is_supported_here(protocol_type_t pr, uint32_t ver);
24+
25+
/* Define for compatibility, used in main.c */
26+
void protover_free_all(void) {};
27+
28+
/*
29+
* Wrap rust_protover_is_supported_here, located in /src/rust/protover
30+
*/
31+
int
32+
protover_is_supported_here(protocol_type_t pr, uint32_t ver)
33+
{
34+
return rust_protover_is_supported_here(pr, ver);
35+
}
36+
37+
/*
38+
* Wrap rust_protover_list_supports_protocol, located in /src/rust/protover
39+
*/
40+
int
41+
protocol_list_supports_protocol(const char *list, protocol_type_t tp,
42+
uint32_t version)
43+
{
44+
return rust_protocol_list_supports_protocol(list, tp, version);
45+
}
46+
47+
/*
48+
* Wrap rust_protover_get_supported_protocols, located in /src/rust/protover
49+
*/
50+
const char *
51+
protover_get_supported_protocols(void)
52+
{
53+
rust_str_ref_t rust_protocols = rust_protover_get_supported_protocols();
54+
55+
char *protocols = NULL;
56+
if (rust_protocols != NULL) {
57+
move_rust_str_to_c_and_free(rust_protocols, &protocols);
58+
}
59+
return protocols;
60+
}
61+
62+
/*
63+
* Wrap rust_protover_compute_vote, located in /src/rust/protover
64+
*/
65+
char *
66+
protover_compute_vote(const smartlist_t *proto_strings,
67+
int threshold)
68+
{
69+
rust_str_ref_t rust_protocols = rust_protover_compute_vote(proto_strings,
70+
threshold);
71+
72+
char *protocols = NULL;
73+
if (rust_protocols != NULL) {
74+
move_rust_str_to_c_and_free(rust_protocols, &protocols);
75+
}
76+
return protocols;
77+
}
78+
79+
/*
80+
* Wrap rust_protover_all_supported, located in /src/rust/protover
81+
*/
82+
int
83+
protover_all_supported(const char *s, char **missing_out)
84+
{
85+
rust_str_ref_t missing_out_copy = NULL;
86+
int is_supported = rust_protover_all_supported(s, &missing_out_copy);
87+
88+
if (!is_supported) {
89+
move_rust_str_to_c_and_free(missing_out_copy, missing_out);
90+
}
91+
92+
return is_supported;
93+
}
94+
95+
/*
96+
* Wrap rust_compute_for_old_tor, located in /src/rust/protover
97+
*/
98+
const char *
99+
protover_compute_for_old_tor(const char *version)
100+
{
101+
rust_str_ref_t rust_protocols = rust_protover_compute_for_old_tor(version);
102+
103+
char *protocols = NULL;
104+
if (rust_protocols != NULL) {
105+
move_rust_str_to_c_and_free(rust_protocols, &protocols);
106+
}
107+
return protocols;
108+
}
109+
110+
#endif
111+

src/rust/Cargo.lock

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = ["tor_util"]
2+
members = ["tor_util", "protover", "smartlist", "external", "c_string"]
33

44
[profile.release]
55
debug = true

src/rust/c_string/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
authors = ["The Tor Project"]
3+
version = "0.0.1"
4+
name = "c_string"
5+
6+
[dependencies]
7+
libc = "0.2.22"
8+
9+
[lib]
10+
name = "c_string"
11+
path = "ffi.rs"
12+
crate_type = ["rlib", "staticlib"]
13+

src/rust/c_string/ffi.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//! FFI functions, only to be called from C.
2+
//!
3+
//! This module provides the ability for C to free strings that have been
4+
//! allocated in Rust.
5+
6+
extern crate libc;
7+
8+
use libc::c_char;
9+
use std::ffi::CString;
10+
11+
/// This allows strings allocated in Rust to be freed in Rust. Every string
12+
/// sent across the Rust/C FFI boundary should utilize this function for
13+
/// freeing strings allocated in Rust.
14+
#[no_mangle]
15+
pub extern "C" fn free_rust_str(ptr: *mut c_char) {
16+
if !ptr.is_null() {
17+
unsafe { CString::from_raw(ptr) };
18+
}
19+
}

src/rust/c_string/include.am

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
EXTRA_DIST +=\
2+
src/rust/c_string/Cargo.toml \
3+
src/rust/c_string/ffi.rs
4+
5+
src/rust/target/release/@TOR_RUST_C_STRING_STATIC_NAME@: FORCE
6+
( cd "$(abs_top_srcdir)/src/rust/c_string" ; \
7+
CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
8+
CARGO_HOME="$(abs_top_builddir)/src/rust" \
9+
$(CARGO) build --release --quiet $(CARGO_ONLINE) )
10+
11+
FORCE:
12+

src/rust/external/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
authors = ["The Tor Project"]
3+
version = "0.0.1"
4+
name = "external"
5+
6+
[dependencies]
7+
libc = "0.2.22"
8+
9+
[lib]
10+
name = "external"
11+
path = "lib.rs"
12+
crate_type = ["rlib", "staticlib"]
13+

0 commit comments

Comments
 (0)