tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2015
- 14 participants
- 1182 discussions

29 Oct '15
commit 2f063781c8863554a0dba55fdc4778096dc6b774
Author: Translation commit bot <translation(a)torproject.org>
Date: Thu Oct 29 19:15:03 2015 +0000
Update translations for bridgedb
---
es/LC_MESSAGES/bridgedb.po | 338 ++++++++++++++++++++++----------------------
1 file changed, 170 insertions(+), 168 deletions(-)
diff --git a/es/LC_MESSAGES/bridgedb.po b/es/LC_MESSAGES/bridgedb.po
index 0115618..cedf564 100644
--- a/es/LC_MESSAGES/bridgedb.po
+++ b/es/LC_MESSAGES/bridgedb.po
@@ -11,20 +11,22 @@
# NinjaTuna <nort0ngh0st(a)hotmail.com>, 2011
# Noel Torres <envite(a)rolamasao.org>, 2013
# Paola Falcon <cacoepy(a)gmail.com>, 2014
+# ROSA CRUELLS <thelmacat65(a)hotmail.com>, 2015
# Jonis <srvial(a)hotmail.com>, 2014
# strel, 2013-2015
# strel, 2012
msgid ""
msgstr ""
"Project-Id-Version: The Tor Project\n"
-"Report-Msgid-Bugs-To: 'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…'POT-Creation-Date: 2015-03-19 22:13+0000\n"
-"PO-Revision-Date: 2015-07-03 07:21+0000\n"
-"Last-Translator: Ignacio Rodríguez <ignacio(a)sugarlabs.org>\n"
-"Language-Team: Spanish (http://www.transifex.com/projects/p/torproject/language/es/)\n"
+"Report-Msgid-Bugs-To: 'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…'\n"
+"POT-Creation-Date: 2015-07-25 03:40+0000\n"
+"PO-Revision-Date: 2015-10-29 19:12+0000\n"
+"Last-Translator: ROSA CRUELLS <thelmacat65(a)hotmail.com>\n"
+"Language-Team: Spanish (http://www.transifex.com/otf/torproject/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -39,57 +41,182 @@ msgstr ""
#. "fteproxy"
#. "Tor"
#. "Tor Browser"
-#: lib/bridgedb/HTTPServer.py:107
+#: bridgedb/https/server.py:167
msgid "Sorry! Something went wrong with your request."
msgstr "¡Lo sentimos! Algo mal pasó con tu solicitud."
-#: lib/bridgedb/strings.py:18
+#: bridgedb/https/templates/base.html:79
+msgid "Report a Bug"
+msgstr "Reportar una falla"
+
+#: bridgedb/https/templates/base.html:82
+msgid "Source Code"
+msgstr "Código fuente"
+
+#: bridgedb/https/templates/base.html:85
+msgid "Changelog"
+msgstr "Registro de cambios"
+
+#: bridgedb/https/templates/base.html:88
+msgid "Contact"
+msgstr "Contacto"
+
+#: bridgedb/https/templates/bridges.html:35
+msgid "Select All"
+msgstr "Seleccionar todos"
+
+#: bridgedb/https/templates/bridges.html:40
+msgid "Show QRCode"
+msgstr "Mostrar código QR"
+
+#: bridgedb/https/templates/bridges.html:52
+msgid "QRCode for your bridge lines"
+msgstr "Código QR para sus líneas de repetidores puente"
+
+#. TRANSLATORS: Please translate this into some silly way to say
+#. "There was a problem!" in your language. For example,
+#. for Italian, you might translate this into "Mama mia!",
+#. or for French: "Sacrebleu!". :)
+#: bridgedb/https/templates/bridges.html:67
+#: bridgedb/https/templates/bridges.html:125
+msgid "Uh oh, spaghettios!"
+msgstr "Oh oh, ¡la liamos!"
+
+#: bridgedb/https/templates/bridges.html:68
+msgid "It seems there was an error getting your QRCode."
+msgstr "Parece que hubo un error al obtener su código QR."
+
+#: bridgedb/https/templates/bridges.html:73
+msgid ""
+"This QRCode contains your bridge lines. Scan it with a QRCode reader to copy"
+" your bridge lines onto mobile and other devices."
+msgstr "Este código QR contiene sus líneas de repetidores puente (bridges). Escanéelo con un lector de códigos QR para copiar sus líneas de puentes a dispositivos móviles/celulares y otros dispositivos."
+
+#: bridgedb/https/templates/bridges.html:131
+msgid "There currently aren't any bridges available..."
+msgstr "Ahora mismo no hay ningún bridge disponible..."
+
+#: bridgedb/https/templates/bridges.html:132
+#, python-format
+msgid ""
+" Perhaps you should try %s going back %s and choosing a different bridge "
+"type!"
+msgstr "¡Tal vez debas probar %s volviendo atrás %s y seleccionando un tipo diferente de bridge!"
+
+#: bridgedb/https/templates/index.html:11
+#, python-format
+msgid "Step %s1%s"
+msgstr "Paso %s1%s"
+
+#: bridgedb/https/templates/index.html:13
+#, python-format
+msgid "Download %s Tor Browser %s"
+msgstr "Descarga %s Tor Browser %s"
+
+#: bridgedb/https/templates/index.html:25
+#, python-format
+msgid "Step %s2%s"
+msgstr "Paso %s2%s"
+
+#: bridgedb/https/templates/index.html:27
+#, python-format
+msgid "Get %s bridges %s"
+msgstr "Obtenga los %s puentes ('bridges') %s"
+
+#: bridgedb/https/templates/index.html:36
+#, python-format
+msgid "Step %s3%s"
+msgstr "Paso %s3%s"
+
+#: bridgedb/https/templates/index.html:38
+#, python-format
+msgid "Now %s add the bridges to Tor Browser %s"
+msgstr "Ahora %s añada los puentes de red al Navegador Tor %s"
+
+#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
+#. beginning of words are present in your final translation. Thanks!
+#. (These are used to insert HTML5 underlining tags, to mark accesskeys
+#. for disabled users.)
+#: bridgedb/https/templates/options.html:38
+#, python-format
+msgid "%sJ%sust give me bridges!"
+msgstr "¡%sS%sólo dame puentes de red!"
+
+#: bridgedb/https/templates/options.html:51
+msgid "Advanced Options"
+msgstr "Opciones avanzadas"
+
+#: bridgedb/https/templates/options.html:86
+msgid "No"
+msgstr "No"
+
+#: bridgedb/https/templates/options.html:87
+msgid "none"
+msgstr "ninguno"
+
+#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
+#. beginning of words are present in your final translation. Thanks!
+#. TRANSLATORS: Translate "Yes!" as in "Yes! I do need IPv6 addresses."
+#: bridgedb/https/templates/options.html:124
+#, python-format
+msgid "%sY%ses!"
+msgstr "¡%sS%sí!"
+
+#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
+#. beginning of words are present in your final translation. Thanks!
+#. TRANSLATORS: Please do NOT translate the word "bridge"!
+#: bridgedb/https/templates/options.html:147
+#, python-format
+msgid "%sG%set Bridges"
+msgstr "%sO%sbtener bridges"
+
+#: bridgedb/strings.py:43
msgid "[This is an automated message; please do not reply.]"
msgstr "[Este es un mensaje automático; por favor no responda.]"
-#: lib/bridgedb/strings.py:20
+#: bridgedb/strings.py:45
msgid "Here are your bridges:"
msgstr "Aquí están sus bridges:"
-#: lib/bridgedb/strings.py:22
+#: bridgedb/strings.py:47
#, python-format
msgid ""
"You have exceeded the rate limit. Please slow down! The minimum time between\n"
"emails is %s hours. All further emails during this time period will be ignored."
msgstr "Ha excedido el límite de velocidad. Por favor, ¡más despacio! El tiempo mínimo entre correos electrónicos es %s horas. Los siguientes correos durante este periodo de tiempo serán ignorados. "
-#: lib/bridgedb/strings.py:25
+#: bridgedb/strings.py:50
msgid ""
"COMMANDs: (combine COMMANDs to specify multiple options simultaneously)"
msgstr "COMMANDs: (combine COMMANDs (comandos) para especificar múltiples opciones simultáneamente)"
#. TRANSLATORS: Please DO NOT translate the word "BridgeDB".
-#: lib/bridgedb/strings.py:28
+#: bridgedb/strings.py:53
msgid "Welcome to BridgeDB!"
msgstr "¡Bienvenido a BridgeDB!"
#. TRANSLATORS: Please DO NOT translate the words "transport" or "TYPE".
-#: lib/bridgedb/strings.py:30
+#: bridgedb/strings.py:55
msgid "Currently supported transport TYPEs:"
msgstr "Transport TYPEs actualmente soportados:"
-#: lib/bridgedb/strings.py:31
+#: bridgedb/strings.py:56
#, python-format
msgid "Hey, %s!"
msgstr "¡Eh, %s!"
-#: lib/bridgedb/strings.py:32
+#: bridgedb/strings.py:57
msgid "Hello, friend!"
msgstr "¡Hola amigo!"
-#: lib/bridgedb/strings.py:33 lib/bridgedb/templates/base.html:100
+#: bridgedb/strings.py:58 bridgedb/https/templates/base.html:90
msgid "Public Keys"
msgstr "Claves públicas"
#. TRANSLATORS: This string will end up saying something like:
#. "This email was generated with rainbows, unicorns, and sparkles
#. for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39."
-#: lib/bridgedb/strings.py:37
+#: bridgedb/strings.py:62
#, python-format
msgid ""
"This email was generated with rainbows, unicorns, and sparkles\n"
@@ -100,7 +227,7 @@ msgstr "Este correo fue generado con arcoiris, unicornios y chispitas para %s el
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
#. TRANSLATORS: Please DO NOT translate "Tor".
#. TRANSLATORS: Please DO NOT translate "Tor Network".
-#: lib/bridgedb/strings.py:47
+#: bridgedb/strings.py:72
#, python-format
msgid ""
"BridgeDB can provide bridges with several %stypes of Pluggable Transports%s,\n"
@@ -111,7 +238,7 @@ msgid ""
msgstr "BridgeDB puede proveer bridges con varios %stipos de Pluggable Transports%s que pueden ayudar a ofuscar sus conexiones a la red Tor, haciendo que sea más difícil para alguien que esté viendo su tráfico en la red el determinar que ud. está usando Tor.\n"
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
-#: lib/bridgedb/strings.py:54
+#: bridgedb/strings.py:79
msgid ""
"Some bridges with IPv6 addresses are also available, though some Pluggable\n"
"Transports aren't IPv6 compatible.\n"
@@ -123,7 +250,7 @@ msgstr "También hay disponibles varios bridges con direcciones IPv6, aunque alg
#. regular, or unexciting". Like vanilla ice cream. It refers to bridges
#. which do not have Pluggable Transports, and only speak the regular,
#. boring Tor protocol. Translate it as you see fit. Have fun with it.
-#: lib/bridgedb/strings.py:63
+#: bridgedb/strings.py:88
#, python-format
msgid ""
"Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any\n"
@@ -132,20 +259,20 @@ msgid ""
"\n"
msgstr "Además, BridgeDB tiene un montón de sencillos-clásicos-estándar (vanilla) bridges\n%s sin ningún Pluggable Transport %s, lo que tal vez no suena tan molón, pero que\naún pueden ayudar a eludir la censura en Internet en muchos casos.\n\n\n"
-#: lib/bridgedb/strings.py:76
+#: bridgedb/strings.py:101
msgid "What are bridges?"
msgstr "¿Qué son los puentes ('bridges')?"
-#: lib/bridgedb/strings.py:77
+#: bridgedb/strings.py:102
#, python-format
msgid "%s Bridges %s are Tor relays that help you circumvent censorship."
msgstr "Los %s bridges %s son un tipo de repetidores Tor que le ayudan a eludir la censura."
-#: lib/bridgedb/strings.py:82
+#: bridgedb/strings.py:107
msgid "I need an alternative way of getting bridges!"
msgstr "¡Necesito un modo alternativo de conseguir puentes!"
-#: lib/bridgedb/strings.py:83
+#: bridgedb/strings.py:108
#, python-format
msgid ""
"Another way to get bridges is to send an email to %s. Please note that you must\n"
@@ -153,12 +280,12 @@ msgid ""
"%s, %s or %s."
msgstr "Otra forma de obtener repetidores puente (bridges) es enviar un correo electrónico a %s. Por favor observe que tiene que enviar el correo usando la dirección de uno de los siguientes proveedores de correo electrónico:\n%s, %s or %s."
-#: lib/bridgedb/strings.py:90
+#: bridgedb/strings.py:115
msgid "My bridges don't work! I need help!"
msgstr "¡Mis bridges/puentes no funcionan! ¡Necesito ayuda!"
#. TRANSLATORS: Please DO NOT translate "Tor".
-#: lib/bridgedb/strings.py:92
+#: bridgedb/strings.py:117
#, python-format
msgid "If your Tor doesn't work, you should email %s."
msgstr "Si su Tor no funciona, debe enviar un correo a %s"
@@ -166,48 +293,48 @@ msgstr "Si su Tor no funciona, debe enviar un correo a %s"
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
#. TRANSLATORS: Please DO NOT translate "Tor".
-#: lib/bridgedb/strings.py:96
+#: bridgedb/strings.py:121
msgid ""
"Try including as much info about your case as you can, including the list of\n"
"bridges and Pluggable Transports you tried to use, your Tor Browser version,\n"
"and any messages which Tor gave out, etc."
msgstr "Intenta incluir tanta información como puedas de tu caso, incluyendo la lista de\nbridges (repetidores puente) y Pluggable Transports (transportes conectables) que\nintentaste usar, tu versión de Navegador Tor y cualquier mensaje que haya dado Tor, etc."
-#: lib/bridgedb/strings.py:103
+#: bridgedb/strings.py:128
msgid "Here are your bridge lines:"
msgstr "Aquí están tus líneas de bridge:"
-#: lib/bridgedb/strings.py:104
+#: bridgedb/strings.py:129
msgid "Get Bridges!"
msgstr "¡Obtener bridges!"
-#: lib/bridgedb/strings.py:108
+#: bridgedb/strings.py:133
msgid "Please select options for bridge type:"
msgstr "Por favor, selecciona opciones para el tipo de bridge:"
-#: lib/bridgedb/strings.py:109
+#: bridgedb/strings.py:134
msgid "Do you need IPv6 addresses?"
msgstr "¿Necesitas direcciones IPv6?"
-#: lib/bridgedb/strings.py:110
+#: bridgedb/strings.py:135
#, python-format
msgid "Do you need a %s?"
msgstr "¿Necesitas un %s?"
-#: lib/bridgedb/strings.py:114
+#: bridgedb/strings.py:139
msgid "Your browser is not displaying images properly."
msgstr "Tu navegador no está mostrando las imágenes correctamente."
-#: lib/bridgedb/strings.py:115
+#: bridgedb/strings.py:140
msgid "Enter the characters from the image above..."
msgstr "Introduce los caracteres de la imagen de arriba..."
-#: lib/bridgedb/strings.py:119
+#: bridgedb/strings.py:144
msgid "How to start using your bridges"
msgstr "Cómo comenzar a usar tus bridges"
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
-#: lib/bridgedb/strings.py:121
+#: bridgedb/strings.py:146
#, python-format
msgid ""
"To enter bridges into Tor Browser, first go to the %s Tor Browser download\n"
@@ -216,21 +343,21 @@ msgid ""
msgstr "Para introducir bridges (repetidores puente) en el Navegador Tor, primero vaya\na la %s página de descarga del Navegador Tor %s y luego siga las instrucciones\nallí para descargar e iniciar el Navegador Tor."
#. TRANSLATORS: Please DO NOT translate "Tor".
-#: lib/bridgedb/strings.py:126
+#: bridgedb/strings.py:151
msgid ""
"When the 'Tor Network Settings' dialogue pops up, click 'Configure' and follow\n"
"the wizard until it asks:"
msgstr "Cuando el cuadro de 'Configuraciones de red Tor' aparezca, haz clic en 'Configurar'\ny sigue el asistente hasta que pregunte:"
#. TRANSLATORS: Please DO NOT translate "Tor".
-#: lib/bridgedb/strings.py:130
+#: bridgedb/strings.py:155
msgid ""
"Does your Internet Service Provider (ISP) block or otherwise censor connections\n"
"to the Tor network?"
msgstr "¿Su proveedor de Internet (ISP) bloquea o censura de alguna manera las conexiones a la red Tor?"
#. TRANSLATORS: Please DO NOT translate "Tor".
-#: lib/bridgedb/strings.py:134
+#: bridgedb/strings.py:159
msgid ""
"Select 'Yes' and then click 'Next'. To configure your new bridges, copy and\n"
"paste the bridge lines into the text input box. Finally, click 'Connect', and\n"
@@ -238,153 +365,28 @@ msgid ""
"button in the 'Tor Network Settings' wizard for further assistance."
msgstr "Selecciona 'Sí' y luego haz clic en 'Siguiente'. Para configurar tus nuevos\nbridges, copia y pega las líneas de bridges en el cuadro de texto.\nPor último, haz clic en 'Conectar', ¡y listo!\nSi encuentras problemas, prueba dando clic en el botón 'Ayuda'\nen el asistente de 'Configuraciones de red Tor' para asistencia adicional."
-#: lib/bridgedb/strings.py:142
+#: bridgedb/strings.py:167
msgid "Displays this message."
msgstr "Muestra este mensaje."
#. TRANSLATORS: Please try to make it clear that "vanilla" here refers to the
#. same non-Pluggable Transport bridges described above as being
#. "plain-ol'-vanilla" bridges.
-#: lib/bridgedb/strings.py:146
+#: bridgedb/strings.py:171
msgid "Request vanilla bridges."
msgstr "Solicitar bridges estándar (vanilla)."
-#: lib/bridgedb/strings.py:147
+#: bridgedb/strings.py:172
msgid "Request IPv6 bridges."
msgstr "Solicitar bridges IPv6."
#. TRANSLATORS: Please DO NOT translate the word the word "TYPE".
-#: lib/bridgedb/strings.py:149
+#: bridgedb/strings.py:174
msgid "Request a Pluggable Transport by TYPE."
msgstr "Solicitar un Pluggable Transport por TYPE."
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "GnuPG".
-#: lib/bridgedb/strings.py:152
+#: bridgedb/strings.py:177
msgid "Get a copy of BridgeDB's public GnuPG key."
msgstr "Obtener una copia de la clave pública GnuPG de BridgeDB."
-
-#: lib/bridgedb/templates/base.html:89
-msgid "Report a Bug"
-msgstr "Reportar una falla"
-
-#: lib/bridgedb/templates/base.html:92
-msgid "Source Code"
-msgstr "Código fuente"
-
-#: lib/bridgedb/templates/base.html:95
-msgid "Changelog"
-msgstr "Registro de cambios"
-
-#: lib/bridgedb/templates/base.html:98
-msgid "Contact"
-msgstr "Contactar"
-
-#: lib/bridgedb/templates/bridges.html:81
-msgid "Select All"
-msgstr "Seleccionar todos"
-
-#: lib/bridgedb/templates/bridges.html:87
-msgid "Show QRCode"
-msgstr "Mostrar código QR"
-
-#: lib/bridgedb/templates/bridges.html:100
-msgid "QRCode for your bridge lines"
-msgstr "Código QR para sus líneas de repetidores puente"
-
-#. TRANSLATORS: Please translate this into some silly way to say
-#. "There was a problem!" in your language. For example,
-#. for Italian, you might translate this into "Mama mia!",
-#. or for French: "Sacrebleu!". :)
-#: lib/bridgedb/templates/bridges.html:115
-#: lib/bridgedb/templates/bridges.html:175
-msgid "Uh oh, spaghettios!"
-msgstr "Oh oh, ¡la liamos!"
-
-#: lib/bridgedb/templates/bridges.html:116
-msgid "It seems there was an error getting your QRCode."
-msgstr "Parece que hubo un error al obtener su código QR."
-
-#: lib/bridgedb/templates/bridges.html:121
-msgid ""
-"This QRCode contains your bridge lines. Scan it with a QRCode reader to copy"
-" your bridge lines onto mobile and other devices."
-msgstr "Este código QR contiene sus líneas de repetidores puente (bridges). Escanéelo con un lector de códigos QR para copiar sus líneas de puentes a dispositivos móviles/celulares y otros dispositivos."
-
-#: lib/bridgedb/templates/bridges.html:181
-msgid "There currently aren't any bridges available..."
-msgstr "Ahora mismo no hay ningún bridge disponible..."
-
-#: lib/bridgedb/templates/bridges.html:182
-#, python-format
-msgid ""
-" Perhaps you should try %s going back %s and choosing a different bridge "
-"type!"
-msgstr "¡Tal vez debas probar %s volviendo atrás %s y seleccionando un tipo diferente de bridge!"
-
-#: lib/bridgedb/templates/index.html:11
-#, python-format
-msgid "Step %s1%s"
-msgstr "Paso %s1%s"
-
-#: lib/bridgedb/templates/index.html:13
-#, python-format
-msgid "Download %s Tor Browser %s"
-msgstr "Descarga %s Tor Browser %s"
-
-#: lib/bridgedb/templates/index.html:25
-#, python-format
-msgid "Step %s2%s"
-msgstr "Paso %s2%s"
-
-#: lib/bridgedb/templates/index.html:27
-#, python-format
-msgid "Get %s bridges %s"
-msgstr "Obtenga los %s puentes ('bridges') %s"
-
-#: lib/bridgedb/templates/index.html:36
-#, python-format
-msgid "Step %s3%s"
-msgstr "Paso %s3%s"
-
-#: lib/bridgedb/templates/index.html:38
-#, python-format
-msgid "Now %s add the bridges to Tor Browser %s"
-msgstr "Ahora %s añada los bridges al Tor Browser %s"
-
-#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
-#. beginning of words are present in your final translation. Thanks!
-#. (These are used to insert HTML5 underlining tags, to mark accesskeys
-#. for disabled users.)
-#: lib/bridgedb/templates/options.html:38
-#, python-format
-msgid "%sJ%sust give me bridges!"
-msgstr "¡%sS%sólo dame los bridges!"
-
-#: lib/bridgedb/templates/options.html:52
-msgid "Advanced Options"
-msgstr "Opciones avanzadas"
-
-#: lib/bridgedb/templates/options.html:88
-msgid "No"
-msgstr "No"
-
-#: lib/bridgedb/templates/options.html:89
-msgid "none"
-msgstr "ninguno"
-
-#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
-#. beginning of words are present in your final translation. Thanks!
-#. TRANSLATORS: Translate "Yes!" as in "Yes! I do need IPv6 addresses."
-#: lib/bridgedb/templates/options.html:127
-#, python-format
-msgid "%sY%ses!"
-msgstr "¡%sS%sí!"
-
-#. TRANSLATORS: Please make sure the '%s' surrounding single letters at the
-#. beginning of words are present in your final translation. Thanks!
-#. TRANSLATORS: Please do NOT translate the word "bridge"!
-#: lib/bridgedb/templates/options.html:151
-#, python-format
-msgid "%sG%set Bridges"
-msgstr "%sO%sbtener bridges"
1
0

29 Oct '15
commit 45d6743548f56d63ece3d1e13abb047f78cd8151
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Thu Oct 29 18:58:18 2015 +0100
Add Nick's dos-taxonomy report.
---
2015/dos-taxonomy/.gitignore | 5 +
2015/dos-taxonomy/Makefile | 31 +++
2015/dos-taxonomy/dos-taxonomy.md | 498 +++++++++++++++++++++++++++++++++++++
2015/dos-taxonomy/tex_header.tex | 38 +++
2015/dos-taxonomy/tortechrep.cls | 1 +
5 files changed, 573 insertions(+)
diff --git a/2015/dos-taxonomy/.gitignore b/2015/dos-taxonomy/.gitignore
new file mode 100644
index 0000000..f16048a
--- /dev/null
+++ b/2015/dos-taxonomy/.gitignore
@@ -0,0 +1,5 @@
+dos-taxonomy.html
+dos-taxonomy.pdf
+dos-taxonomy-2015-10-29.pdf
+dos-taxonomy.tex
+
diff --git a/2015/dos-taxonomy/Makefile b/2015/dos-taxonomy/Makefile
new file mode 100644
index 0000000..fa8e85f
--- /dev/null
+++ b/2015/dos-taxonomy/Makefile
@@ -0,0 +1,31 @@
+.PHONY : main
+
+MAIN=dos-taxonomy
+LATEX=pdflatex
+MARKDOWN=maruku
+
+all: paper html tidy
+
+html: $(MAIN).md
+ $(MARKDOWN) $(MAIN).md
+
+$(MAIN).tex.tmp: $(MAIN).md
+ $(MARKDOWN) --tex $(MAIN).md -o $(MAIN).tex.tmp
+
+$(MAIN).tex: $(MAIN).tex.tmp tex_header.tex
+ cat tex_header.tex > $(MAIN).tex
+ perl -ne 'BEGIN{$$P=0;} print if $$P; if (/begin.document/) {$$P=1;} ' $(MAIN).tex.tmp >> $(MAIN).tex
+
+paper: $(MAIN).pdf
+
+$(MAIN).pdf: $(MAIN).tex
+ $(LATEX) $(MAIN)
+ # bibtex $(MAIN)
+ $(LATEX) $(MAIN)
+ $(LATEX) $(MAIN)
+
+tidy:
+ rm -f *.dvi *.aux *.log *.nav *.snm *.toc *.out *.vrb *.bbl *.blg $(MAIN).tex.tmp
+
+clean:
+ rm -f *.dvi *.aux *.log *.nav *.snm *.toc *.out *.vrb *.bbl *.blg $(MAIN).ps $(MAIN).pdf $(MAIN).tex $(MAIN).tex.tmp
diff --git a/2015/dos-taxonomy/dos-taxonomy.md b/2015/dos-taxonomy/dos-taxonomy.md
new file mode 100644
index 0000000..6d3c6e3
--- /dev/null
+++ b/2015/dos-taxonomy/dos-taxonomy.md
@@ -0,0 +1,498 @@
+
+Introduction
+------------
+
+This document surveys what we know about potential denial-of-service
+attacks against Tor, in order to focus our efforts over the coming years
+to increase Tor's resistance against these attacks.
+
+Why? We spend a lot of time thinking about anonymity defenses and
+security defenses, and less about DoS defenses. And while actual DoS
+attacks up to present have been (with a couple of exceptions)
+comparatively unsophisticated, we should not let our approach to them
+become reactive: instead we should systematize our approach to defending
+Tor against these attacks, and take a proactive stance towards them.
+
+Denial of service attacks are a special problem for anonymity networks,
+since many of them can be adapted to weaken anonymity. Bugs
+that would simply be annoying resource exhaustion issues against other
+network programs can be a real threat to user security.
+
+Here we provide an overview of denial-of-service vectors against
+anonymity networks in general and Tor in particular, and discuss how
+best to prioritize responses against them.
+
+We'll conclude below that our best focus in each area is to look for
+categorical defenses and protocol improvements, to better resist
+more categories of attacks before they occur.
+
+
+Methodology
+-----------
+
+There are quite a few ways to classify DoS attacks: by the exhausted
+resource, by the kind of service targeted, by the required
+attacker resources, by the required attacker expertise, etc.
+
+Here we are considering each attack in terms of how well the attack
+achieves the attacker's goals. For each attack we will consider:
+
+ * How difficult the attack is to perform.
+ * How difficult it is to exploit the attack to achieve particular
+ outcomes.
+ * How repeatable the attack is over time. (How hard it is to detect;
+ how hard it is to prevent once detected.)
+ * The difficulty of mitigating this sort of attack.
+
+Results and Taxonomy
+--------------------
+
+### Attacks by resource ###
+
+#### CPU consumption attacks ####
+
+Onion routing servers perform expensive cryptographic computations on behalf of
+their users. Additionally, some computations internal to the Tor process
+use inefficient algorithms (like linear searches), which might
+prove problematic if those algorithms' inputs prove large.
+
+An attacker could mount CPU consumption attacks by running a large
+number of legitimate clients and shoving traffic through them.
+That's comparatively simple to do, but comparatively expensive.
+
+Worse, an attacker could construct bogus cryptographic requests that
+require relays to perform a lot of computation before realizing that
+the request was spurious. An attacker can also mount CPU
+consumption attacks by finding an inefficient algorithm in and
+provoking it to be used far more than it would be in ordinary
+operation. These attacks need a little engineering and programming
+skill, but create a higher impact for a given amount of computation.
+
+CPU exhaustion attacks can reduce the CPU resources available for
+legitimate operations. They can also interfere with other traffic,
+thereby creating patterns in users' streams that can be observed
+elsewhere in the network.
+
+CPU exhaustion attacks are usually noticeable only when
+done blatantly. If a large number of nodes suddenly see their
+CPU load spike, or if usage slows to a crawl across the whole
+network, we'll get reports of it-- but small
+interference with targeted relays or nodes is harder to
+detect.
+
+To defend against CPU exhaustion attacks, our best responses are:
+
+ * To improve the efficiency of our implementation in places where
+ it uses inefficient algorithms.
+
+ * To move more work from the main thread into other threads,
+ thereby increasing other threads.
+
+ * To modify our protocols so that an attacker cannot spend a small
+ amount of CPU in order to force the server to use a lot.
+
+ * To radically improve our work- and cell-scheduling architectures
+ so that it is harder for one user's traffic to interfere with
+ another's.
+
+ * Possibly, to instrument our code so that we can better detect
+ strange patterns in CPU usage. We'd need privacy-preserving
+ ways to do this.
+
+#### RAM consumption attacks ####
+
+Tor servers will, for many purposes, allocate memory in order to fulfil
+un-trusted requests. Operations that allocate memory are below. Ones
+that Tor currently handles in its OOM-handler (see below) are marked
+with HANDLED.
+
+ * Queueing cells on a circuit for transmission. (HANDLED)
+ * Queueing data to be sent on an edge connection. (HANDLED)
+ * Storing hidden service directory entries. (HANDLED)
+ * Queueing directory data for compression. (HANDLED)
+ * Internal OpenSSL buffers. (HANDLED.)
+
+ * Storing uploaded descriptors as a directory authority. (!)
+ * Key-pinning entries on directory authorities. (!)
+ * Cached DNS replies. (!)
+
+ * Replay caching on hidden services.
+ * Storing votes from other directory authorities.
+ * Storing statistics as a statistics-collecting node.
+ * Per-circuit storage.
+ * Per-connection storage.
+ * Per-stream storage.
+ * Queued circuit-creation requests.
+
+
+For cases when Tor knows how to handle memory pressure in a given
+area, it keeps track of the amount allocated, and responds to memory
+pressure by killing off long-unused connections and circuits.
+
+When Tor has not been taught to handle memory pressure in a
+particular area, it runs a risk of running out of memory in response
+to attacks. Whens the Tor process uses too much memory, the OS will
+respond in one of two ways:
+
+ 1. On some operating systems, memory allocation functions will
+ return NULL. Tor responds to this currently by aborting the
+ process.
+
+ 2. On Linux, the kernel kills processes when the system runs low
+ on memory, using a set of heuristics that pleases nobody.
+
+Memory exhaustion attacks per se are comparatively inexpensive: the most
+usual types require the attacker to transmit only one encrypted byte
+per byte consumed on the target. (Tor already takes steps to prevent the
+even cheaper versions, where the attacker uploads a compressed zlib bomb.)
+
+The impact of a memory exhaustion attack can be blatant (crashing the
+Tor process, see below), or subtle (triggering the Tor process's
+internal OOM handler and causing _other_ circuits or connections to get
+closed, or information to get dropped). We'll focus on subtle
+exhaustion here; for analysis on crashes, see the next section.
+
+Memory exhaustion attacks usually require a little programming
+skill to exploit, and more if the goal is more subtle than shutting
+down a server.
+
+The most promising ways to resist memory-exhaustion DoS attacks are:
+
+ * Include more types of memory (see list above) among those that
+ the OOM handler is able to free on demand. Those marked with
+ (!) seem most valuable to do first.
+
+ * Extend our OOM handler to be triggered by raw memory
+ allocation or by detectable OOM events. This would allow it to
+ _respond_ to every kind of RAM exhaustion attack, though it
+ would not necessarily be able to correct every time.
+
+More difficult methods would include:
+
+ * Improve our OOM handler to offload offending information to
+ disk rather than deleting it entirely.
+
+ * Analyze memory leak bugs discovered in the past,
+ looking for patterns. Preliminary analysis suggests
+ that our biggest antipatterns here are:
+
+ * Forgetting to call free;
+
+ * Using any kind of memory management more complicated
+ than alloc/free pairs;
+
+ * Forgetting to run Coverity right before a release.
+
+#### Crash attacks ####
+
+Due to programming errors, there may be as-yet-unknown ways to shut down Tor
+and/or other programs remotely, either with a memory violation, with an
+assertion failure, or with RAM exhaustion.
+
+Generally, these require that the attacker discover a programming
+flaw in the program. So long as Tor is actively maintained, these
+attacks can't be used too often without being detected, since they
+usually leave a trace of why servers are crashing--either as a
+stack trace in the log, or an assertion failure message, or both.
+Thus, they require an up-front investment with a limited shelf life.
+
+Nevertheless, these attacks are problematic when they have the ability
+to force a user to change guards (see the Sniper Attack paper by Jansen
+et al.); to mount traffic confirmation attacks; or to attack anonymity
+in other ways as well.
+
+To resist these attacks better we could:
+
+ * Further improve our guard node selection algorithms to resist
+ multiple induced guard failures.
+
+ * Consider designs that would allow circuits and their traffic to
+ migrate across different nodes, so as to better survive the
+ collapse of a single node. (HARD!)
+
+ * Get stack trace support working on Windows, so we can better
+ detect patterns in Windows crashes.
+
+ * Use fewer assertions, and more circuit-level or
+ connection-level error handling.
+
+ * Introduce patterns for handling unexpected bugs more
+ gracefully, possibly modeling them on the BUG_ON() etc macros
+ used by the Linux kernel.
+
+ * Analyze memory crash bugs discovered in the past, and search for
+ trends to identify more. Preliminary analysis suggests that our
+ most crash-prone code has historically been:
+ * Parsing text-based formats.
+ * Parsing binary formats.
+ * Failing to enforce checks in one part of the code that are
+ later enforced with an assertion.
+ * Hand-coded state machines with unexpected transition modes.
+ * Extending the type of an existing field (especially IPv4->IPv6)
+ and elsewhere asserting that the field is the original type.
+ * High-complexity functions, especially ones with "you must
+ call A after B" dependencies.
+ * Code not currently tested by our integration tests.
+
+#### Disk space exhaustion attacks ####
+
+Attacks of this kind are most threatening to systems with extremely
+low disk capacity. To carry one out, an attacker needs a way to
+force the target to store an unbounded amount of information.
+
+Directory authorities are also a concerning target for disk exhaustion
+attacks, since they store published relay descriptors on request.
+To mount a disk exhaustion attack against a non-authority Tor process, an
+attacker would need either to compromise enough authorities to make
+the directory grow without bound, to run enough legitimate-looking
+nodes to make the directory grow without bound, to find an
+unsuspected bug in Tor's code, or to fill up the disk with log
+messages.
+
+Our best defenses here are:
+
+ * Work harder to make directory authorities throw away
+ descriptors if they become low on disk space.
+
+ * Ensure that all of our packages use log rotation.
+
+ * Respond to low disk space by diminishing the amount of storage
+ we use.
+
+#### Bandwidth consumption attacks ####
+
+These attacks are among the most fundamental. A Tor server's job,
+after all, is to receive bytes, transform them, and retransmit
+them. Simply by sending data to a Tor server, an attacker forces
+that server to receive and retransmit the data.
+
+Servers defend themselves against some of these attacks already: by
+declining to accept data on circuits whose buffers are already too
+full, and by using fairness metrics to ensure that quieter circuits
+receive priority service.
+
+The potential impact of one of these attacks can be degraded service
+from a targeted server. But the most dangerous aspect is that it
+can interfere with other traffic, introducing patterns to it that
+can be observed remotely.
+
+Mounting these attacks requires only a botnet running traffic generation
+code. Exploiting interference is a little trickier, and requires a bit
+of engineering.
+
+The highest-impact bandwidth consumption attacks are those with a
+bandwidth multiplier: that is, those in which an attacker can spend
+only a little bandwidth (and minimal CPU) in order to force the
+server to spend a lot. These include directory fetches, HTTP
+requests, and any other traffic pattern where a small request
+generates a large response.
+
+These attacks are difficult to detect in practice.
+
+Our most promising ways to prevent or mitigate these attacks
+include:
+
+ * Possibly, when bandwidth is scarce, consider prioritizing 1:1
+ traffic over asymmetric traffic.
+
+ * Implement KIST (or something like it) to become more responsive
+ to TCP congestion.
+
+ * Implement a scheme like DonnchaC's "split
+ introduction/ rendezvous" proposal (#255) in order to make it
+ harder to congest a hidden service's bandwidth.
+
+ * Improve TorFlow (or another bandwidth scanning system) to
+ follow less predictable patterns for bandwidth scanning.
+
+ * As above, consider schemes to allow busy circuits to migrate
+ from one path to another.
+
+#### Socket/port usage attacks ####
+
+TCP reserves around 64000 usable ports per IP address. In practice, the
+operating system will often have us use many fewer sockets than this.
+By exhausting the available port count, an attacker can prevent a server
+from opening new connections to other servers, prevent an exit server
+from making new exit connections, or prevent a hidden service from
+serving additional users.
+
+These attacks are less easy to turn into a deanonymization vector
+than others, except that by reducing service at a guard or exit
+server, an attacker can force its users to use another. The attacker
+does not control the next server chosen, though, so unless the client
+retries indefinitely, the attack has low odds of success.
+
+These attacks require a little engineering to perform optimally,
+but a less skilled attacker can make a skill/resource tradeoff.
+
+These attacks can be noticed, but are hard to distinguish
+(currently) from legitimate port/socket exhaustion.
+
+To defend against these attacks, we have a few options:
+
+ * Respond to socket/port exhaustion as we currently respond to
+ memory exhaustion: not only refusing to accept new connections,
+ but by looking for long-idle connections that might need to get
+ closed.
+
+ * When looking for connections to close, we could look for
+ suspicious patterns (many connections to the same address,
+ many outbound connections to relays not listed in the
+ consensus, etc). This could be a bad resource use, however,
+ since these patterns are easy to suppress in practice.
+
+ * Make better use of systems where we have multiple interfaces to
+ use for outbound connections.
+
+ * Make better use of multiple IPv6/IPv4 addresses on a single
+ relay, to increase the number of CPU ports we can use.
+
+ * Possibly, deploy some sort of UDP-based transport, to prevent
+ socket exhaustion from interfering with client-relay or
+ relay-relay connections.
+
+### Attacks by target ###
+
+In parallel to considering DoS attacks based on the resource
+exhausted, we can also distinguish them based on the sort of
+system that they target.
+
+#### Attacking clients ####
+
+Performing resource-based DoS attacks against Tor clients serves a
+couple of possible purposes:
+
+ * Traffic confirmation, by forcing a suspected client to degrade
+ performance or to leave the network entirely, and looking to
+ see whether other observed circuits degrade in a corresponding
+ way.
+
+ * Traffic shifting, by encouraging users to stop using Tor,
+ thereby receiving less cover themselves and providing less
+ cover than others.
+
+#### Attacking applications ####
+
+Performing a denial-of-service attack against a (client- or
+server-side) application can serve an attacker's goals by:
+
+ * Encouraging the client to shift to a less-anonymized
+ application
+
+ * Gaining a resource-multiplier effect by forcing the client
+ to introduce itself to more nodes on the Tor network.
+
+#### Attacking hidden services ####
+
+There are a few key opportunities to perform denial-of-service
+attacks against hidden services:
+
+ * Attacking (or becoming) hidden service directories, so clients
+ can't find how to contact a targetted HS.
+
+ * Attacking (or becoming) introduction points, so clients can't
+ make contact with a targetted HS
+
+ * Attacking a hidden service itself.
+
+Similarly, these attacks can be used either to degrade a HS's
+performance, or to attempt to mount traffic confirmation against it.
+
+#### Attacking relays ####
+
+Attacking a relay is at its most powerful when that relay is known
+to be the guard node for a user of interest, and at its next most
+powerful when an attacker is running a large number of their own
+relays and wants to shift traffic onto them.
+
+#### Attacking directory authorities ####
+
+The directory authorities, thanks to their special position in the
+Tor network, are an especially concerning attack for DoS attacks.
+Remove a few authorities, and the voting process becomes less
+robust; remove enough of them, and the entire network becomes
+inoperable.
+
+Our best approach here is separating authority functions and
+isolating their most sensitive duties from their most expensive.
+(Proposal 257 has more ideas on this topic.)
+
+#### Attacking other services via Tor ####
+
+By using the Tor network as a vector for performing
+denial-of-service attacks on other services, an attacker can
+encourage those services to block or restrict Tor users over time,
+thereby discouraging Tor usage. This attack can also make it more
+difficult to host exit nodes.
+
+The best known methodology for resisting these attacks is:
+
+ * Developing technology to restrict abusive Tor users without
+ blocking non-abusive ones, and encouraging the use of this
+ technology. (The present author is a fan of various anonymous
+ blacklistable credential systems, but they have yet to be used
+ in practice, and might prove too unwieldy when actually
+ deployed. We should also consider other approaches.)
+
+
+#### Attacking project infrastructure ####
+
+All attacks become stronger when engineers can't respond to them.
+If, instead of targetting the Tor network, an attacker targets the
+infrastructure that Tor developers use to coordinate, any other
+attack will be more powerful and successful.
+
+Our best response here is likely to ensure that we have backup means
+of coordination and communication prepared _before_ we need them.
+
+Similarly, an attack against user-facing project infrastructure
+could prevent us from communicating with users during an emergency,
+or prevent us from distributing updates effectively.
+
+To resist this kind of attack, we should grow our mirror
+capacity, and build an emergency response plan for a temporary DoS
+against our current software distribution methods.
+
+Recommendations
+---------------
+
+In general, we should favor defenses that close multiple
+attack vectors simultaneously over defenses that simply close one at a
+time. Remember: An attacker needs only one attack that works, while
+we need to prevent _every_ good attack.
+
+Therefore, we should look for general solutions and process
+improvements, rather than piecemeal responses to a single discovered
+attack at a time.
+
+Solutions with the potential to close many attack vectors at once
+include:
+
+ * Changes to the Tor network's structure to prevent single-server
+ attacks from aiding traffic confirmation attacks. These seem
+ particularly difficult, but quite powerful if we can come up
+ with a design that works.
+
+ * Changes to the directory authority infrastructure to remove
+ them (in part or entirely) as a viable DoS target.
+
+ * Changes in our coding practices to make it more difficult for
+ programming errors to propagate into large-scale DoS vectors.
+
+ * Changes in the code used to handle resource exhaustion should
+ look at the consumed resource directly rather than at indirect
+ counts of it. For example, our OOM-handler should look at the
+ operating system's view of our memory consumption, rather than
+ simply counting an incomplete set of memory consumers.
+
+ * Future revisions of our public-key algorithms should consider
+ resource-exhaustion attacks and resource asymmetries.
+
+ * Look for areas that have been historically problematic for
+ programming errors, and investigate ways to reduce future
+ errors of this kind.
+
+ * Isolate parts of the Tor process to different modules, and try
+ to make crashes or resource exhaustion in any particular part
+ as survivable as possible.
diff --git a/2015/dos-taxonomy/tex_header.tex b/2015/dos-taxonomy/tex_header.tex
new file mode 100644
index 0000000..b9ef0d6
--- /dev/null
+++ b/2015/dos-taxonomy/tex_header.tex
@@ -0,0 +1,38 @@
+\documentclass{tortechrep}
+\usepackage{url}
+\usepackage{graphicx}
+\usepackage{hyperref}
+\usepackage{longtable}
+\usepackage{paralist}
+
+%\usepackage{styles/pdfdraftcopy}
+%\draftcolor{gray20}
+%\draftstring{DRAFT}
+%\draftfontsize{150pt}
+
+\begin{document}
+
+\title{Denial-of-service attacks in Tor: Taxonomy and defenses}
+
+\author{Nick Mathewson\\The Tor Project\\ \href{mailto:nickm@torproject.org}{nickm@torproject.org} }
+%\footnotemark[\ref{tpi}]
+
+\reportid{2015-10-001}
+\date{October 29, 2015}
+
+\maketitle
+
+% Text conventions
+% - Each sentence ends with a newline, even inside a paragraph.
+% - Lines are at most 74 characters wide.
+% - Abbreviations are best avoided.
+% - Code, cell names, etc. are put inside \verb+...+.
+
+%\tableofcontents
+
+\begin{abstract}
+This document surveys what we know about potential denial-of-service
+attacks against Tor, in order to focus our efforts over the coming years
+to increase Tor's resistance against these attacks.
+\end{abstract}
+
diff --git a/2015/dos-taxonomy/tortechrep.cls b/2015/dos-taxonomy/tortechrep.cls
new file mode 120000
index 0000000..4c24db2
--- /dev/null
+++ b/2015/dos-taxonomy/tortechrep.cls
@@ -0,0 +1 @@
+../../tortechrep.cls
\ No newline at end of file
1
0

[obfs4/master] Add the "meek_lite" transport, which does what one would expect.
by yawning@torproject.org 29 Oct '15
by yawning@torproject.org 29 Oct '15
29 Oct '15
commit 611205be681322883a4d73dd00fcb13c4352fe53
Author: Yawning Angel <yawning(a)torproject.org>
Date: Thu Oct 29 17:29:21 2015 +0000
Add the "meek_lite" transport, which does what one would expect.
This is a meek client only implementation, with the following
differences with dcf's `meek-client`:
- It is named `meek_lite` to differentiate it from the real thing.
- It does not support using an external helper to normalize TLS
signatures, so adversaries can look for someone using the Go
TLS library to do HTTP.
- It does the right thing with TOR_PT_PROXY, even when a helper is
not present.
Most of the credit goes to dcf, who's code I librerally cribbed and
stole. It is intended primarily as a "better than nothina" option
for enviornments that do not or can not presently use an external
Firefox helper.
---
ChangeLog | 4 +
doc/obfs4proxy.1 | 4 +-
transports/meeklite/base.go | 89 +++++++++++
transports/meeklite/meek.go | 358 +++++++++++++++++++++++++++++++++++++++++++
transports/transports.go | 2 +
5 files changed, 455 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 774be88..1d04d8d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
Changes in version 0.0.6 - UNRELEASED:
- Delay transport factory initialization till after logging has been
initialized.
+ - Add a meek client implementation (WARNING: Does not support using a
+ helper to normalize TLS signatures). The brave people that want to use
+ it can do so as the "meek_lite" transport, with identical bridge lines
+ to the real meek-client.
Changes in version 0.0.5 - 2015-04-15:
- Go vet/fmt fixes, and misc. code cleanups. Patches by mvdan.
diff --git a/doc/obfs4proxy.1 b/doc/obfs4proxy.1
index 9fb5f28..13b89fd 100644
--- a/doc/obfs4proxy.1
+++ b/doc/obfs4proxy.1
@@ -1,4 +1,4 @@
-.TH OBFS4PROXY 1 "2015-04-03"
+.TH OBFS4PROXY 1 "2015-10-29"
.SH NAME
obfs4proxy \- pluggable transport proxy for Tor, implementing obfs4
.SH SYNOPSIS
@@ -12,7 +12,7 @@ will see innocent-looking transformed traffic instead of the actual Tor
traffic.
.PP
obfs4proxy implements the obfuscation protocols obfs2, obfs3,
-ScrambleSuit (client only) and obfs4.
+ScrambleSuit (client only), meek (client only) and obfs4.
.PP
obfs4proxy is currently only supported as a managed pluggable transport
spawned as a helper process via the \fBtor\fR daemon.
diff --git a/transports/meeklite/base.go b/transports/meeklite/base.go
new file mode 100644
index 0000000..2a4cf80
--- /dev/null
+++ b/transports/meeklite/base.go
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Yawning Angel <yawning at torproject dot org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package meeklite provides an implementation of the Meek circumvention
+// protocol. Only a client implementation is provided, and no effort is
+// made to normalize the TLS fingerprint.
+//
+// It borrows quite liberally from the real meek-client code.
+package meeklite
+
+import (
+ "fmt"
+ "net"
+
+ "git.torproject.org/pluggable-transports/goptlib.git"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/base"
+)
+
+const transportName = "meek_lite"
+
+// Transport is the Meek implementation of the base.Transport interface.
+type Transport struct{}
+
+// Name returns the name of the Meek transport protocol.
+func (t *Transport) Name() string {
+ return transportName
+}
+
+// ClientFactory returns a new meekClientFactory instance.
+func (t *Transport) ClientFactory(stateDir string) (base.ClientFactory, error) {
+ cf := &meekClientFactory{transport: t}
+ return cf, nil
+}
+
+// ServerFactory will one day return a new meekServerFactory instance.
+func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
+ // TODO: Fill this in eventually, though for servers people should
+ // just use the real thing.
+ return nil, fmt.Errorf("server not supported")
+}
+
+type meekClientFactory struct {
+ transport base.Transport
+}
+
+func (cf *meekClientFactory) Transport() base.Transport {
+ return cf.transport
+}
+
+func (cf *meekClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
+ return newClientArgs(args)
+}
+
+func (cf *meekClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ // Validate args before opening outgoing connection.
+ ca, ok := args.(*meekClientArgs)
+ if !ok {
+ return nil, fmt.Errorf("invalid argument type for args")
+ }
+
+ return newMeekConn(network, addr, dialFn, ca)
+}
+
+var _ base.ClientFactory = (*meekClientFactory)(nil)
+var _ base.Transport = (*Transport)(nil)
diff --git a/transports/meeklite/meek.go b/transports/meeklite/meek.go
new file mode 100644
index 0000000..5842704
--- /dev/null
+++ b/transports/meeklite/meek.go
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2015, Yawning Angel <yawning at torproject dot org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package meeklite
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ gourl "net/url"
+ "runtime"
+ "sync"
+ "time"
+
+ "git.torproject.org/pluggable-transports/goptlib.git"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/base"
+)
+
+const (
+ urlArg = "url"
+ frontArg = "front"
+
+ maxChanBacklog = 16
+
+ // Constants shamelessly stolen from meek-client.go...
+ maxPayloadLength = 0x10000
+ initPollInterval = 100 * time.Millisecond
+ maxPollInterval = 5 * time.Second
+ pollIntervalMultiplier = 1.5
+ maxRetries = 10
+ retryDelay = 30 * time.Second
+)
+
+var (
+ // ErrNotSupported is the error returned for a unsupported operation.
+ ErrNotSupported = errors.New("meek_lite: operation not supported")
+
+ loopbackAddr = net.IPv4(127, 0, 0, 1)
+)
+
+type meekClientArgs struct {
+ url *gourl.URL
+ front string
+}
+
+func (ca *meekClientArgs) Network() string {
+ return transportName
+}
+
+func (ca *meekClientArgs) String() string {
+ return transportName + ":" + ca.front + ":" + ca.url.String()
+}
+
+func newClientArgs(args *pt.Args) (ca *meekClientArgs, err error) {
+ ca = &meekClientArgs{}
+
+ // Parse the URL argument.
+ str, ok := args.Get(urlArg)
+ if !ok {
+ return nil, fmt.Errorf("missing argument '%s'", urlArg)
+ }
+ ca.url, err = gourl.Parse(str)
+ if err != nil {
+ return nil, fmt.Errorf("malformed url: '%s'", str)
+ }
+ switch ca.url.Scheme {
+ case "http", "https":
+ default:
+ return nil, fmt.Errorf("invalid scheme: '%s'", ca.url.Scheme)
+ }
+
+ // Parse the (optional) front argument.
+ ca.front, _ = args.Get(frontArg)
+
+ return ca, nil
+}
+
+type meekConn struct {
+ sync.Mutex
+
+ args *meekClientArgs
+ sessionID string
+ transport *http.Transport
+
+ workerRunning bool
+ workerWrChan chan []byte
+ workerRdChan chan []byte
+ workerCloseChan chan bool
+ rdBuf *bytes.Buffer
+}
+
+func (c *meekConn) Read(p []byte) (n int, err error) {
+ // If there is data left over from the previous read,
+ // service the request using the buffered data.
+ if c.rdBuf != nil {
+ if c.rdBuf.Len() == 0 {
+ panic("empty read buffer")
+ }
+ n, err = c.rdBuf.Read(p)
+ if c.rdBuf.Len() == 0 {
+ c.rdBuf = nil
+ }
+ return
+ }
+
+ // Wait for the worker to enqueue more incoming data.
+ b, ok := <-c.workerRdChan
+ if !ok {
+ // Close() was called and the worker's shutting down.
+ return 0, io.ErrClosedPipe
+ }
+
+ // Ew, an extra copy, but who am I kidding, it's meek.
+ buf := bytes.NewBuffer(b)
+ n, err = buf.Read(p)
+ if buf.Len() > 0 {
+ // If there's data pending, stash the buffer so the next
+ // Read() call will use it to fulfuill the Read().
+ c.rdBuf = buf
+ }
+ return
+}
+
+func (c *meekConn) Write(b []byte) (n int, err error) {
+ // Check to see if the connection is actually open.
+ c.Lock()
+ closed := !c.workerRunning
+ c.Unlock()
+ if closed {
+ return 0, io.ErrClosedPipe
+ }
+
+ if len(b) > 0 {
+ // Copy the data to be written to a new slice, since
+ // we return immediately after queuing and the peer can
+ // happily reuse `b` before data has been sent.
+ toWrite := len(b)
+ b2 := make([]byte, toWrite)
+ copy(b2, b)
+ offset := 0
+ for toWrite > 0 {
+ // Chunk up the writes to keep them under the maximum
+ // payload length.
+ sz := toWrite
+ if sz > maxPayloadLength {
+ sz = maxPayloadLength
+ }
+
+ // Enqueue a properly sized subslice of our copy.
+ if ok := c.enqueueWrite(b2[offset : offset+sz]); !ok {
+ // Technically we did enqueue data, but the worker's
+ // got closed out from under us.
+ return 0, io.ErrClosedPipe
+ }
+ toWrite -= sz
+ offset += sz
+ runtime.Gosched()
+ }
+ }
+ return len(b), nil
+}
+
+func (c *meekConn) Close() error {
+ // Ensure that we do this once and only once.
+ c.Lock()
+ defer c.Unlock()
+ if !c.workerRunning {
+ return nil
+ }
+
+ // Tear down the worker.
+ c.workerRunning = false
+ c.workerCloseChan <- true
+
+ return nil
+}
+
+func (c *meekConn) LocalAddr() net.Addr {
+ return &net.IPAddr{IP: loopbackAddr}
+}
+
+func (c *meekConn) RemoteAddr() net.Addr {
+ return c.args
+}
+
+func (c *meekConn) SetDeadline(t time.Time) error {
+ return ErrNotSupported
+}
+
+func (c *meekConn) SetReadDeadline(t time.Time) error {
+ return ErrNotSupported
+}
+
+func (c *meekConn) SetWriteDeadline(t time.Time) error {
+ return ErrNotSupported
+}
+
+func (c *meekConn) enqueueWrite(b []byte) (ok bool) {
+ defer func() { recover() }()
+ c.workerWrChan <- b
+ return true
+}
+
+func (c *meekConn) roundTrip(sndBuf []byte) (recvBuf []byte, err error) {
+ var req *http.Request
+ var resp *http.Response
+
+ for retries := 0; retries < maxRetries; retries++ {
+ url := *c.args.url
+ host := url.Host
+ if c.args.front != "" {
+ url.Host = c.args.front
+ }
+ req, err = http.NewRequest("POST", url.String(), bytes.NewReader(sndBuf))
+ if err != nil {
+ return nil, err
+ }
+ if c.args.front != "" {
+ req.Host = host
+ }
+ req.Header.Set("X-Session-Id", c.sessionID)
+
+ resp, err = c.transport.RoundTrip(req)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode != http.StatusOK {
+ err = fmt.Errorf("status code was %d, not %d", resp.StatusCode, http.StatusOK)
+ time.Sleep(retryDelay)
+ } else {
+ defer resp.Body.Close()
+ recvBuf, err = ioutil.ReadAll(io.LimitReader(resp.Body, maxPayloadLength))
+ return
+ }
+ }
+ return
+}
+
+func (c *meekConn) ioWorker() {
+ interval := initPollInterval
+loop:
+ for {
+ var sndBuf []byte
+ select {
+ case <-time.After(interval):
+ // If the poll interval has elapsed, issue a request.
+ case sndBuf = <-c.workerWrChan:
+ // If there is data pending a send, issue a request.
+ case _ = <-c.workerCloseChan:
+ break loop
+ }
+
+ // Issue a request.
+ rdBuf, err := c.roundTrip(sndBuf)
+ if err != nil {
+ // Welp, something went horrifically wrong.
+ break loop
+ }
+ if len(rdBuf) > 0 {
+ // Received data, enqueue the read.
+ c.workerRdChan <- rdBuf
+
+ // And poll immediately.
+ interval = 0
+ } else if sndBuf != nil {
+ // Sent data, poll immediately.
+ interval = 0
+ } else if interval == 0 {
+ // Neither sent nor received data, initialize the delay.
+ interval = initPollInterval
+ } else {
+ // Apply a multiplicative backoff.
+ interval = time.Duration(float64(interval) * pollIntervalMultiplier)
+ if interval > maxPollInterval {
+ interval = maxPollInterval
+ }
+ }
+
+ runtime.Gosched()
+ }
+
+ // Unblock callers waiting in Read() for data that will never arrive,
+ // and callers waiting in Write() for data that will never get sent.
+ close(c.workerRdChan)
+ close(c.workerWrChan)
+
+ // In case the close was done on an error condition, update the state
+ // variable so that further calls to Write() will fail.
+ c.Lock()
+ defer c.Unlock()
+ c.workerRunning = false
+}
+
+func newMeekConn(network, addr string, dialFn base.DialFunc, ca *meekClientArgs) (net.Conn, error) {
+ id, err := newSessionID()
+ if err != nil {
+ return nil, err
+ }
+
+ tr := &http.Transport{Dial: dialFn}
+ conn := &meekConn{
+ args: ca,
+ sessionID: id,
+ transport: tr,
+ workerRunning: true,
+ workerWrChan: make(chan []byte, maxChanBacklog),
+ workerRdChan: make(chan []byte, maxChanBacklog),
+ workerCloseChan: make(chan bool),
+ }
+
+ // Start the I/O worker.
+ go conn.ioWorker()
+
+ return conn, nil
+}
+
+func newSessionID() (string, error) {
+ var b [64]byte
+ if _, err := rand.Read(b[:]); err != nil {
+ return "", err
+ }
+ h := sha256.Sum256(b[:])
+ return hex.EncodeToString(h[:16]), nil
+}
+
+var _ net.Conn = (*meekConn)(nil)
+var _ net.Addr = (*meekClientArgs)(nil)
diff --git a/transports/transports.go b/transports/transports.go
index e35673b..51a3f08 100644
--- a/transports/transports.go
+++ b/transports/transports.go
@@ -34,6 +34,7 @@ import (
"sync"
"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/meeklite"
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs2"
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs3"
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
@@ -83,6 +84,7 @@ func Get(name string) base.Transport {
// Init initializes all of the integrated transports.
func Init() error {
+ Register(new(meeklite.Transport))
Register(new(obfs2.Transport))
Register(new(obfs3.Transport))
Register(new(obfs4.Transport))
1
0

[torspec/master] Proposal 258: Denial-of-service resistance for directory authorities
by nickm@torproject.org 29 Oct '15
by nickm@torproject.org 29 Oct '15
29 Oct '15
commit d1eb16cf35113b3ef87bb01298c6cb510f7a1604
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Oct 29 11:56:50 2015 -0400
Proposal 258: Denial-of-service resistance for directory authorities
---
proposals/000-index.txt | 2 +
proposals/258-dirauth-dos.txt | 96 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+)
diff --git a/proposals/000-index.txt b/proposals/000-index.txt
index c5fabc9..0add538 100644
--- a/proposals/000-index.txt
+++ b/proposals/000-index.txt
@@ -178,6 +178,7 @@ Proposals by number:
255 Controller features to allow for load-balancing hidden services [DRAFT]
256 Key revocation for relays and authorities [OPEN]
257 Refactoring authorities and taking parts offline [DRAFT]
+258 Denial-of-service resistance for directory authorities [OPEN]
Proposals by status:
@@ -228,6 +229,7 @@ Proposals by status:
242 Better performance and usability for the MyFamily option
246 Merging Hidden Service Directories and Introduction Points
256 Key revocation for relays and authorities
+ 258 Denial-of-service resistance for directory authorities
ACCEPTED:
140 Provide diffs between consensuses
172 GETINFO controller option for circuit information
diff --git a/proposals/258-dirauth-dos.txt b/proposals/258-dirauth-dos.txt
new file mode 100644
index 0000000..28a0e9a
--- /dev/null
+++ b/proposals/258-dirauth-dos.txt
@@ -0,0 +1,96 @@
+Filename: 258-dirauth-dos.txt
+Title: Denial-of-service resistance for directory authorities
+Author: Andrea Shepard
+Created: 2015-10-27
+Status: Open
+
+1. Problem statement
+
+ The directory authorities are few in number and vital for the functioning
+ of the Tor network; threats of denial of service attacks against them have
+ occurred in the past. They should be more resistant to unreasonably large
+ connection volumes.
+
+2. Design overview
+
+ There are two possible ways a new connection to a directory authority can
+ be established, directly by a TCP connection to the DirPort, or tunneled
+ inside a Tor circuit and initiated with a begindir cell. The client can
+ originate the former as direct connections or from a Tor exit, and the
+ latter either as fully anonymized circuits or one-hop links to the
+ dirauth's ORPort.
+
+ The dirauth will try to heuristically classify incoming requests as one of
+ these four indirection types, and then in the two non-anonymized cases
+ further sort them into hash buckets on the basis of source IP. It will use
+ an exponentially-weighted moving average to measure the rate of connection
+ attempts in each bucket, and also separately limit the number of begindir
+ cells permitted on each circuit. It will periodically scan the hash tables
+ and forget counters which have fallen below a threshold to prevent memory
+ exhaustion.
+
+3. Classification of incoming connections
+
+ Clients can originate connections as one of four indirection types:
+
+ - DIRIND_ONEHOP: begindir cell on a single-hop Tor circuit
+ - DIRIND_ANONYMOUS: begindir cell on a fully anonymized Tor circuit
+ - DIRIND_DIRECT_CONN: direct TCP connection to dirport
+ - DIRIND_ANON_DIRPORT: TCP connection to dirport from an exit relay
+
+ The directory authority can always tell a dirport connection from a
+ begindir, but it must use its knowledge of the current consensus and
+ exit policies to disambiguate whether the connection is anonymized.
+
+ It should treat a begindir as DIRIND_ANONYMOUS when the previous hop
+ in the circuit it appears on is in the current consensus, and as
+ DIRIND_ONEHOP otherwise; it should treat a dirport connection as
+ DIRIND_ANON_DIRPORT if the source address appears in the consensus
+ and allows exits to the dirport in question, or as DIRIND_DIRECT_CONN
+ otherwise. In the case of relays which also act as clients, these
+ heuristics may falsely classify direct/onehop connections as anonymous,
+ but will never falsely classify anonymous connections as direct/onehop.
+
+4. Exponentially-weighted moving average counters and hash table
+
+ The directory authority implements a set of exponentially-weighted moving
+ averages to measure the rate of incoming connections in each bucket. The
+ two anonymous connection types are each a single bucket, but the two non-
+ anonymous cases get a single bucket per source IP each, stored in a hash
+ table. The directory authority must periodically scan this hash table for
+ counters which have decayed close to zero and free them to avoid permitting
+ memory exhaustion.
+
+ This introduces five new configuration parameters:
+
+ - DirDoSFilterEWMATimeConstant: the time for an EWMA counter to decay by a
+ factor of 1/e, in seconds.
+ - DirDoSFilterMaxAnonConnectRate: the threshold to trigger the DoS filter
+ on DIRIND_ANONYMOUS connections.
+ - DirDoSFilterMaxAnonDirportConnectRate: the threshold to trigger the DoS
+ filter on DIRIND_ANON_DIRPORT connections.
+ - DirDoSFilterMaxBegindirRatePerIP: the threshold per source IP to trigger
+ the DoS filter on DIRIND_ONEHOP connections.
+ - DirDoSFilterMaxDirectConnRatePerIP: the threshold per source IP to
+ trigger the DoS filter on DIRIND_DIRECT_CONN connections.
+
+ When incrementing a counter would put it over the relevant threshold, the
+ filter is said to be triggered. In this case, the directory authority does
+ not update the counter, but instead suppresses the incoming request. In
+ the DIRIND_ONEHOP and DIRIND_ANONYMOUS cases, the directory authority must
+ kill the circuit rather than merely refusing the request, to prevent
+ an unending stream of client retries on the same circuit.
+
+5. Begindir cap
+
+ Directory authorities limit the number of begindir cells permitted in the
+ lifetime of a particular circuit, separately from the EWMA counters. This
+ can only affect the DIRIND_ANONYMOUS and DIRIND_ONEHOP connetion types.
+ A sixth configuration variable, DirDoSFilterMaxBegindirPerCircuit, controls
+ this feature.
+
+6. Limitations
+
+ Widely distributed DoS attacks with many source IPs may still be able to
+ avoid raising any single DIRIND_ONEHOP or DIRIND_DIRECT_CONN counter above
+ threshold.
1
0
commit 64d80bb5ca66a264c64e2e40c2dc52c3f64d89cb
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Oct 29 12:23:41 2015 -0400
Reformat 258.
---
proposals/258-dirauth-dos.txt | 207 ++++++++++++++++++++++-------------------
1 file changed, 111 insertions(+), 96 deletions(-)
diff --git a/proposals/258-dirauth-dos.txt b/proposals/258-dirauth-dos.txt
index 28a0e9a..966a094 100644
--- a/proposals/258-dirauth-dos.txt
+++ b/proposals/258-dirauth-dos.txt
@@ -1,96 +1,111 @@
-Filename: 258-dirauth-dos.txt
-Title: Denial-of-service resistance for directory authorities
-Author: Andrea Shepard
-Created: 2015-10-27
-Status: Open
-
-1. Problem statement
-
- The directory authorities are few in number and vital for the functioning
- of the Tor network; threats of denial of service attacks against them have
- occurred in the past. They should be more resistant to unreasonably large
- connection volumes.
-
-2. Design overview
-
- There are two possible ways a new connection to a directory authority can
- be established, directly by a TCP connection to the DirPort, or tunneled
- inside a Tor circuit and initiated with a begindir cell. The client can
- originate the former as direct connections or from a Tor exit, and the
- latter either as fully anonymized circuits or one-hop links to the
- dirauth's ORPort.
-
- The dirauth will try to heuristically classify incoming requests as one of
- these four indirection types, and then in the two non-anonymized cases
- further sort them into hash buckets on the basis of source IP. It will use
- an exponentially-weighted moving average to measure the rate of connection
- attempts in each bucket, and also separately limit the number of begindir
- cells permitted on each circuit. It will periodically scan the hash tables
- and forget counters which have fallen below a threshold to prevent memory
- exhaustion.
-
-3. Classification of incoming connections
-
- Clients can originate connections as one of four indirection types:
-
- - DIRIND_ONEHOP: begindir cell on a single-hop Tor circuit
- - DIRIND_ANONYMOUS: begindir cell on a fully anonymized Tor circuit
- - DIRIND_DIRECT_CONN: direct TCP connection to dirport
- - DIRIND_ANON_DIRPORT: TCP connection to dirport from an exit relay
-
- The directory authority can always tell a dirport connection from a
- begindir, but it must use its knowledge of the current consensus and
- exit policies to disambiguate whether the connection is anonymized.
-
- It should treat a begindir as DIRIND_ANONYMOUS when the previous hop
- in the circuit it appears on is in the current consensus, and as
- DIRIND_ONEHOP otherwise; it should treat a dirport connection as
- DIRIND_ANON_DIRPORT if the source address appears in the consensus
- and allows exits to the dirport in question, or as DIRIND_DIRECT_CONN
- otherwise. In the case of relays which also act as clients, these
- heuristics may falsely classify direct/onehop connections as anonymous,
- but will never falsely classify anonymous connections as direct/onehop.
-
-4. Exponentially-weighted moving average counters and hash table
-
- The directory authority implements a set of exponentially-weighted moving
- averages to measure the rate of incoming connections in each bucket. The
- two anonymous connection types are each a single bucket, but the two non-
- anonymous cases get a single bucket per source IP each, stored in a hash
- table. The directory authority must periodically scan this hash table for
- counters which have decayed close to zero and free them to avoid permitting
- memory exhaustion.
-
- This introduces five new configuration parameters:
-
- - DirDoSFilterEWMATimeConstant: the time for an EWMA counter to decay by a
- factor of 1/e, in seconds.
- - DirDoSFilterMaxAnonConnectRate: the threshold to trigger the DoS filter
- on DIRIND_ANONYMOUS connections.
- - DirDoSFilterMaxAnonDirportConnectRate: the threshold to trigger the DoS
- filter on DIRIND_ANON_DIRPORT connections.
- - DirDoSFilterMaxBegindirRatePerIP: the threshold per source IP to trigger
- the DoS filter on DIRIND_ONEHOP connections.
- - DirDoSFilterMaxDirectConnRatePerIP: the threshold per source IP to
- trigger the DoS filter on DIRIND_DIRECT_CONN connections.
-
- When incrementing a counter would put it over the relevant threshold, the
- filter is said to be triggered. In this case, the directory authority does
- not update the counter, but instead suppresses the incoming request. In
- the DIRIND_ONEHOP and DIRIND_ANONYMOUS cases, the directory authority must
- kill the circuit rather than merely refusing the request, to prevent
- an unending stream of client retries on the same circuit.
-
-5. Begindir cap
-
- Directory authorities limit the number of begindir cells permitted in the
- lifetime of a particular circuit, separately from the EWMA counters. This
- can only affect the DIRIND_ANONYMOUS and DIRIND_ONEHOP connetion types.
- A sixth configuration variable, DirDoSFilterMaxBegindirPerCircuit, controls
- this feature.
-
-6. Limitations
-
- Widely distributed DoS attacks with many source IPs may still be able to
- avoid raising any single DIRIND_ONEHOP or DIRIND_DIRECT_CONN counter above
- threshold.
+Filename: 258-dirauth-dos.txt
+Title: Denial-of-service resistance for directory authorities
+Author: Andrea Shepard
+Created: 2015-10-27
+Status: Open
+
+1. Problem statement
+
+ The directory authorities are few in number and vital for the
+ functioning of the Tor network; threats of denial of service
+ attacks against them have occurred in the past. They should be
+ more resistant to unreasonably large connection volumes.
+
+2. Design overview
+
+ There are two possible ways a new connection to a directory
+ authority can be established, directly by a TCP connection to the
+ DirPort, or tunneled inside a Tor circuit and initiated with a
+ begindir cell. The client can originate the former as direct
+ connections or from a Tor exit, and the latter either as fully
+ anonymized circuits or one-hop links to the dirauth's ORPort.
+
+ The dirauth will try to heuristically classify incoming requests
+ as one of these four indirection types, and then in the two
+ non-anonymized cases further sort them into hash buckets on the
+ basis of source IP. It will use an exponentially-weighted moving
+ average to measure the rate of connection attempts in each
+ bucket, and also separately limit the number of begindir cells
+ permitted on each circuit. It will periodically scan the hash
+ tables and forget counters which have fallen below a threshold to
+ prevent memory exhaustion.
+
+3. Classification of incoming connections
+
+ Clients can originate connections as one of four indirection
+ types:
+
+
+ - DIRIND_ONEHOP: begindir cell on a single-hop Tor circuit
+ - DIRIND_ANONYMOUS: begindir cell on a fully anonymized Tor
+ circuit
+ - DIRIND_DIRECT_CONN: direct TCP connection to dirport
+ - DIRIND_ANON_DIRPORT: TCP connection to dirport from an exit
+ relay
+
+ The directory authority can always tell a dirport connection from
+ a begindir, but it must use its knowledge of the current
+ consensus and exit policies to disambiguate whether the
+ connection is anonymized.
+
+ It should treat a begindir as DIRIND_ANONYMOUS when the previous
+ hop in the circuit it appears on is in the current consensus, and
+ as DIRIND_ONEHOP otherwise; it should treat a dirport connection
+ as DIRIND_ANON_DIRPORT if the source address appears in the
+ consensus and allows exits to the dirport in question, or as
+ DIRIND_DIRECT_CONN otherwise. In the case of relays which also
+ act as clients, these heuristics may falsely classify
+ direct/onehop connections as anonymous, but will never falsely
+ classify anonymous connections as direct/onehop.
+
+4. Exponentially-weighted moving average counters and hash table
+
+ The directory authority implements a set of
+ exponentially-weighted moving averages to measure the rate of
+ incoming connections in each bucket. The two anonymous
+ connection types are each a single bucket, but the two non-
+ anonymous cases get a single bucket per source IP each, stored in
+ a hash table. The directory authority must periodically scan
+ this hash table for counters which have decayed close to zero and
+ free them to avoid permitting memory exhaustion.
+
+ This introduces five new configuration parameters:
+
+ - DirDoSFilterEWMATimeConstant: the time for an EWMA counter to
+ decay by a factor of 1/e, in seconds.
+
+ - DirDoSFilterMaxAnonConnectRate: the threshold to trigger the
+ DoS filter on DIRIND_ANONYMOUS connections.
+
+ - DirDoSFilterMaxAnonDirportConnectRate: the threshold to
+ trigger the DoS filter on DIRIND_ANON_DIRPORT connections.
+
+ - DirDoSFilterMaxBegindirRatePerIP: the threshold per source IP
+ to trigger the DoS filter on DIRIND_ONEHOP connections.
+
+ - DirDoSFilterMaxDirectConnRatePerIP: the threshold per source
+ IP to trigger the DoS filter on DIRIND_DIRECT_CONN
+ connections.
+
+ When incrementing a counter would put it over the relevant
+ threshold, the filter is said to be triggered. In this case, the
+ directory authority does not update the counter, but instead
+ suppresses the incoming request. In the DIRIND_ONEHOP and
+ DIRIND_ANONYMOUS cases, the directory authority must kill the
+ circuit rather than merely refusing the request, to prevent an
+ unending stream of client retries on the same circuit.
+
+5. Begindir cap
+
+ Directory authorities limit the number of begindir cells
+ permitted in the lifetime of a particular circuit, separately
+ from the EWMA counters. This can only affect the
+ DIRIND_ANONYMOUS and DIRIND_ONEHOP connetion types. A sixth
+ configuration variable, DirDoSFilterMaxBegindirPerCircuit,
+ controls this feature.
+
+6. Limitations
+
+ Widely distributed DoS attacks with many source IPs may still be
+ able to avoid raising any single DIRIND_ONEHOP or
+ DIRIND_DIRECT_CONN counter above threshold.
1
0
commit e5976482a39ba28efa64764cdb19e310c84aec21
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Oct 29 10:29:21 2015 -0400
More issues that Karsten spotted
---
doc/HACKING/GettingStarted.txt | 7 -------
doc/HACKING/HelpfulTools.txt | 2 +-
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/doc/HACKING/GettingStarted.txt b/doc/HACKING/GettingStarted.txt
index e684ed7..ee024fe 100644
--- a/doc/HACKING/GettingStarted.txt
+++ b/doc/HACKING/GettingStarted.txt
@@ -1,9 +1,4 @@
-
-(DRAFT)
-
-
-
Getting started in Tor development
==================================
@@ -189,6 +184,4 @@ Once you've reached this point, here's what you need to know.
it integrated into mainline Tor.
-Where do I go from here?
-------------------------
diff --git a/doc/HACKING/HelpfulTools.txt b/doc/HACKING/HelpfulTools.txt
index fd3b713..cf74063 100644
--- a/doc/HACKING/HelpfulTools.txt
+++ b/doc/HACKING/HelpfulTools.txt
@@ -156,7 +156,7 @@ Profiling Tor with oprofile
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The oprofile tool runs (on Linux only!) to tell you what functions Tor is
-spending its CPU time in, so we can identify berformance pottlenecks.
+spending its CPU time in, so we can identify performance bottlenecks.
Here are some basic instructions
1
0
commit 92a6c578d7038556af391de23081d314091dea32
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Oct 29 10:30:27 2015 -0400
hacking is now markdown
Not good markdown, mind you.
---
doc/HACKING/CodingStandards.md | 238 +++++++++++++++++++++++
doc/HACKING/CodingStandards.txt | 238 -----------------------
doc/HACKING/GettingStarted.md | 187 ++++++++++++++++++
doc/HACKING/GettingStarted.txt | 187 ------------------
doc/HACKING/HelpfulTools.md | 303 +++++++++++++++++++++++++++++
doc/HACKING/HelpfulTools.txt | 303 -----------------------------
doc/HACKING/HowToReview.md | 85 +++++++++
doc/HACKING/HowToReview.txt | 85 ---------
doc/HACKING/README.1st | 60 ------
doc/HACKING/README.1st.md | 60 ++++++
doc/HACKING/ReleasingTor.md | 125 ++++++++++++
doc/HACKING/ReleasingTor.txt | 125 ------------
doc/HACKING/WritingTests.md | 403 +++++++++++++++++++++++++++++++++++++++
doc/HACKING/WritingTests.txt | 403 ---------------------------------------
doc/include.am | 14 +-
15 files changed, 1408 insertions(+), 1408 deletions(-)
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
new file mode 100644
index 0000000..ff602bd
--- /dev/null
+++ b/doc/HACKING/CodingStandards.md
@@ -0,0 +1,238 @@
+Coding conventions for Tor
+--------------------------
+
+tl;dr:
+
+ * Run configure with '--enable-gcc-warnings'
+ * Run 'make check-spaces' to catch whitespace errors
+ * Document your functions
+ * Write unit tests
+ * Add a file in 'changes' for your branch.
+
+Patch checklist
+~~~~~~~~~~~~~~~
+
+If possible, send your patch as one of these (in descending order of
+preference)
+
+ - A git branch we can pull from
+ - Patches generated by git format-patch
+ - A unified diff
+
+Did you remember...
+
+ - To build your code while configured with --enable-gcc-warnings?
+ - To run "make check-spaces" on your code?
+ - To run "make check-docs" to see whether all new options are on
+ the manpage?
+ - To write unit tests, as possible?
+ - To base your code on the appropriate branch?
+ - To include a file in the "changes" directory as appropriate?
+
+How we use Git branches
+-----------------------
+
+Each main development series (like 0.2.1, 0.2.2, etc) has its main work
+applied to a single branch. At most one series can be the development series
+at a time; all other series are maintenance series that get bug-fixes only.
+The development series is built in a git branch called "master"; the
+maintenance series are built in branches called "maint-0.2.0", "maint-0.2.1",
+and so on. We regularly merge the active maint branches forward.
+
+For all series except the development series, we also have a "release" branch
+(as in "release-0.2.1"). The release series is based on the corresponding
+maintenance series, except that it deliberately lags the maint series for
+most of its patches, so that bugfix patches are not typically included in a
+maintenance release until they've been tested for a while in a development
+release. Occasionally, we'll merge an urgent bugfix into the release branch
+before it gets merged into maint, but that's rare.
+
+If you're working on a bugfix for a bug that occurs in a particular version,
+base your bugfix branch on the "maint" branch for the first supported series
+that has that bug. (As of June 2013, we're supporting 0.2.3 and later.) If
+you're working on a new feature, base it on the master branch.
+
+
+How we log changes
+------------------
+
+When you do a commit that needs a ChangeLog entry, add a new file to
+the "changes" toplevel subdirectory. It should have the format of a
+one-entry changelog section from the current ChangeLog file, as in
+
+ o Major bugfixes:
+ - Fix a potential buffer overflow. Fixes bug 99999; bugfix on
+ 0.3.1.4-beta.
+
+To write a changes file, first categorize the change. Some common categories
+are: Minor bugfixes, Major bugfixes, Minor features, Major features, Code
+simplifications and refactoring. Then say what the change does. If
+it's a bugfix, mention what bug it fixes and when the bug was
+introduced. To find out which Git tag the change was introduced in,
+you can use "git describe --contains <sha1 of commit>".
+
+If at all possible, try to create this file in the same commit where you are
+making the change. Please give it a distinctive name that no other branch will
+use for the lifetime of your change. To verify the format of the changes file,
+you can use "make check-changes".
+
+When we go to make a release, we will concatenate all the entries
+in changes to make a draft changelog, and clear the directory. We'll
+then edit the draft changelog into a nice readable format.
+
+What needs a changes file?::
+ A not-exhaustive list: Anything that might change user-visible
+ behavior. Anything that changes internals, documentation, or the build
+ system enough that somebody could notice. Big or interesting code
+ rewrites. Anything about which somebody might plausibly wonder "when
+ did that happen, and/or why did we do that" 6 months down the line.
+
+Why use changes files instead of Git commit messages?::
+ Git commit messages are written for developers, not users, and they
+ are nigh-impossible to revise after the fact.
+
+Why use changes files instead of entries in the ChangeLog?::
+ Having every single commit touch the ChangeLog file tended to create
+ zillions of merge conflicts.
+
+Whitespace and C conformance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Invoke "make check-spaces" from time to time, so it can tell you about
+deviations from our C whitespace style. Generally, we use:
+
+ - Unix-style line endings
+ - K&R-style indentation
+ - No space before newlines
+ - A blank line at the end of each file
+ - Never more than one blank line in a row
+ - Always spaces, never tabs
+ - No more than 79-columns per line.
+ - Two spaces per indent.
+ - A space between control keywords and their corresponding paren
+ "if (x)", "while (x)", and "switch (x)", never "if(x)", "while(x)", or
+ "switch(x)".
+ - A space between anything and an open brace.
+ - No space between a function name and an opening paren. "puts(x)", not
+ "puts (x)".
+ - Function declarations at the start of the line.
+
+We try hard to build without warnings everywhere. In particular, if you're
+using gcc, you should invoke the configure script with the option
+"--enable-gcc-warnings". This will give a bunch of extra warning flags to
+the compiler, and help us find divergences from our preferred C style.
+
+Functions to use; functions not to use
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We have some wrapper functions like tor_malloc, tor_free, tor_strdup, and
+tor_gettimeofday; use them instead of their generic equivalents. (They
+always succeed or exit.)
+
+You can get a full list of the compatibility functions that Tor provides by
+looking through src/common/util*.h and src/common/compat*.h. You can see the
+available containers in src/common/containers*.h. You should probably
+familiarize yourself with these modules before you write too much code, or
+else you'll wind up reinventing the wheel.
+
+Use 'INLINE' instead of 'inline' -- it's a vestige of an old hack to make
+sure that we worked on MSVC6.
+
+We don't use strcat or strcpy or sprintf of any of those notoriously broken
+old C functions. Use strlcat, strlcpy, or tor_snprintf/tor_asprintf instead.
+
+We don't call memcmp() directly. Use fast_memeq(), fast_memneq(),
+tor_memeq(), or tor_memneq() for most purposes.
+
+Functions not to write
+~~~~~~~~~~~~~~~~~~~~~~
+
+Try to never hand-write new code to parse or generate binary
+formats. Instead, use trunnel if at all possible. See
+ https://gitweb.torproject.org/trunnel.git/tree
+for more information about trunnel.
+
+For information on adding new trunnel code to Tor, see src/trunnel/README
+
+
+Calling and naming conventions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Whenever possible, functions should return -1 on error and 0 on success.
+
+For multi-word identifiers, use lowercase words combined with
+underscores. (e.g., "multi_word_identifier"). Use ALL_CAPS for macros and
+constants.
+
+Typenames should end with "_t".
+
+Function names should be prefixed with a module name or object name. (In
+general, code to manipulate an object should be a module with the same name
+as the object, so it's hard to tell which convention is used.)
+
+Functions that do things should have imperative-verb names
+(e.g. buffer_clear, buffer_resize); functions that return booleans should
+have predicate names (e.g. buffer_is_empty, buffer_needs_resizing).
+
+If you find that you have four or more possible return code values, it's
+probably time to create an enum. If you find that you are passing three or
+more flags to a function, it's probably time to create a flags argument that
+takes a bitfield.
+
+What To Optimize
+~~~~~~~~~~~~~~~~
+
+Don't optimize anything if it's not in the critical path. Right now, the
+critical path seems to be AES, logging, and the network itself. Feel free to
+do your own profiling to determine otherwise.
+
+Log conventions
+~~~~~~~~~~~~~~~
+
+https://www.torproject.org/docs/faq#LogLevel
+
+No error or warning messages should be expected during normal OR or OP
+operation.
+
+If a library function is currently called such that failure always means ERR,
+then the library function should log WARN and let the caller log ERR.
+
+Every message of severity INFO or higher should either (A) be intelligible
+to end-users who don't know the Tor source; or (B) somehow inform the
+end-users that they aren't expected to understand the message (perhaps
+with a string like "internal error"). Option (A) is to be preferred to
+option (B).
+
+
+
+Doxygen comment conventions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Say what functions do as a series of one or more imperative sentences, as
+though you were telling somebody how to be the function. In other words, DO
+NOT say:
+
+ /** The strtol function parses a number.
+ *
+ * nptr -- the string to parse. It can include whitespace.
+ * endptr -- a string pointer to hold the first thing that is not part
+ * of the number, if present.
+ * base -- the numeric base.
+ * returns: the resulting number.
+ */
+ long strtol(const char *nptr, char **nptr, int base);
+
+Instead, please DO say:
+
+ /** Parse a number in radix <b>base</b> from the string <b>nptr</b>,
+ * and return the result. Skip all leading whitespace. If
+ * <b>endptr</b> is not NULL, set *<b>endptr</b> to the first character
+ * after the number parsed.
+ **/
+ long strtol(const char *nptr, char **nptr, int base);
+
+Doxygen comments are the contract in our abstraction-by-contract world: if
+the functions that call your function rely on it doing something, then your
+function should mention that it does that something in the documentation. If
+you rely on a function doing something beyond what is in its documentation,
+then you should watch out, or it might do something else later.
diff --git a/doc/HACKING/CodingStandards.txt b/doc/HACKING/CodingStandards.txt
deleted file mode 100644
index ff602bd..0000000
--- a/doc/HACKING/CodingStandards.txt
+++ /dev/null
@@ -1,238 +0,0 @@
-Coding conventions for Tor
---------------------------
-
-tl;dr:
-
- * Run configure with '--enable-gcc-warnings'
- * Run 'make check-spaces' to catch whitespace errors
- * Document your functions
- * Write unit tests
- * Add a file in 'changes' for your branch.
-
-Patch checklist
-~~~~~~~~~~~~~~~
-
-If possible, send your patch as one of these (in descending order of
-preference)
-
- - A git branch we can pull from
- - Patches generated by git format-patch
- - A unified diff
-
-Did you remember...
-
- - To build your code while configured with --enable-gcc-warnings?
- - To run "make check-spaces" on your code?
- - To run "make check-docs" to see whether all new options are on
- the manpage?
- - To write unit tests, as possible?
- - To base your code on the appropriate branch?
- - To include a file in the "changes" directory as appropriate?
-
-How we use Git branches
------------------------
-
-Each main development series (like 0.2.1, 0.2.2, etc) has its main work
-applied to a single branch. At most one series can be the development series
-at a time; all other series are maintenance series that get bug-fixes only.
-The development series is built in a git branch called "master"; the
-maintenance series are built in branches called "maint-0.2.0", "maint-0.2.1",
-and so on. We regularly merge the active maint branches forward.
-
-For all series except the development series, we also have a "release" branch
-(as in "release-0.2.1"). The release series is based on the corresponding
-maintenance series, except that it deliberately lags the maint series for
-most of its patches, so that bugfix patches are not typically included in a
-maintenance release until they've been tested for a while in a development
-release. Occasionally, we'll merge an urgent bugfix into the release branch
-before it gets merged into maint, but that's rare.
-
-If you're working on a bugfix for a bug that occurs in a particular version,
-base your bugfix branch on the "maint" branch for the first supported series
-that has that bug. (As of June 2013, we're supporting 0.2.3 and later.) If
-you're working on a new feature, base it on the master branch.
-
-
-How we log changes
-------------------
-
-When you do a commit that needs a ChangeLog entry, add a new file to
-the "changes" toplevel subdirectory. It should have the format of a
-one-entry changelog section from the current ChangeLog file, as in
-
- o Major bugfixes:
- - Fix a potential buffer overflow. Fixes bug 99999; bugfix on
- 0.3.1.4-beta.
-
-To write a changes file, first categorize the change. Some common categories
-are: Minor bugfixes, Major bugfixes, Minor features, Major features, Code
-simplifications and refactoring. Then say what the change does. If
-it's a bugfix, mention what bug it fixes and when the bug was
-introduced. To find out which Git tag the change was introduced in,
-you can use "git describe --contains <sha1 of commit>".
-
-If at all possible, try to create this file in the same commit where you are
-making the change. Please give it a distinctive name that no other branch will
-use for the lifetime of your change. To verify the format of the changes file,
-you can use "make check-changes".
-
-When we go to make a release, we will concatenate all the entries
-in changes to make a draft changelog, and clear the directory. We'll
-then edit the draft changelog into a nice readable format.
-
-What needs a changes file?::
- A not-exhaustive list: Anything that might change user-visible
- behavior. Anything that changes internals, documentation, or the build
- system enough that somebody could notice. Big or interesting code
- rewrites. Anything about which somebody might plausibly wonder "when
- did that happen, and/or why did we do that" 6 months down the line.
-
-Why use changes files instead of Git commit messages?::
- Git commit messages are written for developers, not users, and they
- are nigh-impossible to revise after the fact.
-
-Why use changes files instead of entries in the ChangeLog?::
- Having every single commit touch the ChangeLog file tended to create
- zillions of merge conflicts.
-
-Whitespace and C conformance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Invoke "make check-spaces" from time to time, so it can tell you about
-deviations from our C whitespace style. Generally, we use:
-
- - Unix-style line endings
- - K&R-style indentation
- - No space before newlines
- - A blank line at the end of each file
- - Never more than one blank line in a row
- - Always spaces, never tabs
- - No more than 79-columns per line.
- - Two spaces per indent.
- - A space between control keywords and their corresponding paren
- "if (x)", "while (x)", and "switch (x)", never "if(x)", "while(x)", or
- "switch(x)".
- - A space between anything and an open brace.
- - No space between a function name and an opening paren. "puts(x)", not
- "puts (x)".
- - Function declarations at the start of the line.
-
-We try hard to build without warnings everywhere. In particular, if you're
-using gcc, you should invoke the configure script with the option
-"--enable-gcc-warnings". This will give a bunch of extra warning flags to
-the compiler, and help us find divergences from our preferred C style.
-
-Functions to use; functions not to use
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We have some wrapper functions like tor_malloc, tor_free, tor_strdup, and
-tor_gettimeofday; use them instead of their generic equivalents. (They
-always succeed or exit.)
-
-You can get a full list of the compatibility functions that Tor provides by
-looking through src/common/util*.h and src/common/compat*.h. You can see the
-available containers in src/common/containers*.h. You should probably
-familiarize yourself with these modules before you write too much code, or
-else you'll wind up reinventing the wheel.
-
-Use 'INLINE' instead of 'inline' -- it's a vestige of an old hack to make
-sure that we worked on MSVC6.
-
-We don't use strcat or strcpy or sprintf of any of those notoriously broken
-old C functions. Use strlcat, strlcpy, or tor_snprintf/tor_asprintf instead.
-
-We don't call memcmp() directly. Use fast_memeq(), fast_memneq(),
-tor_memeq(), or tor_memneq() for most purposes.
-
-Functions not to write
-~~~~~~~~~~~~~~~~~~~~~~
-
-Try to never hand-write new code to parse or generate binary
-formats. Instead, use trunnel if at all possible. See
- https://gitweb.torproject.org/trunnel.git/tree
-for more information about trunnel.
-
-For information on adding new trunnel code to Tor, see src/trunnel/README
-
-
-Calling and naming conventions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Whenever possible, functions should return -1 on error and 0 on success.
-
-For multi-word identifiers, use lowercase words combined with
-underscores. (e.g., "multi_word_identifier"). Use ALL_CAPS for macros and
-constants.
-
-Typenames should end with "_t".
-
-Function names should be prefixed with a module name or object name. (In
-general, code to manipulate an object should be a module with the same name
-as the object, so it's hard to tell which convention is used.)
-
-Functions that do things should have imperative-verb names
-(e.g. buffer_clear, buffer_resize); functions that return booleans should
-have predicate names (e.g. buffer_is_empty, buffer_needs_resizing).
-
-If you find that you have four or more possible return code values, it's
-probably time to create an enum. If you find that you are passing three or
-more flags to a function, it's probably time to create a flags argument that
-takes a bitfield.
-
-What To Optimize
-~~~~~~~~~~~~~~~~
-
-Don't optimize anything if it's not in the critical path. Right now, the
-critical path seems to be AES, logging, and the network itself. Feel free to
-do your own profiling to determine otherwise.
-
-Log conventions
-~~~~~~~~~~~~~~~
-
-https://www.torproject.org/docs/faq#LogLevel
-
-No error or warning messages should be expected during normal OR or OP
-operation.
-
-If a library function is currently called such that failure always means ERR,
-then the library function should log WARN and let the caller log ERR.
-
-Every message of severity INFO or higher should either (A) be intelligible
-to end-users who don't know the Tor source; or (B) somehow inform the
-end-users that they aren't expected to understand the message (perhaps
-with a string like "internal error"). Option (A) is to be preferred to
-option (B).
-
-
-
-Doxygen comment conventions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Say what functions do as a series of one or more imperative sentences, as
-though you were telling somebody how to be the function. In other words, DO
-NOT say:
-
- /** The strtol function parses a number.
- *
- * nptr -- the string to parse. It can include whitespace.
- * endptr -- a string pointer to hold the first thing that is not part
- * of the number, if present.
- * base -- the numeric base.
- * returns: the resulting number.
- */
- long strtol(const char *nptr, char **nptr, int base);
-
-Instead, please DO say:
-
- /** Parse a number in radix <b>base</b> from the string <b>nptr</b>,
- * and return the result. Skip all leading whitespace. If
- * <b>endptr</b> is not NULL, set *<b>endptr</b> to the first character
- * after the number parsed.
- **/
- long strtol(const char *nptr, char **nptr, int base);
-
-Doxygen comments are the contract in our abstraction-by-contract world: if
-the functions that call your function rely on it doing something, then your
-function should mention that it does that something in the documentation. If
-you rely on a function doing something beyond what is in its documentation,
-then you should watch out, or it might do something else later.
diff --git a/doc/HACKING/GettingStarted.md b/doc/HACKING/GettingStarted.md
new file mode 100644
index 0000000..ee024fe
--- /dev/null
+++ b/doc/HACKING/GettingStarted.md
@@ -0,0 +1,187 @@
+
+Getting started in Tor development
+==================================
+
+Congratulations! You've found this file, and you're reading it! This
+means that you might be interested in getting started in developing Tor.
+
+(This guide is just about Tor itself--the small network program at the
+heart of the Tor network--and not about all the other programs in the
+whole Tor ecosystem.)
+
+
+If you are looking for a more bare-bones, less user-friendly information
+dump of important information, you might like reading doc/HACKING
+instead. You should probably read it before you write your first patch.
+
+
+Required background
+-------------------
+
+First, I'm going to assume that you can build Tor from source, and that
+you know enough of the C language to read and write it. (See the README
+file that comes with the Tor source for more information on building it,
+and any high-quality guide to C for information on programming.)
+
+I'm also going to assume that you know a little bit about how to use
+Git, or that you're able to follow one of the several excellent guides
+at http://git-scm.org to learn.
+
+Most Tor developers develop using some Unix-based system, such as Linux,
+BSD, or OSX. It's okay to develop on Windows if you want, but you're
+going to have a more difficult time.
+
+
+Getting your first patch into Tor
+---------------------------------
+
+Once you've reached this point, here's what you need to know.
+
+ 1) Get the source.
+
+ We keep our source under version control in Git. To get the latest
+ version, run
+ git clone https://git.torproject.org/git/tor
+
+ This will give you a checkout of the master branch. If you're
+ going to fix a bug that appears in a stable version, check out the
+ appropriate "maint" branch, as in:
+
+ git checkout maint-0.2.7
+
+ 2) Find your way around the source
+
+ Our overall code structure is explained in the "torguts" documents,
+ currently at
+ git clone https://git.torproject.org/user/nickm/torguts.git
+
+ Find a part of the code that looks interesting to you, and start
+ looking around it to see how it fits together!
+
+ We do some unusual things in our codebase. Our testing-related
+ practices and kludges are explained in doc/WritingTests.txt.
+
+ If you see something that doesn't make sense, we love to get
+ questions!
+
+ 3) Find something cool to hack on.
+
+ You may already have a good idea of what you'd like to work on, or
+ you might be looking for a way to contribute.
+
+ Many people have gotten started by looking for an area where they
+ personally felt Tor was underperforming, and investigating ways to
+ fix it. If you're looking for ideas, you can head to our bug
+ tracker at trac.torproject.org and look for tickets that have
+ received the "easy" tag: these are ones that developers think would
+ be pretty simple for a new person to work on. For a bigger
+ challenge, you might want to look for tickets with the "lorax"
+ keyword: these are tickets that the developers think might be a
+ good idea to build, but which we have no time to work on any time
+ soon.
+
+ Or you might find another open ticket that piques your
+ interest. It's all fine!
+
+ For your first patch, it is probably NOT a good idea to make
+ something huge or invasive. In particular, you should probably
+ avoid:
+ * Major changes spread across many parts of the codebase.
+ * Major changes to programming practice or coding style.
+ * Huge new features or protocol changes.
+
+ 4) Meet the developers!
+
+ We discuss stuff on the tor-dev mailing list and on the #tor-dev
+ IRC channel on OFTC. We're generally friendly and approachable,
+ and we like to talk about how Tor fits together. If we have ideas
+ about how something should be implemented, we'll be happy to share
+ them.
+
+ We currently have a patch workshop at least once a week, where
+ people share patches they've made and discuss how to make them
+ better. The time might change in the future, but generally,
+ there's no bad time to talk, and ask us about patch ideas.
+
+ 5) Do you need to write a design proposal?
+
+ If your idea is very large, or it will require a change to Tor's
+ protocols, there needs to be a written design proposal before it
+ can be merged. (We use this process to manage changes in the
+ protocols.) To write one, see the instructions at
+ https://gitweb.torproject.org/torspec.git/tree/proposals/001-process.txt
+ . If you'd like help writing a proposal, just ask! We're happy to
+ help out with good ideas.
+
+ You might also like to look around the rest of that directory, to
+ see more about open and past proposed changes to Tor's behavior.
+
+ 6) Writing your patch
+
+ As you write your code, you'll probably want it to fit in with the
+ standards of the rest of the Tor codebase so it will be easy for us
+ to review and merge. You can learn our coding standards in
+ doc/HACKING.
+
+ If your patch is large and/or is divided into multiple logical
+ components, remember to divide it into a series of Git commits. A
+ series of small changes is much easier to review than one big lump.
+
+ 7) Testing your patch
+
+ We prefer that all new or modified code have unit tests for it to
+ ensure that it runs correctly. Also, all code should actually be
+ _run_ by somebody, to make sure it works.
+
+ See doc/WritingTests.txt for more information on how we test things
+ in Tor. If you'd like any help writing tests, just ask! We're
+ glad to help out.
+
+ 8) Submitting your patch
+
+ We review patches through tickets on our bugtracker at
+ trac.torproject.org. You can either upload your patches there, or
+ put them at a public git repository somewhere we can fetch them
+ (like github or bitbucket) and then paste a link on the appropriate
+ trac ticket.
+
+ Once your patches are available, write a short explanation of what
+ you've done on trac, and then change the status of the ticket to
+ needs_review.
+
+ 9) Review, Revision, and Merge
+
+ With any luck, somebody will review your patch soon! If not, you
+ can ask on the IRC channel; sometimes we get really busy and take
+ longer than we should. But don't let us slow you down: you're the
+ one who's offering help here, and we should respect your time and
+ contributions.
+
+ When your patch is reviewed, one of these things will happen:
+
+ * The reviewer will say "looks good to me" and your
+ patch will get merged right into Tor. [Assuming we're not
+ in the middle of a code-freeze window. If the codebase is
+ frozen, your patch will go into the next release series.]
+
+ * OR the reviewer will say "looks good, just needs some small
+ changes!" And then the reviewer will make those changes,
+ and merge the modified patch into Tor.
+
+ * OR the reviewer will say "Here are some questions and
+ comments," followed by a bunch of stuff that the reviewer
+ thinks should change in your code, or questions that the
+ reviewer has.
+
+ At this point, you might want to make the requested changes
+ yourself, and comment on the trac ticket once you have done
+ so. Or if you disagree with any of the comments, you should
+ say so! And if you won't have time to make some of the
+ changes, you should say that too, so that other developers
+ will be able to pick up the unfinished portion
+
+ Congratulations! You have now written your first patch, and gotten
+ it integrated into mainline Tor.
+
+
+
diff --git a/doc/HACKING/GettingStarted.txt b/doc/HACKING/GettingStarted.txt
deleted file mode 100644
index ee024fe..0000000
--- a/doc/HACKING/GettingStarted.txt
+++ /dev/null
@@ -1,187 +0,0 @@
-
-Getting started in Tor development
-==================================
-
-Congratulations! You've found this file, and you're reading it! This
-means that you might be interested in getting started in developing Tor.
-
-(This guide is just about Tor itself--the small network program at the
-heart of the Tor network--and not about all the other programs in the
-whole Tor ecosystem.)
-
-
-If you are looking for a more bare-bones, less user-friendly information
-dump of important information, you might like reading doc/HACKING
-instead. You should probably read it before you write your first patch.
-
-
-Required background
--------------------
-
-First, I'm going to assume that you can build Tor from source, and that
-you know enough of the C language to read and write it. (See the README
-file that comes with the Tor source for more information on building it,
-and any high-quality guide to C for information on programming.)
-
-I'm also going to assume that you know a little bit about how to use
-Git, or that you're able to follow one of the several excellent guides
-at http://git-scm.org to learn.
-
-Most Tor developers develop using some Unix-based system, such as Linux,
-BSD, or OSX. It's okay to develop on Windows if you want, but you're
-going to have a more difficult time.
-
-
-Getting your first patch into Tor
----------------------------------
-
-Once you've reached this point, here's what you need to know.
-
- 1) Get the source.
-
- We keep our source under version control in Git. To get the latest
- version, run
- git clone https://git.torproject.org/git/tor
-
- This will give you a checkout of the master branch. If you're
- going to fix a bug that appears in a stable version, check out the
- appropriate "maint" branch, as in:
-
- git checkout maint-0.2.7
-
- 2) Find your way around the source
-
- Our overall code structure is explained in the "torguts" documents,
- currently at
- git clone https://git.torproject.org/user/nickm/torguts.git
-
- Find a part of the code that looks interesting to you, and start
- looking around it to see how it fits together!
-
- We do some unusual things in our codebase. Our testing-related
- practices and kludges are explained in doc/WritingTests.txt.
-
- If you see something that doesn't make sense, we love to get
- questions!
-
- 3) Find something cool to hack on.
-
- You may already have a good idea of what you'd like to work on, or
- you might be looking for a way to contribute.
-
- Many people have gotten started by looking for an area where they
- personally felt Tor was underperforming, and investigating ways to
- fix it. If you're looking for ideas, you can head to our bug
- tracker at trac.torproject.org and look for tickets that have
- received the "easy" tag: these are ones that developers think would
- be pretty simple for a new person to work on. For a bigger
- challenge, you might want to look for tickets with the "lorax"
- keyword: these are tickets that the developers think might be a
- good idea to build, but which we have no time to work on any time
- soon.
-
- Or you might find another open ticket that piques your
- interest. It's all fine!
-
- For your first patch, it is probably NOT a good idea to make
- something huge or invasive. In particular, you should probably
- avoid:
- * Major changes spread across many parts of the codebase.
- * Major changes to programming practice or coding style.
- * Huge new features or protocol changes.
-
- 4) Meet the developers!
-
- We discuss stuff on the tor-dev mailing list and on the #tor-dev
- IRC channel on OFTC. We're generally friendly and approachable,
- and we like to talk about how Tor fits together. If we have ideas
- about how something should be implemented, we'll be happy to share
- them.
-
- We currently have a patch workshop at least once a week, where
- people share patches they've made and discuss how to make them
- better. The time might change in the future, but generally,
- there's no bad time to talk, and ask us about patch ideas.
-
- 5) Do you need to write a design proposal?
-
- If your idea is very large, or it will require a change to Tor's
- protocols, there needs to be a written design proposal before it
- can be merged. (We use this process to manage changes in the
- protocols.) To write one, see the instructions at
- https://gitweb.torproject.org/torspec.git/tree/proposals/001-process.txt
- . If you'd like help writing a proposal, just ask! We're happy to
- help out with good ideas.
-
- You might also like to look around the rest of that directory, to
- see more about open and past proposed changes to Tor's behavior.
-
- 6) Writing your patch
-
- As you write your code, you'll probably want it to fit in with the
- standards of the rest of the Tor codebase so it will be easy for us
- to review and merge. You can learn our coding standards in
- doc/HACKING.
-
- If your patch is large and/or is divided into multiple logical
- components, remember to divide it into a series of Git commits. A
- series of small changes is much easier to review than one big lump.
-
- 7) Testing your patch
-
- We prefer that all new or modified code have unit tests for it to
- ensure that it runs correctly. Also, all code should actually be
- _run_ by somebody, to make sure it works.
-
- See doc/WritingTests.txt for more information on how we test things
- in Tor. If you'd like any help writing tests, just ask! We're
- glad to help out.
-
- 8) Submitting your patch
-
- We review patches through tickets on our bugtracker at
- trac.torproject.org. You can either upload your patches there, or
- put them at a public git repository somewhere we can fetch them
- (like github or bitbucket) and then paste a link on the appropriate
- trac ticket.
-
- Once your patches are available, write a short explanation of what
- you've done on trac, and then change the status of the ticket to
- needs_review.
-
- 9) Review, Revision, and Merge
-
- With any luck, somebody will review your patch soon! If not, you
- can ask on the IRC channel; sometimes we get really busy and take
- longer than we should. But don't let us slow you down: you're the
- one who's offering help here, and we should respect your time and
- contributions.
-
- When your patch is reviewed, one of these things will happen:
-
- * The reviewer will say "looks good to me" and your
- patch will get merged right into Tor. [Assuming we're not
- in the middle of a code-freeze window. If the codebase is
- frozen, your patch will go into the next release series.]
-
- * OR the reviewer will say "looks good, just needs some small
- changes!" And then the reviewer will make those changes,
- and merge the modified patch into Tor.
-
- * OR the reviewer will say "Here are some questions and
- comments," followed by a bunch of stuff that the reviewer
- thinks should change in your code, or questions that the
- reviewer has.
-
- At this point, you might want to make the requested changes
- yourself, and comment on the trac ticket once you have done
- so. Or if you disagree with any of the comments, you should
- say so! And if you won't have time to make some of the
- changes, you should say that too, so that other developers
- will be able to pick up the unfinished portion
-
- Congratulations! You have now written your first patch, and gotten
- it integrated into mainline Tor.
-
-
-
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
new file mode 100644
index 0000000..cf74063
--- /dev/null
+++ b/doc/HACKING/HelpfulTools.md
@@ -0,0 +1,303 @@
+Useful tools
+------------
+
+These aren't strictly necessary for hacking on Tor, but they can help track
+down bugs.
+
+Jenkins
+~~~~~~~
+
+https://jenkins.torproject.org
+
+Dmalloc
+~~~~~~~
+
+The dmalloc library will keep track of memory allocation, so you can find out
+if we're leaking memory, doing any double-frees, or so on.
+
+ dmalloc -l ~/dmalloc.log
+ (run the commands it tells you)
+ ./configure --with-dmalloc
+
+Valgrind
+~~~~~~~~
+
+valgrind --leak-check=yes --error-limit=no --show-reachable=yes src/or/tor
+
+(Note that if you get a zillion openssl warnings, you will also need to
+pass --undef-value-errors=no to valgrind, or rebuild your openssl
+with -DPURIFY.)
+
+Coverity
+~~~~~~~~
+
+Nick regularly runs the coverity static analyzer on the Tor codebase.
+
+The preprocessor define __COVERITY__ is used to work around instances
+where coverity picks up behavior that we wish to permit.
+
+clang Static Analyzer
+~~~~~~~~~~~~~~~~~~~~~
+
+The clang static analyzer can be run on the Tor codebase using Xcode (WIP)
+or a command-line build.
+
+The preprocessor define __clang_analyzer__ is used to work around instances
+where clang picks up behavior that we wish to permit.
+
+clang Runtime Sanitizers
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To build the Tor codebase with the clang Address and Undefined Behavior
+sanitizers, see the file contrib/clang/sanitize_blacklist.txt.
+
+Preprocessor workarounds for instances where clang picks up behavior that
+we wish to permit are also documented in the blacklist file.
+
+Running lcov for unit test coverage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lcov is a utility that generates pretty HTML reports of test code coverage.
+To generate such a report:
+
+-----
+ ./configure --enable-coverage
+ make
+ make coverage-html
+ $BROWSER ./coverage_html/index.html
+-----
+
+This will run the tor unit test suite `./src/test/test` and generate the HTML
+coverage code report under the directory ./coverage_html/. To change the
+output directory, use `make coverage-html HTML_COVER_DIR=./funky_new_cov_dir`.
+
+Coverage diffs using lcov are not currently implemented, but are being
+investigated (as of July 2014).
+
+Running the unit tests
+~~~~~~~~~~~~~~~~~~~~~~
+
+To quickly run all the tests distributed with Tor:
+-----
+ make check
+-----
+
+To run the fast unit tests only:
+-----
+ make test
+-----
+
+To selectively run just some tests (the following can be combined
+arbitrarily):
+-----
+ ./src/test/test <name_of_test> [<name of test 2>] ...
+ ./src/test/test <prefix_of_name_of_test>.. [<prefix_of_name_of_test2>..] ...
+ ./src/test/test :<name_of_excluded_test> [:<name_of_excluded_test2]...
+-----
+
+To run all tests, including those based on Stem or Chutney:
+-----
+ make test-full
+-----
+
+To run all tests, including those based on Stem or Chutney that require a
+working connection to the internet:
+-----
+ make test-full-online
+-----
+
+Running gcov for unit test coverage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-----
+ ./configure --enable-coverage
+ make
+ make check
+ # or--- make test-full ? make test-full-online?
+ mkdir coverage-output
+ ./scripts/test/coverage coverage-output
+-----
+
+(On OSX, you'll need to start with "--enable-coverage CC=clang".)
+
+Then, look at the .gcov files in coverage-output. '-' before a line means
+that the compiler generated no code for that line. '######' means that the
+line was never reached. Lines with numbers were called that number of times.
+
+If that doesn't work:
+ * Try configuring Tor with --disable-gcc-hardening
+ * You might need to run 'make clean' after you run './configure'.
+
+If you make changes to Tor and want to get another set of coverage results,
+you can run "make reset-gcov" to clear the intermediary gcov output.
+
+If you have two different "coverage-output" directories, and you want to see
+a meaningful diff between them, you can run:
+
+-----
+ ./scripts/test/cov-diff coverage-output1 coverage-output2 | less
+-----
+
+In this diff, any lines that were visited at least once will have coverage
+"1". This lets you inspect what you (probably) really want to know: which
+untested lines were changed? Are there any new untested lines?
+
+Running integration tests
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We have the beginnings of a set of scripts to run integration tests using
+Chutney. To try them, set CHUTNEY_PATH to your chutney source directory, and
+run "make test-network".
+
+We also have scripts to run integration tests using Stem. To try them, set
+STEM_SOURCE_DIR to your Stem source directory, and run "test-stem".
+
+Profiling Tor with oprofile
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The oprofile tool runs (on Linux only!) to tell you what functions Tor is
+spending its CPU time in, so we can identify performance bottlenecks.
+
+Here are some basic instructions
+
+ - Build tor with debugging symbols (you probably already have, unless
+ you messed with CFLAGS during the build process).
+ - Build all the libraries you care about with debugging symbols
+ (probably you only care about libssl, maybe zlib and Libevent).
+ - Copy this tor to a new directory
+ - Copy all the libraries it uses to that dir too (ldd ./tor will
+ tell you)
+ - Set LD_LIBRARY_PATH to include that dir. ldd ./tor should now
+ show you it's using the libs in that dir
+ - Run that tor
+ - Reset oprofiles counters/start it
+ * "opcontrol --reset; opcontrol --start", if Nick remembers right.
+ - After a while, have it dump the stats on tor and all the libs
+ in that dir you created.
+ * "opcontrol --dump;"
+ * "opreport -l that_dir/*"
+ - Profit
+
+Generating and analyzing a callgraph
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Run ./scripts/maint/generate_callgraph.sh . This will generate a
+ bunch of files in a new ./callgraph directory.
+
+2. Run ./scripts/maint/analyze_callgraph.py callgraph/src/*/* . This
+ will do a lot of graph operations and then dump out a new
+ "callgraph.pkl" file, containing data in Python's "pickle" format.
+
+3. Run ./scripts/maint/display_callgraph.py . It will display:
+ - the number of functions reachable from each function.
+ - all strongly-connnected components in the Tor callgraph
+ - the largest bottlenecks in the largest SCC in the Tor callgraph.
+
+Note that currently the callgraph generator can't detect calls that pass
+through function pointers.
+
+Getting emacs to edit Tor source properly
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Nick likes to put the following snippet in his .emacs file:
+
+-----
+ (add-hook 'c-mode-hook
+ (lambda ()
+ (font-lock-mode 1)
+ (set-variable 'show-trailing-whitespace t)
+
+ (let ((fname (expand-file-name (buffer-file-name))))
+ (cond
+ ((string-match "^/home/nickm/src/libevent" fname)
+ (set-variable 'indent-tabs-mode t)
+ (set-variable 'c-basic-offset 4)
+ (set-variable 'tab-width 4))
+ ((string-match "^/home/nickm/src/tor" fname)
+ (set-variable 'indent-tabs-mode nil)
+ (set-variable 'c-basic-offset 2))
+ ((string-match "^/home/nickm/src/openssl" fname)
+ (set-variable 'indent-tabs-mode t)
+ (set-variable 'c-basic-offset 8)
+ (set-variable 'tab-width 8))
+ ))))
+-----
+
+You'll note that it defaults to showing all trailing whitespace. The "cond"
+test detects whether the file is one of a few C free software projects that I
+often edit, and sets up the indentation level and tab preferences to match
+what they want.
+
+If you want to try this out, you'll need to change the filename regex
+patterns to match where you keep your Tor files.
+
+If you use emacs for editing Tor and nothing else, you could always just say:
+
+-----
+ (add-hook 'c-mode-hook
+ (lambda ()
+ (font-lock-mode 1)
+ (set-variable 'show-trailing-whitespace t)
+ (set-variable 'indent-tabs-mode nil)
+ (set-variable 'c-basic-offset 2)))
+-----
+
+There is probably a better way to do this. No, we are probably not going
+to clutter the files with emacs stuff.
+
+
+Doxygen
+~~~~~~~
+
+We use the 'doxygen' utility to generate documentation from our
+source code. Here's how to use it:
+
+ 1. Begin every file that should be documented with
+ /**
+ * \file filename.c
+ * \brief Short description of the file.
+ */
+
+ (Doxygen will recognize any comment beginning with /** as special.)
+
+ 2. Before any function, structure, #define, or variable you want to
+ document, add a comment of the form:
+
+ /** Describe the function's actions in imperative sentences.
+ *
+ * Use blank lines for paragraph breaks
+ * - and
+ * - hyphens
+ * - for
+ * - lists.
+ *
+ * Write <b>argument_names</b> in boldface.
+ *
+ * \code
+ * place_example_code();
+ * between_code_and_endcode_commands();
+ * \endcode
+ */
+
+ 3. Make sure to escape the characters "<", ">", "\", "%" and "#" as "\<",
+ "\>", "\\", "\%", and "\#".
+
+ 4. To document structure members, you can use two forms:
+
+ struct foo {
+ /** You can put the comment before an element; */
+ int a;
+ int b; /**< Or use the less-than symbol to put the comment
+ * after the element. */
+ };
+
+ 5. To generate documentation from the Tor source code, type:
+
+ $ doxygen -g
+
+ To generate a file called 'Doxyfile'. Edit that file and run
+ 'doxygen' to generate the API documentation.
+
+ 6. See the Doxygen manual for more information; this summary just
+ scratches the surface.
+
diff --git a/doc/HACKING/HelpfulTools.txt b/doc/HACKING/HelpfulTools.txt
deleted file mode 100644
index cf74063..0000000
--- a/doc/HACKING/HelpfulTools.txt
+++ /dev/null
@@ -1,303 +0,0 @@
-Useful tools
-------------
-
-These aren't strictly necessary for hacking on Tor, but they can help track
-down bugs.
-
-Jenkins
-~~~~~~~
-
-https://jenkins.torproject.org
-
-Dmalloc
-~~~~~~~
-
-The dmalloc library will keep track of memory allocation, so you can find out
-if we're leaking memory, doing any double-frees, or so on.
-
- dmalloc -l ~/dmalloc.log
- (run the commands it tells you)
- ./configure --with-dmalloc
-
-Valgrind
-~~~~~~~~
-
-valgrind --leak-check=yes --error-limit=no --show-reachable=yes src/or/tor
-
-(Note that if you get a zillion openssl warnings, you will also need to
-pass --undef-value-errors=no to valgrind, or rebuild your openssl
-with -DPURIFY.)
-
-Coverity
-~~~~~~~~
-
-Nick regularly runs the coverity static analyzer on the Tor codebase.
-
-The preprocessor define __COVERITY__ is used to work around instances
-where coverity picks up behavior that we wish to permit.
-
-clang Static Analyzer
-~~~~~~~~~~~~~~~~~~~~~
-
-The clang static analyzer can be run on the Tor codebase using Xcode (WIP)
-or a command-line build.
-
-The preprocessor define __clang_analyzer__ is used to work around instances
-where clang picks up behavior that we wish to permit.
-
-clang Runtime Sanitizers
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-To build the Tor codebase with the clang Address and Undefined Behavior
-sanitizers, see the file contrib/clang/sanitize_blacklist.txt.
-
-Preprocessor workarounds for instances where clang picks up behavior that
-we wish to permit are also documented in the blacklist file.
-
-Running lcov for unit test coverage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Lcov is a utility that generates pretty HTML reports of test code coverage.
-To generate such a report:
-
------
- ./configure --enable-coverage
- make
- make coverage-html
- $BROWSER ./coverage_html/index.html
------
-
-This will run the tor unit test suite `./src/test/test` and generate the HTML
-coverage code report under the directory ./coverage_html/. To change the
-output directory, use `make coverage-html HTML_COVER_DIR=./funky_new_cov_dir`.
-
-Coverage diffs using lcov are not currently implemented, but are being
-investigated (as of July 2014).
-
-Running the unit tests
-~~~~~~~~~~~~~~~~~~~~~~
-
-To quickly run all the tests distributed with Tor:
------
- make check
------
-
-To run the fast unit tests only:
------
- make test
------
-
-To selectively run just some tests (the following can be combined
-arbitrarily):
------
- ./src/test/test <name_of_test> [<name of test 2>] ...
- ./src/test/test <prefix_of_name_of_test>.. [<prefix_of_name_of_test2>..] ...
- ./src/test/test :<name_of_excluded_test> [:<name_of_excluded_test2]...
------
-
-To run all tests, including those based on Stem or Chutney:
------
- make test-full
------
-
-To run all tests, including those based on Stem or Chutney that require a
-working connection to the internet:
------
- make test-full-online
------
-
-Running gcov for unit test coverage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
------
- ./configure --enable-coverage
- make
- make check
- # or--- make test-full ? make test-full-online?
- mkdir coverage-output
- ./scripts/test/coverage coverage-output
------
-
-(On OSX, you'll need to start with "--enable-coverage CC=clang".)
-
-Then, look at the .gcov files in coverage-output. '-' before a line means
-that the compiler generated no code for that line. '######' means that the
-line was never reached. Lines with numbers were called that number of times.
-
-If that doesn't work:
- * Try configuring Tor with --disable-gcc-hardening
- * You might need to run 'make clean' after you run './configure'.
-
-If you make changes to Tor and want to get another set of coverage results,
-you can run "make reset-gcov" to clear the intermediary gcov output.
-
-If you have two different "coverage-output" directories, and you want to see
-a meaningful diff between them, you can run:
-
------
- ./scripts/test/cov-diff coverage-output1 coverage-output2 | less
------
-
-In this diff, any lines that were visited at least once will have coverage
-"1". This lets you inspect what you (probably) really want to know: which
-untested lines were changed? Are there any new untested lines?
-
-Running integration tests
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We have the beginnings of a set of scripts to run integration tests using
-Chutney. To try them, set CHUTNEY_PATH to your chutney source directory, and
-run "make test-network".
-
-We also have scripts to run integration tests using Stem. To try them, set
-STEM_SOURCE_DIR to your Stem source directory, and run "test-stem".
-
-Profiling Tor with oprofile
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The oprofile tool runs (on Linux only!) to tell you what functions Tor is
-spending its CPU time in, so we can identify performance bottlenecks.
-
-Here are some basic instructions
-
- - Build tor with debugging symbols (you probably already have, unless
- you messed with CFLAGS during the build process).
- - Build all the libraries you care about with debugging symbols
- (probably you only care about libssl, maybe zlib and Libevent).
- - Copy this tor to a new directory
- - Copy all the libraries it uses to that dir too (ldd ./tor will
- tell you)
- - Set LD_LIBRARY_PATH to include that dir. ldd ./tor should now
- show you it's using the libs in that dir
- - Run that tor
- - Reset oprofiles counters/start it
- * "opcontrol --reset; opcontrol --start", if Nick remembers right.
- - After a while, have it dump the stats on tor and all the libs
- in that dir you created.
- * "opcontrol --dump;"
- * "opreport -l that_dir/*"
- - Profit
-
-Generating and analyzing a callgraph
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Run ./scripts/maint/generate_callgraph.sh . This will generate a
- bunch of files in a new ./callgraph directory.
-
-2. Run ./scripts/maint/analyze_callgraph.py callgraph/src/*/* . This
- will do a lot of graph operations and then dump out a new
- "callgraph.pkl" file, containing data in Python's "pickle" format.
-
-3. Run ./scripts/maint/display_callgraph.py . It will display:
- - the number of functions reachable from each function.
- - all strongly-connnected components in the Tor callgraph
- - the largest bottlenecks in the largest SCC in the Tor callgraph.
-
-Note that currently the callgraph generator can't detect calls that pass
-through function pointers.
-
-Getting emacs to edit Tor source properly
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Nick likes to put the following snippet in his .emacs file:
-
------
- (add-hook 'c-mode-hook
- (lambda ()
- (font-lock-mode 1)
- (set-variable 'show-trailing-whitespace t)
-
- (let ((fname (expand-file-name (buffer-file-name))))
- (cond
- ((string-match "^/home/nickm/src/libevent" fname)
- (set-variable 'indent-tabs-mode t)
- (set-variable 'c-basic-offset 4)
- (set-variable 'tab-width 4))
- ((string-match "^/home/nickm/src/tor" fname)
- (set-variable 'indent-tabs-mode nil)
- (set-variable 'c-basic-offset 2))
- ((string-match "^/home/nickm/src/openssl" fname)
- (set-variable 'indent-tabs-mode t)
- (set-variable 'c-basic-offset 8)
- (set-variable 'tab-width 8))
- ))))
------
-
-You'll note that it defaults to showing all trailing whitespace. The "cond"
-test detects whether the file is one of a few C free software projects that I
-often edit, and sets up the indentation level and tab preferences to match
-what they want.
-
-If you want to try this out, you'll need to change the filename regex
-patterns to match where you keep your Tor files.
-
-If you use emacs for editing Tor and nothing else, you could always just say:
-
------
- (add-hook 'c-mode-hook
- (lambda ()
- (font-lock-mode 1)
- (set-variable 'show-trailing-whitespace t)
- (set-variable 'indent-tabs-mode nil)
- (set-variable 'c-basic-offset 2)))
------
-
-There is probably a better way to do this. No, we are probably not going
-to clutter the files with emacs stuff.
-
-
-Doxygen
-~~~~~~~
-
-We use the 'doxygen' utility to generate documentation from our
-source code. Here's how to use it:
-
- 1. Begin every file that should be documented with
- /**
- * \file filename.c
- * \brief Short description of the file.
- */
-
- (Doxygen will recognize any comment beginning with /** as special.)
-
- 2. Before any function, structure, #define, or variable you want to
- document, add a comment of the form:
-
- /** Describe the function's actions in imperative sentences.
- *
- * Use blank lines for paragraph breaks
- * - and
- * - hyphens
- * - for
- * - lists.
- *
- * Write <b>argument_names</b> in boldface.
- *
- * \code
- * place_example_code();
- * between_code_and_endcode_commands();
- * \endcode
- */
-
- 3. Make sure to escape the characters "<", ">", "\", "%" and "#" as "\<",
- "\>", "\\", "\%", and "\#".
-
- 4. To document structure members, you can use two forms:
-
- struct foo {
- /** You can put the comment before an element; */
- int a;
- int b; /**< Or use the less-than symbol to put the comment
- * after the element. */
- };
-
- 5. To generate documentation from the Tor source code, type:
-
- $ doxygen -g
-
- To generate a file called 'Doxyfile'. Edit that file and run
- 'doxygen' to generate the API documentation.
-
- 6. See the Doxygen manual for more information; this summary just
- scratches the surface.
-
diff --git a/doc/HACKING/HowToReview.md b/doc/HACKING/HowToReview.md
new file mode 100644
index 0000000..d6b40db
--- /dev/null
+++ b/doc/HACKING/HowToReview.md
@@ -0,0 +1,85 @@
+How to review a patch
+=====================
+
+Some folks have said that they'd like to review patches more often, but they
+don't know how.
+
+So, here are a bunch of things to check for when reviewing a patch!
+
+Note that if you can't do every one of these, that doesn't mean you can't do
+a good review! Just make it clear what you checked for and what you didn't.
+
+
+Top-level smell-checks
+----------------------
+
+(Difficulty: easy)
+
+Does it compile with --enable-gcc-warnings?
+
+Does 'make check-spaces' pass?
+
+Does it have a reasonable amount of tests? Do they pass? Do they leak
+memory?
+
+Do all the new functions, global variables, types, and structure members have
+documentation?
+
+Do all the functions, global variables, types, and structure members with
+modified behavior have modified documentation?
+
+Do all the new torrc options have documentation?
+
+If this changes Tor's behavior on the wire, is there a design proposal?
+
+
+
+Let's look at the code!
+-----------------------
+
+Does the code conform to CodingStandards.txt?
+
+Does the code leak memory?
+
+If two or more pointers ever point to the same object, is it clear which
+pointer "owns" the object?
+
+Are all allocated resources freed?
+
+Are all pointers that should be const, const?
+
+Are #defines used for 'magic' numbers?
+
+Can you understand what the code is trying to do?
+
+Can you convince yourself that the code really does that?
+
+Is there duplicated code that could be turned into a function?
+
+
+Let's look at the documentation!
+--------------------------------
+
+Does the documentation confirm to CodingStandards.txt?
+
+Does it make sense?
+
+Can you predict what the function will do from its documentation?
+
+
+Let's think about security!
+---------------------------
+
+If there are any arrays, buffers, are you 100% sure that they cannot
+overflow?
+
+If there is any integer math, can it overflow or underflow?
+
+If there are any allocations, are you sure there are corresponding
+deallocations?
+
+Is there a safer pattern that could be used in any case?
+
+Have they used one of the Forbidden Functions?
+
+(Also see your favorite secure C programming guides.)
diff --git a/doc/HACKING/HowToReview.txt b/doc/HACKING/HowToReview.txt
deleted file mode 100644
index d6b40db..0000000
--- a/doc/HACKING/HowToReview.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-How to review a patch
-=====================
-
-Some folks have said that they'd like to review patches more often, but they
-don't know how.
-
-So, here are a bunch of things to check for when reviewing a patch!
-
-Note that if you can't do every one of these, that doesn't mean you can't do
-a good review! Just make it clear what you checked for and what you didn't.
-
-
-Top-level smell-checks
-----------------------
-
-(Difficulty: easy)
-
-Does it compile with --enable-gcc-warnings?
-
-Does 'make check-spaces' pass?
-
-Does it have a reasonable amount of tests? Do they pass? Do they leak
-memory?
-
-Do all the new functions, global variables, types, and structure members have
-documentation?
-
-Do all the functions, global variables, types, and structure members with
-modified behavior have modified documentation?
-
-Do all the new torrc options have documentation?
-
-If this changes Tor's behavior on the wire, is there a design proposal?
-
-
-
-Let's look at the code!
------------------------
-
-Does the code conform to CodingStandards.txt?
-
-Does the code leak memory?
-
-If two or more pointers ever point to the same object, is it clear which
-pointer "owns" the object?
-
-Are all allocated resources freed?
-
-Are all pointers that should be const, const?
-
-Are #defines used for 'magic' numbers?
-
-Can you understand what the code is trying to do?
-
-Can you convince yourself that the code really does that?
-
-Is there duplicated code that could be turned into a function?
-
-
-Let's look at the documentation!
---------------------------------
-
-Does the documentation confirm to CodingStandards.txt?
-
-Does it make sense?
-
-Can you predict what the function will do from its documentation?
-
-
-Let's think about security!
----------------------------
-
-If there are any arrays, buffers, are you 100% sure that they cannot
-overflow?
-
-If there is any integer math, can it overflow or underflow?
-
-If there are any allocations, are you sure there are corresponding
-deallocations?
-
-Is there a safer pattern that could be used in any case?
-
-Have they used one of the Forbidden Functions?
-
-(Also see your favorite secure C programming guides.)
diff --git a/doc/HACKING/README.1st b/doc/HACKING/README.1st
deleted file mode 100644
index 3bee9ad..0000000
--- a/doc/HACKING/README.1st
+++ /dev/null
@@ -1,60 +0,0 @@
-
-In this directory
------------------
-
-This directory has helpful information about what you need to know to
-hack on Tor!
-
-First, read 'GettingStarted.txt' to learn how to get a start in Tor
-development.
-
-If you've decided to write a patch, 'CodingStandards.txt' will give
-you a bunch of information about how we structure our code.
-
-It's important to get code right! Reading 'WritingTests.txt' will
-tell you how to write and run tests in the Tor codebase.
-
-There are a bunch of other programs we use to help maintain and
-develop the codebase: 'HelpfulTools.txt' can tell you how to use them
-with Tor.
-
-If it's your job to put out Tor releases, see 'ReleasingTor.txt' so
-that you don't miss any steps!
-
-
-
------------------------
-
-For full information on how Tor is supposed to work, look at the files in
-https://gitweb.torproject.org/torspec.git/tree
-
-For an explanation of how to change Tor's design to work differently, look at
-https://gitweb.torproject.org/torspec.git/blob_plain/HEAD:/proposals/001-process.txt
-
-For the latest version of the code, get a copy of git, and
-
- git clone https://git.torproject.org/git/tor
-
-We talk about Tor on the tor-talk mailing list. Design proposals and
-discussion belong on the tor-dev mailing list. We hang around on
-irc.oftc.net, with general discussion happening on #tor and development
-happening on #tor-dev.
-
-The other files in this "HACKING" directory may also be useful as you
-get started working with Tor.
-
-Happy hacking!
-
-XXXXX also describe
-
-doc/HACKING/WritingTests.txt
-
-torguts.git
-
-torspec.git
-
-The design paper
-
-freehaven.net/anonbib
-
-XXXX describe these and add links.
diff --git a/doc/HACKING/README.1st.md b/doc/HACKING/README.1st.md
new file mode 100644
index 0000000..3bee9ad
--- /dev/null
+++ b/doc/HACKING/README.1st.md
@@ -0,0 +1,60 @@
+
+In this directory
+-----------------
+
+This directory has helpful information about what you need to know to
+hack on Tor!
+
+First, read 'GettingStarted.txt' to learn how to get a start in Tor
+development.
+
+If you've decided to write a patch, 'CodingStandards.txt' will give
+you a bunch of information about how we structure our code.
+
+It's important to get code right! Reading 'WritingTests.txt' will
+tell you how to write and run tests in the Tor codebase.
+
+There are a bunch of other programs we use to help maintain and
+develop the codebase: 'HelpfulTools.txt' can tell you how to use them
+with Tor.
+
+If it's your job to put out Tor releases, see 'ReleasingTor.txt' so
+that you don't miss any steps!
+
+
+
+-----------------------
+
+For full information on how Tor is supposed to work, look at the files in
+https://gitweb.torproject.org/torspec.git/tree
+
+For an explanation of how to change Tor's design to work differently, look at
+https://gitweb.torproject.org/torspec.git/blob_plain/HEAD:/proposals/001-process.txt
+
+For the latest version of the code, get a copy of git, and
+
+ git clone https://git.torproject.org/git/tor
+
+We talk about Tor on the tor-talk mailing list. Design proposals and
+discussion belong on the tor-dev mailing list. We hang around on
+irc.oftc.net, with general discussion happening on #tor and development
+happening on #tor-dev.
+
+The other files in this "HACKING" directory may also be useful as you
+get started working with Tor.
+
+Happy hacking!
+
+XXXXX also describe
+
+doc/HACKING/WritingTests.txt
+
+torguts.git
+
+torspec.git
+
+The design paper
+
+freehaven.net/anonbib
+
+XXXX describe these and add links.
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
new file mode 100644
index 0000000..dcf551b
--- /dev/null
+++ b/doc/HACKING/ReleasingTor.md
@@ -0,0 +1,125 @@
+
+Putting out a new release
+-------------------------
+
+Here are the steps Roger takes when putting out a new Tor release:
+
+1) Use it for a while, as a client, as a relay, as a hidden service,
+and as a directory authority. See if it has any obvious bugs, and
+resolve those.
+
+1.5) As applicable, merge the maint-X branch into the release-X branch.
+
+2) Gather the changes/* files into a changelog entry, rewriting many
+of them and reordering to focus on what users and funders would find
+interesting and understandable.
+
+ 2.1) Make sure that everything that wants a bug number has one.
+ Make sure that everything which is a bugfix says what version
+ it was a bugfix on.
+ 2.2) Concatenate them.
+ 2.3) Sort them by section. Within each section, sort by "version it's
+ a bugfix on", else by numerical ticket order.
+
+ 2.4) Clean them up:
+
+ Standard idioms:
+ "Fixes bug 9999; bugfix on 0.3.3.3-alpha."
+
+ One space after a period.
+
+ Make stuff very terse
+
+ Make sure each section name ends with a colon
+
+ Describe the user-visible problem right away
+
+ Mention relevant config options by name. If they're rare or unusual,
+ remind people what they're for
+
+ Avoid starting lines with open-paren
+
+ Present and imperative tense: not past.
+
+ 'Relays', not 'servers' or 'nodes' or 'Tor relays'.
+
+ "Stop FOOing", not "Fix a bug where we would FOO".
+
+ Try not to let any given section be longer than about a page. Break up
+ long sections into subsections by some sort of common subtopic. This
+ guideline is especially important when organizing Release Notes for
+ new stable releases.
+
+ If a given changes stanza showed up in a different release (e.g.
+ maint-0.2.1), be sure to make the stanzas identical (so people can
+ distinguish if these are the same change).
+
+ 2.5) Merge them in.
+
+ 2.6) Clean everything one last time.
+
+ 2.7) Run ./scripts/maint/format_changelog.py to make it prettier.
+
+3) Compose a short release blurb to highlight the user-facing
+changes. Insert said release blurb into the ChangeLog stanza. If it's
+a stable release, add it to the ReleaseNotes file too. If we're adding
+to a release-0.2.x branch, manually commit the changelogs to the later
+git branches too.
+
+4) In maint-0.2.x, bump the version number in configure.ac and run
+ scripts/maint/updateVersions.pl to update version numbers in other
+ places, and commit. Then merge maint-0.2.x into release-0.2.x.
+
+ (NOTE: To bump the version number, edit configure.ac, and then run
+ either make, or 'perl scripts/maint/updateVersions.pl', depending on
+ your version.)
+
+5) Make dist, put the tarball up somewhere, and tell #tor about it. Wait
+a while to see if anybody has problems building it. Try to get Sebastian
+or somebody to try building it on Windows.
+
+6) Get at least two of weasel/arma/Sebastian to put the new version number
+in their approved versions list.
+
+7) Sign the tarball, then sign and push the git tag:
+ gpg -ba <the_tarball>
+ git tag -u <keyid> tor-0.2.x.y-status
+ git push origin tag tor-0.2.x.y-status
+
+8a) scp the tarball and its sig to the dist website, i.e.
+/srv/dist-master.torproject.org/htdocs/ on dist-master. When you want
+it to go live, you run "static-update-component dist.torproject.org"
+on dist-master.
+
+8b) Edit "include/versions.wmi" and "Makefile" to note the new version.
+
+9) Email the packagers (cc'ing tor-assistants) that a new tarball is up.
+ The current list of packagers is:
+ {weasel,gk,mikeperry} at torproject dot org
+ {blueness} at gentoo dot org
+ {paul} at invizbox dot io
+ {ondrej.mikle} at gmail dot com
+ {lfleischer} at archlinux dot org
+ {tails-dev} at doum dot org
+
+10) Add the version number to Trac. To do this, go to Trac, log in,
+select "Admin" near the top of the screen, then select "Versions" from
+the menu on the left. At the right, there will be an "Add version"
+box. By convention, we enter the version in the form "Tor:
+0.2.2.23-alpha" (or whatever the version is), and we select the date as
+the date in the ChangeLog.
+
+11) Forward-port the ChangeLog.
+
+12) Wait up to a day or two (for a development release), or until most
+packages are up (for a stable release), and mail the release blurb and
+changelog to tor-talk or tor-announce.
+
+ (We might be moving to faster announcements, but don't announce until
+ the website is at least updated.)
+
+13) If it's a stable release, bump the version number in the maint-x.y.z
+ branch to "newversion-dev", and do a "merge -s ours" merge to avoid
+ taking that change into master. Do a similar 'merge -s theirs'
+ merge to get the change (and only that change) into release. (Some
+ of the build scripts require that maint merge cleanly into release.)
diff --git a/doc/HACKING/ReleasingTor.txt b/doc/HACKING/ReleasingTor.txt
deleted file mode 100644
index dcf551b..0000000
--- a/doc/HACKING/ReleasingTor.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-
-Putting out a new release
--------------------------
-
-Here are the steps Roger takes when putting out a new Tor release:
-
-1) Use it for a while, as a client, as a relay, as a hidden service,
-and as a directory authority. See if it has any obvious bugs, and
-resolve those.
-
-1.5) As applicable, merge the maint-X branch into the release-X branch.
-
-2) Gather the changes/* files into a changelog entry, rewriting many
-of them and reordering to focus on what users and funders would find
-interesting and understandable.
-
- 2.1) Make sure that everything that wants a bug number has one.
- Make sure that everything which is a bugfix says what version
- it was a bugfix on.
- 2.2) Concatenate them.
- 2.3) Sort them by section. Within each section, sort by "version it's
- a bugfix on", else by numerical ticket order.
-
- 2.4) Clean them up:
-
- Standard idioms:
- "Fixes bug 9999; bugfix on 0.3.3.3-alpha."
-
- One space after a period.
-
- Make stuff very terse
-
- Make sure each section name ends with a colon
-
- Describe the user-visible problem right away
-
- Mention relevant config options by name. If they're rare or unusual,
- remind people what they're for
-
- Avoid starting lines with open-paren
-
- Present and imperative tense: not past.
-
- 'Relays', not 'servers' or 'nodes' or 'Tor relays'.
-
- "Stop FOOing", not "Fix a bug where we would FOO".
-
- Try not to let any given section be longer than about a page. Break up
- long sections into subsections by some sort of common subtopic. This
- guideline is especially important when organizing Release Notes for
- new stable releases.
-
- If a given changes stanza showed up in a different release (e.g.
- maint-0.2.1), be sure to make the stanzas identical (so people can
- distinguish if these are the same change).
-
- 2.5) Merge them in.
-
- 2.6) Clean everything one last time.
-
- 2.7) Run ./scripts/maint/format_changelog.py to make it prettier.
-
-3) Compose a short release blurb to highlight the user-facing
-changes. Insert said release blurb into the ChangeLog stanza. If it's
-a stable release, add it to the ReleaseNotes file too. If we're adding
-to a release-0.2.x branch, manually commit the changelogs to the later
-git branches too.
-
-4) In maint-0.2.x, bump the version number in configure.ac and run
- scripts/maint/updateVersions.pl to update version numbers in other
- places, and commit. Then merge maint-0.2.x into release-0.2.x.
-
- (NOTE: To bump the version number, edit configure.ac, and then run
- either make, or 'perl scripts/maint/updateVersions.pl', depending on
- your version.)
-
-5) Make dist, put the tarball up somewhere, and tell #tor about it. Wait
-a while to see if anybody has problems building it. Try to get Sebastian
-or somebody to try building it on Windows.
-
-6) Get at least two of weasel/arma/Sebastian to put the new version number
-in their approved versions list.
-
-7) Sign the tarball, then sign and push the git tag:
- gpg -ba <the_tarball>
- git tag -u <keyid> tor-0.2.x.y-status
- git push origin tag tor-0.2.x.y-status
-
-8a) scp the tarball and its sig to the dist website, i.e.
-/srv/dist-master.torproject.org/htdocs/ on dist-master. When you want
-it to go live, you run "static-update-component dist.torproject.org"
-on dist-master.
-
-8b) Edit "include/versions.wmi" and "Makefile" to note the new version.
-
-9) Email the packagers (cc'ing tor-assistants) that a new tarball is up.
- The current list of packagers is:
- {weasel,gk,mikeperry} at torproject dot org
- {blueness} at gentoo dot org
- {paul} at invizbox dot io
- {ondrej.mikle} at gmail dot com
- {lfleischer} at archlinux dot org
- {tails-dev} at doum dot org
-
-10) Add the version number to Trac. To do this, go to Trac, log in,
-select "Admin" near the top of the screen, then select "Versions" from
-the menu on the left. At the right, there will be an "Add version"
-box. By convention, we enter the version in the form "Tor:
-0.2.2.23-alpha" (or whatever the version is), and we select the date as
-the date in the ChangeLog.
-
-11) Forward-port the ChangeLog.
-
-12) Wait up to a day or two (for a development release), or until most
-packages are up (for a stable release), and mail the release blurb and
-changelog to tor-talk or tor-announce.
-
- (We might be moving to faster announcements, but don't announce until
- the website is at least updated.)
-
-13) If it's a stable release, bump the version number in the maint-x.y.z
- branch to "newversion-dev", and do a "merge -s ours" merge to avoid
- taking that change into master. Do a similar 'merge -s theirs'
- merge to get the change (and only that change) into release. (Some
- of the build scripts require that maint merge cleanly into release.)
diff --git a/doc/HACKING/WritingTests.md b/doc/HACKING/WritingTests.md
new file mode 100644
index 0000000..2f59c9a
--- /dev/null
+++ b/doc/HACKING/WritingTests.md
@@ -0,0 +1,403 @@
+
+Writing tests for Tor: an incomplete guide
+==========================================
+
+Tor uses a variety of testing frameworks and methodologies to try to
+keep from introducing bugs. The major ones are:
+
+ 1. Unit tests written in C and shipped with the Tor distribution.
+
+ 2. Integration tests written in Python and shipped with the Tor
+ distribution.
+
+ 3. Integration tests written in Python and shipped with the Stem
+ library. Some of these use the Tor controller protocol.
+
+ 4. System tests written in Python and SH, and shipped with the
+ Chutney package. These work by running many instances of Tor
+ locally, and sending traffic through them.
+
+ 5. The Shadow network simulator.
+
+How to run these tests
+----------------------
+
+=== The easy version
+
+To run all the tests that come bundled with Tor, run "make check"
+
+To run the Stem tests as well, fetch stem from the git repository,
+set STEM_SOURCE_DIR to the checkout, and run "make test-stem".
+
+To run the Chutney tests as well, fetch chutney from the git repository,
+set CHUTNEY_PATH to the checkout, and run "make test-network".
+
+To run all of the above, run "make test-full".
+
+To run all of the above, plus tests that require a working connection to the
+internet, run "make test-full-online".
+
+=== Running particular subtests
+
+The Tor unit tests are divided into separate programs and a couple of
+bundled unit test programs.
+
+Separate programs are easy. For example, to run the memwipe tests in
+isolation, you just run ./src/test/test-memwipe .
+
+To run tests within the unit test programs, you can specify the name
+of the test. The string ".." can be used as a wildcard at the end of the
+test name. For example, to run all the cell format tests, enter
+"./src/test/test cellfmt/..". To run
+
+Many tests that need to mess with global state run in forked subprocesses in
+order to keep from contaminating one another. But when debugging a failing test,
+you might want to run it without forking a subprocess. To do so, use the
+"--no-fork" option with a single test. (If you specify it along with
+multiple tests, they might interfere.)
+
+You can turn on logging in the unit tests by passing one of "--debug",
+"--info", "--notice", or "--warn". By default only errors are displayed.
+
+Unit tests are divided into "./src/test/test" and "./src/test/test-slow".
+The former are those that should finish in a few seconds; the latter tend to
+take more time, and may include CPU-intensive operations, deliberate delays,
+and stuff like that.
+
+=== Finding test coverage
+
+Test coverage is a measurement of which lines your tests actually visit.
+
+When you configure Tor with the --enable-coverage option, it should
+build with support for coverage in the unit tests, and in a special
+"tor-cov" binary.
+
+Then, run the tests you'd like to see coverage from. If you have old
+coverage output, you may need to run "reset-gcov" first.
+
+Now you've got a bunch of files scattered around your build directories
+called "*.gcda". In order to extract the coverage output from them, make a
+temporary directory for them and run "./scripts/test/coverage ${TMPDIR}",
+where ${TMPDIR} is the temporary directory you made. This will create a
+".gcov" file for each source file under tests, containing that file's source
+annotated with the number of times the tests hit each line. (You'll need to
+have gcov installed.)
+
+You can get a summary of the test coverage for each file by running
+"./scripts/test/cov-display ${TMPDIR}/*" . Each line lists the file's name,
+the number of uncovered lines, the number of uncovered lines, and the
+coverage percentage.
+
+For a summary of the test coverage for each _function_, run
+"./scripts/test/cov-display -f ${TMPDIR}/*" .
+
+=== Comparing test coverage
+
+Sometimes it's useful to compare test coverage for a branch you're writing to
+coverage from another branch (such as git master, for example). But you
+can't run "diff" on the two coverage outputs directly, since the actual
+number of times each line is executed aren't so important, and aren't wholly
+deterministic.
+
+Instead, follow the instructions above for each branch, creating a separate
+temporary directory for each. Then, run "./scripts/test/cov-diff ${D1}
+${D2}", where D1 and D2 are the directories you want to compare. This will
+produce a diff of the two directories, with all lines normalized to be either
+covered or uncovered.
+
+To count new or modified uncovered lines in D2, you can run:
+
+ "./scripts/test/cov-diff ${D1} ${D2}" | grep '^+ *\#' |wc -l
+
+
+What kinds of test should I write?
+----------------------------------
+
+Integration testing and unit testing are complementary: it's probably a
+good idea to make sure that your code is hit by both if you can.
+
+If your code is very-low level, and its behavior is easily described in
+terms of a relation between inputs and outputs, or a set of state
+transitions, then it's a natural fit for unit tests. (If not, please
+consider refactoring it until most of it _is_ a good fit for unit
+tests!)
+
+If your code adds new externally visible functionality to Tor, it would
+be great to have a test for that functionality. That's where
+integration tests more usually come in.
+
+Unit and regression tests: Does this function do what it's supposed to?
+-----------------------------------------------------------------------
+
+Most of Tor's unit tests are made using the "tinytest" testing framework.
+You can see a guide to using it in the tinytest manual at
+
+ https://github.com/nmathewson/tinytest/blob/master/tinytest-manual.md
+
+To add a new test of this kind, either edit an existing C file in src/test/,
+or create a new C file there. Each test is a single function that must
+be indexed in the table at the end of the file. We use the label "done:" as
+a cleanup point for all test functions.
+
+(Make sure you read tinytest-manual.md before proceeding.)
+
+I use the term "unit test" and "regression tests" very sloppily here.
+
+=== A simple example
+
+Here's an example of a test function for a simple function in util.c:
+
+ static void
+ test_util_writepid(void *arg)
+ {
+ (void) arg;
+
+ char *contents = NULL;
+ const char *fname = get_fname("tmp_pid");
+ unsigned long pid;
+ char c;
+
+ write_pidfile(fname);
+
+ contents = read_file_to_str(fname, 0, NULL);
+ tt_assert(contents);
+
+ int n = sscanf(contents, "%lu\n%c", &pid, &c);
+ tt_int_op(n, OP_EQ, 1);
+ tt_int_op(pid, OP_EQ, getpid());
+
+ done:
+ tor_free(contents);
+ }
+
+This should look pretty familiar to you if you've read the tinytest
+manual. One thing to note here is that we use the testing-specific
+function "get_fname" to generate a file with respect to a temporary
+directory that the tests use. You don't need to delete the file;
+it will get removed when the tests are done.
+
+Also note our use of OP_EQ instead of == in the tt_int_op() calls.
+We define OP_* macros to use instead of the binary comparison
+operators so that analysis tools can more easily parse our code.
+(Coccinelle really hates to see == used as a macro argument.)
+
+Finally, remember that by convention, all *_free() functions that
+Tor defines are defined to accept NULL harmlessly. Thus, you don't
+need to say "if (contents)" in the cleanup block.
+
+=== Exposing static functions for testing
+
+Sometimes you need to test a function, but you don't want to expose
+it outside its usual module.
+
+To support this, Tor's build system compiles a testing version of
+each module, with extra identifiers exposed. If you want to
+declare a function as static but available for testing, use the
+macro "STATIC" instead of "static". Then, make sure there's a
+macro-protected declaration of the function in the module's header.
+
+For example, crypto_curve25519.h contains:
+
+#ifdef CRYPTO_CURVE25519_PRIVATE
+STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
+ const uint8_t *basepoint);
+#endif
+
+The crypto_curve25519.c file and the test_crypto.c file both define
+CRYPTO_CURVE25519_PRIVATE, so they can see this declaration.
+
+=== Mock functions for testing in isolation
+
+Often we want to test that a function works right, but the function to
+be tested depends on other functions whose behavior is hard to observe,
+or which require a working Tor network, or something like that.
+
+To write tests for this case, you can replace the underlying functions
+with testing stubs while your unit test is running. You need to declare
+the underlying function as 'mockable', as follows:
+
+ MOCK_DECL(returntype, functionname, (argument list));
+
+and then later implement it as:
+
+ MOCK_IMPL(returntype, functionname, (argument list))
+ {
+ /* implementation here */
+ }
+
+For example, if you had a 'connect to remote server' function, you could
+declare it as:
+
+
+ MOCK_DECL(int, connect_to_remote, (const char *name, status_t *status));
+
+When you declare a function this way, it will be declared as normal in
+regular builds, but when the module is built for testing, it is declared
+as a function pointer initialized to the actual implementation.
+
+In your tests, if you want to override the function with a temporary
+replacement, you say:
+
+ MOCK(functionname, replacement_function_name);
+
+And later, you can restore the original function with:
+
+ UNMOCK(functionname);
+
+For more information, see the definitions of this mocking logic in
+testsupport.h.
+
+=== Okay but what should my tests actually do?
+
+We talk above about "test coverage" -- making sure that your tests visit
+every line of code, or every branch of code. But visiting the code isn't
+enough: we want to verify that it's correct.
+
+So when writing tests, try to make tests that should pass with any correct
+implementation of the code, and that should fail if the code doesn't do what
+it's supposed to do.
+
+You can write "black-box" tests or "glass-box" tests. A black-box test is
+one that you write without looking at the structure of the function. A
+glass-box one is one you implement while looking at how the function is
+implemented.
+
+In either case, make sure to consider common cases *and* edge cases; success
+cases and failure csaes.
+
+For example, consider testing this function:
+
+ /** Remove all elements E from sl such that E==element. Preserve
+ * the order of any elements before E, but elements after E can be
+ * rearranged.
+ */
+ void smartlist_remove(smartlist_t *sl, const void *element);
+
+In order to test it well, you should write tests for at least all of the
+following cases. (These would be black-box tests, since we're only looking
+at the declared behavior for the function:
+
+ * Remove an element that is in the smartlist.
+ * Remove an element that is not in the smartlist.
+ * Remove an element that appears in the smartlist more than once.
+
+And your tests should verify that it behaves correct. At minimum, you should
+test:
+
+ * That other elements before E are in the same order after you call the
+ functions.
+ * That the target element is really removed.
+ * That _only_ the target element is removed.
+
+When you consider edge cases, you might try:
+
+ * Remove an element from an empty list.
+ * Remove an element from a singleton list containing that element.
+ * Remove an element for a list containing several instances of that
+ element, and nothing else.
+
+Now let's look at the implementation:
+
+ void
+ smartlist_remove(smartlist_t *sl, const void *element)
+ {
+ int i;
+ if (element == NULL)
+ return;
+ for (i=0; i < sl->num_used; i++)
+ if (sl->list[i] == element) {
+ sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
+ i--; /* so we process the new i'th element */
+ sl->list[sl->num_used] = NULL;
+ }
+ }
+
+Based on the implementation, we now see three more edge cases to test:
+
+ * Removing NULL from the list.
+ * Removing an element from the end of the list
+ * Removing an element from a position other than the end of the list.
+
+
+=== What should my tests NOT do?
+
+Tests shouldn't require a network connection.
+
+Whenever possible, tests shouldn't take more than a second. Put the test
+into test/slow if it genuinely needs to be run.
+
+Tests should not alter global state unless they run with TT_FORK: Tests
+should not require other tests to be run before or after them.
+
+Tests should not leak memory or other resources. To find out if your tests
+are leaking memory, run them under valgrind (see HelpfulTools.txt for more
+information on how to do that).
+
+When possible, tests should not be over-fit to the implementation. That is,
+the test should verify that the documented behavior is implemented, but
+should not break if other permissible behavior is later implemented.
+
+
+=== Advanced techniques: Namespaces
+
+Sometimes, when you're doing a lot of mocking at once, it's convenient to
+isolate your identifiers within a single namespace. If this were C++, we'd
+already have namespaces, but for C, we do the best we can with macros and
+token-pasting.
+
+We have some macros defined for this purpose in src/test/test.h. To use
+them, you define NS_MODULE to a prefix to be used for your identifiers, and
+then use other macros in place of identifier names. See src/test/test.h for
+more documentation.
+
+
+Integration tests: Calling Tor from the outside
+-----------------------------------------------
+
+Some tests need to invoke Tor from the outside, and shouldn't run from the
+same process as the Tor test program. Reasons for doing this might include:
+
+ * Testing the actual behavior of Tor when run from the command line
+ * Testing that a crash-handler correctly logs a stack trace
+ * Verifying that violating a sandbox or capability requirement will
+ actually crash the program.
+ * Needing to run as root in order to test capability inheritance or
+ user switching.
+
+To add one of these, you generally want a new C program in src/test. Add it
+to TESTS and noinst_PROGRAMS if it can run on its own and return success or
+failure. If it needs to be invoked multiple times, or it needs to be
+wrapped, add a new shell script to TESTS, and the new program to
+noinst_PROGRAMS. If you need access to any environment variable from the
+makefile (eg ${PYTHON} for a python interpreter), then make sure that the
+makefile exports them.
+
+Writing integration tests with Stem
+-----------------------------------
+
+The 'stem' library includes extensive unit tests for the Tor controller
+protocol.
+
+For more information on writing new tests for stem, have a look around
+the test/* directory in stem, and find a good example to emulate. You
+might want to start with
+https://gitweb.torproject.org/stem.git/tree/test/integ/control/controller.py
+to improve Tor's test coverage.
+
+You can run stem tests from tor with "make test-stem", or see
+https://stem.torproject.org/faq.html#how-do-i-run-the-tests .
+
+System testing with Chutney
+---------------------------
+
+The 'chutney' program configures and launches a set of Tor relays,
+authorities, and clients on your local host. It has a 'test network'
+functionality to send traffic through them and verify that the traffic
+arrives correctly.
+
+You can write new test networks by adding them to 'networks'. To add
+them to Tor's tests, add them to the test-network or test-network-all
+targets in Makefile.am.
+
+(Adding new kinds of program to chutney will still require hacking the
+code.)
diff --git a/doc/HACKING/WritingTests.txt b/doc/HACKING/WritingTests.txt
deleted file mode 100644
index 2f59c9a..0000000
--- a/doc/HACKING/WritingTests.txt
+++ /dev/null
@@ -1,403 +0,0 @@
-
-Writing tests for Tor: an incomplete guide
-==========================================
-
-Tor uses a variety of testing frameworks and methodologies to try to
-keep from introducing bugs. The major ones are:
-
- 1. Unit tests written in C and shipped with the Tor distribution.
-
- 2. Integration tests written in Python and shipped with the Tor
- distribution.
-
- 3. Integration tests written in Python and shipped with the Stem
- library. Some of these use the Tor controller protocol.
-
- 4. System tests written in Python and SH, and shipped with the
- Chutney package. These work by running many instances of Tor
- locally, and sending traffic through them.
-
- 5. The Shadow network simulator.
-
-How to run these tests
-----------------------
-
-=== The easy version
-
-To run all the tests that come bundled with Tor, run "make check"
-
-To run the Stem tests as well, fetch stem from the git repository,
-set STEM_SOURCE_DIR to the checkout, and run "make test-stem".
-
-To run the Chutney tests as well, fetch chutney from the git repository,
-set CHUTNEY_PATH to the checkout, and run "make test-network".
-
-To run all of the above, run "make test-full".
-
-To run all of the above, plus tests that require a working connection to the
-internet, run "make test-full-online".
-
-=== Running particular subtests
-
-The Tor unit tests are divided into separate programs and a couple of
-bundled unit test programs.
-
-Separate programs are easy. For example, to run the memwipe tests in
-isolation, you just run ./src/test/test-memwipe .
-
-To run tests within the unit test programs, you can specify the name
-of the test. The string ".." can be used as a wildcard at the end of the
-test name. For example, to run all the cell format tests, enter
-"./src/test/test cellfmt/..". To run
-
-Many tests that need to mess with global state run in forked subprocesses in
-order to keep from contaminating one another. But when debugging a failing test,
-you might want to run it without forking a subprocess. To do so, use the
-"--no-fork" option with a single test. (If you specify it along with
-multiple tests, they might interfere.)
-
-You can turn on logging in the unit tests by passing one of "--debug",
-"--info", "--notice", or "--warn". By default only errors are displayed.
-
-Unit tests are divided into "./src/test/test" and "./src/test/test-slow".
-The former are those that should finish in a few seconds; the latter tend to
-take more time, and may include CPU-intensive operations, deliberate delays,
-and stuff like that.
-
-=== Finding test coverage
-
-Test coverage is a measurement of which lines your tests actually visit.
-
-When you configure Tor with the --enable-coverage option, it should
-build with support for coverage in the unit tests, and in a special
-"tor-cov" binary.
-
-Then, run the tests you'd like to see coverage from. If you have old
-coverage output, you may need to run "reset-gcov" first.
-
-Now you've got a bunch of files scattered around your build directories
-called "*.gcda". In order to extract the coverage output from them, make a
-temporary directory for them and run "./scripts/test/coverage ${TMPDIR}",
-where ${TMPDIR} is the temporary directory you made. This will create a
-".gcov" file for each source file under tests, containing that file's source
-annotated with the number of times the tests hit each line. (You'll need to
-have gcov installed.)
-
-You can get a summary of the test coverage for each file by running
-"./scripts/test/cov-display ${TMPDIR}/*" . Each line lists the file's name,
-the number of uncovered lines, the number of uncovered lines, and the
-coverage percentage.
-
-For a summary of the test coverage for each _function_, run
-"./scripts/test/cov-display -f ${TMPDIR}/*" .
-
-=== Comparing test coverage
-
-Sometimes it's useful to compare test coverage for a branch you're writing to
-coverage from another branch (such as git master, for example). But you
-can't run "diff" on the two coverage outputs directly, since the actual
-number of times each line is executed aren't so important, and aren't wholly
-deterministic.
-
-Instead, follow the instructions above for each branch, creating a separate
-temporary directory for each. Then, run "./scripts/test/cov-diff ${D1}
-${D2}", where D1 and D2 are the directories you want to compare. This will
-produce a diff of the two directories, with all lines normalized to be either
-covered or uncovered.
-
-To count new or modified uncovered lines in D2, you can run:
-
- "./scripts/test/cov-diff ${D1} ${D2}" | grep '^+ *\#' |wc -l
-
-
-What kinds of test should I write?
-----------------------------------
-
-Integration testing and unit testing are complementary: it's probably a
-good idea to make sure that your code is hit by both if you can.
-
-If your code is very-low level, and its behavior is easily described in
-terms of a relation between inputs and outputs, or a set of state
-transitions, then it's a natural fit for unit tests. (If not, please
-consider refactoring it until most of it _is_ a good fit for unit
-tests!)
-
-If your code adds new externally visible functionality to Tor, it would
-be great to have a test for that functionality. That's where
-integration tests more usually come in.
-
-Unit and regression tests: Does this function do what it's supposed to?
------------------------------------------------------------------------
-
-Most of Tor's unit tests are made using the "tinytest" testing framework.
-You can see a guide to using it in the tinytest manual at
-
- https://github.com/nmathewson/tinytest/blob/master/tinytest-manual.md
-
-To add a new test of this kind, either edit an existing C file in src/test/,
-or create a new C file there. Each test is a single function that must
-be indexed in the table at the end of the file. We use the label "done:" as
-a cleanup point for all test functions.
-
-(Make sure you read tinytest-manual.md before proceeding.)
-
-I use the term "unit test" and "regression tests" very sloppily here.
-
-=== A simple example
-
-Here's an example of a test function for a simple function in util.c:
-
- static void
- test_util_writepid(void *arg)
- {
- (void) arg;
-
- char *contents = NULL;
- const char *fname = get_fname("tmp_pid");
- unsigned long pid;
- char c;
-
- write_pidfile(fname);
-
- contents = read_file_to_str(fname, 0, NULL);
- tt_assert(contents);
-
- int n = sscanf(contents, "%lu\n%c", &pid, &c);
- tt_int_op(n, OP_EQ, 1);
- tt_int_op(pid, OP_EQ, getpid());
-
- done:
- tor_free(contents);
- }
-
-This should look pretty familiar to you if you've read the tinytest
-manual. One thing to note here is that we use the testing-specific
-function "get_fname" to generate a file with respect to a temporary
-directory that the tests use. You don't need to delete the file;
-it will get removed when the tests are done.
-
-Also note our use of OP_EQ instead of == in the tt_int_op() calls.
-We define OP_* macros to use instead of the binary comparison
-operators so that analysis tools can more easily parse our code.
-(Coccinelle really hates to see == used as a macro argument.)
-
-Finally, remember that by convention, all *_free() functions that
-Tor defines are defined to accept NULL harmlessly. Thus, you don't
-need to say "if (contents)" in the cleanup block.
-
-=== Exposing static functions for testing
-
-Sometimes you need to test a function, but you don't want to expose
-it outside its usual module.
-
-To support this, Tor's build system compiles a testing version of
-each module, with extra identifiers exposed. If you want to
-declare a function as static but available for testing, use the
-macro "STATIC" instead of "static". Then, make sure there's a
-macro-protected declaration of the function in the module's header.
-
-For example, crypto_curve25519.h contains:
-
-#ifdef CRYPTO_CURVE25519_PRIVATE
-STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *basepoint);
-#endif
-
-The crypto_curve25519.c file and the test_crypto.c file both define
-CRYPTO_CURVE25519_PRIVATE, so they can see this declaration.
-
-=== Mock functions for testing in isolation
-
-Often we want to test that a function works right, but the function to
-be tested depends on other functions whose behavior is hard to observe,
-or which require a working Tor network, or something like that.
-
-To write tests for this case, you can replace the underlying functions
-with testing stubs while your unit test is running. You need to declare
-the underlying function as 'mockable', as follows:
-
- MOCK_DECL(returntype, functionname, (argument list));
-
-and then later implement it as:
-
- MOCK_IMPL(returntype, functionname, (argument list))
- {
- /* implementation here */
- }
-
-For example, if you had a 'connect to remote server' function, you could
-declare it as:
-
-
- MOCK_DECL(int, connect_to_remote, (const char *name, status_t *status));
-
-When you declare a function this way, it will be declared as normal in
-regular builds, but when the module is built for testing, it is declared
-as a function pointer initialized to the actual implementation.
-
-In your tests, if you want to override the function with a temporary
-replacement, you say:
-
- MOCK(functionname, replacement_function_name);
-
-And later, you can restore the original function with:
-
- UNMOCK(functionname);
-
-For more information, see the definitions of this mocking logic in
-testsupport.h.
-
-=== Okay but what should my tests actually do?
-
-We talk above about "test coverage" -- making sure that your tests visit
-every line of code, or every branch of code. But visiting the code isn't
-enough: we want to verify that it's correct.
-
-So when writing tests, try to make tests that should pass with any correct
-implementation of the code, and that should fail if the code doesn't do what
-it's supposed to do.
-
-You can write "black-box" tests or "glass-box" tests. A black-box test is
-one that you write without looking at the structure of the function. A
-glass-box one is one you implement while looking at how the function is
-implemented.
-
-In either case, make sure to consider common cases *and* edge cases; success
-cases and failure csaes.
-
-For example, consider testing this function:
-
- /** Remove all elements E from sl such that E==element. Preserve
- * the order of any elements before E, but elements after E can be
- * rearranged.
- */
- void smartlist_remove(smartlist_t *sl, const void *element);
-
-In order to test it well, you should write tests for at least all of the
-following cases. (These would be black-box tests, since we're only looking
-at the declared behavior for the function:
-
- * Remove an element that is in the smartlist.
- * Remove an element that is not in the smartlist.
- * Remove an element that appears in the smartlist more than once.
-
-And your tests should verify that it behaves correct. At minimum, you should
-test:
-
- * That other elements before E are in the same order after you call the
- functions.
- * That the target element is really removed.
- * That _only_ the target element is removed.
-
-When you consider edge cases, you might try:
-
- * Remove an element from an empty list.
- * Remove an element from a singleton list containing that element.
- * Remove an element for a list containing several instances of that
- element, and nothing else.
-
-Now let's look at the implementation:
-
- void
- smartlist_remove(smartlist_t *sl, const void *element)
- {
- int i;
- if (element == NULL)
- return;
- for (i=0; i < sl->num_used; i++)
- if (sl->list[i] == element) {
- sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl->list[sl->num_used] = NULL;
- }
- }
-
-Based on the implementation, we now see three more edge cases to test:
-
- * Removing NULL from the list.
- * Removing an element from the end of the list
- * Removing an element from a position other than the end of the list.
-
-
-=== What should my tests NOT do?
-
-Tests shouldn't require a network connection.
-
-Whenever possible, tests shouldn't take more than a second. Put the test
-into test/slow if it genuinely needs to be run.
-
-Tests should not alter global state unless they run with TT_FORK: Tests
-should not require other tests to be run before or after them.
-
-Tests should not leak memory or other resources. To find out if your tests
-are leaking memory, run them under valgrind (see HelpfulTools.txt for more
-information on how to do that).
-
-When possible, tests should not be over-fit to the implementation. That is,
-the test should verify that the documented behavior is implemented, but
-should not break if other permissible behavior is later implemented.
-
-
-=== Advanced techniques: Namespaces
-
-Sometimes, when you're doing a lot of mocking at once, it's convenient to
-isolate your identifiers within a single namespace. If this were C++, we'd
-already have namespaces, but for C, we do the best we can with macros and
-token-pasting.
-
-We have some macros defined for this purpose in src/test/test.h. To use
-them, you define NS_MODULE to a prefix to be used for your identifiers, and
-then use other macros in place of identifier names. See src/test/test.h for
-more documentation.
-
-
-Integration tests: Calling Tor from the outside
------------------------------------------------
-
-Some tests need to invoke Tor from the outside, and shouldn't run from the
-same process as the Tor test program. Reasons for doing this might include:
-
- * Testing the actual behavior of Tor when run from the command line
- * Testing that a crash-handler correctly logs a stack trace
- * Verifying that violating a sandbox or capability requirement will
- actually crash the program.
- * Needing to run as root in order to test capability inheritance or
- user switching.
-
-To add one of these, you generally want a new C program in src/test. Add it
-to TESTS and noinst_PROGRAMS if it can run on its own and return success or
-failure. If it needs to be invoked multiple times, or it needs to be
-wrapped, add a new shell script to TESTS, and the new program to
-noinst_PROGRAMS. If you need access to any environment variable from the
-makefile (eg ${PYTHON} for a python interpreter), then make sure that the
-makefile exports them.
-
-Writing integration tests with Stem
------------------------------------
-
-The 'stem' library includes extensive unit tests for the Tor controller
-protocol.
-
-For more information on writing new tests for stem, have a look around
-the test/* directory in stem, and find a good example to emulate. You
-might want to start with
-https://gitweb.torproject.org/stem.git/tree/test/integ/control/controller.py
-to improve Tor's test coverage.
-
-You can run stem tests from tor with "make test-stem", or see
-https://stem.torproject.org/faq.html#how-do-i-run-the-tests .
-
-System testing with Chutney
----------------------------
-
-The 'chutney' program configures and launches a set of Tor relays,
-authorities, and clients on your local host. It has a 'test network'
-functionality to send traffic through them and verify that the traffic
-arrives correctly.
-
-You can write new test networks by adding them to 'networks'. To add
-them to Tor's tests, add them to the test-network or test-network-all
-targets in Makefile.am.
-
-(Adding new kinds of program to chutney will still require hacking the
-code.)
diff --git a/doc/include.am b/doc/include.am
index b235211..01a5ef2 100644
--- a/doc/include.am
+++ b/doc/include.am
@@ -39,13 +39,13 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
doc/state-contents.txt \
doc/torrc_format.txt \
doc/TUNING \
- doc/HACKING/README.1st \
- doc/HACKING/CodingStandards.txt \
- doc/HACKING/GettingStarted.txt \
- doc/HACKING/HelpfulTools.txt \
- doc/HACKING/HowToReview.txt \
- doc/HACKING/ReleasingTor.txt \
- doc/HACKING/WritingTests.txt
+ doc/HACKING/README.1st.md \
+ doc/HACKING/CodingStandards.md \
+ doc/HACKING/GettingStarted.md \
+ doc/HACKING/HelpfulTools.md \
+ doc/HACKING/HowToReview.md \
+ doc/HACKING/ReleasingTor.md \
+ doc/HACKING/WritingTests.md
docdir = @docdir@
1
0
commit f40dc287bd97d96936359313376b777415e5db65
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Thu Oct 29 14:28:17 2015 +0100
Clean up the doc/HACKING/* docs a bit.
---
doc/HACKING/CodingStandards.txt | 2 +-
doc/HACKING/GettingStarted.txt | 2 +-
doc/HACKING/HelpfulTools.txt | 8 ++++----
doc/HACKING/HowToReview.txt | 2 +-
doc/HACKING/ReleasingTor.txt | 4 ++--
doc/HACKING/WritingTests.txt | 6 +++---
6 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/doc/HACKING/CodingStandards.txt b/doc/HACKING/CodingStandards.txt
index f135fd1..ff602bd 100644
--- a/doc/HACKING/CodingStandards.txt
+++ b/doc/HACKING/CodingStandards.txt
@@ -122,7 +122,7 @@ using gcc, you should invoke the configure script with the option
"--enable-gcc-warnings". This will give a bunch of extra warning flags to
the compiler, and help us find divergences from our preferred C style.
-Functions to use; functions not to use.
+Functions to use; functions not to use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We have some wrapper functions like tor_malloc, tor_free, tor_strdup, and
diff --git a/doc/HACKING/GettingStarted.txt b/doc/HACKING/GettingStarted.txt
index af55977..e684ed7 100644
--- a/doc/HACKING/GettingStarted.txt
+++ b/doc/HACKING/GettingStarted.txt
@@ -29,7 +29,7 @@ file that comes with the Tor source for more information on building it,
and any high-quality guide to C for information on programming.)
I'm also going to assume that you know a little bit about how to use
-Git, or that you're able to fillow one of the several excellent guides
+Git, or that you're able to follow one of the several excellent guides
at http://git-scm.org to learn.
Most Tor developers develop using some Unix-based system, such as Linux,
diff --git a/doc/HACKING/HelpfulTools.txt b/doc/HACKING/HelpfulTools.txt
index f5a0c97..fd3b713 100644
--- a/doc/HACKING/HelpfulTools.txt
+++ b/doc/HACKING/HelpfulTools.txt
@@ -46,7 +46,7 @@ The preprocessor define __clang_analyzer__ is used to work around instances
where clang picks up behavior that we wish to permit.
clang Runtime Sanitizers
-~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~
To build the Tor codebase with the clang Address and Undefined Behavior
sanitizers, see the file contrib/clang/sanitize_blacklist.txt.
@@ -100,7 +100,7 @@ To run all tests, including those based on Stem or Chutney:
make test-full
-----
-To run all tests, including those basedd on Stem or Chutney that require a
+To run all tests, including those based on Stem or Chutney that require a
working connection to the internet:
-----
make test-full-online
@@ -247,7 +247,7 @@ to clutter the files with emacs stuff.
Doxygen
-~~~~~~~~
+~~~~~~~
We use the 'doxygen' utility to generate documentation from our
source code. Here's how to use it:
@@ -256,7 +256,7 @@ source code. Here's how to use it:
/**
* \file filename.c
* \brief Short description of the file.
- **/
+ */
(Doxygen will recognize any comment beginning with /** as special.)
diff --git a/doc/HACKING/HowToReview.txt b/doc/HACKING/HowToReview.txt
index 1380411..d6b40db 100644
--- a/doc/HACKING/HowToReview.txt
+++ b/doc/HACKING/HowToReview.txt
@@ -25,7 +25,7 @@ memory?
Do all the new functions, global variables, types, and structure members have
documentation?
-Do all the the functions, global variables, types, and structure members with
+Do all the functions, global variables, types, and structure members with
modified behavior have modified documentation?
Do all the new torrc options have documentation?
diff --git a/doc/HACKING/ReleasingTor.txt b/doc/HACKING/ReleasingTor.txt
index f95c02d..dcf551b 100644
--- a/doc/HACKING/ReleasingTor.txt
+++ b/doc/HACKING/ReleasingTor.txt
@@ -70,7 +70,7 @@ git branches too.
scripts/maint/updateVersions.pl to update version numbers in other
places, and commit. Then merge maint-0.2.x into release-0.2.x.
- (NOTE: TO bump the version number, edit configure.ac, and then run
+ (NOTE: To bump the version number, edit configure.ac, and then run
either make, or 'perl scripts/maint/updateVersions.pl', depending on
your version.)
@@ -78,7 +78,7 @@ git branches too.
a while to see if anybody has problems building it. Try to get Sebastian
or somebody to try building it on Windows.
-6) Get at least two of weasel/arma/sebastian to put the new version number
+6) Get at least two of weasel/arma/Sebastian to put the new version number
in their approved versions list.
7) Sign the tarball, then sign and push the git tag:
diff --git a/doc/HACKING/WritingTests.txt b/doc/HACKING/WritingTests.txt
index d2e05dd..2f59c9a 100644
--- a/doc/HACKING/WritingTests.txt
+++ b/doc/HACKING/WritingTests.txt
@@ -249,7 +249,7 @@ testsupport.h.
=== Okay but what should my tests actually do?
-We talk above about "test coverage" -- making sure that your tests visit
+We talk above about "test coverage" -- making sure that your tests visit
every line of code, or every branch of code. But visiting the code isn't
enough: we want to verify that it's correct.
@@ -359,7 +359,7 @@ same process as the Tor test program. Reasons for doing this might include:
* Testing the actual behavior of Tor when run from the command line
* Testing that a crash-handler correctly logs a stack trace
- * Verifying that a violating a sandbox or capability requirement will
+ * Verifying that violating a sandbox or capability requirement will
actually crash the program.
* Needing to run as root in order to test capability inheritance or
user switching.
@@ -379,7 +379,7 @@ The 'stem' library includes extensive unit tests for the Tor controller
protocol.
For more information on writing new tests for stem, have a look around
-the tst/* directory in stem, and find a good example to emulate. You
+the test/* directory in stem, and find a good example to emulate. You
might want to start with
https://gitweb.torproject.org/stem.git/tree/test/integ/control/controller.py
to improve Tor's test coverage.
1
0

[obfs4/master] Make establishing outgoing connections the transport's responsibility.
by yawning@torproject.org 29 Oct '15
by yawning@torproject.org 29 Oct '15
29 Oct '15
commit e52258edac55d82ff153755493d770bfbbc9a346
Author: Yawning Angel <yawning(a)torproject.org>
Date: Thu Oct 29 14:09:34 2015 +0000
Make establishing outgoing connections the transport's responsibility.
ClientFactories now have a Dial() method instead of a WrapConn()
method, so that it is possible to write something like meek-client
using the obfs4proxy framework.
This breaks the external interface if anyone is using obfs4proxy as
a library, but the new way of doing things is a trivial modification,
to a single routine that shouldn't have been very large to begin with.
---
obfs4proxy/obfs4proxy.go | 13 ++-----------
transports/base/base.go | 10 ++++++----
transports/obfs2/obfs2.go | 12 ++++++++++--
transports/obfs3/obfs3.go | 12 ++++++++++--
transports/obfs4/obfs4.go | 14 +++++++++++---
transports/scramblesuit/base.go | 14 ++++++++++++--
6 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/obfs4proxy/obfs4proxy.go b/obfs4proxy/obfs4proxy.go
index a817583..5c23ba2 100644
--- a/obfs4proxy/obfs4proxy.go
+++ b/obfs4proxy/obfs4proxy.go
@@ -155,22 +155,13 @@ func clientHandler(f base.ClientFactory, conn net.Conn, proxyURI *url.URL) {
}
dialFn = dialer.Dial
}
- remoteConn, err := dialFn("tcp", socksReq.Target) // XXX: Allow UDP?
+ remote, err := f.Dial("tcp", socksReq.Target, dialFn, args)
if err != nil {
log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(err))
socksReq.Reply(socks5.ErrorToReplyCode(err))
return
}
- defer remoteConn.Close()
-
- // Instantiate the client transport method, handshake, and start pushing
- // bytes back and forth.
- remote, err := f.WrapConn(remoteConn, args)
- if err != nil {
- log.Errorf("%s(%s) - handshake failed: %s", name, addrStr, log.ElideError(err))
- socksReq.Reply(socks5.ReplyGeneralFailure)
- return
- }
+ defer remote.Close()
err = socksReq.Reply(socks5.ReplySucceeded)
if err != nil {
log.Errorf("%s(%s) - SOCKS reply failed: %s", name, addrStr, log.ElideError(err))
diff --git a/transports/base/base.go b/transports/base/base.go
index e81ea03..bb0902e 100644
--- a/transports/base/base.go
+++ b/transports/base/base.go
@@ -35,6 +35,8 @@ import (
"git.torproject.org/pluggable-transports/goptlib.git"
)
+type DialFunc func(string, string) (net.Conn, error)
+
// ClientFactory is the interface that defines the factory for creating
// pluggable transport protocol client instances.
type ClientFactory interface {
@@ -48,10 +50,10 @@ type ClientFactory interface {
// generation) to be hidden from third parties.
ParseArgs(args *pt.Args) (interface{}, error)
- // WrapConn wraps the provided net.Conn with a transport protocol
- // implementation, and does whatever is required (eg: handshaking) to get
- // the connection to a point where it is ready to relay data.
- WrapConn(conn net.Conn, args interface{}) (net.Conn, error)
+ // Dial creates an outbound net.Conn, and does whatever is required
+ // (eg: handshaking) to get the connection to the point where it is
+ // ready to relay data.
+ Dial(network, address string, dialFn DialFunc, args interface{}) (net.Conn, error)
}
// ServerFactory is the interface that defines the factory for creating
diff --git a/transports/obfs2/obfs2.go b/transports/obfs2/obfs2.go
index bc2532b..a926141 100644
--- a/transports/obfs2/obfs2.go
+++ b/transports/obfs2/obfs2.go
@@ -108,8 +108,16 @@ func (cf *obfs2ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return nil, validateArgs(args)
}
-func (cf *obfs2ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
- return newObfs2ClientConn(conn)
+func (cf *obfs2ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ conn, err := dialFn(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ if conn, err = newObfs2ClientConn(conn); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
}
type obfs2ServerFactory struct {
diff --git a/transports/obfs3/obfs3.go b/transports/obfs3/obfs3.go
index d215c49..e4c3ba6 100644
--- a/transports/obfs3/obfs3.go
+++ b/transports/obfs3/obfs3.go
@@ -92,8 +92,16 @@ func (cf *obfs3ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return nil, nil
}
-func (cf *obfs3ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
- return newObfs3ClientConn(conn)
+func (cf *obfs3ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ conn, err := dialFn(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ if conn, err = newObfs3ClientConn(conn); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
}
type obfs3ServerFactory struct {
diff --git a/transports/obfs4/obfs4.go b/transports/obfs4/obfs4.go
index 07af9ab..5701535 100644
--- a/transports/obfs4/obfs4.go
+++ b/transports/obfs4/obfs4.go
@@ -204,13 +204,21 @@ func (cf *obfs4ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return &obfs4ClientArgs{nodeID, publicKey, sessionKey, iatMode}, nil
}
-func (cf *obfs4ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
+func (cf *obfs4ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ // Validate args before bothering to open connection.
ca, ok := args.(*obfs4ClientArgs)
if !ok {
return nil, fmt.Errorf("invalid argument type for args")
}
-
- return newObfs4ClientConn(conn, ca)
+ conn, err := dialFn(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ if conn, err = newObfs4ClientConn(conn, ca); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
}
type obfs4ServerFactory struct {
diff --git a/transports/scramblesuit/base.go b/transports/scramblesuit/base.go
index 711c046..223d085 100644
--- a/transports/scramblesuit/base.go
+++ b/transports/scramblesuit/base.go
@@ -76,12 +76,22 @@ func (cf *ssClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return newClientArgs(args)
}
-func (cf *ssClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
+func (cf *ssClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ // Validate args before opening outgoing connection.
ca, ok := args.(*ssClientArgs)
if !ok {
return nil, fmt.Errorf("invalid argument type for args")
}
- return newScrambleSuitClientConn(conn, cf.ticketStore, ca)
+
+ conn, err := dialFn(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ if conn, err = newScrambleSuitClientConn(conn, cf.ticketStore, ca); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
}
var _ base.ClientFactory = (*ssClientFactory)(nil)
1
0

29 Oct '15
commit 52afb5a8e99cbd117e14f40c5450b7cc26b04f18
Author: Georg Koppen <gk(a)torproject.org>
Date: Thu Oct 29 12:25:56 2015 +0000
Bug 17122: Rename Japanese OS X bundle
In order to avoid user confusion we change the locale part in the bundle
name from `ja-JP-mac` to `ja` like it is on other platforms we support.
The workings of Tor Browser on OS X are not affected as `ja-JP-mac` is
used internally.
---
gitian/descriptors/mac/gitian-bundle.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/gitian/descriptors/mac/gitian-bundle.yml b/gitian/descriptors/mac/gitian-bundle.yml
index e3baa3c..458d613 100644
--- a/gitian/descriptors/mac/gitian-bundle.yml
+++ b/gitian/descriptors/mac/gitian-bundle.yml
@@ -276,6 +276,10 @@ script: |
#
MAR_FILE=tor-browser-osx${GBUILD_BITS}-${TORBROWSER_VERSION}_$LANG.mar
MAR=$MARTOOLS/mar MBSDIFF=$MARTOOLS/mbsdiff $MARTOOLS/make_full_update.sh -q $OUTDIR/$MAR_FILE ~/build/dmg/$DEST.app
+ # Rename the Japanese bundle to not confuse users
+ if [ "$LANG" = "ja-JP-mac" ]; then
+ LANG="ja"
+ fi
~/build/ddmg.sh $OUTDIR/TorBrowser-${TORBROWSER_VERSION}-osx${GBUILD_BITS}_$LANG.dmg ~/build/dmg/
rm -rf ~/build/dmg/$DEST.app
done
1
0