forked from I2P_Developers/i2p.www
propagate from branch 'i2p.www' (head 046364f77d72c10ee7ffcf74e7aaa08eb644ed96)
to branch 'i2p.www.str4d' (head 28335acea75ecad4a4edfeb19993dbe80dd95ca8)
This commit is contained in:
@@ -105,6 +105,7 @@ GETTEXT_DOMAIN_MAPPING = {
|
|||||||
|
|
||||||
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
|
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
|
||||||
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
||||||
|
SPEC_DIR = os.path.join(os.path.dirname(__file__), 'spec')
|
||||||
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
|
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
|
||||||
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings/logs')
|
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings/logs')
|
||||||
SITE_DIR = os.path.join(TEMPLATE_DIR, 'site')
|
SITE_DIR = os.path.join(TEMPLATE_DIR, 'site')
|
||||||
|
@@ -6,16 +6,17 @@ import os
|
|||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from i2p2www import BLOG_DIR
|
from i2p2www import BLOG_DIR
|
||||||
|
from i2p2www import helpers
|
||||||
|
|
||||||
|
|
||||||
SUPPORTED_METATAGS = {
|
BLOG_METATAGS = {
|
||||||
'author': u'I2P devs',
|
'author': u'I2P devs',
|
||||||
'category': None,
|
'category': None,
|
||||||
'date': None,
|
'date': None,
|
||||||
'excerpt': u'',
|
'excerpt': u'',
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_METATAGS = [
|
BLOG_LIST_METATAGS = [
|
||||||
'category',
|
'category',
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -108,11 +109,4 @@ def render_blog_post(slug):
|
|||||||
return publish_parts(source=rendered_content, source_path=BLOG_DIR, writer_name="html")
|
return publish_parts(source=rendered_content, source_path=BLOG_DIR, writer_name="html")
|
||||||
|
|
||||||
def get_metadata_from_meta(meta):
|
def get_metadata_from_meta(meta):
|
||||||
metaLines = meta.split('\n')
|
return helpers.get_metadata_from_meta(meta, BLOG_METATAGS, BLOG_LIST_METATAGS)
|
||||||
ret = {}
|
|
||||||
for metaTag in SUPPORTED_METATAGS:
|
|
||||||
metaLine = [s for s in metaLines if 'name="%s"' % metaTag in s]
|
|
||||||
ret[metaTag] = metaLine[0].split('content="')[1].split('"')[0] if len(metaLine) > 0 else SUPPORTED_METATAGS[metaTag]
|
|
||||||
if metaTag in LIST_METATAGS and ret[metaTag]:
|
|
||||||
ret[metaTag] = [s.strip() for s in ret[metaTag].split(',')]
|
|
||||||
return ret
|
|
||||||
|
@@ -17,7 +17,7 @@ except ImportError:
|
|||||||
|
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
from i2p2www.formatters import I2PHtmlFormatter
|
from i2p2www.formatters import I2PHtmlFormatter, TextSpecFormatter
|
||||||
from i2p2www.lexers import DataSpecLexer
|
from i2p2www.lexers import DataSpecLexer
|
||||||
|
|
||||||
|
|
||||||
@@ -55,13 +55,14 @@ class HighlightExtension(Extension):
|
|||||||
# extract the language if available
|
# extract the language if available
|
||||||
# Any additional parameters are passed to HtmlFormatter
|
# Any additional parameters are passed to HtmlFormatter
|
||||||
lang = None
|
lang = None
|
||||||
|
formatter = None
|
||||||
parameters = []
|
parameters = []
|
||||||
while parser.stream.current.type != 'block_end':
|
while parser.stream.current.type != 'block_end':
|
||||||
if lang or parameters:
|
if lang or parameters:
|
||||||
parser.stream.expect('comma')
|
parser.stream.expect('comma')
|
||||||
|
|
||||||
name = parser.stream.expect('name')
|
name = parser.stream.expect('name')
|
||||||
if name.value in parameters or (name.value == 'lang' and lang):
|
if name.value in parameters or (name.value == 'lang' and lang) or (name.value == 'formatter' and formatter):
|
||||||
parser.fail('parameter %r defined twice.' %
|
parser.fail('parameter %r defined twice.' %
|
||||||
name.value, name.lineno,
|
name.value, name.lineno,
|
||||||
exc=TemplateAssertionError)
|
exc=TemplateAssertionError)
|
||||||
@@ -70,20 +71,24 @@ class HighlightExtension(Extension):
|
|||||||
next(parser.stream)
|
next(parser.stream)
|
||||||
if name.value == 'lang':
|
if name.value == 'lang':
|
||||||
lang = parser.parse_expression()
|
lang = parser.parse_expression()
|
||||||
|
elif name.value == 'formatter':
|
||||||
|
formatter = parser.parse_expression()
|
||||||
else:
|
else:
|
||||||
parameters.append(nodes.Pair(nodes.Const(name.value), parser.parse_expression()))
|
parameters.append(nodes.Pair(nodes.Const(name.value), parser.parse_expression()))
|
||||||
|
|
||||||
if lang == None:
|
if lang == None:
|
||||||
lang = nodes.Const(None)
|
lang = nodes.Const(None)
|
||||||
|
if formatter == None:
|
||||||
|
formatter = nodes.Const('html')
|
||||||
parameters = nodes.Dict(parameters)
|
parameters = nodes.Dict(parameters)
|
||||||
|
|
||||||
# body of the block
|
# body of the block
|
||||||
body = parser.parse_statements(['name:endhighlight'], drop_needle=True)
|
body = parser.parse_statements(['name:endhighlight'], drop_needle=True)
|
||||||
|
|
||||||
return nodes.CallBlock(self.call_method('_highlight', [lang, parameters]),
|
return nodes.CallBlock(self.call_method('_highlight', [lang, formatter, parameters]),
|
||||||
[], [], body).set_lineno(lineno)
|
[], [], body).set_lineno(lineno)
|
||||||
|
|
||||||
def _highlight(self, lang, parameters, caller=None):
|
def _highlight(self, lang, formatter, parameters, caller=None):
|
||||||
# highlight code using Pygments
|
# highlight code using Pygments
|
||||||
body = caller()
|
body = caller()
|
||||||
try:
|
try:
|
||||||
@@ -100,14 +105,17 @@ class HighlightExtension(Extension):
|
|||||||
|
|
||||||
if ctags:
|
if ctags:
|
||||||
if 'tagsfile' not in parameters:
|
if 'tagsfile' not in parameters:
|
||||||
parameters['tagsfile'] = module_path() + '/pages/site/spectags'
|
parameters['tagsfile'] = module_path() + '/spec/spectags'
|
||||||
|
|
||||||
if 'tagurlformat' not in parameters:
|
if 'tagurlformat' not in parameters:
|
||||||
lang = 'en'
|
lang = 'en'
|
||||||
if hasattr(g, 'lang') and g.lang:
|
if hasattr(g, 'lang') and g.lang:
|
||||||
lang = g.lang
|
lang = g.lang
|
||||||
parameters['tagurlformat'] = '/' + lang + '/%(path)s%(fname)s'
|
parameters['tagurlformat'] = '/spec/%(path)s%(fname)s'
|
||||||
|
|
||||||
formatter = I2PHtmlFormatter(**parameters)
|
if formatter == 'textspec':
|
||||||
|
formatter = TextSpecFormatter(**parameters)
|
||||||
|
else:
|
||||||
|
formatter = I2PHtmlFormatter(**parameters)
|
||||||
code = highlight(Markup(body).unescape(), lexer, formatter)
|
code = highlight(Markup(body).unescape(), lexer, formatter)
|
||||||
return code
|
return code
|
||||||
|
@@ -23,7 +23,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
ctags = None
|
ctags = None
|
||||||
|
|
||||||
__all__ = ['I2PHtmlFormatter']
|
__all__ = ['I2PHtmlFormatter', 'TextSpecFormatter']
|
||||||
|
|
||||||
|
|
||||||
_escape_html_table = {
|
_escape_html_table = {
|
||||||
@@ -727,8 +727,8 @@ class I2PHtmlFormatter(Formatter):
|
|||||||
filename, extension = os.path.splitext(filename)
|
filename, extension = os.path.splitext(filename)
|
||||||
url = self.tagurlformat % {'path': base, 'fname': filename,
|
url = self.tagurlformat % {'path': base, 'fname': filename,
|
||||||
'fext': extension}
|
'fext': extension}
|
||||||
parts[0] = "<a href=\"%s#%s_%s\">%s" % \
|
parts[0] = "<a href=\"%s#%s-%s\">%s" % \
|
||||||
(url, kinds[kind], value, parts[0])
|
(url, kinds[kind], value.lower(), parts[0])
|
||||||
parts[-1] = parts[-1] + "</a>"
|
parts[-1] = parts[-1] + "</a>"
|
||||||
|
|
||||||
# for all but the last line
|
# for all but the last line
|
||||||
@@ -829,3 +829,70 @@ class I2PHtmlFormatter(Formatter):
|
|||||||
|
|
||||||
for t, piece in source:
|
for t, piece in source:
|
||||||
outfile.write(piece)
|
outfile.write(piece)
|
||||||
|
|
||||||
|
|
||||||
|
class TextSpecFormatter(Formatter):
|
||||||
|
"""
|
||||||
|
Output the text unchanged without any formatting.
|
||||||
|
"""
|
||||||
|
name = 'Text spec'
|
||||||
|
aliases = ['textspec']
|
||||||
|
filenames = ['*.txt']
|
||||||
|
|
||||||
|
def __init__(self, **options):
|
||||||
|
Formatter.__init__(self, **options)
|
||||||
|
self.tagsfile = self._decodeifneeded(options.get('tagsfile', ''))
|
||||||
|
self.tagurlformat = self._decodeifneeded(options.get('tagurlformat', ''))
|
||||||
|
|
||||||
|
if self.tagsfile:
|
||||||
|
if not ctags:
|
||||||
|
raise RuntimeError('The "ctags" package must to be installed '
|
||||||
|
'to be able to use the "tagsfile" feature.')
|
||||||
|
self._ctags = ctags.CTags(self.tagsfile)
|
||||||
|
|
||||||
|
def _decodeifneeded(self, value):
|
||||||
|
if isinstance(value, bytes):
|
||||||
|
if self.encoding:
|
||||||
|
return value.decode(self.encoding)
|
||||||
|
return value.decode()
|
||||||
|
return value
|
||||||
|
|
||||||
|
def format(self, tokensource, outfile):
|
||||||
|
enc = self.encoding
|
||||||
|
tagsfile = self.tagsfile
|
||||||
|
refs = {}
|
||||||
|
|
||||||
|
for ttype, value in tokensource:
|
||||||
|
if tagsfile and ttype in Token.Name.Class:
|
||||||
|
filename, kind = self._lookup_ctag(value)
|
||||||
|
# Handle message types
|
||||||
|
if not kind and value.endswith('Message'):
|
||||||
|
value = value[:-7]
|
||||||
|
filename, kind = self._lookup_ctag(value)
|
||||||
|
if kind:
|
||||||
|
base, filename = os.path.split(filename)
|
||||||
|
if base:
|
||||||
|
base += '/'
|
||||||
|
filename, extension = os.path.splitext(filename)
|
||||||
|
url = self.tagurlformat % {'path': base, 'fname': filename,
|
||||||
|
'fext': extension}
|
||||||
|
refs[value] = '\n[%s]: %s#%s-%s' % (value, url, kinds[kind], value.lower())
|
||||||
|
value = '[%s]' % value
|
||||||
|
|
||||||
|
if enc:
|
||||||
|
outfile.write(value.encode(enc))
|
||||||
|
else:
|
||||||
|
outfile.write(value)
|
||||||
|
|
||||||
|
for ref in refs.values():
|
||||||
|
if enc:
|
||||||
|
outfile.write(ref.encode(enc))
|
||||||
|
else:
|
||||||
|
outfile.write(ref)
|
||||||
|
|
||||||
|
def _lookup_ctag(self, token):
|
||||||
|
entry = ctags.TagEntry()
|
||||||
|
if self._ctags.find(entry, token, 0):
|
||||||
|
return entry['file'], entry['kind']
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
@@ -9,6 +9,16 @@ def get_for_page(items, page, per_page):
|
|||||||
to_item = page*per_page
|
to_item = page*per_page
|
||||||
return items[from_item:to_item]
|
return items[from_item:to_item]
|
||||||
|
|
||||||
|
def get_metadata_from_meta(meta, supported_metatags, list_metatags):
|
||||||
|
metaLines = meta.split('\n')
|
||||||
|
ret = {}
|
||||||
|
for metaTag in supported_metatags:
|
||||||
|
metaLine = [s for s in metaLines if 'name="%s"' % metaTag in s]
|
||||||
|
ret[metaTag] = metaLine[0].split('content="')[1].split('"')[0] if len(metaLine) > 0 else supported_metatags[metaTag]
|
||||||
|
if metaTag in list_metatags and ret[metaTag]:
|
||||||
|
ret[metaTag] = [s.strip() for s in ret[metaTag].split(',')]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# General helper classes
|
# General helper classes
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{%- macro change_lang(lang) -%}
|
{%- macro change_lang(lang) -%}
|
||||||
{%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }}
|
{%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }}
|
||||||
|
{%- elif request.endpoint == 'spec_show' -%}{{ url_for('spec_show', name=name) }}
|
||||||
{%- elif request.endpoint == 'blog_index' -%}
|
{%- elif request.endpoint == 'blog_index' -%}
|
||||||
{%- if category -%}{{ url_for('blog_index', lang=lang, category=category) }}
|
{%- if category -%}{{ url_for('blog_index', lang=lang, category=category) }}
|
||||||
{%- else -%}{{ url_for('blog_index', lang=lang) }}
|
{%- else -%}{{ url_for('blog_index', lang=lang) }}
|
||||||
|
@@ -29,23 +29,7 @@
|
|||||||
<li><a href="{{ site_url('docs/how/elgamal-aes') }}"><div class="menuitem"><span>{{ _('ElGamal/AES+SessionTags') }}</span></div></a></li>
|
<li><a href="{{ site_url('docs/how/elgamal-aes') }}"><div class="menuitem"><span>{{ _('ElGamal/AES+SessionTags') }}</span></div></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="has-sub"><div class="menuitem"><span>{{ _('Specifications') }}</span></div>
|
<li><a href="{{ url_for('spec_index') }}"><div class="menuitem"><span>{{ _('Specifications') }}</span></div></a></li>
|
||||||
<ul>
|
|
||||||
<li><a href="{{ site_url('docs/spec/blockfile') }}"><div class="menuitem"><span>{{ _('Blockfile') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/common-structures') }}"><div class="menuitem"><span>{{ _('Common structures') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/configuration') }}"><div class="menuitem"><span>{{ _('Configuration files') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/datagrams') }}"><div class="menuitem"><span>{{ _('Datagrams') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/geoip') }}"><div class="menuitem"><span>{{ _('GeoIP files') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/i2cp') }}"><div class="menuitem"><span>I2CP</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/i2np') }}"><div class="menuitem"><span>I2NP</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/plugin') }}"><div class="menuitem"><span>{{ _('Plugins') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/ssu') }}"><div class="menuitem"><span>SSU</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/streaming') }}"><div class="menuitem"><span>{{ _('Streaming library') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/tunnel-creation') }}"><div class="menuitem"><span>{{ _('Tunnel creation') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/tunnel-message') }}"><div class="menuitem"><span>{{ _('Tunnel messages') }}</span></div></a></li>
|
|
||||||
<li><a href="{{ site_url('docs/spec/updates') }}"><div class="menuitem"><span>{{ _('Software updates') }}</span></div></a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="has-sub"><div class="menuitem"><span>{{ _('API') }}</span></div>
|
<li class="has-sub"><div class="menuitem"><span>{{ _('API') }}</span></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ site_url('docs/api/i2ptunnel') }}"><div class="menuitem"><span>I2PTunnel</span></div></a></li>
|
<li><a href="{{ site_url('docs/api/i2ptunnel') }}"><div class="menuitem"><span>I2PTunnel</span></div></a></li>
|
||||||
|
@@ -39,13 +39,13 @@ If you find any inaccuracies in the documents linked below, please
|
|||||||
<li><a href="{{ site_url('get-involved/develop/applications') }}">Application Development Overview and Guide</a></li>
|
<li><a href="{{ site_url('get-involved/develop/applications') }}">Application Development Overview and Guide</a></li>
|
||||||
<li><a href="{{ site_url('docs/naming') }}">{{ _('Naming and Addressbook') }}</a></li>
|
<li><a href="{{ site_url('docs/naming') }}">{{ _('Naming and Addressbook') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/plugins') }}">{{ _('Plugins Overview') }}</a></li>
|
<li><a href="{{ site_url('docs/plugins') }}">{{ _('Plugins Overview') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/plugin') }}">{{ _('Plugin Specification') }}</a></li>
|
<li><a href="{{ spec_url('plugin') }}">{{ _('Plugin Specification') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/applications/managed-clients') }}">{{ _('Managed Clients') }}</a></li>
|
<li><a href="{{ site_url('docs/applications/managed-clients') }}">{{ _('Managed Clients') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/applications/embedding') }}">{{ _('Embedding the router in your application') }}</a></li>
|
<li><a href="{{ site_url('docs/applications/embedding') }}">{{ _('Embedding the router in your application') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/applications/bittorrent') }}">{{ _('Bittorrent over I2P') }}</a></li>
|
<li><a href="{{ site_url('docs/applications/bittorrent') }}">{{ _('Bittorrent over I2P') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/api/i2pcontrol') }}">{{ _('I2PControl Plugin API') }}</a></li>
|
<li><a href="{{ site_url('docs/api/i2pcontrol') }}">{{ _('I2PControl Plugin API') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li>
|
<li><a href="{{ spec_url('blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li>
|
<li><a href="{{ spec_url('configuration') }}">{{ _('Configuration File Format') }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>{% trans %}Application Layer API and Protocols{% endtrans %}</h3>
|
<h3>{% trans %}Application Layer API and Protocols{% endtrans %}</h3>
|
||||||
@@ -55,7 +55,7 @@ If you find any inaccuracies in the documents linked below, please
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a>
|
<a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/configuration') }}">{{ _('I2PTunnel Configuration') }}</a></li>
|
<a href="{{ spec_url('configuration') }}">{{ _('I2PTunnel Configuration') }}</a></li>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/api/socks') }}">SOCKS Proxy</a>
|
<a href="{{ site_url('docs/api/socks') }}">SOCKS Proxy</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -85,11 +85,11 @@ HTTP Bidir Proxy
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="{{ site_url('docs/api/streaming') }}">{{ _('Streaming Library') }}</a>
|
<a href="{{ site_url('docs/api/streaming') }}">{{ _('Streaming Library') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/streaming') }}">{{ _('Streaming Protocol Specification') }}</a>
|
<a href="{{ spec_url('streaming') }}">{{ _('Streaming Protocol Specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html">{{ _('Streaming Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/streaming/package-summary.html">{{ _('Streaming Javadoc') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/datagrams') }}">{{ _('Datagrams') }}</a>
|
<a href="{{ spec_url('datagrams') }}">{{ _('Datagrams') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/datagram/package-summary.html">{{ _('Datagram Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/datagram/package-summary.html">{{ _('Datagram Javadoc') }}</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
@@ -102,11 +102,11 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="{{ site_url('docs/protocol/i2cp') }}">{{ _('I2CP - I2P Control Protocol / API overview') }}</a>
|
<a href="{{ site_url('docs/protocol/i2cp') }}">{{ _('I2CP - I2P Control Protocol / API overview') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/i2cp') }}">{{ _('I2CP Specification') }}</a>
|
<a href="{{ spec_url('i2cp') }}">{{ _('I2CP Specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/package-summary.html">{{ _('I2CP API Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/client/package-summary.html">{{ _('I2CP API Javadoc') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a>
|
<a href="{{ spec_url('common-structures') }}">{{ _('Common data structures specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
@@ -124,7 +124,7 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
<li><a href="{{ site_url('docs/how/network-database') }}">{{ _('Network database overview, details, and threat analysis') }}</a></li>
|
<li><a href="{{ site_url('docs/how/network-database') }}">{{ _('Network database overview, details, and threat analysis') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/how/cryptography') }}#SHA256">{{ _('Cryptographic hashes') }}</a></li>
|
<li><a href="{{ site_url('docs/how/cryptography') }}#SHA256">{{ _('Cryptographic hashes') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/how/cryptography') }}#sig">{{ _('Cryptographic signatures') }}</a></li>
|
<li><a href="{{ site_url('docs/how/cryptography') }}#sig">{{ _('Cryptographic signatures') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/updates') }}">{{ _('Router reseed specification') }}</a></li>
|
<li><a href="{{ spec_url('updates') }}">{{ _('Router reseed specification') }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>{% trans %}Router Message Protocol{% endtrans %}</h3>
|
<h3>{% trans %}Router Message Protocol{% endtrans %}</h3>
|
||||||
@@ -132,11 +132,11 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="{{ site_url('docs/protocol/i2np') }}">{{ _('I2NP - I2P Network Protocol Overview') }}</a>
|
<a href="{{ site_url('docs/protocol/i2np') }}">{{ _('I2NP - I2P Network Protocol Overview') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}">{{ _('I2NP Specification') }}</a>
|
<a href="{{ spec_url('i2np') }}">{{ _('I2NP Specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/package-summary.html">{{ _('I2NP Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/package-summary.html">{{ _('I2NP Javadoc') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a>
|
<a href="{{ spec_url('common-structures') }}">{{ _('Common data structures specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
|
<a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
@@ -150,8 +150,8 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
<li><a href="{{ site_url('docs/tunnels/implementation') }}">{{ _('Tunnel building and encryption') }}</a></li>
|
<li><a href="{{ site_url('docs/tunnels/implementation') }}">{{ _('Tunnel building and encryption') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES') }}</a> {{ _('for build request encryption') }}</li>
|
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES') }}</a> {{ _('for build request encryption') }}</li>
|
||||||
<li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li>
|
<li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/tunnel-creation') }}">{{ _('Tunnel building specification') }}</a></li>
|
<li><a href="{{ spec_url('tunnel-creation') }}">{{ _('Tunnel building specification') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/spec/tunnel-message') }}">{{ _('Low-level tunnel message specification') }}</a></li>
|
<li><a href="{{ spec_url('tunnel-message') }}">{{ _('Low-level tunnel message specification') }}</a></li>
|
||||||
<li><a href="{{ site_url('docs/tunnels/unidirectional') }}">{{ _('Unidirectional Tunnels') }}</a></li>
|
<li><a href="{{ site_url('docs/tunnels/unidirectional') }}">{{ _('Unidirectional Tunnels') }}</a></li>
|
||||||
<li><a href="{{ url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') }}">{{ _('Peer Profiling and Selection in the I2P Anonymous Network') }}</a>
|
<li><a href="{{ url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') }}">{{ _('Peer Profiling and Selection in the I2P Anonymous Network') }}</a>
|
||||||
{{ _('2009 paper (pdf), not current but still generally accurate') }}</li>
|
{{ _('2009 paper (pdf), not current but still generally accurate') }}</li>
|
||||||
@@ -166,7 +166,7 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/transport/ssu') }}">SSU</a> {{ _('UDP-based transport overview') }}
|
<a href="{{ site_url('docs/transport/ssu') }}">SSU</a> {{ _('UDP-based transport overview') }}
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/ssu') }}">{{ _('SSU specification') }}</a>
|
<a href="{{ spec_url('ssu') }}">{{ _('SSU specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#tcp">{{ _('NTCP transport encryption') }}</a>
|
<a href="{{ site_url('docs/how/cryptography') }}#tcp">{{ _('NTCP transport encryption') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -181,9 +181,9 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
|
|
||||||
<h3>{% trans %}Other Router Topics{% endtrans %}</h3>
|
<h3>{% trans %}Other Router Topics{% endtrans %}</h3>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="{{ site_url('docs/spec/updates') }}">{{ _('Router software updates') }}</a>
|
<a href="{{ spec_url('updates') }}">{{ _('Router software updates') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/updates') }}">{{ _('Router reseed specification') }}</a>
|
<a href="{{ spec_url('updates') }}">{{ _('Router reseed specification') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('misc/jbigi') }}">{{ _('Native BigInteger Library') }}</a>
|
<a href="{{ site_url('misc/jbigi') }}">{{ _('Native BigInteger Library') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -191,9 +191,9 @@ Traditionally used only by Java applications and higher-level APIs.
|
|||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('about/performance') }}">{{ _('Performance') }}</a>
|
<a href="{{ site_url('about/performance') }}">{{ _('Performance') }}</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li>
|
<a href="{{ spec_url('configuration') }}">{{ _('Configuration File Format') }}</a></li>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="{{ site_url('docs/spec/geoip') }}">GeoIP File Format</a></li>
|
<a href="{{ spec_url('geoip') }}">GeoIP File Format</a></li>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
|
|
||||||
<h3>{% trans %}Developer's Guides and Resources{% endtrans %}</h3>
|
<h3>{% trans %}Developer's Guides and Resources{% endtrans %}</h3>
|
||||||
|
@@ -1,230 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}Blockfile and Hosts Database Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}November 2014{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.17{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h3>{% trans %}Overview{% endtrans %}</h3>
|
|
||||||
<p>{% trans naming=site_url('docs/naming') -%}
|
|
||||||
This document specifies
|
|
||||||
the I2P blockfile file format
|
|
||||||
and the tables in the hostsdb.blockfile used by the Blockfile <a href="{{ naming }}">Naming Service</a>.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The blockfile provides fast Destination lookup in a compact format. While the blockfile page overhead is substantial,
|
|
||||||
the destinations are stored in binary rather than in Base 64 as in the hosts.txt format.
|
|
||||||
In addition, the blockfile provides the capability of arbitrary metadata storage
|
|
||||||
(such as added date, source, and comments) for each entry.
|
|
||||||
The metadata may be used in the future to provide advanced addressbook features.
|
|
||||||
The blockfile storage requirement is a modest increase over the hosts.txt format, and the blockfile provides
|
|
||||||
approximately 10x reduction in lookup times.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans url='http://www.metanotion.net/software/sandbox/block.html' -%}
|
|
||||||
A blockfile is simply on-disk storage of multiple sorted maps (key-value pairs),
|
|
||||||
implemented as skiplists.
|
|
||||||
The blockfile format is adopted from the
|
|
||||||
<a href="{{ url }}">Metanotion Blockfile Database</a>.
|
|
||||||
First we will define the file format, then the use of that format by the BlockfileNamingService.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Blockfile Format{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The original blockfile spec was modified to add magic numbers to each page.
|
|
||||||
The file is structured in 1024-byte pages. Pages are numbered starting from 1.
|
|
||||||
The "superblock" is always at page 1, i.e. starting at byte 0 in the file.
|
|
||||||
The metaindex skiplist is always at page 2, i.e. starting at byte 1024 in the file.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
All 2-byte integer values are unsigned.
|
|
||||||
All 4-byte integer values (page numbers) are signed and negative values are illegal.
|
|
||||||
All integer values are stored in network byte order (big endian).
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The database is designed to be opened and accessed by a single thread.
|
|
||||||
The BlockfileNamingService provides synchronization.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Superblock format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-5 Magic number 0x3141de493250 ("1A" 0xde "I2P")
|
|
||||||
6 Major version 0x01
|
|
||||||
7 Minor version 0x02
|
|
||||||
8-15 File length Total length in bytes
|
|
||||||
16-19 First free list page
|
|
||||||
20-21 Mounted flag 0x01 = yes
|
|
||||||
22-23 Span size Max number of key/value pairs per span (16 for hostsdb)
|
|
||||||
Used for new skip lists.
|
|
||||||
24-27 Page size As of version 1.2. Prior to 1.2, 1024 is assumed.
|
|
||||||
28-1023 unused
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Skip list block page format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-7 Magic number 0x536b69704c697374 "SkipList"
|
|
||||||
8-11 First span page
|
|
||||||
12-15 First level page
|
|
||||||
16-19 Size (total number of keys - may only be valid at startup)
|
|
||||||
20-23 Spans (total number of spans - may only be valid at startup)
|
|
||||||
24-27 Levels (total number of levels - may only be valid at startup)
|
|
||||||
28-29 Span size - As of version 1.2. Max number of key/value pairs per span.
|
|
||||||
Prior to that, specified for all skiplists in the superblock.
|
|
||||||
Used for new spans in this skip list.
|
|
||||||
30-1023 unused
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Skip level block page format is as follows.
|
|
||||||
All levels have a span. Not all spans have levels.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-7 Magic number 0x42534c6576656c73 "BSLevels"
|
|
||||||
8-9 Max height
|
|
||||||
10-11 Current height
|
|
||||||
12-15 Span page
|
|
||||||
16- Next level pages ('current height' entries, 4 bytes each, lowest first)
|
|
||||||
remaining bytes unused
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Skip span block page format is as follows.
|
|
||||||
Key/value structures are sorted by key within each span and across all spans.
|
|
||||||
Key/value structures are sorted by key within each span.
|
|
||||||
Spans other than the first span may not be empty.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-3 Magic number 0x5370616e "Span"
|
|
||||||
4-7 First continuation page or 0
|
|
||||||
8-11 Previous span page or 0
|
|
||||||
12-15 Next span page or 0
|
|
||||||
16-17 Max keys (16 for hostsdb)
|
|
||||||
18-19 Size (current number of keys)
|
|
||||||
20-1023 key/value structures
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Span Continuation block page format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-3 Magic number 0x434f4e54 "CONT"
|
|
||||||
4-7 Next continuation page or 0
|
|
||||||
8-1023 key/value structures
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Key/value structure format is as follows.
|
|
||||||
Key and value lengths must not be split across pages, i.e. all 4 bytes must be on the same page.
|
|
||||||
If there is not enough room the last 1-3 bytes of a page are unused and the lengths will
|
|
||||||
be at offset 8 in the continuation page.
|
|
||||||
Key and value data may be split across pages.
|
|
||||||
Max key and value lengths are 65535 bytes.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-1 key length in bytes
|
|
||||||
2-3 value length in bytes
|
|
||||||
4- key data
|
|
||||||
value data
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Free list block page format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-7 Magic number 0x2366724c69737423 "#frList#"
|
|
||||||
8-11 Next free list block or 0 if none
|
|
||||||
12-15 Number of valid free pages in this block (0 - 252)
|
|
||||||
16-1023 Free pages (4 bytes each), only the first (valid number) are valid
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Free page block format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Byte Contents
|
|
||||||
0-7 Magic number 0x7e2146524545217e "~!FREE!~"
|
|
||||||
8-1023 unused
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The metaindex (located at page 2) is a mapping of US-ASCII strings to 4-byte integers.
|
|
||||||
The key is the name of the skiplist and the value is the page index of the skiplist.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Blockfile Naming Service Tables{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The tables created and used by the BlockfileNamingService are as follows.
|
|
||||||
The maximum number of entries per span is 16.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h4>{% trans %}Properties Skiplist{% endtrans %}</h4>
|
|
||||||
<p>{% trans INFO='"%%__INFO__%%"' -%}
|
|
||||||
{{ INFO }} is the master database skiplist with String/Properties key/value entries containing only one entry:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<pre>
|
|
||||||
"info": a Properties (UTF-8 String/String Map), serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>:
|
|
||||||
"version": "3"
|
|
||||||
"created": Java long time (ms)
|
|
||||||
"upgraded": Java long time (ms) (as of database version 2)
|
|
||||||
"lists": Comma-separated list of host databases, to be
|
|
||||||
searched in-order for lookups. Almost always "privatehosts.txt,userhosts.txt,hosts.txt".
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4>{% trans %}Reverse Lookup Skiplist{% endtrans %}</h4>
|
|
||||||
<p>{% trans REVERSE='"%%__REVERSE__%%"' -%}
|
|
||||||
{{ REVERSE }} is the reverse lookup skiplist with Integer/Properties key/value entries
|
|
||||||
(as of database version 2):
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<pre>
|
|
||||||
The skiplist keys are 4-byte Integers, the first 4 bytes of the hash of the Destination.
|
|
||||||
The skiplist values are each a Properties (a UTF-8 String/String Map) serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>
|
|
||||||
There may be multiple entries in the properties, each one is a reverse mapping,
|
|
||||||
as there may be more than one hostname for a given destination,
|
|
||||||
or there could be collisions with the same first 4 bytes of the hash.
|
|
||||||
Each property key is a hostname.
|
|
||||||
Each property value is the empty string.
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4>{% trans %}hosts.txt, userhosts.txt, and privatehosts.txt Skiplists{% endtrans %}</h4>
|
|
||||||
<p>{% trans -%}
|
|
||||||
For each host database, there is a skiplist containing
|
|
||||||
the hosts for that database.
|
|
||||||
The keys/values in these skiplists are as follows:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<pre>
|
|
||||||
key: a UTF-8 String (the hostname)
|
|
||||||
value: a DestEntry, which is a Properties (a UTF-8 String/String Map) serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>
|
|
||||||
followed by a binary Destination (serialized <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">as usual</a>).
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The DestEntry Properties typically contains:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<pre>
|
|
||||||
"a": The time added (Java long time in ms)
|
|
||||||
"s": The original source of the entry (typically a file name or subscription URL)
|
|
||||||
others: TBD
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Hostname keys are stored in lower-case and always end in ".i2p".
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,403 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}Configuration File Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}November 2015{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.24{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h2>{% trans %}Overview{% endtrans %}</h2>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This page provides a general specification of I2P configuration files,
|
|
||||||
used by the router and various applications.
|
|
||||||
It also gives an overview of the information contained in the various files,
|
|
||||||
and links to detailed documentation where available.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>{% trans %}General Format{% endtrans %}</h2>
|
|
||||||
<p>{% trans url='http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html#load%28java.io.InputStream%29' -%}
|
|
||||||
An I2P configuration file is formatted as specified in
|
|
||||||
<a href="{{ url }}">Java Properties</a>
|
|
||||||
with the following exceptions:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans %}Encoding must be UTF-8{% endtrans %}</li>
|
|
||||||
<li>{% trans %}Does not use or recognize any escapes, including '\', so lines may not be continued{% endtrans %}</li>
|
|
||||||
<li>{% trans %}'#' or ';' starts a comment, but '!' does not{% endtrans %}</li>
|
|
||||||
<li>{% trans %}'#' starts a comment in any position but ';' must be in column 1 to start a comment{% endtrans %}</li>
|
|
||||||
<li>{% trans %}Leading and trailing whitespace is not trimmed on keys{% endtrans %}</li>
|
|
||||||
<li>{% trans %}Leading and trailing whitespace is trimmed on values{% endtrans %}</li>
|
|
||||||
<li>{% trans %}'=' is the only key-termination character (not ':' or whitespace){% endtrans %}</li>
|
|
||||||
<li>{% trans %}Lines without '=' are ignored. As of release 0.9.10, keys with a value of "" are supported.{% endtrans %}</li>
|
|
||||||
<li>{% trans %}As there are no escapes, keys may not contain '#', '=', or '\n', or start with ';'{% endtrans %}</li>
|
|
||||||
<li>{% trans %}As there are no escapes, values may not contain '#' or '\n', or start or end with '\r' or whitespace{% endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The file need not be sorted, but most applications do sort by key when
|
|
||||||
writing to the file, for ease of reading and manual editing.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html',
|
|
||||||
commonstructures=site_url('docs/spec/common-structures') -%}
|
|
||||||
Reads and writes are implemented in
|
|
||||||
<a href="{{ url }}">DataHelper loadProps() and storeProps()</a>.
|
|
||||||
Note that the file format is significantly different than the
|
|
||||||
serialized format for I2P protocols specified in
|
|
||||||
<a href="{{ commonstructures }}#type_Mapping">Mapping</a>.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h2>{% trans %}Core library and router{% endtrans %}</h2>
|
|
||||||
|
|
||||||
<h3>{% trans %}Clients{% endtrans %} (clients.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Configured via /configclients in the router console.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<p>
|
|
||||||
The format is as follows:
|
|
||||||
</p><p>
|
|
||||||
Lines are of the form clientApp.x.prop=val, where x is the app number.
|
|
||||||
App numbers MUST start with 0 and be consecutive.
|
|
||||||
</p><p>
|
|
||||||
Properties are as follows:
|
|
||||||
<pre>
|
|
||||||
main: Full class name. Required. The constructor or main() method in this
|
|
||||||
class will be run, depending on whether the client is managed or unmanaged.
|
|
||||||
See below for details.
|
|
||||||
name: Name to be displayed on console.
|
|
||||||
args: Arguments to the main class, separated by spaces or tabs.
|
|
||||||
Arguments containing spaces or tabs may be quoted with ' or "
|
|
||||||
delay: Seconds before starting, default 120
|
|
||||||
onBoot: {true|false}, default false, forces a delay of 0,
|
|
||||||
overrides delay setting
|
|
||||||
startOnLoad: {true|false} Is the client to be run at all?
|
|
||||||
Default true
|
|
||||||
</pre>
|
|
||||||
</p><p>
|
|
||||||
The following additional properties are used only by plugins:
|
|
||||||
<pre>
|
|
||||||
stopargs: Arguments to stop the client.
|
|
||||||
uninstallargs: Arguments to uninstall the client.
|
|
||||||
classpath: Additional classpath elements for the client,
|
|
||||||
separated by commas.
|
|
||||||
</pre>
|
|
||||||
</p><p>
|
|
||||||
The following substitutions are made in the args, stopargs,
|
|
||||||
uninstallargs, and classpath lines, for plugins only:
|
|
||||||
<pre>
|
|
||||||
$I2P: The base I2P install directory
|
|
||||||
$CONFIG: The user's configuration directory (e.g. ~/.i2p)
|
|
||||||
$PLUGIN: This plugin's directory (e.g. ~/.i2p/plugins/foo)
|
|
||||||
</pre>
|
|
||||||
</p><p>
|
|
||||||
All properties except "main" are optional.
|
|
||||||
Lines starting with "#" are comments.
|
|
||||||
</p><p>
|
|
||||||
If the delay is less than zero, the client is run immediately,
|
|
||||||
in the same thread, so that exceptions may be propagated to the console.
|
|
||||||
In this case, the client should either throw an exception, return quickly,
|
|
||||||
or spawn its own thread.
|
|
||||||
If the delay is greater than or equal to zero, it will be run
|
|
||||||
in a new thread, and exceptions will be logged but not propagated
|
|
||||||
to the console.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Clients may be "managed" or "unmanaged".
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}Logger{% endtrans %} (logger.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Configured via /configlogging in the router console.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<p>
|
|
||||||
{% trans -%}
|
|
||||||
Properties are as follows:
|
|
||||||
{%- endtrans %}
|
|
||||||
<pre>
|
|
||||||
# Default 20
|
|
||||||
logger.consoleBufferSize=n
|
|
||||||
# Default from locale; format as specified by Java SimpleDateFormat
|
|
||||||
logger.dateFormat=HH:mm:ss.SSS
|
|
||||||
# Default ERROR
|
|
||||||
logger.defaultLevel=CRIT|ERROR|WARN|INFO|DEBUG
|
|
||||||
# Default true
|
|
||||||
logger.displayOnScreen=true|false
|
|
||||||
# Default true
|
|
||||||
logger.dropDuplicates=true|false
|
|
||||||
# Default false
|
|
||||||
logger.dropOnOverflow=true|false
|
|
||||||
# As of 0.9.18. Default 29 (seconds)
|
|
||||||
logger.flushInterval=nnn
|
|
||||||
# d = date, c = class, t = thread name, p = priority, m = message
|
|
||||||
logger.format={dctpm}*
|
|
||||||
# Max to buffer before flushing. Default 1024
|
|
||||||
logger.logBufferSize=n
|
|
||||||
# Default logs/log-@.txt; @ replaced with number
|
|
||||||
logger.logFileName=name
|
|
||||||
logger.logFilenameOverride=name
|
|
||||||
# Default 10M
|
|
||||||
logger.logFileSize=nnn[K|M|G]
|
|
||||||
# Highest file number. Default 2
|
|
||||||
logger.logRotationLimit=n
|
|
||||||
# Default CRIT
|
|
||||||
logger.minimumOnScreenLevel=CRIT|ERROR|WARN|INFO|DEBUG
|
|
||||||
logger.record.{class}=CRIT|ERROR|WARN|INFO|DEBUG
|
|
||||||
</pre>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Individual Plugin{% endtrans %} (xxx/plugin.config)</h3>
|
|
||||||
<p>{% trans pluginspec=site_url('docs/spec/plugin') -%}
|
|
||||||
See <a href="{{ pluginspec }}">the plugin specification</a>.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Plugins{% endtrans %} (plugins.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Enable/disable for each installed plugin.
|
|
||||||
{%- endtrans %}
|
|
||||||
{% trans -%}
|
|
||||||
Properties are as follows:
|
|
||||||
{%- endtrans %}
|
|
||||||
<pre>
|
|
||||||
plugin.{name}.startOnLoad=true|false
|
|
||||||
</pre>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Webapps{% endtrans %} (webapps.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Enable/disable for each installed webapp.
|
|
||||||
{%- endtrans %}
|
|
||||||
{% trans -%}
|
|
||||||
Properties are as follows:
|
|
||||||
{%- endtrans %}
|
|
||||||
<pre>
|
|
||||||
webapps.{name}.classpath=[space- or comma-separated paths]
|
|
||||||
webapps.{name}.startOnLoad=true|false
|
|
||||||
</pre>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Router{% endtrans %} (router.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Configured via /configadvanced in the router console.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h2>{% trans %}Applications{% endtrans %}</h2>
|
|
||||||
|
|
||||||
<h3>{% trans %}Addressbook{% endtrans %} (addressbook/config.txt)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
See documentation in SusiDNS.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>I2PSnark (i2psnark.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Configured via the application gui.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>I2PTunnel (i2ptunnel.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Configured via the /i2ptunnel application in the router console.
|
|
||||||
{%- endtrans %}
|
|
||||||
{% trans -%}
|
|
||||||
Properties are as follows:
|
|
||||||
{%- endtrans %}
|
|
||||||
<pre>
|
|
||||||
# Display description for UI
|
|
||||||
tunnel.N.description=
|
|
||||||
|
|
||||||
# Router IP address or host name. Ignored if in router context.
|
|
||||||
tunnel.N.i2cpHost=127.0.0.1
|
|
||||||
|
|
||||||
# Router I2CP port. Ignored if in router context.
|
|
||||||
tunnel.N.i2cpPort=nnnn
|
|
||||||
|
|
||||||
# For clients only. Local listen IP address or host name.
|
|
||||||
tunnel.N.interface=127.0.0.1
|
|
||||||
|
|
||||||
# For clients only. Local listen port.
|
|
||||||
tunnel.N.listenPort=nnnn
|
|
||||||
|
|
||||||
# Display name for UI
|
|
||||||
tunnel.N.name=
|
|
||||||
|
|
||||||
# Servers only. Default false. Originate connections to local server with a unique IP per-remote-destination.
|
|
||||||
tunnel.N.option.enableUniqueLocal=true|false
|
|
||||||
|
|
||||||
# Servers only. The maximum size of the thread pool, default 65. Ignored for standard servers.
|
|
||||||
tunnel.N.option.i2ptunnel.blockingHandlerCount=nnn
|
|
||||||
|
|
||||||
# HTTP client only. Whether to use allow SSL connections to i2p addresses. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.allowInternalSSL=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Whether to disable address helper links. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.disableAddressHelper=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Comma- or space-separated list of jump server URLs.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.jumpServers=http://example.i2p/jump
|
|
||||||
|
|
||||||
# HTTP client only. Whether to pass Accept* headers through. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.sendAccept=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Whether to pass Referer headers through. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.sendReferer=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Whether to pass User-Agent headers through. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.sendUserAgent=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Whether to pass Via headers through. Default false.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.sendVia=true|false
|
|
||||||
|
|
||||||
# HTTP client only. Comma- or space-separated list of in-network SSL outproxies.
|
|
||||||
tunnel.N.option.i2ptunnel.httpclient.SSLOutproxies=example.i2p
|
|
||||||
|
|
||||||
# SOCKS client only. Comma- or space-separated list of in-network outproxies for any ports not specified.
|
|
||||||
tunnel.N.option.i2ptunnel.socks.proxy.default=example.i2p
|
|
||||||
|
|
||||||
# SOCKS client only. Comma- or space-separated list of in-network outproxies for port NNNN.
|
|
||||||
tunnel.N.option.i2ptunnel.socks.proxy.NNNN=example.i2p
|
|
||||||
|
|
||||||
# HTTP client only. Whether to use a registered local outproxy plugin. Default true.
|
|
||||||
tunnel.N.option.i2ptunnel.useLocalOutproxy=true|false
|
|
||||||
|
|
||||||
# Servers only. Whether to use a thread pool. Default true. Ignored for standard servers, always false.
|
|
||||||
tunnel.N.option.i2ptunnel.usePool=true|false
|
|
||||||
|
|
||||||
# IRC Server only. Only used if fakeHostname contains a %c.
|
|
||||||
# If unset, cloak with a random value that is persistent for
|
|
||||||
# the life of this tunnel. If set, cloak with the hash of this passphrase.
|
|
||||||
# Use to have consistent mangling across restarts, or for multiple IRC servers cloak consistently to
|
|
||||||
# be able to track users even when they switch servers.
|
|
||||||
# Note: don't quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
|
|
||||||
tunnel.N.option.ircserver.cloakKey=
|
|
||||||
|
|
||||||
# IRC Server only. Set the fake hostname sent by I2PTunnel,
|
|
||||||
# %f is the full B32 destination hash, %c is the cloaked hash.
|
|
||||||
tunnel.N.option.ircserver.fakeHostname=%f.b32.i2p
|
|
||||||
|
|
||||||
# IRC Server only. Default user.
|
|
||||||
tunnel.N.option.ircserver.method=user|webirc
|
|
||||||
|
|
||||||
# IRC Server only. The password to use for the webirc protocol.
|
|
||||||
# Note: don't quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
|
|
||||||
tunnel.N.option.ircserver.webircPassword=
|
|
||||||
|
|
||||||
# IRC Server only.
|
|
||||||
tunnel.N.option.ircserver.webircSpoofIP=
|
|
||||||
|
|
||||||
# For clients only. Alias for the the private key in the keystore for the SSL socket.
|
|
||||||
# Will be autogenerated if a new key is created.
|
|
||||||
tunnel.N.option.keyAlias=
|
|
||||||
|
|
||||||
# For clients only. Password for the private key for the SSL socket.
|
|
||||||
# Will be autogenerated if a new key is created.
|
|
||||||
tunnel.N.option.keyPassword=
|
|
||||||
|
|
||||||
# For clients only. Path to the keystore file containing the private key for the SSL socket.
|
|
||||||
# Will be autogenerated if a new keystore is created.
|
|
||||||
# Relative to $(I2P_CONFIG_DIR)/keystore/ if not absolute.
|
|
||||||
tunnel.N.option.keystoreFile=i2ptunnel-(random string).ks
|
|
||||||
|
|
||||||
# For clients only. Password for the keystore containing the private key for the SSL socket.
|
|
||||||
# Default is "changeit"
|
|
||||||
tunnel.N.option.keystorePassword=changeit
|
|
||||||
|
|
||||||
# HTTP Server only. Max number of POSTs allowed for one destination per postCheckTime. Default 0 (unlimited)
|
|
||||||
tunnel.N.option.maxPosts=nnn
|
|
||||||
|
|
||||||
# HTTP Server only. Max number of POSTs allowed for all destinations per postCheckTime. Default 0 (unlimited)
|
|
||||||
tunnel.N.option.maxTotalPosts=nnn
|
|
||||||
|
|
||||||
# HTTP Clients only. Whether to send authorization to an outproxy. Default false.
|
|
||||||
tunnel.N.option.outproxyAuth=true|false
|
|
||||||
|
|
||||||
# HTTP Clients only. The password for the outproxy authorization.
|
|
||||||
tunnel.N.option.outproxyPassword=
|
|
||||||
|
|
||||||
# HTTP Clients only. The username for the outproxy authorization.
|
|
||||||
tunnel.N.option.outproxyUsername=
|
|
||||||
|
|
||||||
# HTTP Clients only. Whether to send authorization to an outproxy. Default false.
|
|
||||||
tunnel.N.option.outproxyAuth=true|false
|
|
||||||
|
|
||||||
# Clients only. Whether to store a destination in a private key file and reuse it. Default false.
|
|
||||||
tunnel.N.option.persistentClientKey=true|false
|
|
||||||
|
|
||||||
# HTTP Server only. Time period for banning POSTs from a single destination after maxPosts is exceeded, in seconds. Default 1800 seconds.
|
|
||||||
tunnel.N.option.postBanTime=nnn
|
|
||||||
|
|
||||||
# HTTP Server only. Time period for checking maxPosts and maxTotalPosts, in seconds. Default 300 seconds.
|
|
||||||
tunnel.N.option.postCheckTime=nnn
|
|
||||||
|
|
||||||
# HTTP Server only. Time period for banning all POSTs after maxTotalPosts is exceeded, in seconds. Default 600 seconds.
|
|
||||||
tunnel.N.option.postTotalBanTime=nnn
|
|
||||||
|
|
||||||
# HTTP Clients only. Whether to require local authorization for the proxy. Default false. "true" is the same as "basic".
|
|
||||||
tunnel.N.option.proxyAuth=true|false|basic|digest
|
|
||||||
|
|
||||||
# HTTP Clients only. The MD5 of the password for local authorization for user USER.
|
|
||||||
tunnel.N.option.proxy.auth.USER.md5=
|
|
||||||
|
|
||||||
# HTTP Servers only. Whether to reject incoming connections apparently via an inproxy. Default false.
|
|
||||||
tunnel.N.option.rejectInproxy=true|false
|
|
||||||
|
|
||||||
# Servers only. Overrides targetHost and targetPort for incoming port NNNN.
|
|
||||||
tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn
|
|
||||||
|
|
||||||
# Default false. For servers, use SSL for connections to local server.
|
|
||||||
# For clients, SSL is required for connections from local clients.
|
|
||||||
tunnel.N.option.useSSL=false
|
|
||||||
|
|
||||||
# Each option is passed to I2CP and streaming with "tunnel.N.option." stripped off. See those docs.
|
|
||||||
tunnel.N.option.*=
|
|
||||||
|
|
||||||
# For servers and clients with persistent keys only. Absolute path or relative to config directory.
|
|
||||||
tunnel.N.privKeyFile=filename
|
|
||||||
|
|
||||||
# For proxies only. Comma- or space-separated host names.
|
|
||||||
tunnel.N.proxyList=example.i2p[,example2.i2p]
|
|
||||||
|
|
||||||
# For clients only. Default false.
|
|
||||||
tunnel.N.sharedClient=true|false
|
|
||||||
|
|
||||||
# For HTTP servers only. Host name to be passed to the local server in the HTTP headers.
|
|
||||||
# Default is the base 32 hostname.
|
|
||||||
tunnel.N.spoofedHost=example.i2p
|
|
||||||
|
|
||||||
# For HTTP servers only. Host name to be passed to the local server in the HTTP headers.
|
|
||||||
# Overrides above setting for incoming port NNNN, to allow virtual hosts.
|
|
||||||
tunnel.N.spoofedHost.NNNN=example.i2p
|
|
||||||
|
|
||||||
# Default true
|
|
||||||
tunnel.N.startOnLoad=true|false
|
|
||||||
|
|
||||||
# For clients only. Comma- or space-separated host names or host:port.
|
|
||||||
tunnel.N.targetDestination=example.i2p[:nnnn][,example2.i2p[:nnnn]]
|
|
||||||
|
|
||||||
# For servers only. Local IP address or host name to connect to.
|
|
||||||
tunnel.N.targetHost=
|
|
||||||
|
|
||||||
# For servers only. Port on targetHost to connect to.
|
|
||||||
tunnel.N.targetPort=nnnn
|
|
||||||
|
|
||||||
# The type of i2ptunnel
|
|
||||||
tunnel.N.type=client|connectclient|httpbidirserver|httpclient|httpserver|ircclient|ircserver|
|
|
||||||
server|socksirctunnel|sockstunnel|streamrclient|streamrserver
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
Note: Each 'N' is a tunnel number starting with 0.
|
|
||||||
There may not be any gaps in numbering.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Router Console{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The router console uses the router.config file.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>SusiMail (susimail.config)</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
See post on zzz.i2p.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<!--
|
|
||||||
<h3>Systray (systray.config)</h3>
|
|
||||||
<p>
|
|
||||||
TBD
|
|
||||||
</p>
|
|
||||||
-->
|
|
||||||
{% endblock %}
|
|
@@ -1,109 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}Datagram Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}July 2014{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.14{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<p><a href="{{ site_url('docs/api/datagrams') }}">{% trans -%}
|
|
||||||
See the Datagrams page for an overview of the Datagrams API.
|
|
||||||
{%- endtrans %}</a></p>
|
|
||||||
|
|
||||||
<h2 id="spec">{% trans %}Specification{% endtrans %}</h2>
|
|
||||||
|
|
||||||
<h3 id="raw">{% trans %}Non-Repliable Datagrams{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Non-repliable datagrams have no 'from' address and are not authenticated.
|
|
||||||
They are also called "raw" datagrams.
|
|
||||||
Strictly speaking, they are not "datagrams" at all, they are just raw data.
|
|
||||||
They are not handled by the datagram API.
|
|
||||||
However, SAM and the I2PTunnel classes support "raw datagrams".
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h4>{% trans %}Format{% endtrans %}</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----//
|
|
||||||
| payload...
|
|
||||||
+----+----+----+----+----//
|
|
||||||
|
|
||||||
length: 0 - unlimited (see notes)
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>{% trans %}Notes{% endtrans %}</h4>
|
|
||||||
<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message'),
|
|
||||||
transports=site_url('docs/transport') -%}
|
|
||||||
The practical length is limited by lower layers of protocols - the
|
|
||||||
<a href="{{ tunnelmessage }}#notes">tunnel message spec</a>
|
|
||||||
limits messages to about 61.2 KB and the
|
|
||||||
<a href="{{ transports }}">transports</a>
|
|
||||||
currently limit messages to about 32 KB, although this may be raised in the future.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3 id="repliable">{% trans %}Repliable Datagrams{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
Repliable datagrams contain a 'from' address and a signature. These add at least 427 bytes of overhead.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<h4>Format</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| from |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
~ ~
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| signature |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| payload...
|
|
||||||
+----+----+----+----//
|
|
||||||
|
|
||||||
|
|
||||||
from :: a `Destination`
|
|
||||||
length: 387+ bytes
|
|
||||||
The originator and signer of the datagram
|
|
||||||
|
|
||||||
signature :: a `Signature`
|
|
||||||
Signature type must match the signing public key type of $from
|
|
||||||
length: 40+ bytes, as implied by the Signature type.
|
|
||||||
For the default DSA_SHA1 key type:
|
|
||||||
The DSA `Signature` of the SHA-256 hash of the payload.
|
|
||||||
For other key types:
|
|
||||||
The `Signature` of the payload.
|
|
||||||
The signature may be verified by the signing public key of $from
|
|
||||||
|
|
||||||
payload :: The data
|
|
||||||
Length: 0 to ~31.5 KB (see notes)
|
|
||||||
|
|
||||||
Total length: Payload length + 427+
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>{% trans %}Notes{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans transports=site_url('docs/transport') -%}
|
|
||||||
The practical length is limited by lower layers of protocols - the
|
|
||||||
<a href="{{ transports }}">transports</a>
|
|
||||||
currently limit messages to about 32 KB, so the data length here is limited to about
|
|
||||||
31.5 KB.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans dgrams=site_url('docs/api/datagrams') -%}
|
|
||||||
See <a href="{{ dgrams }}">important notes</a> about the reliability of large datagrams.
|
|
||||||
For best results, limit the payload to about 10 KB or less.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Signatures for types other than DSA_SHA1 were redefined in release 0.9.14.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -1,81 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}GeoIP File Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}December 2013{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.9{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<h2>{% trans %}Overview{% endtrans %}</h2>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This page specifies the format of the various GeoIP files,
|
|
||||||
used by the router to look up a country for an IP.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>{% trans %}Country Name (countries.txt) Format{% endtrans %}</h2>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This format is easily generated from data files available from many public sources.
|
|
||||||
For example:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight lang='bash' %}
|
|
||||||
$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
|
|
||||||
$ unzip GeoIPCountryCSV.zip
|
|
||||||
$ cut -d, -f5,6 < GeoIPCountryWhois.csv |sed 's/"//g' | sort | uniq > countries.txt
|
|
||||||
{% endhighlight %}
|
|
||||||
<ul>
|
|
||||||
<li>Encoding is UTF-8
|
|
||||||
<li>'#' in column 1 specifies a comment line
|
|
||||||
<li>Entry lines are CountryCode,CountryName
|
|
||||||
<li>CountryCode is the ISO two-letter code, upper case
|
|
||||||
<li>CountryName is in English
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>{% trans %}IPv4 (geoip.txt) Format{% endtrans %}</h2>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This format is borrowed from Tor and is easily generated from data files available from many public sources.
|
|
||||||
For example:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight lang='bash' %}
|
|
||||||
$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
|
|
||||||
$ unzip GeoIPCountryCSV.zip
|
|
||||||
$ cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip.txt
|
|
||||||
$ cut -d, -f5,6 < GeoIPCountryWhois.csv |sed 's/"//g' | sort | uniq > countries.txt
|
|
||||||
{% endhighlight %}
|
|
||||||
<ul>
|
|
||||||
<li>Encoding is ASCII
|
|
||||||
<li>'#' in column 1 specifies a comment line
|
|
||||||
<li>Entry lines are FromIP,ToIP,CountryCode
|
|
||||||
<li>FromIP and ToIP are unsigned integer representations of the 4-byte IP
|
|
||||||
<li>CountryCode is the ISO two-letter code, upper case
|
|
||||||
<li>Entry lines must be sorted by numeric FromIP
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>{% trans %}IPv6 (geoipv6.dat.gz) Format{% endtrans %}</h2>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This is a compressed binary format designed for I2P.
|
|
||||||
The file is gzipped. Ungzipped format:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight %}
|
|
||||||
Bytes 0-9: Magic number "I2PGeoIPv6"
|
|
||||||
Bytes 10-11: Version (0x0001)
|
|
||||||
Bytes 12-15 Options (0x00000000) (future use)
|
|
||||||
Bytes 16-23: Creation date (ms since 1970-01-01)
|
|
||||||
Bytes 24-xx: Optional comment (UTF-8) terminated by zero byte
|
|
||||||
Bytes xx-255: null padding
|
|
||||||
Bytes 256-: 18 byte records:
|
|
||||||
8 byte from (/64)
|
|
||||||
8 byte to (/64)
|
|
||||||
2 byte ISO country code LOWER case (ASCII)
|
|
||||||
{% endhighlight %}
|
|
||||||
<p>{% trans %}NOTES:{% endtrans %}</p>
|
|
||||||
<ul>
|
|
||||||
<li>Data must be sorted (SIGNED long twos complement), no overlap.
|
|
||||||
So the order is 80000000 ... FFFFFFFF 00000000 ... 7FFFFFFF.
|
|
||||||
<li>
|
|
||||||
The GeoIPv6.java class contains a program to generate this format from
|
|
||||||
public sources such as the Maxmind GeoLite data.
|
|
||||||
<li>
|
|
||||||
IPv6 GeoIP lookup is supported as of release 0.9.8.
|
|
||||||
</ul>
|
|
||||||
{% endblock %}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,539 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}I2P Plugin Specification{% endblock %}
|
|
||||||
{% block lastupdated %}May 2015{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.20{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h3>Overview</h3>
|
|
||||||
<p>
|
|
||||||
This document specifies
|
|
||||||
a .xpi2p file format (like the Firefox .xpi), but with a simple
|
|
||||||
plugin.config description file instead of an XML install.rdf file.
|
|
||||||
This file format is used for both initial plugin installs and plugin updates.
|
|
||||||
<p>
|
|
||||||
In addition, this document provides a brief overview of how the router installs plugins,
|
|
||||||
and policies and guidelines for plugin developers.
|
|
||||||
<p>
|
|
||||||
The basic .xpi2p file format is the same as a i2pupdate.sud file
|
|
||||||
(the format used for router updates),
|
|
||||||
but the installer will let the user install the
|
|
||||||
addon even if it doesn't know the signer's key yet.
|
|
||||||
<p>
|
|
||||||
As of release 0.9.15, the <a href="updates">su3 file format</a> is supported and is preferred.
|
|
||||||
This format enables stronger signing keys.
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The standard directory structure will let users install the following types of addons:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
console webapps
|
|
||||||
<li>
|
|
||||||
new eepsite with cgi-bin, webapps
|
|
||||||
<li>
|
|
||||||
console themes
|
|
||||||
<li>
|
|
||||||
console translations
|
|
||||||
<li>
|
|
||||||
Java programs
|
|
||||||
<li>
|
|
||||||
Java programs in a separate JVM
|
|
||||||
<li>
|
|
||||||
Any shell script or program
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
A plugin installs all its files in ~/.i2p/plugins/name/ (%APPDIR%\I2P\plugins\name\ on Windows). The installer will prevent
|
|
||||||
installation anywhere else, although the plugin can access libraries elsewhere when running.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This should be viewed only as a way to make installation, uninstallation, and upgrading easier,
|
|
||||||
and to lessen basic inter-plugin conflicts.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
There is essentially no security model once the plugin is running, however. The plugin runs
|
|
||||||
in the same JVM and with the same permissions as the router, and has full access to the file
|
|
||||||
system, the router, executing external programs, etc.
|
|
||||||
|
|
||||||
<h3>Details</h3>
|
|
||||||
<p>
|
|
||||||
foo.xpi2p is a <a href="{{ site_url('docs/spec/updates') }}">signed update (sud) file</a> containing the following:
|
|
||||||
<h4>
|
|
||||||
Standard .sud header prepended to the zip file, containing the following:
|
|
||||||
</h4>
|
|
||||||
<pre>
|
|
||||||
40-byte <a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA signature</a>
|
|
||||||
16-byte plugin version in UTF-8, padded with trailing zeroes if necessary
|
|
||||||
</pre>
|
|
||||||
<h4>
|
|
||||||
Zip file containing the following:
|
|
||||||
</h4>
|
|
||||||
<h5>
|
|
||||||
plugin.config file
|
|
||||||
</h5>
|
|
||||||
<p>
|
|
||||||
This file is required. It is a
|
|
||||||
<a href="{{ site_url('docs/spec/configuration') }}">standard I2P configuration file</a>,
|
|
||||||
containing the following properties:
|
|
||||||
</p>
|
|
||||||
</p><p>
|
|
||||||
The following four are required properties.
|
|
||||||
The first three must be identical to those in the installed plugin for an update plugin.
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
name (will be installed in this directory name)
|
|
||||||
For native plugins, you may want separate names in different packages -
|
|
||||||
foo-windows and foo-linux, for example
|
|
||||||
|
|
||||||
key (<a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA public key</a> as 172 B64 chars ending with '=')
|
|
||||||
Omit for SU3 format.
|
|
||||||
|
|
||||||
signer (yourname@mail.i2p recommended)
|
|
||||||
|
|
||||||
version (must be in a format VersionComparator can parse, e.g. 1.2.3-4)
|
|
||||||
16 bytes max (must match sud version)
|
|
||||||
Valid number separators are '.', '-', and '_'
|
|
||||||
This must be greater than the one in the installed plugin for an update plugin.
|
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
Values for the following properties are displayed on /configclients in the router console if present:
|
|
||||||
<pre>
|
|
||||||
date (Java time - long int)
|
|
||||||
author (yourname@mail.i2p recommended)
|
|
||||||
websiteURL (http://foo.i2p/)
|
|
||||||
updateURL (http://foo.i2p/foo.xpi2p)
|
|
||||||
The update checker will check bytes 41-56 at this URL
|
|
||||||
to determine whether a newer version is available
|
|
||||||
( Should the checker fetch with ?currentVersion=1.2.3?...
|
|
||||||
No. If the dev wants to have the URL contain the current version, just
|
|
||||||
set it in the config file, and remember to change it every release)
|
|
||||||
updateURL.su3 (http://foo.i2p/foo.su3)
|
|
||||||
The location of the su3-format update file, as of 0.9.15
|
|
||||||
description
|
|
||||||
description_xx (for language xx)
|
|
||||||
license
|
|
||||||
disableStop=true
|
|
||||||
Default false.
|
|
||||||
If true, the stop button will not be shown. Use this if there are no
|
|
||||||
webapps and no clients with stopargs.
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
The following properties are used to add a link on the console summary bar:
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
consoleLinkName (will be added to summary bar)
|
|
||||||
consoleLinkName_xx (for language xx)
|
|
||||||
consoleLinkURL (/appname/index.jsp)
|
|
||||||
consoleLinkTooltip (supported as of 0.7.12-6)
|
|
||||||
consoleLinkTooltip_xx (lang xx as of 0.7.12-6)
|
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
The following optional property may be used to add a custom icon on the console:
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
console-icon (supported as of 0.9.20) Only for webapps.
|
|
||||||
A path within the webapp to a 32x32 image, e.g. /icon.png
|
|
||||||
Applies to all webapps in the plugin.
|
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
The following properties are used by the plugin installer:
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
type (app/theme/locale/webapp/...) (unimplemented, probably not necessary)
|
|
||||||
min-i2p-version
|
|
||||||
max-i2p-version
|
|
||||||
min-java-version
|
|
||||||
min-jetty-version (supported as of 0.8.13, use 6 for Jetty 6 webapps)
|
|
||||||
max-jetty-version (supported as of 0.8.13, use 5.99999 for Jetty 5 webapps)
|
|
||||||
required-platform-OS (unimplemented - perhaps will be displayed only, not verified)
|
|
||||||
other-requirements (unimplemented e.g. python x.y - not verified by the installer, just displayed to the user)
|
|
||||||
dont-start-at-install=true
|
|
||||||
Default false.
|
|
||||||
Won't start the plugin when it is installed or updated. On initial installation,
|
|
||||||
configures the plugin so the user must manually start it. An update will not change
|
|
||||||
the user's preference to start it if they choose to do so.
|
|
||||||
router-restart-required=true
|
|
||||||
Default false.
|
|
||||||
This does not restart the router or the plugin on an update, it just informs the user that a restart is required.
|
|
||||||
It has no effect on initial plugin installation.
|
|
||||||
update-only=true
|
|
||||||
Default false.
|
|
||||||
If true, will fail if an installation does not exist.
|
|
||||||
install-only=true
|
|
||||||
Default false.
|
|
||||||
If true, will fail if an installation exists.
|
|
||||||
min-installed-version (to update over, if an installation exists)
|
|
||||||
max-installed-version (to update over, if an installation exists)
|
|
||||||
depends=plugin1,plugin2,plugin3 (unimplemented - is this too hard? proposed by sponge)
|
|
||||||
depends-version=0.3.4,,5.6.7 (unimplemented)
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
The following property is used for translation plugins:
|
|
||||||
<pre>
|
|
||||||
langs=xx,yy,Klingon,... (unimplemented) (yy is the country flag)
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
<h5>
|
|
||||||
Application Directories and Files
|
|
||||||
</h5>
|
|
||||||
<p>
|
|
||||||
Each of the following directories or files is optional, but something must be there or it won't do anything:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
console/
|
|
||||||
locale/
|
|
||||||
Only jars containing new resource bundles (translations) for apps in the base I2P installation.
|
|
||||||
Bundles for this plugin should go inside console/webapp/foo.war or lib/foo.jar
|
|
||||||
|
|
||||||
themes/
|
|
||||||
New themes for the router console
|
|
||||||
Place each theme in a subdirectory.
|
|
||||||
|
|
||||||
webapps/
|
|
||||||
(See important notes below about webapps)
|
|
||||||
.wars
|
|
||||||
These will be run at install time unless disabled in webapps.config
|
|
||||||
The war name does not have to be the same as the plugin name.
|
|
||||||
Do not duplicate war names in the base I2P installation.
|
|
||||||
|
|
||||||
webapps.config
|
|
||||||
Same format as router's webapps.config
|
|
||||||
Also used to specify additional jars in $PLUGIN/lib/ or $I2P/lib for the webapp classpath,
|
|
||||||
with webapps.warname.classpath=$PLUGIN/lib/foo.jar,$I2P/lib/bar.jar
|
|
||||||
NOTE: Currently, the classpath line is only loaded if the warname is
|
|
||||||
the same as the plugin name.
|
|
||||||
NOTE: Prior to router version 0.7.12-9, the router looked for plugin.warname.startOnLoad instead
|
|
||||||
of webapps.warname.startOnLoad. For compatibility with older router versions, a plugin
|
|
||||||
wishing to disable a war should include both lines.
|
|
||||||
|
|
||||||
eepsite/
|
|
||||||
(See important notes below about eepsites)
|
|
||||||
cgi-bin/
|
|
||||||
docroot/
|
|
||||||
logs/
|
|
||||||
webapps/
|
|
||||||
jetty.xml
|
|
||||||
The installer will have to do variable substitution in here to set the path
|
|
||||||
The location and name of this file doesn't really matter, as long as it is set in
|
|
||||||
clients.config - it may be more convenient to be up one level from here
|
|
||||||
(that's what the zzzot plugin does)
|
|
||||||
|
|
||||||
lib/
|
|
||||||
Put any jars here, and specify them in a classpath line in console/webapps.config and/or clients.config
|
|
||||||
</pre>
|
|
||||||
<h5>
|
|
||||||
clients.config file
|
|
||||||
</h5>
|
|
||||||
<p>
|
|
||||||
This file is optional,
|
|
||||||
and specifies clients that will be run when a plugin is started.
|
|
||||||
It uses the same format as the router's clients.config file.
|
|
||||||
See the <a href="{{ site_url('docs/spec/configuration') }}">clients.config configuration file specification</a>
|
|
||||||
for more information about the format and important details
|
|
||||||
about how clients are started and stopped.
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
property clientApp.0.stopargs=foo bar stop baz
|
|
||||||
If present, the class will be called with these args to stop the client
|
|
||||||
All stop tasks are called with zero delay
|
|
||||||
Note: The router can't tell if your unmanaged clients are running or not.
|
|
||||||
Each should handle stopping an app that isn't running without complaint.
|
|
||||||
That probably goes for starting a client that is already started too.
|
|
||||||
property clientApp.0.uninstallargs=foo bar uninstall baz
|
|
||||||
If present, the class will be called with these args just before deleting $PLUGIN
|
|
||||||
All uninstall tasks are called with zero delay
|
|
||||||
property clientApp.0.classpath=$I2P/lib/foo.bar,$PLUGIN/lib/bar.jar
|
|
||||||
The plugin runner will do variable substitution in the args and stopargs lines as follows:
|
|
||||||
$I2P => i2p base installation dir;
|
|
||||||
$CONFIG => i2p config dir (typically ~/.i2p)
|
|
||||||
$PLUGIN => this plugin's installation dir (typically ~/.i2p/plugins/appname)
|
|
||||||
(See important notes below about running shell scripts or external programs)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Plugin installer tasks</h3>
|
|
||||||
This lists what happens when a plugin is installed by I2P.
|
|
||||||
<ul>
|
|
||||||
|
|
||||||
<li>The .xpi2p file is downloaded.</li>
|
|
||||||
<li>The .sud signature is verified against stored keys.
|
|
||||||
As of release 0.9.14.1,
|
|
||||||
if there is no matching key, the installation fails, unless an advanced router property is set to allow all keys.</li>
|
|
||||||
<li>Verify the integrity of the zip file.</li>
|
|
||||||
<li>Extract the plugin.config file.</li>
|
|
||||||
<li>Verify the I2P version, to make sure the plugin will work.</li>
|
|
||||||
<li>Check that webapps don't duplicate the existing $I2P applications.</li>
|
|
||||||
<li>Stop the existing plugin (if present).</li>
|
|
||||||
<li>Verify that the install directory does not exist yet if update=false, or ask to overwrite.</li>
|
|
||||||
<li>Verify that the install directory does exist if update=true, or ask to create.</li>
|
|
||||||
<li>Unzip the plugin in to appDir/plugins/name/</li>
|
|
||||||
<li>Add the plugin to plugins.config</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Plugin starter tasks
|
|
||||||
</h3>
|
|
||||||
This lists what happens when plugins are started.
|
|
||||||
First, plugins.config is checked to see which plugins need to be started.
|
|
||||||
For each plugin:
|
|
||||||
<ul>
|
|
||||||
<li>Check clients.config, and load and start each item (add the configured jars to the classpath).</li>
|
|
||||||
<li>Check console/webapp and console/webapp.config. Load and start required items (add the configured jars to the classpath).</li>
|
|
||||||
<li>Add console/locale/foo.jar to the translation classpath if present.</li>
|
|
||||||
<li>Add console/theme to the theme search path if present.</li>
|
|
||||||
<li>Add the summary bar link.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Console webapp notes
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
Console webapps with background tasks should implement a ServletContextListener
|
|
||||||
(see seedless or i2pbote for examples), or override destroy() in the servlet,
|
|
||||||
so that they can be stopped.
|
|
||||||
As of router version 0.7.12-3, console webapps will always be stopped before they
|
|
||||||
are restarted, so you do not need to worry about multiple instances,
|
|
||||||
as long as you do this.
|
|
||||||
Also as of router version 0.7.12-3, console webapps will be stopped at router shutdown.
|
|
||||||
<p>
|
|
||||||
Don't bundle library jars in the webapp; put them in lib/ and put a classpath in webapps.config.
|
|
||||||
Then you can make separate install and update plugins, where the update plugin does not
|
|
||||||
contain the library jars.
|
|
||||||
<p>
|
|
||||||
Don't include .java or .jsp files; otherwise jetty will recompile them at installation.
|
|
||||||
<p>
|
|
||||||
For now, a webapp needing to add classpath files in $PLUGIN must be the same name as the plugin.
|
|
||||||
For example, a webapp in plugin foo must be named foo.war.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Eepsite notes
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
It isn't clear how to have a plugin install to an existing eepsite.
|
|
||||||
The router has no hook to the eepsite, and it may or may not be running,
|
|
||||||
and there may be more than one.
|
|
||||||
Better is to start your own Jetty instance and I2PTunnel instance,
|
|
||||||
for a brand new eepsite.
|
|
||||||
<p>
|
|
||||||
It can instantiate a new I2PTunnel (somewhat like the i2ptunnel CLI does),
|
|
||||||
but it won't appear in the i2ptunnel gui of course, that's a different instance.
|
|
||||||
But that's ok. Then you can start and stop i2ptunnel and jetty together.
|
|
||||||
<p>
|
|
||||||
So don't count on the router to automatically merge this with some existing eepsite. It probably won't happen.
|
|
||||||
Start a new I2PTunnel and Jetty from clients.config.
|
|
||||||
The best examples of this are the zzzot and pebble plugins,
|
|
||||||
available at <a href="http://{{ i2pconv('stats.i2p') }}/i2p/plugins/">zzz's plugins page</a>.
|
|
||||||
<p>
|
|
||||||
How to get path substitution into jetty.xml?
|
|
||||||
See zzzot and pebble plugins for examples.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Client start/stop notes
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
As of release 0.9.4, the router supports "managed" plugin clients.
|
|
||||||
Managed plugin clients are instantiated and started by the <code>ClientAppManager</code>.
|
|
||||||
The ClientAppManager maintains a reference to the client and receives updates on the client's state.
|
|
||||||
Managed plugin client are preferred, as it is much easier to implement state tracking
|
|
||||||
and to start and stop a client. It also is much easier to avoid static references in the client code
|
|
||||||
which could lead to excessive memory usage after a client is stopped.
|
|
||||||
See the <a href="{{ site_url('docs/spec/configuration') }}">clients.config configuration file specification</a>
|
|
||||||
for more information on writing a managed client.
|
|
||||||
</p><p>
|
|
||||||
For "unmanaged" plugin clients,
|
|
||||||
The router has no way to monitor the state of clients started via clients.config.
|
|
||||||
The plugin author should handle multiple start or stop calls gracefully, if at all possible,
|
|
||||||
by keeping a static state table, or using PID files, etc.
|
|
||||||
Avoid logging or exceptions on multiple starts or stops.
|
|
||||||
This also goes for a stop call without a previous start.
|
|
||||||
As of router version 0.7.12-3, plugins will be stopped at router shutdown,
|
|
||||||
which means that all clients with stopargs in clients.config will be called,
|
|
||||||
whether or not they were previously started.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Shell script and external program notes
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
To run shell scripts or other external programs, see <a href="http://{{ i2pconv('zzz.i2p') }}/topics/141">{{ i2pconv('zzz.i2p') }}</a>
|
|
||||||
<p>
|
|
||||||
To work on both Windows and Linux, write a small Java class that checks the OS type, then
|
|
||||||
runs ShellCommand on either the .bat or a .sh file you provide.
|
|
||||||
<p>
|
|
||||||
External programs won't be stopped when the router stops, and a second copy will
|
|
||||||
fire up when the router starts. To work around this, you could
|
|
||||||
write a wrapper class or shell script that does the usual storage of the PID
|
|
||||||
in a PID file, and check for it on start.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Other plugin guidelines
|
|
||||||
</h3>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p file generator to make it easy.
|
|
||||||
<li>
|
|
||||||
Pack200 of jars and wars is strongly recommended for plugins, it generally shrinks plugins by 60-65%.
|
|
||||||
See any of the sample plugins on zzz's page for an example.
|
|
||||||
Pack200 unpacking is supported on routers 0.7.11-5 or higher, which is essentially all routers that
|
|
||||||
support plugins at all.
|
|
||||||
|
|
||||||
<li>
|
|
||||||
Plugins should not attempt to write anywhere in $I2P as it may be readonly, and that isn't good policy anyway.
|
|
||||||
<li>
|
|
||||||
Plugins may write to $CONFIG but keeping files in $PLUGIN only is recommended.
|
|
||||||
All files in $PLUGIN will be deleted at uninstall.
|
|
||||||
Files elsewhere will not be deleted at uninstall unless the plugin does it explicitly
|
|
||||||
with a client in clients.config run with uninstallargs.
|
|
||||||
If the user may want to save data after uninstallation, the uninstallargs hook
|
|
||||||
could ask.
|
|
||||||
|
|
||||||
<li>
|
|
||||||
$CWD may be anywhere; do not assume it is in a particular place, do not attempt to read or write files relative to $CWD.
|
|
||||||
<li>
|
|
||||||
Java programs should find out where they are with the directory getters in I2PAppContext.
|
|
||||||
<li>
|
|
||||||
Plugin directory is I2PAppContext.getGlobalContext().getAppDir().getAbsolutePath() + "/plugins/" + appname,
|
|
||||||
or put a $PLUGIN argument in the args line in clients.config.
|
|
||||||
There is no reliable way to find the i2p install or config or plugin directory without using the
|
|
||||||
context API in i2p.jar.
|
|
||||||
<li>
|
|
||||||
See <a href="http://{{ i2pconv('zzz.i2p') }}/topics/16">Howto</a> for info on generating signing keys and generating/verifying keys and sud files
|
|
||||||
<li>
|
|
||||||
All config files must be UTF-8.
|
|
||||||
<li>
|
|
||||||
To run in a separate JVM, use ShellCommand with java -cp foo:bar:baz my.main.class arg1 arg2 arg3.
|
|
||||||
Of course, it will be a lot harder to stop the plugin then...
|
|
||||||
But with some trickery with PID files it should be possible.
|
|
||||||
<li>
|
|
||||||
As an alternative to stopargs in clients.config,
|
|
||||||
a Java client may register a shutdown hook with I2PAppContext.addShutdownTask().
|
|
||||||
But this wouldn't shut down a plugin when upgrading, so stopargs is recommended.
|
|
||||||
Also, set all created threads to daemon mode.
|
|
||||||
<li>
|
|
||||||
Do not include classes duplicating those in the standard installation. Extend the classes if necessary.
|
|
||||||
<li>
|
|
||||||
Beware of the different classpath definitions in wrapper.config between old and new installations -
|
|
||||||
see classpath section below.
|
|
||||||
<li>
|
|
||||||
Clients will reject duplicate keys with different keynames, and duplicate keynames with different keys,
|
|
||||||
and different keys or keynames in upgrade packages. Safeguard your keys. Only generate them once.
|
|
||||||
<li>
|
|
||||||
Do not modify the plugin.config file at runtime as it will be overwritten on upgrade.
|
|
||||||
Use a different config file in the directory for storing runtime configuration.
|
|
||||||
<li>
|
|
||||||
In general, plugins should not require access to $I2P/lib/router.jar. Do not access router classes,
|
|
||||||
unless you are doing something special.
|
|
||||||
The router may in the future implement a restricted classpath for plugins that prevents
|
|
||||||
access to router classes.
|
|
||||||
<li>
|
|
||||||
Since each version must be higher than the one before, you could enhance your build
|
|
||||||
script to add a build number to the end of the version.
|
|
||||||
This helps for testing. Most of zzz's plugins have that feature, check build.xml for an example.
|
|
||||||
<li>
|
|
||||||
Plugins must never call System.exit().
|
|
||||||
<li>
|
|
||||||
Please respect licenses by meeting license requirements for any software you bundle.
|
|
||||||
<li>
|
|
||||||
The router sets the JVM time zone to UTC. If a plugin needs to know the user's actual time zone,
|
|
||||||
it is stored by the router in the I2PAppContext property "i2p.systemTimeZone".
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Classpaths
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
The following jars in $I2P/lib can be assumed to be in the standard classpath for all I2P installations,
|
|
||||||
no matter how old or how new the original installation:
|
|
||||||
<p>
|
|
||||||
i2p.jar, router.jar, jbigi.jar, sam.jar, mstreaming.jar, streaming.jar, i2ptunnel.jar,
|
|
||||||
org.mortbay.jetty.jar, javax.servlet.jar, jasper-compiler.jar, jasper-runtime.jar,
|
|
||||||
commons-logging.jar, commons-el.jar, wrapper.jar, systray.jar, systray4j.jar
|
|
||||||
<p>
|
|
||||||
|
|
||||||
The following jars in $I2P/lib can be assumed to be present for all I2P installations,
|
|
||||||
no matter how old or how new the original installation,
|
|
||||||
but are not necessarily in the classpath:
|
|
||||||
<p>
|
|
||||||
jstl.jar, standard.jar
|
|
||||||
<p>
|
|
||||||
|
|
||||||
Anything not listed above may not be present in everybody's classpath, even if you
|
|
||||||
have it in the classpath in YOUR version of i2p.
|
|
||||||
If you need any jar not listed above, add $I2P/lib/foo.jar to the classpath specified
|
|
||||||
in clients.config or webapps.config in your plugin.
|
|
||||||
<p>
|
|
||||||
Previously, a classpath entry specified in clients.config was added to the classpath for
|
|
||||||
the entire JVM.
|
|
||||||
However, as of 0.7.13-3, this was fixed using class loaders, and now, as originally intended,
|
|
||||||
the specified classpath in clients.config is only for the particular thread.
|
|
||||||
See the section on JVM crashes below, and
|
|
||||||
<a href="http://{{ i2pconv('zzz.i2p') }}/topics/633">this thread on zzz.i2p</a> for background.
|
|
||||||
Therefore, specify the full required classpath for each client.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
Java Version Notes
|
|
||||||
</h3>
|
|
||||||
While most I2P users are running a 1.6 (6.0) JVM, we support 1.5 (5.0) and higher JVMs.
|
|
||||||
Unless you require 1.6 features, you should create your plugin so it works on 1.5.
|
|
||||||
<p>
|
|
||||||
If your plugin <b>does not require 1.6</b>:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Ensure that all java and jsp files are compiled with source="1.5" target="1.5".
|
|
||||||
<li>
|
|
||||||
Ensure that all bundled library jars are also for 1.5 or lower.
|
|
||||||
<li>
|
|
||||||
If you are using pack200, any 1.6 classes in a jar will
|
|
||||||
cause pack200 to create a 1.6 pack format, and
|
|
||||||
plugin installation will fail on a 1.5 system
|
|
||||||
with the misleading message "plugin is corrupt".
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If your plugin <b>requires 1.6</b>:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Note that on your download page.
|
|
||||||
<li>
|
|
||||||
Add min-java-version=1.6 to your plugin.config
|
|
||||||
<li>
|
|
||||||
If you are using pack200, plugin installation will fail on a 1.5 system
|
|
||||||
with the misleading message "plugin is corrupt".
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
JVM Crashes When Updating
|
|
||||||
</h3>
|
|
||||||
Note - this should all be fixed now.
|
|
||||||
<p>
|
|
||||||
The JVM has a tendency to crash when updating jars in a plugin if that plugin was running
|
|
||||||
since i2p was started (even if the plugin was later stopped).
|
|
||||||
This may have been fixed with the class loader implementation in 0.7.13-3, but it may not.
|
|
||||||
For further testing.
|
|
||||||
<p>
|
|
||||||
The safest is to design your plugin with the jar inside the war (for a webapp), or to require a restart
|
|
||||||
after update, or don't update the jars in your plugin.
|
|
||||||
<p>
|
|
||||||
Due to the way class loaders work inside a webapp, it _may_ be safe to have external jars if
|
|
||||||
you specify the classpath in webapps.config.
|
|
||||||
More testing is required to verify this.
|
|
||||||
Don't specify the classpath with a 'fake' client in clients.config if it's only
|
|
||||||
needed for a webapp - use webapps.config instead.
|
|
||||||
<p>
|
|
||||||
The least safe, and apparently the source of most crashes, is clients with plugin jars specified
|
|
||||||
in the classpath in clients.config.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
None of this should be a problem on initial install - you should not ever have to require a restart
|
|
||||||
for an initial install of a plugin.
|
|
||||||
|
|
||||||
{% endblock %}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,169 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}Streaming Library Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}June 2015{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.20{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<p><a href="{{ site_url('docs/api/streaming') }}">{% trans -%}
|
|
||||||
See the Streaming page for an overview of the Streaming Library.
|
|
||||||
{%- endtrans %}</a></p>
|
|
||||||
|
|
||||||
<h2>{% trans %}Protocol Specification{% endtrans %}</h2>
|
|
||||||
<h3>{% trans %}Packet Format{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The format of a single packet in the streaming protocol is:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| send Stream ID | rcv Stream ID |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| sequence Num | ack Through |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| nc | NACKs ...
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| rd | flags | opt size| opt data
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
... |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| payload ...
|
|
||||||
+----+----+----+-//
|
|
||||||
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr><th>{{ _('Field') }}<th>{{ _('Length') }}<th>{{ _('Contents') }}
|
|
||||||
<tr><td>sendStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a>
|
|
||||||
<td>Random number selected by the packet recipient before sending the first SYN reply packet
|
|
||||||
and constant for the life of the connection.
|
|
||||||
0 in the SYN message sent by the connection originator, and in subsequent messages, until a SYN reply is received,
|
|
||||||
containing the peer's stream ID.
|
|
||||||
|
|
||||||
<tr><td>receiveStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a>
|
|
||||||
<td>Random number selected by the packet originator before sending the first SYN packet
|
|
||||||
and constant for the life of the connection. May be 0 if unknown, for example in a RESET packet.
|
|
||||||
|
|
||||||
<tr><td>sequenceNum <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
The sequence for this message, starting at 0 in the SYN message,
|
|
||||||
and incremented by 1 in each message except for plain ACKs and retransmissions.
|
|
||||||
If the sequenceNum is 0 and the SYN flag is not set, this is a plain ACK
|
|
||||||
packet that should not be ACKed.
|
|
||||||
|
|
||||||
<tr><td>ackThrough <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
The highest packet sequence number that was received
|
|
||||||
on the receiveStreamId. This field is ignored on the initial
|
|
||||||
connection packet (where receiveStreamId is the unknown id) or
|
|
||||||
if the NO_ACK flag set.
|
|
||||||
All packets up to and including this sequence number are ACKed,
|
|
||||||
EXCEPT for those listed in NACKs below.
|
|
||||||
|
|
||||||
<tr><td>NACK count<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
The number of 4-byte NACKs in the next field
|
|
||||||
|
|
||||||
<tr><td>NACKs <td>n * 4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integers</a><td>
|
|
||||||
Sequence numbers less than ackThrough that are not yet received.
|
|
||||||
Two NACKs of a packet is a request for a 'fast retransmit' of that packet.
|
|
||||||
|
|
||||||
<tr><td>resendDelay<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
How long is the creator of this packet going to wait before
|
|
||||||
resending this packet (if it hasn't yet been ACKed). The
|
|
||||||
value is seconds since the packet was created.
|
|
||||||
Currently ignored on receive.
|
|
||||||
|
|
||||||
<tr><td>flags <td>2 byte value<td>
|
|
||||||
See below.
|
|
||||||
|
|
||||||
<tr><td>option size<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
The number of bytes in the next field
|
|
||||||
|
|
||||||
<tr><td>option data<td>0 or more bytes<td>
|
|
||||||
As specified by the flags. See below.
|
|
||||||
|
|
||||||
<tr><td>payload <td>remaining packet size<td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>{% trans %}Flags and Option Data Fields{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The flags field above specifies some metadata about the packet, and in
|
|
||||||
turn may require certain additional data to be included. The flags are
|
|
||||||
as follows. Any data structures specified must be added to the options area
|
|
||||||
in the given order.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Bit order: 15....0 (15 is MSB)
|
|
||||||
</p>
|
|
||||||
<table>
|
|
||||||
<tr><th>Bit<th>Flag<th>Option Order<th>Option Data<th>Function
|
|
||||||
<tr><td>0<td>SYNCHRONIZE<td align="center">--<td align="center">--<td>
|
|
||||||
Similar to TCP SYN. Set in the initial packet and in the first response.
|
|
||||||
FROM_INCLUDED and SIGNATURE_INCLUDED must be set also.
|
|
||||||
<tr><td>1<td>CLOSE<td align="center">--<td align="center">--<td>
|
|
||||||
Similar to TCP FIN. If the response to a SYNCHRONIZE fits in a single message, the response
|
|
||||||
will contain both SYNCHRONIZE and CLOSE.
|
|
||||||
SIGNATURE_INCLUDED must be set also.
|
|
||||||
<tr><td>2<td>RESET<td align="center">--<td align="center">--<td>
|
|
||||||
Abnormal close.
|
|
||||||
SIGNATURE_INCLUDED must be set also.
|
|
||||||
Prior to release 0.9.20, due to a bug, FROM_INCLUDED must also be set.
|
|
||||||
<tr><td>3<td>SIGNATURE_INCLUDED<td align="center">4<td>variable length <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a>
|
|
||||||
<td>
|
|
||||||
Currently sent only with SYNCHRONIZE, CLOSE, and RESET, where it is required,
|
|
||||||
and with ECHO, where it is required for a ping.
|
|
||||||
The signature uses the Destination's <a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">signing keys</a>
|
|
||||||
to sign the entire header and payload with the space in the option data field
|
|
||||||
for the signature being set to all zeroes.
|
|
||||||
<br>
|
|
||||||
Prior to release 0.9.11, the signature was always 40 bytes.
|
|
||||||
As of release 0.9.11, the signature may be variable-length, see below for details.
|
|
||||||
<tr><td>4<td>SIGNATURE_REQUESTED<td align="center">--<td align="center">--<td>
|
|
||||||
Unused. Requests every packet in the other direction to have SIGNATURE_INCLUDED
|
|
||||||
<tr><td>5<td>FROM_INCLUDED<td align="center">2<td>387+ byte <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a>
|
|
||||||
<td>
|
|
||||||
Currently sent only with SYNCHRONIZE, where it is required,
|
|
||||||
and with ECHO, where it is required for a ping.
|
|
||||||
Prior to release 0.9.20, due to a bug, must also be sent with RESET.
|
|
||||||
<tr><td>6<td>DELAY_REQUESTED<td align="center">1<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
Optional delay.
|
|
||||||
How many milliseconds the sender of this packet wants the recipient
|
|
||||||
to wait before sending any more data.
|
|
||||||
A value greater than 60000 indicates choking.
|
|
||||||
<tr><td>7<td>MAX_PACKET_SIZE_INCLUDED<td align="center">3<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td>
|
|
||||||
Currently sent with SYNCHRONIZE only.
|
|
||||||
Was also sent in retransmitted packets until release 0.9.1.
|
|
||||||
<tr><td>8<td>PROFILE_INTERACTIVE<td align="center">--<td align="center">--<td>
|
|
||||||
Unused or ignored; the interactive profile is unimplemented.
|
|
||||||
<tr><td>9<td>ECHO<td align="center">--<td align="center">--<td>
|
|
||||||
Unused except by ping programs.
|
|
||||||
If set, most other options are ignored. See
|
|
||||||
<a href="{{ site_url('docs/api/streaming') }}">the streaming docs</a>.
|
|
||||||
<tr><td>10<td>NO_ACK<td align="center">--<td align="center">--<td>
|
|
||||||
This flag simply tells the recipient to ignore the ackThrough field in the header.
|
|
||||||
Currently set in the inital SYN packet, otherwise the ackThrough field is always valid.
|
|
||||||
Note that this does not save any space, the ackThrough field is before the flags
|
|
||||||
and is always present.
|
|
||||||
<tr><td>11-15<td>unused<td><td><td>
|
|
||||||
Set to zero for compatibility with future uses.
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4>Variable Length Signature Notes</h4>
|
|
||||||
<p>
|
|
||||||
Prior to release 0.9.11, the signature in the option field was always 40 bytes.
|
|
||||||
As of release 0.9.11, the signature is variable length.
|
|
||||||
The Signature type and length are inferred from the type of key used in the FROM_INCLUDED option
|
|
||||||
and the <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature documentation</a>.
|
|
||||||
<ul><li>
|
|
||||||
When a packet contains both FROM_INCLUDED and SIGNATURE_INCLUDED (as in SYNCHRONIZE), the inference may be made directly.
|
|
||||||
</li><li>
|
|
||||||
When a packet does not contain FROM_INCLUDED, the inference must be made from a previous SYNCHRONIZE packet.
|
|
||||||
</li><li>
|
|
||||||
When a packet does not contain FROM_INCLUDED, and there was no previous SYNCHRONIZE packet
|
|
||||||
(for example a stray CLOSE or RESET packet), the inference can be made from the length of the remaining options
|
|
||||||
(since SIGNATURE_INCLUDED is the last option), but the packet will probably be discarded anyway, since there is no FROM available
|
|
||||||
to validate the signature.
|
|
||||||
If more option fields are defined in the future, they must be accounted for.
|
|
||||||
</li></ul>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -1,347 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}Tunnel Creation{% endblock %}
|
|
||||||
{% block lastupdated %}September 2014{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.15{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
This page documents the current tunnel build implementation.
|
|
||||||
|
|
||||||
<h2 id="tunnelCreate.overview">Tunnel Creation Specification</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This document specifies the details of the encrypted tunnel build messages
|
|
||||||
used to create tunnels using a "non-interactive telescoping" method.
|
|
||||||
See <a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel build document</a>
|
|
||||||
for an overview of the process, including peer selection and ordering methods.
|
|
||||||
|
|
||||||
<p>The tunnel creation is accomplished by a single message passed along
|
|
||||||
the path of peers in the tunnel, rewritten in place, and transmitted
|
|
||||||
back to the tunnel creator. This single tunnel message is made up
|
|
||||||
of a variable number of records (up to 8) - one for each potential peer in
|
|
||||||
the tunnel. Individual records are asymmetrically
|
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">(ElGamal)</a>
|
|
||||||
encrypted to be
|
|
||||||
read only by a specific peer along the path, while an additional
|
|
||||||
symmetric layer of encryption
|
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#AES">(AES)</a>
|
|
||||||
is added at each hop so as to expose
|
|
||||||
the asymmetrically encrypted record only at the appropriate time.</p>
|
|
||||||
|
|
||||||
<h3 id="number">Number of Records</h3>
|
|
||||||
Not all records must contain valid data.
|
|
||||||
The build message for a 3-hop tunnel, for example, may contain more records
|
|
||||||
to hide the actual length of the tunnel from the participants.
|
|
||||||
There are two build message types. The original
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#msg_TunnelBuild">Tunnel Build Message</a> (TBM)
|
|
||||||
contains 8 records, which is more than enough for any practical tunnel length.
|
|
||||||
The newer
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#msg_VariableTunnelBuild">Variable Tunnel Build Message</a> (VTBM)
|
|
||||||
contains 1 to 8 records. The originator may trade off the size of the message
|
|
||||||
with the desired amount of tunnel length obfuscation.
|
|
||||||
<p>
|
|
||||||
In the current network, most tunnels are 2 or 3 hops long.
|
|
||||||
The current implementation uses a 5-record VTBM to build tunnels of 4 hops or less,
|
|
||||||
and the 8-record TBM for longer tunnels.
|
|
||||||
The 5-record VTBM (which, when fragmented, fits in three 1KB tunnel messaages) reduces network traffic
|
|
||||||
and increases build sucess rate, because smaller messages are less likely to be dropped.
|
|
||||||
<p>
|
|
||||||
The reply message must be the same type and length as the build message.
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.requestRecord">Request Record Specification</h3>
|
|
||||||
|
|
||||||
Also specified in the
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#struct_BuildRequestRecord">I2NP Specification</a>
|
|
||||||
|
|
||||||
<p>Cleartext of the record, visible only to the hop being asked:</p><pre>
|
|
||||||
bytes 0-3: tunnel ID to receive messages as
|
|
||||||
bytes 4-35: local router identity hash
|
|
||||||
bytes 36-39: next tunnel ID
|
|
||||||
bytes 40-71: next router identity hash
|
|
||||||
bytes 72-103: AES-256 tunnel layer key
|
|
||||||
bytes 104-135: AES-256 tunnel IV key
|
|
||||||
bytes 136-167: AES-256 reply key
|
|
||||||
bytes 168-183: AES-256 reply IV
|
|
||||||
byte 184: flags
|
|
||||||
bytes 185-188: request time (in hours since the epoch, rounded down)
|
|
||||||
bytes 189-192: next message ID
|
|
||||||
bytes 193-221: uninterpreted / random padding</pre>
|
|
||||||
|
|
||||||
<p>The next tunnel ID and next router identity hash fields are used to
|
|
||||||
specify the next hop in the tunnel, though for an outbound tunnel
|
|
||||||
endpoint, they specify where the rewritten tunnel creation reply
|
|
||||||
message should be sent. In addition, the next message ID specifies the
|
|
||||||
message ID that the message (or reply) should use.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The tunnel layer key, tunnel IV key, reply key, and reply IV
|
|
||||||
are each random 32-byte values generated by the creator,
|
|
||||||
for use in this build request record only.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The flags field contains the following:
|
|
||||||
<pre>
|
|
||||||
Bit order: 76543210 (bit 7 is MSB)
|
|
||||||
bit 7: if set, allow messages from anyone
|
|
||||||
bit 6: if set, allow messages to anyone, and send the reply to the
|
|
||||||
specified next hop in a Tunnel Build Reply Message
|
|
||||||
bits 5-0: Undefined, must set to 0 for compatibility with future options
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Bit 7 indicates that the hop will be an inbound gateway (IBGW).
|
|
||||||
Bit 6 indicates that the hop will be an outbound endpoint (OBEP).
|
|
||||||
If neither bit is set, the hop will be an intermediate participant.
|
|
||||||
Both cannot be set at once.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Request Record Creation</h4>
|
|
||||||
<p>
|
|
||||||
Every hop gets a random Tunnel ID.
|
|
||||||
The current and next-hop Tunnel IDs are filled in.
|
|
||||||
Every record gets a random tunnel IV key, reply IV, layer key, and reply key.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h4 id="encryption">Request Record Encryption</h4>
|
|
||||||
|
|
||||||
<p>That cleartext record is <a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal 2048 encrypted</a> with the hop's
|
|
||||||
public encryption key and formatted into a 528 byte record:</p><pre>
|
|
||||||
bytes 0-15: First 16 bytes of the SHA-256 of the current hop's router identity
|
|
||||||
bytes 16-527: ElGamal-2048 encrypted request record</pre>
|
|
||||||
<p>
|
|
||||||
In the 512-byte encrypted record,
|
|
||||||
the ElGamal data contains bytes 1-256 and 258-513 of the
|
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">514-byte ElGamal encrypted block</a>.
|
|
||||||
The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed.
|
|
||||||
</p>
|
|
||||||
<p>Since the cleartext uses the full field, there is no need for
|
|
||||||
additional padding beyond <code>SHA256(cleartext) + cleartext</code>.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Each 528-byte record is then iteratively encrypted
|
|
||||||
(using AES decryption, with the reply key and reply IV for each hop) so that the router identity will only be in cleartext
|
|
||||||
for the hop in question.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.hopProcessing">Hop Processing and Encryption</h3>
|
|
||||||
|
|
||||||
<p>When a hop receives a TunnelBuildMessage, it looks through the
|
|
||||||
records contained within it for one starting with their own identity
|
|
||||||
hash (trimmed to 16 bytes). It then decrypts the ElGamal block from
|
|
||||||
that record and retrieves the protected cleartext. At that point,
|
|
||||||
they make sure the tunnel request is not a duplicate by feeding the
|
|
||||||
AES-256 reply key into a bloom filter.
|
|
||||||
Duplicates or invalid requests
|
|
||||||
are dropped.</p>
|
|
||||||
|
|
||||||
<p>After deciding whether they will agree to participate in the tunnel
|
|
||||||
or not, they replace the record that had contained the request with
|
|
||||||
an encrypted reply block. All other records are <a href="{{ site_url('docs/how/cryptography') }}#AES">AES-256
|
|
||||||
encrypted</a> with the included reply key and IV. Each is
|
|
||||||
AES/CBC encrypted separately with the same reply key and reply IV.
|
|
||||||
The CBC mode is not continued (chained) across records.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Each hop knows only its own response.
|
|
||||||
If it agrees, it will maintain the tunnel until expiration,
|
|
||||||
even if it will not be used,
|
|
||||||
as it cannot know whether all other hops agreed.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h4 id="tunnelCreate.replyRecord">Reply Record Specification</h4>
|
|
||||||
|
|
||||||
<p>After the current hop reads their record, they replace it with a
|
|
||||||
reply record stating whether or not they agree to participate in the
|
|
||||||
tunnel, and if they do not, they classify their reason for
|
|
||||||
rejection. This is simply a 1 byte value, with 0x0 meaning they
|
|
||||||
agree to participate in the tunnel, and higher values meaning higher
|
|
||||||
levels of rejection.
|
|
||||||
<p>
|
|
||||||
The following rejection codes are defined:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
TUNNEL_REJECT_PROBABALISTIC_REJECT = 10
|
|
||||||
<li>
|
|
||||||
TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20
|
|
||||||
<li>
|
|
||||||
TUNNEL_REJECT_BANDWIDTH = 30
|
|
||||||
<li>
|
|
||||||
TUNNEL_REJECT_CRIT = 50
|
|
||||||
</ul>
|
|
||||||
To hide other causes, such as router shutdown, from peers, the current implementation
|
|
||||||
uses TUNNEL_REJECT_BANDWIDTH for almost all rejections.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The reply is encrypted with the AES session
|
|
||||||
key delivered to it in the encrypted block, padded with 495 bytes of random data
|
|
||||||
to reach the full record size.
|
|
||||||
The padding is placed before the status byte:
|
|
||||||
</p><pre>
|
|
||||||
AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)
|
|
||||||
|
|
||||||
bytes 0-31 : SHA-256 of bytes 32-527
|
|
||||||
bytes 32-526 : Random padding
|
|
||||||
byte 527 : Reply value
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
This is also described in the
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#struct_BuildResponseRecord">I2NP spec</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.requestPreparation">Tunnel Build Message Preparation</h3>
|
|
||||||
|
|
||||||
<p>When building a new Tunnel Build Message, all of the Build Request Records must first be
|
|
||||||
built and asymmetrically encrypted using
|
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal</a>.
|
|
||||||
Each record is then
|
|
||||||
premptively decrypted with the reply keys and IVs of the hops earlier in the
|
|
||||||
path, using
|
|
||||||
<a href="{{ site_url('docs/how/cryptography') }}#AES">AES</a>.
|
|
||||||
That decryption should be run in reverse order so that the
|
|
||||||
asymmetrically encrypted data will show up in the clear at the
|
|
||||||
right hop after their predecessor encrypts it.</p>
|
|
||||||
|
|
||||||
<p>The excess records not needed for individual requests are simply
|
|
||||||
filled with random data by the creator.</p>
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.requestDelivery">Tunnel Build Message Delivery</h3>
|
|
||||||
|
|
||||||
<p>For outbound tunnels, the delivery is done directly from the tunnel
|
|
||||||
creator to the first hop, packaging up the TunnelBuildMessage as if
|
|
||||||
the creator was just another hop in the tunnel. For inbound
|
|
||||||
tunnels, the delivery is done through an existing outbound tunnel.
|
|
||||||
The outbound tunnel is generally from the same pool as the new tunnel being built.
|
|
||||||
If no outbound tunnel is available in that pool, an outbound exploratory tunnel is used.
|
|
||||||
At startup, when no outbound exploratory tunnel exists yet, a fake 0-hop
|
|
||||||
outbound tunnel is used.</p>
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.endpointHandling">Tunnel Build Message Endpoint Handling</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For creation of an outbound tunnel,
|
|
||||||
when the request reaches an outbound endpoint (as determined by the
|
|
||||||
'allow messages to anyone' flag), the hop is processed as usual,
|
|
||||||
encrypting a reply in place of the record and encrypting all of the
|
|
||||||
other records, but since there is no 'next hop' to forward the
|
|
||||||
TunnelBuildMessage on to, it instead places the encrypted reply
|
|
||||||
records into a
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#msg_TunnelBuildReply">TunnelBuildReplyMessage</a>
|
|
||||||
or
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#msg_VariableTunnelBuildReply">VariableTunnelBuildReplyMessage</a>
|
|
||||||
(the type of message and number of records must match that of the request)
|
|
||||||
and delivers it to the
|
|
||||||
reply tunnel specified within the request record. That reply tunnel
|
|
||||||
forwards the Tunnel Build Reply Message back to the tunnel creator,
|
|
||||||
<a href="{{ site_url('docs/tunnels/implementation') }}#tunnel.operation">just as for any other message</a>.
|
|
||||||
The tunnel creator then
|
|
||||||
processes it, as described below.</p>
|
|
||||||
|
|
||||||
<p>The reply tunnel was selected by the creator as follows:
|
|
||||||
Generally it is an inbound tunnel from the same pool as the new outbound tunnel being built.
|
|
||||||
If no inbound tunnel is available in that pool, an inbound exploratory tunnel is used.
|
|
||||||
At startup, when no inbound exploratory tunnel exists yet, a fake 0-hop
|
|
||||||
inbound tunnel is used.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For creation of an inbound tunnel,
|
|
||||||
when the request reaches the inbound endpoint (also known as the
|
|
||||||
tunnel creator), there is no need to generate an explicit Tunnel Build Reply Message, and
|
|
||||||
the router processes each of the replies, as below.</p>
|
|
||||||
|
|
||||||
<h3 id="tunnelCreate.replyProcessing">Tunnel Build Reply Message Processing</h3>
|
|
||||||
|
|
||||||
<p>To process the reply records, the creator simply has to AES decrypt
|
|
||||||
each record individually, using the reply key and IV of each hop in
|
|
||||||
the tunnel after the peer (in reverse order). This then exposes the
|
|
||||||
reply specifying whether they agree to participate in the tunnel or
|
|
||||||
why they refuse. If they all agree, the tunnel is considered
|
|
||||||
created and may be used immediately, but if anyone refuses, the
|
|
||||||
tunnel is discarded.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The agreements and rejections are noted in each peer's
|
|
||||||
<a href="{{ site_url('docs/how/peer-selection') }}">profile</a>, to be used in future assessments
|
|
||||||
of peer tunnel capacity.
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="tunnelCreate.notes">History and Notes</h2>
|
|
||||||
<p>
|
|
||||||
This strategy came about during a discussion on the I2P mailing list
|
|
||||||
between Michael Rogers, Matthew Toseland (toad), and jrandom regarding
|
|
||||||
the predecessor attack. See: <ul>
|
|
||||||
<li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00138.html">Summary</a></li>
|
|
||||||
<li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00129.html">Reasoning</a></li>
|
|
||||||
</ul></li>
|
|
||||||
It was introduced in release 0.6.1.10 on 2006-02-16, which was the last time
|
|
||||||
a non-backward-compatible change was made in I2P.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Notes:
|
|
||||||
<ul>
|
|
||||||
<li>This design does not prevent two hostile peers within a tunnel from
|
|
||||||
tagging one or more request or reply records to detect that they are
|
|
||||||
within the same tunnel, but doing so can be detected by the tunnel
|
|
||||||
creator when reading the reply, causing the tunnel to be marked as
|
|
||||||
invalid.</li>
|
|
||||||
<li>This design does not include a proof of work on the asymmetrically
|
|
||||||
encrypted section, though the 16 byte identity hash could be cut in
|
|
||||||
half with the latter replaced by a hashcash function of up to 2^64
|
|
||||||
cost.</li>
|
|
||||||
<li>This design alone does not prevent two hostile peers within a tunnel from
|
|
||||||
using timing information to determine whether they are in the same
|
|
||||||
tunnel. The use of batched and synchronized request delivery
|
|
||||||
could help (batching up requests and sending them off on the
|
|
||||||
(ntp-synchronized) minute). However, doing so lets peers 'tag' the
|
|
||||||
requests by delaying them and detecting the delay later in the
|
|
||||||
tunnel, though perhaps dropping requests not delivered in a small
|
|
||||||
window would work (though doing that would require a high degree of
|
|
||||||
clock synchronization). Alternately, perhaps individual hops could
|
|
||||||
inject a random delay before forwarding on the request?</li>
|
|
||||||
<li>Are there any nonfatal methods of tagging the request?</li>
|
|
||||||
<li>
|
|
||||||
The timestamp with a one-hour resolution is used for replay prevention.
|
|
||||||
The constraint was not enforced until release 0.9.16.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="ref">References</h2>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="http://forensics.umass.edu/pubs/wright-tissec.pdf">Predecessor
|
|
||||||
attack</a>
|
|
||||||
<li>
|
|
||||||
<a href="http://forensics.umass.edu/pubs/wright.tissec.2008.pdf">2008
|
|
||||||
update</a>
|
|
||||||
<li>
|
|
||||||
<a href="http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf">Hashing it out in Public</a>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="future">Future Work</h2>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
In the current implementation, the originator leaves one record empty
|
|
||||||
for itself. Thus a message of n records can only build a
|
|
||||||
tunnel of n-1 hops.
|
|
||||||
This appears to be necessary for inbound tunnels (where the next-to-last hop
|
|
||||||
can see the hash prefix for the next hop), but not for outbound tunnels.
|
|
||||||
This is to be researched and verified.
|
|
||||||
If it is possible to use the remaining record without compromising anonymity,
|
|
||||||
we should do so.
|
|
||||||
<li>
|
|
||||||
Further analysis of possible tagging and timing attacks described in the above notes.
|
|
||||||
</li><li>
|
|
||||||
The Bloom filter rotation time should be evaluated.
|
|
||||||
</li><li>
|
|
||||||
Use only VTBM; do not select old peers that don't support it.
|
|
||||||
</li><li>
|
|
||||||
The Build Request Record does not specify a tunnel lifetime or expiration;
|
|
||||||
each hop expires the tunnel after 10 minutes, which is a network-wide hardcoded constant.
|
|
||||||
We could use a bit in the flag field
|
|
||||||
and take 4 (or 8) bytes out of the padding to specify a lifetime or expiration.
|
|
||||||
The requestor would only specify this option if all participants supported it.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -1,318 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}Tunnel Message Specification{% endblock %}
|
|
||||||
{% block lastupdated %}February 2014{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.11{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<p>
|
|
||||||
This document specifies the format of tunnel messages.
|
|
||||||
For general information about tunnels see
|
|
||||||
<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2>Message preprocessing</h2>
|
|
||||||
|
|
||||||
|
|
||||||
A <i>tunnel gateway</i> is the entrance, or first hop, of a tunnel.
|
|
||||||
For an outbound tunnel, the gateway is the creator of the tunnel.
|
|
||||||
For an inbound tunnel, the gateway is at the opposite end from the creator of the tunnel.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
A gateway <i>preprocesses</i> <a href="{{ site_url('docs/protocol/i2np') }}">I2NP messages</a>
|
|
||||||
by fragmenting and combining them into tunnel messages.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
While I2NP messages are variable size from 0 to almost 64 KB,
|
|
||||||
tunnel messages are fixed-size, approximately 1 KB.
|
|
||||||
Fixed message size
|
|
||||||
restricts several types of attacks that are possible from
|
|
||||||
observing message size.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
After the tunnel messages are created, they are encrypted as described in
|
|
||||||
<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>.
|
|
||||||
|
|
||||||
<h2 id="msg_Tunnel">Tunnel Message (Encrypted)</h2>
|
|
||||||
These are the contents of a tunnel data message after encryption.
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| Tunnel ID | IV |
|
|
||||||
+----+----+----+----+ +
|
|
||||||
| |
|
|
||||||
+ +----+----+----+----+
|
|
||||||
| | |
|
|
||||||
+----+----+----+----+ +
|
|
||||||
| |
|
|
||||||
+ Encrypted Data +
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+ +-------------------+
|
|
||||||
| |
|
|
||||||
+----+----+----+----+
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>Definition</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
Tunnel ID :: `TunnelId`
|
|
||||||
4 bytes
|
|
||||||
the ID of the next hop
|
|
||||||
|
|
||||||
IV ::
|
|
||||||
16 bytes
|
|
||||||
the initialization vector
|
|
||||||
|
|
||||||
Encrypted Data ::
|
|
||||||
1008 bytes
|
|
||||||
the encrypted tunnel message
|
|
||||||
|
|
||||||
total size: 1028 Bytes
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Tunnel Message (Decrypted)</h2>
|
|
||||||
These are the contents of a tunnel data message when decrypted.
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| Tunnel ID | IV |
|
|
||||||
+----+----+----+----+ +
|
|
||||||
| |
|
|
||||||
+ +----+----+----+----+
|
|
||||||
| | Checksum |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| nonzero padding... |
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+ +----+
|
|
||||||
| |zero|
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| |
|
|
||||||
| Delivery Instructions 1 |
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| |
|
|
||||||
+ I2NP Message Fragment 1 +
|
|
||||||
| |
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| |
|
|
||||||
| Delivery Instructions 2... |
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| |
|
|
||||||
+ I2NP Message Fragment 2... +
|
|
||||||
| |
|
|
||||||
~ ~
|
|
||||||
| |
|
|
||||||
+ +-------------------+
|
|
||||||
| |
|
|
||||||
+----+----+----+----+
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>Definition</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
Tunnel ID :: `TunnelId`
|
|
||||||
4 bytes
|
|
||||||
the ID of the next hop
|
|
||||||
|
|
||||||
IV ::
|
|
||||||
16 bytes
|
|
||||||
the initialization vector
|
|
||||||
|
|
||||||
Checksum ::
|
|
||||||
4 bytes
|
|
||||||
the first 4 bytes of the SHA256 hash of (the contents of the message (after the zero byte) + IV)
|
|
||||||
|
|
||||||
Nonzero padding ::
|
|
||||||
0 or more bytes
|
|
||||||
random nonzero data for padding
|
|
||||||
|
|
||||||
Zero ::
|
|
||||||
1 byte
|
|
||||||
the value 0x00
|
|
||||||
|
|
||||||
Delivery Instructions :: `TunnelMessageDeliveryInstructions`
|
|
||||||
length varies but is typically 7, 39, 43, or 47 bytes
|
|
||||||
Indicates the fragment and the routing for the fragment
|
|
||||||
|
|
||||||
Message Fragment ::
|
|
||||||
1 to 996 bytes, actual maximum depends on delivery instruction size
|
|
||||||
A partial or full I2NP Message
|
|
||||||
|
|
||||||
total size: 1028 Bytes
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>Notes</h4>
|
|
||||||
<ul><li>
|
|
||||||
The padding, if any, must be before the instruction/message pairs.
|
|
||||||
There is no provision for padding at the end.
|
|
||||||
</li><li>
|
|
||||||
The checksum does NOT cover the padding or the zero byte.
|
|
||||||
Take the message starting at the first delivery instructions, concatenate the IV,
|
|
||||||
and take the Hash of that.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="struct_TunnelMessageDeliveryInstructions">Tunnel Message Delivery Instructions</h2>
|
|
||||||
|
|
||||||
<p>The instructions are encoded with a single control byte, followed by any
|
|
||||||
necessary additional information. The first bit (MSB) in that control byte determines
|
|
||||||
how the remainder of the header is interpreted - if it is not set, the message
|
|
||||||
is either not fragmented or this is the first fragment in the message. If it is
|
|
||||||
set, this is a follow on fragment.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This specification is for Delivery Instructions inside Tunnel Messages only.
|
|
||||||
Note that "Delivery Instructions" are also used inside
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicClove">Garlic Cloves</a>,
|
|
||||||
where the format is significantly different.
|
|
||||||
See the
|
|
||||||
<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicCloveDeliveryInstructions">I2NP documentation</a>
|
|
||||||
for details.
|
|
||||||
Do NOT use the following specification for Garlic Clove Delivery Instructions!
|
|
||||||
|
|
||||||
|
|
||||||
<h3>First Fragment Delivery Instructions</h3>
|
|
||||||
<p>If the MSB of the first byte is 0, this is an initial I2NP message fragment,
|
|
||||||
or a complete (unfragmented) I2NP message, and the instructions are:</p>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
|flag| Tunnel ID (opt) | |
|
|
||||||
+----+----+----+----+----+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| To Hash (optional) |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +--------------+
|
|
||||||
| |dly | Message
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
ID (opt) |extended opts (opt)| size |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>Definition</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
flag ::
|
|
||||||
1 byte
|
|
||||||
Bit order: 76543210
|
|
||||||
bit 7: 0 to specify an initial fragment or an unfragmented message
|
|
||||||
bits 6-5: delivery type
|
|
||||||
0x0 = LOCAL, 0x01 = TUNNEL, 0x02 = ROUTER, 0x03 = unused, invalid
|
|
||||||
Note: LOCAL is used for inbound tunnels only, unimplemented for outbound tunnels
|
|
||||||
bit 4: delay included? Unimplemented, always 0
|
|
||||||
If 1, a delay byte is included
|
|
||||||
bit 3: fragmented? If 0, the message is not fragmented, what follows is the entire message
|
|
||||||
If 1, the message is fragmented, and the instructions contain a Message ID
|
|
||||||
bit 2: extended options? Unimplemented, always 0
|
|
||||||
If 1, extended options are included
|
|
||||||
bits 1-0: reserved, set to 0 for compatibility with future uses
|
|
||||||
|
|
||||||
Tunnel ID :: `TunnelId`
|
|
||||||
4 bytes
|
|
||||||
Optional, present if delivery type is TUNNEL
|
|
||||||
The destination tunnel ID
|
|
||||||
|
|
||||||
To Hash ::
|
|
||||||
32 bytes
|
|
||||||
Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
|
|
||||||
If DESTINATION, the SHA256 Hash of the destination
|
|
||||||
If ROUTER, the SHA256 Hash of the router
|
|
||||||
If TUNNEL, the SHA256 Hash of the gateway router
|
|
||||||
|
|
||||||
Delay ::
|
|
||||||
1 byte
|
|
||||||
Optional, present if delay included flag is set
|
|
||||||
In tunnel messages: Unimplemented, never present; original specification:
|
|
||||||
bit 7: type (0 = strict, 1 = randomized)
|
|
||||||
bits 6-0: delay exponent (2^value minutes)
|
|
||||||
|
|
||||||
Message ID ::
|
|
||||||
4 bytes
|
|
||||||
Optional, present if this message is the first of 2 or more fragments
|
|
||||||
(i.e. if the fragmented bit is 1)
|
|
||||||
An ID that uniquely identifies all fragments as belonging to a single message
|
|
||||||
(the current implementation uses `I2NPMessageHeader.msg_id`)
|
|
||||||
|
|
||||||
Extended Options ::
|
|
||||||
2 or more bytes
|
|
||||||
Optional, present if extend options flag is set
|
|
||||||
Unimplemented, never present; original specification:
|
|
||||||
One byte length and then that many bytes
|
|
||||||
|
|
||||||
size ::
|
|
||||||
2 bytes
|
|
||||||
The length of the fragment that follows
|
|
||||||
Valid values: 1 to approx. 960 in a tunnel message
|
|
||||||
|
|
||||||
Total length: Typical length is:
|
|
||||||
3 bytes for LOCAL delivery (tunnel message);
|
|
||||||
35 bytes for ROUTER / DESTINATION delivery or 39 bytes for TUNNEL delivery (unfragmented tunnel message);
|
|
||||||
39 bytes for ROUTER delivery or 43 bytes for TUNNEL delivery (first fragment)
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h3>Follow-on Fragment Delivery Instructions</h3>
|
|
||||||
<p>If the MSB of the first byte is 1, this is a follow-on fragment, and the instructions are:</p>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+
|
|
||||||
|frag| Message ID | size |
|
|
||||||
+----+----+----+----+----+----+----+
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h4>Definition</h4>
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
frag ::
|
|
||||||
1 byte
|
|
||||||
Bit order: 76543210
|
|
||||||
binary 1nnnnnnd
|
|
||||||
bit 7: 1 to indicate this is a follow-on fragment
|
|
||||||
bits 6-1: nnnnnn is the 6 bit fragment number from 1 to 63
|
|
||||||
bit 0: d is 1 to indicate the last fragment, 0 otherwise
|
|
||||||
|
|
||||||
Message ID ::
|
|
||||||
4 bytes
|
|
||||||
Identifies the fragment sequence that this fragment belongs to.
|
|
||||||
This will match the message ID of an initial fragment (a fragment
|
|
||||||
with flag bit 7 set to 0 and flag bit 3 set to 1).
|
|
||||||
|
|
||||||
size ::
|
|
||||||
2 bytes
|
|
||||||
the length of the fragment that follows
|
|
||||||
valid values: 1 to 996
|
|
||||||
|
|
||||||
total length: 7 bytes
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
<h3><a href="http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/DeliveryInstructions.html">Delivery Instructions Javadoc</a></h3>
|
|
||||||
|
|
||||||
<h2 id="notes">Notes</h2>
|
|
||||||
<h3>I2NP Message Maximum Size</h3>
|
|
||||||
<p>
|
|
||||||
While the maximum I2NP message size is nominally 64 KB, the size is further constrained by the
|
|
||||||
method of fragmenting I2NP messages into multiple 1 KB tunnel messages.
|
|
||||||
The maximum number of fragments is 64, and the initial fragment may not
|
|
||||||
be perfectly aligned at the start of a tunnel message.
|
|
||||||
So the message must nominally fit in 63 fragments.
|
|
||||||
<p>
|
|
||||||
The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery mode);
|
|
||||||
the maximum size of a follow-on fragment is 996 bytes.
|
|
||||||
Therefore the maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Ordering, Batching, Packing</h3>
|
|
||||||
Tunnel messages may be dropped or reordered.
|
|
||||||
The tunnel gateway, who creates tunnel messages, is free to implement any
|
|
||||||
batching, mixing, or reordering strategy to fragment I2NP messages and
|
|
||||||
efficiently pack fragments into tunnel messages.
|
|
||||||
In general, an optimal packing is not possible (the "packing problem").
|
|
||||||
The gateways may implement various delay and reordering strategies.
|
|
||||||
|
|
||||||
<h3>Cover Traffic</h3>
|
|
||||||
Tunnel messages may contain only padding (i.e. no delivery instructions or message fragments at all)
|
|
||||||
for cover traffic. This is unimplemented.
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -1,572 +0,0 @@
|
|||||||
{% extends "global/layout.html" %}
|
|
||||||
{% block title %}{% trans %}I2P Software Update Specification{% endtrans %}{% endblock %}
|
|
||||||
{% block lastupdated %}{% trans %}May 2015{% endtrans %}{% endblock %}
|
|
||||||
{% block accuratefor %}0.9.20{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h3>{% trans %}Overview{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
I2P uses a simple, yet secure, system for automated software update.
|
|
||||||
The router console periodically pulls a news file from a configurable I2P URL.
|
|
||||||
There is a hardcoded backup URL pointing to the project website, in case
|
|
||||||
the default project news host goes down.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The contents of the news file are displayed on the home page of the router console.
|
|
||||||
In addition, the news file contains the most recent version number of the software.
|
|
||||||
If the version is higher than the router's version number, it will
|
|
||||||
display an indication to the user that an update is available.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The router may optionally download, or download and install, the new version
|
|
||||||
if configured to do so.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Old News File Specification{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This format is replaced by the su3 news format as of release 0.9.17.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The news.xml file may contain the following elements:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<pre>
|
|
||||||
<i2p.news date="$Date: 2010-01-22 00:00:00 $" />
|
|
||||||
<i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" />
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
Parameters in the i2p.release entry are as follows.
|
|
||||||
All keys are case-insensitive. All values must be enclosed in double quotes.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
date: The release date of the router version. Unused. Format not specified.
|
|
||||||
</li><li>
|
|
||||||
minJavaVersion: The minimum version of Java required to run the current version.
|
|
||||||
As of release 0.9.9.
|
|
||||||
</li><li>
|
|
||||||
minVersion: The minimum version of the router required to update to the current version.
|
|
||||||
If a router is older than this, the user must (manually?) update to an intermediate version first.
|
|
||||||
As of release 0.9.9.
|
|
||||||
</li><li>
|
|
||||||
su3Clearnet: One or more HTTP URLs where the .su3 update file may
|
|
||||||
be found on the clearnet (non-I2P).
|
|
||||||
Multiple URLs must be separated by a space or comma.
|
|
||||||
As of release 0.9.9.
|
|
||||||
</li><li>
|
|
||||||
su3SSL: One or more HTTPS URLs where the .su3 update file may
|
|
||||||
be found on the clearnet (non-I2P).
|
|
||||||
Multiple URLs must be separated by a space or comma.
|
|
||||||
As of release 0.9.9.
|
|
||||||
</li><li>
|
|
||||||
sudTorrent: The magnet link for the .sud (non-pack200) torrent of the update.
|
|
||||||
As of release 0.9.4.
|
|
||||||
</li><li>
|
|
||||||
su2Torrent: The magnet link for the .su2 (pack200) torrent of the update.
|
|
||||||
As of release 0.9.4.
|
|
||||||
</li><li>
|
|
||||||
su3Torrent: The magnet link for the .su3 (new format) torrent of the update.
|
|
||||||
As of release 0.9.9.
|
|
||||||
</li><li>
|
|
||||||
version: Required. The latest current router version available.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The elements may be included inside XML comments to prevent interpretation by browsers.
|
|
||||||
The i2p.release element and version are required. All others are optional.
|
|
||||||
NOTE: Due to parser limitations an entire element must be on a single line.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}Update File Specification{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of release 0.9.9, the signed update file, named i2pupdate.su3, will
|
|
||||||
use the "su3" file format specified below.
|
|
||||||
Approved release signers will use 4096-bit RSA keys.
|
|
||||||
The X.509 public key certificates for these signers are distributed in the router installation packages.
|
|
||||||
The updates may contain certificates for new, approved signers, and/or contain
|
|
||||||
a list of certificates to delete for revocation.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}Old Update File Specification{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
This format is obsolete as of release 0.9.9.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The signed update file, traditionally named i2pupdate.sud,
|
|
||||||
is simply a zip file with a prepended 56 byte header.
|
|
||||||
The header contains:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
|
|
||||||
A 40-byte <a href="{{ commonstructures }}#type_signature">DSA signature</a>
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
|
|
||||||
The signature covers only the zip archive - not the prepended version.
|
|
||||||
The signature must match one of the <a href="{{ commonstructures }}#type_SigningPublicKey">DSA public keys</a> configured into the router,
|
|
||||||
which has a hardcoded default list of keys of the current project release managers.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
For version comparison purposes, version fields contain [0-9]*, field separators are
|
|
||||||
'-', '_', and '.', and all other characters are ignored.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of version 0.8.8, the version must also be specified as a zip file comment in UTF-8,
|
|
||||||
without the trailing zeroes.
|
|
||||||
The updating router verifes that the version in the header (not covered by the signature)
|
|
||||||
matches the version in the zip file comment, which is covered by the signature.
|
|
||||||
This prevents spoofing of the version number in the header.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h3>{% trans %}Download and Installation{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
The router first downloads the header of the update file from one in a configurable list of I2P URLs,
|
|
||||||
using the built-in HTTP client and proxy,
|
|
||||||
and checks that the version is newer.
|
|
||||||
This prevents the problem of update hosts that do not have the latest file.
|
|
||||||
The router then downloads the full update file.
|
|
||||||
The router verifies that the update file version is newer before installation.
|
|
||||||
It also, of course, verifies the signature, and
|
|
||||||
verifes that the zip file comment matches the header version, as explained above.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The zip file is extracted and copied to "i2pupdate.zip" in the I2P configuration directory (~/.i2p on Linux).
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of release 0.7.12, the router supports Pack200 decompression.
|
|
||||||
Files inside the zip archive with a .jar.pack or .war.pack suffix
|
|
||||||
are transparently decompressed to a .jar or .war file.
|
|
||||||
Update files containing .pack files are traditionally named with a '.su2' suffix.
|
|
||||||
Pack200 shrinks the update files by about 60%.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of release 0.8.7, the router will delete the libjbigi.so and libjcpuid.so files
|
|
||||||
if the zip archive contains a lib/jbigi.jar file, so that the new files will
|
|
||||||
be extracted from jbigi.jar.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of release 0.8.12, if the zip archive contains a file deletelist.txt, the router will
|
|
||||||
delete the files listed there. The format is:
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans %}One file name per line{% endtrans %}</li>
|
|
||||||
<li>{% trans %}All file names are relative to the installation directory; no absolute file names allowed, no files starting with ".."{% endtrans %}</li>
|
|
||||||
<li>{% trans %}Comments start with '#'{% endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
The router will then delete the deletelist.txt file.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="su3">{% trans %}SU3 File Specification{% endtrans %}</h3>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
This specification is used for router updates as of release 0.9.9, reseed data as of release 0.9.14,
|
|
||||||
plugins as of release 0.9.15, and the news file as of release 0.9.17.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h4>{% trans %}Issues with the previous .sud/.su2 format:{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans -%}
|
|
||||||
No magic number or flags
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
No way to specify compression, pack200 or not, or signing algo
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Version is not covered by signature, so it is enforced by requiring it
|
|
||||||
to be in the zip file comment (for router files) or in the plugin.config
|
|
||||||
file (for plugins)
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Signer not specified so verifier must try all known keys
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Signature-before-data format requires two passes to generate file
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h4>{% trans %}Goals:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Fix above problems
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Migrate to more secure signature algorithm
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Keep version info in same format and offset for compatibility with
|
|
||||||
existing version checkers
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
One-pass signature verification and file extraction
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>{% trans %}Specification:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<table><tr>
|
|
||||||
<th>Bytes<th>Contents
|
|
||||||
<tr><td>
|
|
||||||
0-5 <td>Magic number "I2Psu3"
|
|
||||||
<tr><td>
|
|
||||||
6 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
7 <td>su3 file format version = 0
|
|
||||||
<tr><td>
|
|
||||||
8-9 <td>Signature type
|
|
||||||
<ul><li>0x0000 = DSA-SHA1
|
|
||||||
</li><li>0x0001 = ECDSA-SHA256-P256
|
|
||||||
</li><li>0x0002 = ECDSA-SHA384-P384
|
|
||||||
</li><li>0x0003 = ECDSA-SHA512-P521
|
|
||||||
</li><li>0x0004 = RSA-SHA256-2048
|
|
||||||
</li><li>0x0005 = RSA-SHA384-3072
|
|
||||||
</li><li>0x0006 = RSA-SHA512-4096
|
|
||||||
</li></ul>
|
|
||||||
<tr><td>
|
|
||||||
10-11 <td>Signature length, e.g. 40 (0x0028) for DSA-SHA1.
|
|
||||||
Must match that specified for the signature type on the
|
|
||||||
<a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">common structures page</a>.
|
|
||||||
<tr><td>
|
|
||||||
12 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
13 <td>Version length (in bytes not chars, including padding)
|
|
||||||
must be at least 16 (0x10) for compatibility
|
|
||||||
<tr><td>
|
|
||||||
14 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
15 <td>Signer ID length (in bytes not chars)
|
|
||||||
<tr><td>
|
|
||||||
16-23 <td>Content length (not including header or sig)
|
|
||||||
<tr><td>
|
|
||||||
24 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
25 <td>File type
|
|
||||||
<ul><li>0x00 = zip file
|
|
||||||
</li><li>0x01 = xml file (as of 0.9.15)
|
|
||||||
</li><li>0x02 = html file (as of 0.9.17)
|
|
||||||
</li><li>0x03 = xml.gz file (as of 0.9.17)
|
|
||||||
</li></ul>
|
|
||||||
<tr><td>
|
|
||||||
26 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
27 <td>Content type
|
|
||||||
<ul><li>0x00 = unknown
|
|
||||||
</li><li>0x01 = router update
|
|
||||||
</li><li>0x02 = plugin or plugin update
|
|
||||||
</li><li>0x03 = reseed data
|
|
||||||
</li><li>0x04 = news feed (as of 0.9.15)
|
|
||||||
</li></ul>
|
|
||||||
<tr><td>
|
|
||||||
28-39 <td>unused = 0
|
|
||||||
<tr><td>
|
|
||||||
40-55+ <td>Version, UTF-8 padded with trailing 0x00, 16 bytes minimum, length specified at byte 13.
|
|
||||||
Do not append 0x00 bytes if the length is 16 or more.
|
|
||||||
<tr><td>
|
|
||||||
xx+ <td>ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified at byte 15
|
|
||||||
<tr><td>
|
|
||||||
xx+ <td>Content: Length specified in header at bytes 16-23,
|
|
||||||
format specified in header at byte 25,
|
|
||||||
content specified in header at byte 27
|
|
||||||
<tr><td>
|
|
||||||
xx+ <td>Signature: Length is specified in header at bytes 10-11, covers everything starting at byte 0
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
All unused fields must be set to 0 for compatibility with future versions.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h4>{% trans %}Signature Details{% endtrans %}</h4>
|
|
||||||
<p>
|
|
||||||
The signature covers the entire header starting at byte 0,
|
|
||||||
through the end of the content.
|
|
||||||
We use raw signatures. Take the hash of the data (using the hash type
|
|
||||||
implied by the signature type at bytes 8-9) and pass that
|
|
||||||
to a "raw" sign or verify function (e.g. "NONEwithRSA" in Java).
|
|
||||||
<p></p>
|
|
||||||
While signature verification and content extraction may be implemented in one pass,
|
|
||||||
an implementation must read and buffer the first 10 bytes to determine the hash type
|
|
||||||
before starting to verify.
|
|
||||||
<p></p>
|
|
||||||
Signature lengths for the various signature types are specified on the
|
|
||||||
<a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">common structures page</a>.
|
|
||||||
Pad the signature with leading zeros if necessary.
|
|
||||||
See <a href="{{ site_url('docs/how/cryptography') }}#sig">the cryptography details page</a>
|
|
||||||
for parameters of the various signature types.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>{% trans %}Notes{% endtrans %}</h4>
|
|
||||||
<p>
|
|
||||||
The content type specifies the trust domain.
|
|
||||||
For each content type, clients maintain a set of X.509 public key certificates for
|
|
||||||
parties trusted to sign that content.
|
|
||||||
Only certificates for the specified content type may be used.
|
|
||||||
The certificate is looked up by the ID of the signer.
|
|
||||||
Clients must verify that the content type is that expected for the application.
|
|
||||||
<p></p>
|
|
||||||
All values are in network byte order (big endian).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}SU3 Router Update File Specification{% endtrans %}</h3>
|
|
||||||
|
|
||||||
<p><b>SU3 Details:</b></p>
|
|
||||||
<ul><li>
|
|
||||||
SU3 Content Type: 1 (ROUTER UPDATE)
|
|
||||||
</li><li>
|
|
||||||
SU3 File Type: 0 (ZIP)
|
|
||||||
</li><li>
|
|
||||||
SU3 Version: The router version
|
|
||||||
</li><li>
|
|
||||||
Jar and war files in the zip are compressed with pack200 as documented above for "su2" files.
|
|
||||||
If the client does not support pack200, it must download the update in a "sud" format.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
<p><b>Notes:</b></p>
|
|
||||||
<ul><li>
|
|
||||||
For releases, the SU3 version is the "base" router version, e.g. "0.9.20".
|
|
||||||
</li><li>
|
|
||||||
For development builds, which are supported as of release 0.9.20,
|
|
||||||
the SU3 version is the "full" router version, e.g. "0.9.20-5" or "0.9.20-5-rc".
|
|
||||||
See RouterVersion.java.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}SU3 Reseed File Specification{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of 0.9.14, reseed data is delivered in an "su3" file format.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h4>{% trans %}Goals:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Signed files with strong signatures and trusted certificates
|
|
||||||
to prevent man-in-the-middle attacks that could boot victims into a separate, untrusted network.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Use su3 file format already used for updates, reseeding, and plugins
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Single compressed file to speed up reseeding, which was slow to fetch 200 files
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>{% trans %}Specification:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<p><ol>
|
|
||||||
<li>{% trans -%}
|
|
||||||
The file must be named "i2pseeds.su3".
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
The file must be in the same directory as the router infos on the web server.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
A router will first try to fetch (index URL)/i2pseeds.su3; if that fails it will fetch the index URL
|
|
||||||
and then fetch the individual router info files found in the links.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ol></p>
|
|
||||||
|
|
||||||
<p><b>SU3 Details:</b></p>
|
|
||||||
<ul><li>
|
|
||||||
SU3 Content Type: 3 (RESEED)
|
|
||||||
</li><li>
|
|
||||||
SU3 File Type: 0 (ZIP)
|
|
||||||
</li><li>
|
|
||||||
SU3 Version: Seconds since the epoch, in ASCII (date +%s)
|
|
||||||
</li><li>
|
|
||||||
Router info files in the zip file must be at the "top level". No directories are in the zip file.
|
|
||||||
</li><li>
|
|
||||||
Router info files must be named "routerInfo-(44 character base 64 router hash).dat", as in the old reseed mechanism.
|
|
||||||
The I2P base 64 alphabet must be used.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}SU3 Plugin File Specification{% endtrans %}</h3>
|
|
||||||
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of 0.9.15, plugins may be packaged in an "su3" file format.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<p><b>SU3 Details:</b></p>
|
|
||||||
<ul><li>
|
|
||||||
SU3 Content Type: 2 (PLUGIN)
|
|
||||||
</li><li>
|
|
||||||
SU3 File Type: 0 (ZIP)
|
|
||||||
See <a href="plugin">the plugin specification</a> for details.
|
|
||||||
</li><li>
|
|
||||||
SU3 Version: The plugin version, must match that in plugin.config.
|
|
||||||
</li><li>
|
|
||||||
Jar and war files in the zip are compressed with pack200 as documented above for "su2" files.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}SU3 News File Specification{% endtrans %}</h3>
|
|
||||||
<p>{% trans -%}
|
|
||||||
As of 0.9.17, the news is delivered in an "su3" file format.
|
|
||||||
{%- endtrans %}</p>
|
|
||||||
|
|
||||||
<h4>{% trans %}Goals:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Signed news with strong signatures and trusted certificates
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Use su3 file format already used for updates, reseeding, and plugins
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Standard XML format for use with standard parsers
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Standard Atom format for use with standard feed readers and generators
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Sanitization and verification of HTML before displaying on console
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
<li>{% trans -%}
|
|
||||||
Suitable for easy implementation on Android and other platforms without an HTML console
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>{% trans %}Specification:{% endtrans %}</h4>
|
|
||||||
|
|
||||||
<p><b>SU3 Details:</b></p>
|
|
||||||
<ul><li>
|
|
||||||
SU3 Content Type: 4 (NEWS)
|
|
||||||
</li><li>
|
|
||||||
SU3 File Type: 1 (XML) or 3 (XML.GZ)
|
|
||||||
</li><li>
|
|
||||||
SU3 Version: Seconds since the epoch, in ASCII (date +%s)
|
|
||||||
</li><li>
|
|
||||||
File Format: XML or gzipped XML, containing an <a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) XML Feed</a>.
|
|
||||||
Charset must be UTF-8.
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
<p><b>Atom <feed> Details:</b></p>
|
|
||||||
The following <feed> elements are used:
|
|
||||||
<ul><li>
|
|
||||||
<entry> A news item. See below.
|
|
||||||
</li><li>
|
|
||||||
<i2p:release> I2P update metadata. See below.
|
|
||||||
</li><li>
|
|
||||||
<updated> Timestamp for the feed (conforming to
|
|
||||||
<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and
|
|
||||||
<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (required)
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
<p><b>Atom <entry> Details:</b></p>
|
|
||||||
Each Atom <entry> in the news feed may be parsed and displayed in the router console.
|
|
||||||
The following elements are used:
|
|
||||||
<ul><li>
|
|
||||||
<author> (optional) containing:
|
|
||||||
<ul><li>
|
|
||||||
<name> The name of the entry author
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
|
||||||
<content> Content, must be type="xhtml".
|
|
||||||
The XHTML will be sanitized with a whitelist of allowed elements
|
|
||||||
and a blacklist of disallowed attributes.
|
|
||||||
Clients may ignore an element, or the enclosing entry, or the entire feed
|
|
||||||
when a non-whitelisted element is encountered. (required)
|
|
||||||
</li><li>
|
|
||||||
<link> Link for further information (optional)
|
|
||||||
</li><li>
|
|
||||||
<summary> Short summary, suitable for a tooltip (optional)
|
|
||||||
</li><li>
|
|
||||||
<title> Title of the news entry (required)
|
|
||||||
</li><li>
|
|
||||||
<updated> Timestamp for this entry (conforming to
|
|
||||||
<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and
|
|
||||||
<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (required)
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
<p><b>Atom <i2p:release> Details:</b></p>
|
|
||||||
There must be at least one <i2p:release> entity in the feed. Each contains the following attributes and entities:
|
|
||||||
<ul><li>
|
|
||||||
date (attribute): Timestamp for this entry (conforming to
|
|
||||||
<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and
|
|
||||||
<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (required)
|
|
||||||
The date also may be in truncated format yyyy-mm-dd (without the 'T'); this is the "full-date" format in RFC 3339.
|
|
||||||
In this format the time is assumed to be 00:00:00 UTC for any processing.
|
|
||||||
</li><li>
|
|
||||||
minJavaVersion (attribute): If present, the minimum version of Java required to run the current version.
|
|
||||||
</li><li>
|
|
||||||
minVersion (attribute):
|
|
||||||
If present, the minimum version of the router required to update to the current version.
|
|
||||||
If a router is older than this, the user must (manually?) update to an intermediate version first.
|
|
||||||
</li><li>
|
|
||||||
<i2p:version> Required. The latest current router version available.
|
|
||||||
</li><li>
|
|
||||||
<i2p:update> An update file (one or more). It must contain at least one child.
|
|
||||||
<ul><li>
|
|
||||||
type (attribute): "sud", "su2", or "su3". Must be unique across all <i2p:update> elements.
|
|
||||||
</li><li>
|
|
||||||
<i2p:clearnet> Out-of-network direct download links (zero or more)
|
|
||||||
<ul><li>
|
|
||||||
href (attribute): a standard clearnet http link
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
|
||||||
<i2p:clearnetssl> Out-of-network direct download links (zero or more)
|
|
||||||
<ul><li>
|
|
||||||
href (attribute): a standard clearnet https link
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
|
||||||
<i2p:torrent> In-network magnet link
|
|
||||||
<ul><li>
|
|
||||||
href (attribute): a magnet link
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
|
||||||
<i2p:url> In-network direct download links (zero or more)
|
|
||||||
<ul><li>
|
|
||||||
href (attribute): an in-network http .i2p link
|
|
||||||
</li></ul>
|
|
||||||
</li></ul>
|
|
||||||
</li></ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>{% trans %}Future Work{% endtrans %}</h3>
|
|
||||||
<ul>
|
|
||||||
<li>{% trans -%}
|
|
||||||
The router update mechanism is part of the web router console.
|
|
||||||
There is currently no provision for updates of an embedded router lacking the router console.
|
|
||||||
{%- endtrans %}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -1,76 +0,0 @@
|
|||||||
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
|
||||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
|
||||||
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
|
||||||
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
|
||||||
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
|
||||||
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
|
||||||
BandwidthLimits docs/spec/i2cp.html 588;" m
|
|
||||||
Boolean docs/spec/common-structures.html 74;" t
|
|
||||||
BuildRequestRecord docs/spec/i2np.html 183;" s
|
|
||||||
BuildResponseRecord docs/spec/i2np.html 353;" s
|
|
||||||
Certificate docs/spec/common-structures.html 296;" t
|
|
||||||
CreateLeaseSet docs/spec/i2cp.html 630;" m
|
|
||||||
CreateSession docs/spec/i2cp.html 668;" m
|
|
||||||
Data docs/spec/i2np.html 1118;" m
|
|
||||||
DatabaseLookup docs/spec/i2np.html 688;" m
|
|
||||||
DatabaseSearchReply docs/spec/i2np.html 835;" m
|
|
||||||
DatabaseStore docs/spec/i2np.html 590;" m
|
|
||||||
Date docs/spec/common-structures.html 51;" t
|
|
||||||
DeliveryInstructions docs/spec/common-structures.html 1010;" s
|
|
||||||
DeliveryStatus docs/spec/i2np.html 910;" m
|
|
||||||
DestLookup docs/spec/i2cp.html 697;" m
|
|
||||||
DestReply docs/spec/i2cp.html 719;" m
|
|
||||||
Destination docs/spec/common-structures.html 639;" s
|
|
||||||
Disconnect docs/spec/i2cp.html 763;" m
|
|
||||||
Garlic docs/spec/i2np.html 948;" m
|
|
||||||
GarlicClove docs/spec/i2np.html 395;" s
|
|
||||||
GarlicCloveDeliveryInstructions docs/spec/i2np.html 454;" s
|
|
||||||
GetBandwidthLimits docs/spec/i2cp.html 783;" m
|
|
||||||
GetDate docs/spec/i2cp.html 802;" m
|
|
||||||
Hash docs/spec/common-structures.html 257;" t
|
|
||||||
HostLookup docs/spec/i2cp.html 840;" m
|
|
||||||
HostReply docs/spec/i2cp.html 889;" m
|
|
||||||
I2CPMessageHeader docs/spec/i2cp.html 302;" s
|
|
||||||
I2NPMessageHeader docs/spec/i2np.html 93;" s
|
|
||||||
Integer docs/spec/common-structures.html 41;" t
|
|
||||||
KeysAndCert docs/spec/common-structures.html 549;" s
|
|
||||||
Lease docs/spec/common-structures.html 668;" s
|
|
||||||
LeaseSet docs/spec/common-structures.html 713;" s
|
|
||||||
Mapping docs/spec/common-structures.html 461;" t
|
|
||||||
MessageId docs/spec/i2cp.html 324;" s
|
|
||||||
MessagePayload docs/spec/i2cp.html 921;" m
|
|
||||||
MessageStatus docs/spec/i2cp.html 943;" m
|
|
||||||
Payload docs/spec/i2cp.html 344;" s
|
|
||||||
PrivateKey docs/spec/common-structures.html 102;" t
|
|
||||||
PublicKey docs/spec/common-structures.html 89;" t
|
|
||||||
ReceiveMessageBegin docs/spec/i2cp.html 1048;" m
|
|
||||||
ReceiveMessageEnd docs/spec/i2cp.html 1077;" m
|
|
||||||
ReconfigureSession docs/spec/i2cp.html 1103;" m
|
|
||||||
ReportAbuse docs/spec/i2cp.html 1133;" m
|
|
||||||
RequestLeaseSet docs/spec/i2cp.html 1164;" m
|
|
||||||
RequestVariableLeaseSet docs/spec/i2cp.html 1197;" m
|
|
||||||
RouterAddress docs/spec/common-structures.html 843;" s
|
|
||||||
RouterIdentity docs/spec/common-structures.html 613;" s
|
|
||||||
RouterInfo docs/spec/common-structures.html 910;" s
|
|
||||||
SendMessage docs/spec/i2cp.html 1225;" m
|
|
||||||
SendMessageExpires docs/spec/i2cp.html 1272;" m
|
|
||||||
SessionConfig docs/spec/i2cp.html 366;" s
|
|
||||||
SessionId docs/spec/i2cp.html 398;" s
|
|
||||||
SessionKey docs/spec/common-structures.html 115;" t
|
|
||||||
SessionStatus docs/spec/i2cp.html 1403;" m
|
|
||||||
SessionTag docs/spec/common-structures.html 269;" t
|
|
||||||
SetDate docs/spec/i2cp.html 1437;" m
|
|
||||||
Signature docs/spec/common-structures.html 214;" t
|
|
||||||
SigningPrivateKey docs/spec/common-structures.html 171;" t
|
|
||||||
SigningPublicKey docs/spec/common-structures.html 128;" t
|
|
||||||
String docs/spec/common-structures.html 62;" t
|
|
||||||
Tunnel docs/spec/tunnel-message.html 34;" m
|
|
||||||
TunnelBuild docs/spec/i2np.html 1144;" m
|
|
||||||
TunnelBuildReply docs/spec/i2np.html 1177;" m
|
|
||||||
TunnelData docs/spec/i2np.html 1044;" m
|
|
||||||
TunnelGateway docs/spec/i2np.html 1084;" m
|
|
||||||
TunnelId docs/spec/common-structures.html 281;" t
|
|
||||||
TunnelMessageDeliveryInstructions docs/spec/tunnel-message.html 159;" s
|
|
||||||
VariableTunnelBuild docs/spec/i2np.html 1190;" m
|
|
||||||
VariableTunnelBuildReply docs/spec/i2np.html 1220;" m
|
|
||||||
sampleDatagrams docs/spec/ssu.html 1062;" a
|
|
40
i2p2www/pages/spec/index.html
Normal file
40
i2p2www/pages/spec/index.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{% extends "global/layout.html" %}
|
||||||
|
{% block title %}I2P Specification Documents{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
This page provides the specifications for various components of the I2P network
|
||||||
|
and router software. These are living documents, and the specifications are
|
||||||
|
updated as modifications are made to the network and software.
|
||||||
|
|
||||||
|
<ul><li>
|
||||||
|
"Last updated" is the last date when the specification given within a document
|
||||||
|
was altered in any way, except for changes to the "accurate for" information.
|
||||||
|
</li><li>
|
||||||
|
The "accurate for" column gives the version of the I2P network and reference
|
||||||
|
Java implementation that the document is verified to be valid for. Because the
|
||||||
|
documents are usually only updated when changes are made, the listed versions
|
||||||
|
can sometimes be several releases behind. This does not mean that documents with
|
||||||
|
old listed versions are necessarily inaccurate, but small differences may creep
|
||||||
|
in during the course of development. Periodic reviews are conducted to update
|
||||||
|
the "accurate for" information.
|
||||||
|
</li></ul>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Last updated</th>
|
||||||
|
<th>Accurate for</th>
|
||||||
|
<th>Link</th>
|
||||||
|
</tr>
|
||||||
|
{% for spec in specs %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ spec.title }}</td>
|
||||||
|
<td><time>{{ spec.lastupdated }}</time></td>
|
||||||
|
<td>{{ spec.accuratefor }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('spec_show', name=spec.name) }}">HTML</a> |
|
||||||
|
<a href="{{ url_for('spec_show_txt', name=spec.name) }}">TXT</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
10
i2p2www/pages/spec/show.html
Normal file
10
i2p2www/pages/spec/show.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{% extends "global/layout.html" %}
|
||||||
|
{%- from "global/macros" import render_categories with context -%}
|
||||||
|
{% block title %}{{ title }}{% endblock %}
|
||||||
|
{% block lastupdated %}{{ meta.lastupdated }}{% endblock %}
|
||||||
|
{% block accuratefor %}{{ meta.accuratefor }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% autoescape false %}
|
||||||
|
{{ body }}
|
||||||
|
{% endautoescape %}
|
||||||
|
{% endblock %}
|
0
i2p2www/spec/__init__.py
Normal file
0
i2p2www/spec/__init__.py
Normal file
247
i2p2www/spec/blockfile.rst
Normal file
247
i2p2www/spec/blockfile.rst
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
==========================================
|
||||||
|
Blockfile and Hosts Database Specification
|
||||||
|
==========================================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: November 2014
|
||||||
|
:accuratefor: 0.9.17
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This document specifies the I2P blockfile file format and the tables in the
|
||||||
|
hostsdb.blockfile used by the Blockfile Naming Service [NAMING]_.
|
||||||
|
|
||||||
|
The blockfile provides fast Destination lookup in a compact format. While the
|
||||||
|
blockfile page overhead is substantial, the destinations are stored in binary
|
||||||
|
rather than in Base 64 as in the hosts.txt format. In addition, the blockfile
|
||||||
|
provides the capability of arbitrary metadata storage (such as added date,
|
||||||
|
source, and comments) for each entry. The metadata may be used in the future
|
||||||
|
to provide advanced addressbook features. The blockfile storage requirement is
|
||||||
|
a modest increase over the hosts.txt format, and the blockfile provides
|
||||||
|
approximately 10x reduction in lookup times.
|
||||||
|
|
||||||
|
A blockfile is simply on-disk storage of multiple sorted maps (key-value
|
||||||
|
pairs), implemented as skiplists. The blockfile format is adopted from the
|
||||||
|
Metanotion Blockfile Database [METANOTION]_. First we will define the file
|
||||||
|
format, then the use of that format by the BlockfileNamingService.
|
||||||
|
|
||||||
|
|
||||||
|
Blockfile Format
|
||||||
|
================
|
||||||
|
|
||||||
|
The original blockfile spec was modified to add magic numbers to each page.
|
||||||
|
The file is structured in 1024-byte pages. Pages are numbered starting from 1.
|
||||||
|
The "superblock" is always at page 1, i.e. starting at byte 0 in the file. The
|
||||||
|
metaindex skiplist is always at page 2, i.e. starting at byte 1024 in the file.
|
||||||
|
|
||||||
|
All 2-byte integer values are unsigned. All 4-byte integer values (page
|
||||||
|
numbers) are signed and negative values are illegal. All integer values are
|
||||||
|
stored in network byte order (big endian).
|
||||||
|
|
||||||
|
The database is designed to be opened and accessed by a single thread. The
|
||||||
|
BlockfileNamingService provides synchronization.
|
||||||
|
|
||||||
|
Superblock format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-5 Magic number 0x3141de493250 ("1A" 0xde "I2P")
|
||||||
|
6 Major version 0x01
|
||||||
|
7 Minor version 0x02
|
||||||
|
8-15 File length Total length in bytes
|
||||||
|
16-19 First free list page
|
||||||
|
20-21 Mounted flag 0x01 = yes
|
||||||
|
22-23 Span size Max number of key/value pairs per span (16 for hostsdb)
|
||||||
|
Used for new skip lists.
|
||||||
|
24-27 Page size As of version 1.2. Prior to 1.2, 1024 is assumed.
|
||||||
|
28-1023 unused
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Skip list block page format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-7 Magic number 0x536b69704c697374 "SkipList"
|
||||||
|
8-11 First span page
|
||||||
|
12-15 First level page
|
||||||
|
16-19 Size (total number of keys - may only be valid at startup)
|
||||||
|
20-23 Spans (total number of spans - may only be valid at startup)
|
||||||
|
24-27 Levels (total number of levels - may only be valid at startup)
|
||||||
|
28-29 Span size - As of version 1.2. Max number of key/value pairs per span.
|
||||||
|
Prior to that, specified for all skiplists in the superblock.
|
||||||
|
Used for new spans in this skip list.
|
||||||
|
30-1023 unused
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Skip level block page format is as follows.
|
||||||
|
All levels have a span. Not all spans have levels.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-7 Magic number 0x42534c6576656c73 "BSLevels"
|
||||||
|
8-9 Max height
|
||||||
|
10-11 Current height
|
||||||
|
12-15 Span page
|
||||||
|
16- Next level pages ('current height' entries, 4 bytes each, lowest first)
|
||||||
|
remaining bytes unused
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Skip span block page format is as follows.
|
||||||
|
Key/value structures are sorted by key within each span and across all spans.
|
||||||
|
Key/value structures are sorted by key within each span.
|
||||||
|
Spans other than the first span may not be empty.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-3 Magic number 0x5370616e "Span"
|
||||||
|
4-7 First continuation page or 0
|
||||||
|
8-11 Previous span page or 0
|
||||||
|
12-15 Next span page or 0
|
||||||
|
16-17 Max keys (16 for hostsdb)
|
||||||
|
18-19 Size (current number of keys)
|
||||||
|
20-1023 key/value structures
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Span Continuation block page format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-3 Magic number 0x434f4e54 "CONT"
|
||||||
|
4-7 Next continuation page or 0
|
||||||
|
8-1023 key/value structures
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Key/value structure format is as follows.
|
||||||
|
Key and value lengths must not be split across pages, i.e. all 4 bytes must be on the same page.
|
||||||
|
If there is not enough room the last 1-3 bytes of a page are unused and the lengths will
|
||||||
|
be at offset 8 in the continuation page.
|
||||||
|
Key and value data may be split across pages.
|
||||||
|
Max key and value lengths are 65535 bytes.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-1 key length in bytes
|
||||||
|
2-3 value length in bytes
|
||||||
|
4- key data
|
||||||
|
value data
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Free list block page format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-7 Magic number 0x2366724c69737423 "#frList#"
|
||||||
|
8-11 Next free list block or 0 if none
|
||||||
|
12-15 Number of valid free pages in this block (0 - 252)
|
||||||
|
16-1023 Free pages (4 bytes each), only the first (valid number) are valid
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Free page block format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %}Byte Contents
|
||||||
|
0-7 Magic number 0x7e2146524545217e "~!FREE!~"
|
||||||
|
8-1023 unused
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The metaindex (located at page 2) is a mapping of US-ASCII strings to 4-byte integers.
|
||||||
|
The key is the name of the skiplist and the value is the page index of the skiplist.
|
||||||
|
|
||||||
|
|
||||||
|
Blockfile Naming Service Tables
|
||||||
|
===============================
|
||||||
|
|
||||||
|
The tables created and used by the BlockfileNamingService are as follows.
|
||||||
|
The maximum number of entries per span is 16.
|
||||||
|
|
||||||
|
Properties Skiplist
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
"%%__INFO__%%" is the master database skiplist with String/Properties key/value
|
||||||
|
entries containing only one entry:
|
||||||
|
|
||||||
|
info
|
||||||
|
a Properties (UTF-9 String/String Map), serialized as a [Mapping]_:
|
||||||
|
|
||||||
|
version
|
||||||
|
"3"
|
||||||
|
|
||||||
|
created
|
||||||
|
Java long time (ms)
|
||||||
|
|
||||||
|
upgraded
|
||||||
|
Java long time (ms) (as of database version 2)
|
||||||
|
|
||||||
|
lists
|
||||||
|
Comma-separated list of host databases, to be searched in-order for
|
||||||
|
lookups. Almost always "privatehosts.txt,userhosts.txt,hosts.txt".
|
||||||
|
|
||||||
|
Reverse Lookup Skiplist
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
"%%__REVERSE__%%" is the reverse lookup skiplist with Integer/Properties
|
||||||
|
key/value entries (as of database version 2):
|
||||||
|
|
||||||
|
* The skiplist keys are 4-byte Integers, the first 4 bytes of the hash of the
|
||||||
|
[Destination]_.
|
||||||
|
|
||||||
|
* The skiplist values are each a Properties (a UTF-8 String/String Map)
|
||||||
|
serialized as a [Mapping]_
|
||||||
|
|
||||||
|
* There may be multiple entries in the properties, each one is a reverse
|
||||||
|
mapping, as there may be more than one hostname for a given destination, or
|
||||||
|
there could be collisions with the same first 4 bytes of the hash.
|
||||||
|
|
||||||
|
* Each property key is a hostname.
|
||||||
|
|
||||||
|
* Each property value is the empty string.
|
||||||
|
|
||||||
|
hosts.txt, userhosts.txt, and privatehosts.txt Skiplists
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
|
For each host database, there is a skiplist containing the hosts for that
|
||||||
|
database. The keys/values in these skiplists are as follows:
|
||||||
|
|
||||||
|
key
|
||||||
|
a UTF-8 String (the hostname)
|
||||||
|
|
||||||
|
value
|
||||||
|
a DestEntry, which is a Properties (a UTF-8 String/String Map)
|
||||||
|
serialized as a [Mapping]_ followed by a binary [Destination]_
|
||||||
|
(serialized as usual).
|
||||||
|
|
||||||
|
The DestEntry Properties typically contains:
|
||||||
|
|
||||||
|
"a"
|
||||||
|
The time added (Java long time in ms)
|
||||||
|
|
||||||
|
"s"
|
||||||
|
The original source of the entry (typically a file name or subscription
|
||||||
|
URL)
|
||||||
|
|
||||||
|
Hostname keys are stored in lower-case and always end in ".i2p".
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [Destination]
|
||||||
|
{{ ctags_url('Destination') }}
|
||||||
|
|
||||||
|
.. [Mapping]
|
||||||
|
{{ ctags_url('Mapping') }}
|
||||||
|
|
||||||
|
.. [METANOTION]
|
||||||
|
http://www.metanotion.net/software/sandbox/block.html
|
||||||
|
|
||||||
|
.. [NAMING]
|
||||||
|
{{ site_url('docs/naming', True) }}
|
1107
i2p2www/spec/common-structures.rst
Normal file
1107
i2p2www/spec/common-structures.rst
Normal file
File diff suppressed because it is too large
Load Diff
452
i2p2www/spec/configuration.rst
Normal file
452
i2p2www/spec/configuration.rst
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
================================
|
||||||
|
Configuration File Specification
|
||||||
|
================================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: November 2015
|
||||||
|
:accuratefor: 0.9.24
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This page provides a general specification of I2P configuration files, used by
|
||||||
|
the router and various applications. It also gives an overview of the
|
||||||
|
information contained in the various files, and links to detailed documentation
|
||||||
|
where available.
|
||||||
|
|
||||||
|
|
||||||
|
General Format
|
||||||
|
==============
|
||||||
|
|
||||||
|
An I2P configuration file is formatted as specified in Java [Properties]_ with
|
||||||
|
the following exceptions:
|
||||||
|
|
||||||
|
* Encoding must be UTF-8
|
||||||
|
|
||||||
|
* Does not use or recognize any escapes, including '\', so lines may not be
|
||||||
|
continued
|
||||||
|
|
||||||
|
* '#' or ';' starts a comment, but '!' does not
|
||||||
|
|
||||||
|
* '#' starts a comment in any position but ';' must be in column 1 to start a
|
||||||
|
comment
|
||||||
|
|
||||||
|
* Leading and trailing whitespace is not trimmed on keys
|
||||||
|
|
||||||
|
* Leading and trailing whitespace is trimmed on values
|
||||||
|
|
||||||
|
* '=' is the only key-termination character (not ':' or whitespace)
|
||||||
|
|
||||||
|
* Lines without '=' are ignored. As of release 0.9.10, keys with a value of ""
|
||||||
|
are supported.
|
||||||
|
|
||||||
|
* As there are no escapes, keys may not contain '#', '=', or '\n', or start with
|
||||||
|
';'
|
||||||
|
|
||||||
|
* As there are no escapes, values may not contain '#' or '\n', or start or end
|
||||||
|
with '\r' or whitespace
|
||||||
|
|
||||||
|
The file need not be sorted, but most applications do sort by key when writing
|
||||||
|
to the file, for ease of reading and manual editing.
|
||||||
|
|
||||||
|
Reads and writes are implemented in DataHelper loadProps() and storeProps()
|
||||||
|
[DATAHELPER]_. Note that the file format is significantly different than the
|
||||||
|
serialized format for I2P protocols specified in [Mapping]_.
|
||||||
|
|
||||||
|
|
||||||
|
Core library and router
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Clients (clients.config)
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Configured via /configclients in the router console.
|
||||||
|
|
||||||
|
The format is as follows:
|
||||||
|
|
||||||
|
Lines are of the form clientApp.x.prop=val, where x is the app number. App
|
||||||
|
numbers MUST start with 0 and be consecutive.
|
||||||
|
|
||||||
|
Properties are as follows:
|
||||||
|
|
||||||
|
main
|
||||||
|
Full class name. Required.
|
||||||
|
|
||||||
|
The constructor or main() method in this class will be run, depending on
|
||||||
|
whether the client is managed or unmanaged. See below for details.
|
||||||
|
|
||||||
|
name
|
||||||
|
Name to be displayed on console.
|
||||||
|
|
||||||
|
args
|
||||||
|
Arguments to the main class, separated by spaces or tabs.
|
||||||
|
Arguments containing spaces or tabs may be quoted with ' or "
|
||||||
|
|
||||||
|
delay
|
||||||
|
Seconds before starting, default 120
|
||||||
|
|
||||||
|
onBoot
|
||||||
|
{true|false},
|
||||||
|
|
||||||
|
Default false, forces a delay of 0, overrides delay setting
|
||||||
|
|
||||||
|
startOnLoad:
|
||||||
|
{true|false}
|
||||||
|
|
||||||
|
Is the client to be run at all? Default true
|
||||||
|
|
||||||
|
The following additional properties are used only by plugins:
|
||||||
|
|
||||||
|
stopargs
|
||||||
|
Arguments to stop the client.
|
||||||
|
|
||||||
|
uninstallargs
|
||||||
|
Arguments to uninstall the client.
|
||||||
|
|
||||||
|
classpath
|
||||||
|
Additional classpath elements for the client, separated by commas.
|
||||||
|
|
||||||
|
The following substitutions are made in the args, stopargs,
|
||||||
|
uninstallargs, and classpath lines, for plugins only:
|
||||||
|
|
||||||
|
$I2P
|
||||||
|
The base I2P install directory
|
||||||
|
|
||||||
|
$CONFIG
|
||||||
|
The user's configuration directory (e.g. ~/.i2p)
|
||||||
|
|
||||||
|
$PLUGIN
|
||||||
|
This plugin's directory (e.g. ~/.i2p/plugins/foo)
|
||||||
|
|
||||||
|
All properties except "main" are optional. Lines starting with "#" are
|
||||||
|
comments.
|
||||||
|
|
||||||
|
If the delay is less than zero, the client is run immediately, in the same
|
||||||
|
thread, so that exceptions may be propagated to the console. In this case, the
|
||||||
|
client should either throw an exception, return quickly, or spawn its own
|
||||||
|
thread.
|
||||||
|
|
||||||
|
If the delay is greater than or equal to zero, it will be run in a new thread,
|
||||||
|
and exceptions will be logged but not propagated to the console.
|
||||||
|
|
||||||
|
Clients may be "managed" or "unmanaged".
|
||||||
|
|
||||||
|
Logger (logger.config)
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Configured via /configlogging in the router console.
|
||||||
|
|
||||||
|
Properties are as follows::
|
||||||
|
|
||||||
|
# Default 20
|
||||||
|
logger.consoleBufferSize=n
|
||||||
|
# Default from locale; format as specified by Java SimpleDateFormat
|
||||||
|
logger.dateFormat=HH:mm:ss.SSS
|
||||||
|
# Default ERROR
|
||||||
|
logger.defaultLevel=CRIT|ERROR|WARN|INFO|DEBUG
|
||||||
|
# Default true
|
||||||
|
logger.displayOnScreen=true|false
|
||||||
|
# Default true
|
||||||
|
logger.dropDuplicates=true|false
|
||||||
|
# Default false
|
||||||
|
logger.dropOnOverflow=true|false
|
||||||
|
# As of 0.9.18. Default 29 (seconds)
|
||||||
|
logger.flushInterval=nnn
|
||||||
|
# d = date, c = class, t = thread name, p = priority, m = message
|
||||||
|
logger.format={dctpm}*
|
||||||
|
# Max to buffer before flushing. Default 1024
|
||||||
|
logger.logBufferSize=n
|
||||||
|
# Default logs/log-@.txt; @ replaced with number
|
||||||
|
logger.logFileName=name
|
||||||
|
logger.logFilenameOverride=name
|
||||||
|
# Default 10M
|
||||||
|
logger.logFileSize=nnn[K|M|G]
|
||||||
|
# Highest file number. Default 2
|
||||||
|
logger.logRotationLimit=n
|
||||||
|
# Default CRIT
|
||||||
|
logger.minimumOnScreenLevel=CRIT|ERROR|WARN|INFO|DEBUG
|
||||||
|
logger.record.{class}=CRIT|ERROR|WARN|INFO|DEBUG
|
||||||
|
|
||||||
|
Individual Plugin (xxx/plugin.config)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
See the plugin specification [PLUGIN]_.
|
||||||
|
|
||||||
|
Plugins (plugins.config)
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Enable/disable for each installed plugin.
|
||||||
|
|
||||||
|
Properties are as follows::
|
||||||
|
|
||||||
|
plugin.{name}.startOnLoad=true|false
|
||||||
|
|
||||||
|
Webapps (webapps.config)
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Enable/disable for each installed webapp.
|
||||||
|
|
||||||
|
Properties are as follows::
|
||||||
|
|
||||||
|
webapps.{name}.classpath=[space- or comma-separated paths]
|
||||||
|
webapps.{name}.startOnLoad=true|false
|
||||||
|
|
||||||
|
Router (router.config)
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Configured via /configadvanced in the router console.
|
||||||
|
|
||||||
|
|
||||||
|
Applications
|
||||||
|
============
|
||||||
|
|
||||||
|
Addressbook (addressbook/config.txt)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
See documentation in SusiDNS.
|
||||||
|
|
||||||
|
I2PSnark (i2psnark.config)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Configured via the application gui.
|
||||||
|
|
||||||
|
I2PTunnel (i2ptunnel.config)
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Configured via the /i2ptunnel application in the router console.
|
||||||
|
|
||||||
|
Properties are as follows::
|
||||||
|
|
||||||
|
# Display description for UI
|
||||||
|
tunnel.N.description=
|
||||||
|
|
||||||
|
# Router IP address or host name. Ignored if in router context.
|
||||||
|
tunnel.N.i2cpHost=127.0.0.1
|
||||||
|
|
||||||
|
# Router I2CP port. Ignored if in router context.
|
||||||
|
tunnel.N.i2cpPort=nnnn
|
||||||
|
|
||||||
|
# For clients only. Local listen IP address or host name.
|
||||||
|
tunnel.N.interface=127.0.0.1
|
||||||
|
|
||||||
|
# For clients only. Local listen port.
|
||||||
|
tunnel.N.listenPort=nnnn
|
||||||
|
|
||||||
|
# Display name for UI
|
||||||
|
tunnel.N.name=
|
||||||
|
|
||||||
|
# Servers only. Default false. Originate connections to local server with a
|
||||||
|
# unique IP per-remote-destination.
|
||||||
|
tunnel.N.option.enableUniqueLocal=true|false
|
||||||
|
|
||||||
|
# Servers only. The maximum size of the thread pool, default 65. Ignored
|
||||||
|
# for standard servers.
|
||||||
|
tunnel.N.option.i2ptunnel.blockingHandlerCount=nnn
|
||||||
|
|
||||||
|
# HTTP client only. Whether to use allow SSL connections to i2p addresses.
|
||||||
|
# Default false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.allowInternalSSL=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Whether to disable address helper links. Default false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.disableAddressHelper=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Comma- or space-separated list of jump server URLs.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.jumpServers=http://example.i2p/jump
|
||||||
|
|
||||||
|
# HTTP client only. Whether to pass Accept* headers through. Default false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.sendAccept=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Whether to pass Referer headers through. Default false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.sendReferer=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Whether to pass User-Agent headers through. Default
|
||||||
|
# false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.sendUserAgent=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Whether to pass Via headers through. Default false.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.sendVia=true|false
|
||||||
|
|
||||||
|
# HTTP client only. Comma- or space-separated list of in-network SSL
|
||||||
|
# outproxies.
|
||||||
|
tunnel.N.option.i2ptunnel.httpclient.SSLOutproxies=example.i2p
|
||||||
|
|
||||||
|
# SOCKS client only. Comma- or space-separated list of in-network
|
||||||
|
# outproxies for any ports not specified.
|
||||||
|
tunnel.N.option.i2ptunnel.socks.proxy.default=example.i2p
|
||||||
|
|
||||||
|
# SOCKS client only. Comma- or space-separated list of in-network
|
||||||
|
# outproxies for port NNNN.
|
||||||
|
tunnel.N.option.i2ptunnel.socks.proxy.NNNN=example.i2p
|
||||||
|
|
||||||
|
# HTTP client only. Whether to use a registered local outproxy plugin.
|
||||||
|
# Default true.
|
||||||
|
tunnel.N.option.i2ptunnel.useLocalOutproxy=true|false
|
||||||
|
|
||||||
|
# Servers only. Whether to use a thread pool. Default true. Ignored for
|
||||||
|
# standard servers, always false.
|
||||||
|
tunnel.N.option.i2ptunnel.usePool=true|false
|
||||||
|
|
||||||
|
# IRC Server only. Only used if fakeHostname contains a %c. If unset,
|
||||||
|
# cloak with a random value that is persistent for the life of this tunnel.
|
||||||
|
# If set, cloak with the hash of this passphrase. Use to have consistent
|
||||||
|
# mangling across restarts, or for multiple IRC servers cloak consistently
|
||||||
|
# to be able to track users even when they switch servers. Note: don't
|
||||||
|
# quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
|
||||||
|
tunnel.N.option.ircserver.cloakKey=
|
||||||
|
|
||||||
|
# IRC Server only. Set the fake hostname sent by I2PTunnel, %f is the full
|
||||||
|
# B32 destination hash, %c is the cloaked hash.
|
||||||
|
tunnel.N.option.ircserver.fakeHostname=%f.b32.i2p
|
||||||
|
|
||||||
|
# IRC Server only. Default user.
|
||||||
|
tunnel.N.option.ircserver.method=user|webirc
|
||||||
|
|
||||||
|
# IRC Server only. The password to use for the webirc protocol. Note:
|
||||||
|
# don't quote or put spaces in the passphrase, the i2ptunnel gui can't
|
||||||
|
# handle it.
|
||||||
|
tunnel.N.option.ircserver.webircPassword=
|
||||||
|
|
||||||
|
# IRC Server only.
|
||||||
|
tunnel.N.option.ircserver.webircSpoofIP=
|
||||||
|
|
||||||
|
# For clients only. Alias for the private key in the keystore for the SSL
|
||||||
|
# socket. Will be autogenerated if a new key is created.
|
||||||
|
tunnel.N.option.keyAlias=
|
||||||
|
|
||||||
|
# For clients only. Password for the private key for the SSL socket. Will be
|
||||||
|
# autogenerated if a new key is created.
|
||||||
|
tunnel.N.option.keyPassword=
|
||||||
|
|
||||||
|
# For clients only. Path to the keystore file containing the private key for
|
||||||
|
# the SSL socket. Will be autogenerated if a new keystore is created.
|
||||||
|
# Relative to $(I2P_CONFIG_DIR)/keystore/ if not absolute.
|
||||||
|
tunnel.N.option.keystoreFile=i2ptunnel-(random string).ks
|
||||||
|
|
||||||
|
# For clients only. Password for the keystore containing the private key for
|
||||||
|
# the SSL socket. Default is "changeit".
|
||||||
|
tunnel.N.option.keystorePassword=changeit
|
||||||
|
|
||||||
|
# HTTP Server only. Max number of POSTs allowed for one destination per
|
||||||
|
# postCheckTime. Default 0 (unlimited)
|
||||||
|
tunnel.N.option.maxPosts=nnn
|
||||||
|
|
||||||
|
# HTTP Server only. Max number of POSTs allowed for all destinations per
|
||||||
|
# postCheckTime. Default 0 (unlimited)
|
||||||
|
tunnel.N.option.maxTotalPosts=nnn
|
||||||
|
|
||||||
|
# HTTP Clients only. Whether to send authorization to an outproxy. Default
|
||||||
|
# false.
|
||||||
|
tunnel.N.option.outproxyAuth=true|false
|
||||||
|
|
||||||
|
# HTTP Clients only. The password for the outproxy authorization.
|
||||||
|
tunnel.N.option.outproxyPassword=
|
||||||
|
|
||||||
|
# HTTP Clients only. The username for the outproxy authorization.
|
||||||
|
tunnel.N.option.outproxyUsername=
|
||||||
|
|
||||||
|
# HTTP Clients only. Whether to send authorization to an outproxy. Default
|
||||||
|
# false.
|
||||||
|
tunnel.N.option.outproxyAuth=true|false
|
||||||
|
|
||||||
|
# Clients only. Whether to store a destination in a private key file and
|
||||||
|
# reuse it. Default false.
|
||||||
|
tunnel.N.option.persistentClientKey=true|false
|
||||||
|
|
||||||
|
# HTTP Server only. Time period for banning POSTs from a single destination
|
||||||
|
# after maxPosts is exceeded, in seconds. Default 1800 seconds.
|
||||||
|
tunnel.N.option.postBanTime=nnn
|
||||||
|
|
||||||
|
# HTTP Server only. Time period for checking maxPosts and maxTotalPosts, in
|
||||||
|
# seconds. Default 300 seconds.
|
||||||
|
tunnel.N.option.postCheckTime=nnn
|
||||||
|
|
||||||
|
# HTTP Server only. Time period for banning all POSTs after maxTotalPosts
|
||||||
|
# is exceeded, in seconds. Default 600 seconds.
|
||||||
|
tunnel.N.option.postTotalBanTime=nnn
|
||||||
|
|
||||||
|
# HTTP Clients only. Whether to require local authorization for the proxy.
|
||||||
|
# Default false. "true" is the same as "basic".
|
||||||
|
tunnel.N.option.proxyAuth=true|false|basic|digest
|
||||||
|
|
||||||
|
# HTTP Clients only. The MD5 of the password for local authorization for
|
||||||
|
# user USER.
|
||||||
|
tunnel.N.option.proxy.auth.USER.md5=
|
||||||
|
|
||||||
|
# HTTP Servers only. Whether to reject incoming connections apparently via
|
||||||
|
# an inproxy. Default false.
|
||||||
|
tunnel.N.option.rejectInproxy=true|false
|
||||||
|
|
||||||
|
# Servers only. Overrides targetHost and targetPort for incoming port NNNN.
|
||||||
|
tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn
|
||||||
|
|
||||||
|
# Default false. For servers, use SSL for connections to local server. For
|
||||||
|
# clients, SSL is required for connections from local clients.
|
||||||
|
tunnel.N.option.useSSL=false
|
||||||
|
|
||||||
|
# Each option is passed to I2CP and streaming with "tunnel.N.option."
|
||||||
|
# stripped off. See those docs.
|
||||||
|
tunnel.N.option.*=
|
||||||
|
|
||||||
|
# For servers and clients with persistent keys only. Absolute path or
|
||||||
|
# relative to config directory.
|
||||||
|
tunnel.N.privKeyFile=filename
|
||||||
|
|
||||||
|
# For proxies only. Comma- or space-separated host names.
|
||||||
|
tunnel.N.proxyList=example.i2p[,example2.i2p]
|
||||||
|
|
||||||
|
# For clients only. Default false.
|
||||||
|
tunnel.N.sharedClient=true|false
|
||||||
|
|
||||||
|
# For HTTP servers only. Host name to be passed to the local server in the
|
||||||
|
# HTTP headers. Default is the base 32 hostname.
|
||||||
|
tunnel.N.spoofedHost=example.i2p
|
||||||
|
|
||||||
|
# For HTTP servers only. Host name to be passed to the local server in the
|
||||||
|
# HTTP headers. Overrides above setting for incoming port NNNN, to allow
|
||||||
|
# virtual hosts.
|
||||||
|
tunnel.N.spoofedHost.NNNN=example.i2p
|
||||||
|
|
||||||
|
# Default true
|
||||||
|
tunnel.N.startOnLoad=true|false
|
||||||
|
|
||||||
|
# For clients only. Comma- or space-separated host names or host:port.
|
||||||
|
tunnel.N.targetDestination=example.i2p[:nnnn][,example2.i2p[:nnnn]]
|
||||||
|
|
||||||
|
# For servers only. Local IP address or host name to connect to.
|
||||||
|
tunnel.N.targetHost=
|
||||||
|
|
||||||
|
# For servers only. Port on targetHost to connect to.
|
||||||
|
tunnel.N.targetPort=nnnn
|
||||||
|
|
||||||
|
# The type of i2ptunnel
|
||||||
|
tunnel.N.type=client|connectclient|httpbidirserver|httpclient|httpserver|ircclient|ircserver|
|
||||||
|
server|socksirctunnel|sockstunnel|streamrclient|streamrserver
|
||||||
|
|
||||||
|
Note: Each 'N' is a tunnel number starting with 0.
|
||||||
|
There may not be any gaps in numbering.
|
||||||
|
|
||||||
|
Router Console
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The router console uses the router.config file.
|
||||||
|
|
||||||
|
SusiMail (susimail.config)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
See post on zzz.i2p.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [DATAHELPER]
|
||||||
|
http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html
|
||||||
|
|
||||||
|
.. [Mapping]
|
||||||
|
{{ ctags_url('Mapping') }}
|
||||||
|
|
||||||
|
.. [PLUGIN]
|
||||||
|
{{ spec_url('plugin') }}
|
||||||
|
|
||||||
|
.. [Properties]
|
||||||
|
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html#load%28java.io.InputStream%29
|
128
i2p2www/spec/datagrams.rst
Normal file
128
i2p2www/spec/datagrams.rst
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
======================
|
||||||
|
Datagram Specification
|
||||||
|
======================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: July 2014
|
||||||
|
:accuratefor: 0.9.14
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
See [DATAGRAMS]_ for an overview of the Datagrams API.
|
||||||
|
|
||||||
|
|
||||||
|
.. _raw:
|
||||||
|
|
||||||
|
Non-Repliable Datagrams
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Non-repliable datagrams have no 'from' address and are not authenticated. They
|
||||||
|
are also called "raw" datagrams. Strictly speaking, they are not "datagrams"
|
||||||
|
at all, they are just raw data. They are not handled by the datagram API.
|
||||||
|
However, SAM and the I2PTunnel classes support "raw datagrams".
|
||||||
|
|
||||||
|
Format
|
||||||
|
------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' %}
|
||||||
|
+----+----+----+----+----//
|
||||||
|
| payload...
|
||||||
|
+----+----+----+----+----//
|
||||||
|
|
||||||
|
length: 0 - unlimited (see notes)
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
The practical length is limited by lower layers of protocols - the tunnel
|
||||||
|
message spec [TUNMSG]_ limits messages to about 61.2 KB and the transports
|
||||||
|
[TRANSPORT]_ currently limit messages to about 32 KB, although this may be
|
||||||
|
raised in the future.
|
||||||
|
|
||||||
|
|
||||||
|
.. _repliable:
|
||||||
|
|
||||||
|
Repliable Datagrams
|
||||||
|
===================
|
||||||
|
|
||||||
|
Repliable datagrams contain a 'from' address and a signature. These add at
|
||||||
|
least 427 bytes of overhead.
|
||||||
|
|
||||||
|
Format
|
||||||
|
------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' -%}
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| from |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
~ ~
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| signature |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| payload...
|
||||||
|
+----+----+----+----//
|
||||||
|
|
||||||
|
|
||||||
|
from :: a `Destination`
|
||||||
|
length: 387+ bytes
|
||||||
|
The originator and signer of the datagram
|
||||||
|
|
||||||
|
signature :: a `Signature`
|
||||||
|
Signature type must match the signing public key type of $from
|
||||||
|
length: 40+ bytes, as implied by the Signature type.
|
||||||
|
For the default DSA_SHA1 key type:
|
||||||
|
The DSA `Signature` of the SHA-256 hash of the payload.
|
||||||
|
For other key types:
|
||||||
|
The `Signature` of the payload.
|
||||||
|
The signature may be verified by the signing public key of $from
|
||||||
|
|
||||||
|
payload :: The data
|
||||||
|
Length: 0 to ~31.5 KB (see notes)
|
||||||
|
|
||||||
|
Total length: Payload length + 427+
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
* The practical length is limited by lower layers of protocols - the transports
|
||||||
|
[TRANSPORT]_ currently limit messages to about 32 KB, so the data length here
|
||||||
|
is limited to about 31.5 KB.
|
||||||
|
|
||||||
|
* See important notes about the reliability of large datagrams [DATAGRAMS]_. For
|
||||||
|
best results, limit the payload to about 10 KB or less.
|
||||||
|
|
||||||
|
* Signatures for types other than DSA_SHA1 were redefined in release 0.9.14.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [DATAGRAMS]
|
||||||
|
{{ site_url('docs/api/datagrams', True) }}
|
||||||
|
|
||||||
|
.. [TRANSPORT]
|
||||||
|
{{ site_url('docs/transport', True) }}
|
||||||
|
|
||||||
|
.. [TUNMSG]
|
||||||
|
{{ spec_url('tunnel-message') }}#notes
|
84
i2p2www/spec/geoip.rst
Normal file
84
i2p2www/spec/geoip.rst
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
========================
|
||||||
|
GeoIP File Specification
|
||||||
|
========================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: December 2013
|
||||||
|
:accuratefor: 0.9.9
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This page specifies the format of the various GeoIP files,
|
||||||
|
used by the router to look up a country for an IP.
|
||||||
|
|
||||||
|
|
||||||
|
Country Name (countries.txt) Format
|
||||||
|
===================================
|
||||||
|
|
||||||
|
This format is easily generated from data files available from many public sources.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='bash' %}$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
|
||||||
|
$ unzip GeoIPCountryCSV.zip
|
||||||
|
$ cut -d, -f5,6 < GeoIPCountryWhois.csv | sed 's/"//g' | sort | uniq > countries.txt
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
* Encoding is UTF-8
|
||||||
|
* '#' in column 1 specifies a comment line
|
||||||
|
* Entry lines are CountryCode,CountryName
|
||||||
|
* CountryCode is the ISO two-letter code, upper case
|
||||||
|
* CountryName is in English
|
||||||
|
|
||||||
|
|
||||||
|
IPv4 (geoip.txt) Format
|
||||||
|
=======================
|
||||||
|
|
||||||
|
This format is borrowed from Tor and is easily generated from data files available from many public sources.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='bash' %}$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
|
||||||
|
$ unzip GeoIPCountryCSV.zip
|
||||||
|
$ cut -d, -f3-5 < GeoIPCountryWhois.csv | sed 's/"//g' > geoip.txt
|
||||||
|
$ cut -d, -f5,6 < GeoIPCountryWhois.csv | sed 's/"//g' | sort | uniq > countries.txt
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
* Encoding is ASCII
|
||||||
|
* '#' in column 1 specifies a comment line
|
||||||
|
* Entry lines are FromIP,ToIP,CountryCode
|
||||||
|
* FromIP and ToIP are unsigned integer representations of the 4-byte IP
|
||||||
|
* CountryCode is the ISO two-letter code, upper case
|
||||||
|
* Entry lines must be sorted by numeric FromIP
|
||||||
|
|
||||||
|
|
||||||
|
IPv6 (geoipv6.dat.gz) Format
|
||||||
|
============================
|
||||||
|
|
||||||
|
This is a compressed binary format designed for I2P.
|
||||||
|
The file is gzipped. Ungzipped format:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight %} Bytes 0-9: Magic number "I2PGeoIPv6"
|
||||||
|
Bytes 10-11: Version (0x0001)
|
||||||
|
Bytes 12-15 Options (0x00000000) (future use)
|
||||||
|
Bytes 16-23: Creation date (ms since 1970-01-01)
|
||||||
|
Bytes 24-xx: Optional comment (UTF-8) terminated by zero byte
|
||||||
|
Bytes xx-255: null padding
|
||||||
|
Bytes 256-: 18 byte records:
|
||||||
|
8 byte from (/64)
|
||||||
|
8 byte to (/64)
|
||||||
|
2 byte ISO country code LOWER case (ASCII)
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
NOTES:
|
||||||
|
|
||||||
|
* Data must be sorted (SIGNED long twos complement), no overlap.
|
||||||
|
So the order is 80000000 ... FFFFFFFF 00000000 ... 7FFFFFFF.
|
||||||
|
* The GeoIPv6.java class contains a program to generate this format from
|
||||||
|
public sources such as the Maxmind GeoLite data.
|
||||||
|
* IPv6 GeoIP lookup is supported as of release 0.9.8.
|
1383
i2p2www/spec/i2cp.rst
Normal file
1383
i2p2www/spec/i2cp.rst
Normal file
File diff suppressed because it is too large
Load Diff
1285
i2p2www/spec/i2np.rst
Normal file
1285
i2p2www/spec/i2np.rst
Normal file
File diff suppressed because it is too large
Load Diff
650
i2p2www/spec/plugin.rst
Normal file
650
i2p2www/spec/plugin.rst
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
====================
|
||||||
|
Plugin Specification
|
||||||
|
====================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: May 2015
|
||||||
|
:accuratefor: 0.9.20
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This document specifies a .xpi2p file format (like the Firefox .xpi), but with
|
||||||
|
a simple plugin.config description file instead of an XML install.rdf file.
|
||||||
|
This file format is used for both initial plugin installs and plugin updates.
|
||||||
|
|
||||||
|
In addition, this document provides a brief overview of how the router installs
|
||||||
|
plugins, and policies and guidelines for plugin developers.
|
||||||
|
|
||||||
|
The basic .xpi2p file format is the same as a i2pupdate.sud file (the format
|
||||||
|
used for router updates), but the installer will let the user install the addon
|
||||||
|
even if it doesn't know the signer's key yet.
|
||||||
|
|
||||||
|
As of release 0.9.15, the SU3 file format [UPDATES]_ is supported and is
|
||||||
|
preferred. This format enables stronger signing keys.
|
||||||
|
|
||||||
|
The standard directory structure will let users install the following types of
|
||||||
|
addons:
|
||||||
|
|
||||||
|
* console webapps
|
||||||
|
|
||||||
|
* new eepsite with cgi-bin, webapps
|
||||||
|
|
||||||
|
* console themes
|
||||||
|
|
||||||
|
* console translations
|
||||||
|
|
||||||
|
* Java programs
|
||||||
|
|
||||||
|
* Java programs in a separate JVM
|
||||||
|
|
||||||
|
* Any shell script or program
|
||||||
|
|
||||||
|
A plugin installs all its files in ~/.i2p/plugins/name/
|
||||||
|
(%APPDIR%\I2P\plugins\name\ on Windows). The installer will prevent
|
||||||
|
installation anywhere else, although the plugin can access libraries elsewhere
|
||||||
|
when running.
|
||||||
|
|
||||||
|
This should be viewed only as a way to make installation, uninstallation, and
|
||||||
|
upgrading easier, and to lessen basic inter-plugin conflicts.
|
||||||
|
|
||||||
|
There is essentially no security model once the plugin is running, however. The
|
||||||
|
plugin runs in the same JVM and with the same permissions as the router, and
|
||||||
|
has full access to the file system, the router, executing external programs,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
Details
|
||||||
|
=======
|
||||||
|
|
||||||
|
foo.xpi2p is a signed update (sud) file [UPDATES]_ containing the following:
|
||||||
|
|
||||||
|
Standard .sud header prepended to the zip file, containing the following::
|
||||||
|
|
||||||
|
40-byte DSA signature [CRYPTO-DSA]_
|
||||||
|
16-byte plugin version in UTF-8, padded with trailing zeroes if necessary
|
||||||
|
|
||||||
|
Zip file containing the following:
|
||||||
|
|
||||||
|
plugin.config file
|
||||||
|
``````````````````
|
||||||
|
This file is required. It is a standard I2P configuration file [CONFIG]_,
|
||||||
|
containing the following properties:
|
||||||
|
|
||||||
|
The following four are required properties. The first three must be identical
|
||||||
|
to those in the installed plugin for an update plugin.
|
||||||
|
|
||||||
|
name
|
||||||
|
Will be installed in this directory name
|
||||||
|
|
||||||
|
For native plugins, you may want separate names in different packages -
|
||||||
|
foo-windows and foo-linux, for example
|
||||||
|
|
||||||
|
key
|
||||||
|
DSA public key [CRYPTO-DSA]_ as 172 B64 chars ending with '='
|
||||||
|
|
||||||
|
Omit for SU3 format.
|
||||||
|
|
||||||
|
signer
|
||||||
|
yourname@mail.i2p recommended)
|
||||||
|
|
||||||
|
version
|
||||||
|
Must be in a format VersionComparator can parse, e.g. 1.2.3-4
|
||||||
|
|
||||||
|
16 bytes max (must match sud version)
|
||||||
|
|
||||||
|
Valid number separators are '.', '-', and '_'
|
||||||
|
|
||||||
|
This must be greater than the one in the installed plugin for an update plugin.
|
||||||
|
|
||||||
|
Values for the following properties are displayed on /configclients in the
|
||||||
|
router console if present:
|
||||||
|
|
||||||
|
date
|
||||||
|
Java time - long int
|
||||||
|
|
||||||
|
author
|
||||||
|
yourname@mail.i2p recommended
|
||||||
|
|
||||||
|
websiteURL
|
||||||
|
http://foo.i2p/
|
||||||
|
|
||||||
|
updateURL
|
||||||
|
http://foo.i2p/foo.xpi2p
|
||||||
|
|
||||||
|
The update checker will check bytes 41-56 at this URL
|
||||||
|
to determine whether a newer version is available
|
||||||
|
|
||||||
|
(Should the checker fetch with ?currentVersion=1.2.3?...
|
||||||
|
No. If the dev wants to have the URL contain the current version, just
|
||||||
|
set it in the config file, and remember to change it every release)
|
||||||
|
|
||||||
|
updateURL.su3
|
||||||
|
http://foo.i2p/foo.su3
|
||||||
|
|
||||||
|
The location of the su3-format update file, as of 0.9.15
|
||||||
|
|
||||||
|
description
|
||||||
|
in English
|
||||||
|
|
||||||
|
description_xx
|
||||||
|
for language xx
|
||||||
|
|
||||||
|
license
|
||||||
|
The plugin license
|
||||||
|
|
||||||
|
disableStop=true
|
||||||
|
Default false.
|
||||||
|
If true, the stop button will not be shown. Use this if there are no
|
||||||
|
webapps and no clients with stopargs.
|
||||||
|
|
||||||
|
The following properties are used to add a link on the console summary bar:
|
||||||
|
|
||||||
|
consoleLinkName
|
||||||
|
will be added to summary bar
|
||||||
|
|
||||||
|
consoleLinkName_xx
|
||||||
|
for language xx
|
||||||
|
|
||||||
|
consoleLinkURL
|
||||||
|
/appname/index.jsp
|
||||||
|
|
||||||
|
consoleLinkTooltip
|
||||||
|
supported as of 0.7.12-6
|
||||||
|
|
||||||
|
consoleLinkTooltip_xx
|
||||||
|
lang xx as of 0.7.12-6
|
||||||
|
|
||||||
|
The following optional property may be used to add a custom icon on the
|
||||||
|
console:
|
||||||
|
|
||||||
|
console-icon
|
||||||
|
supported as of 0.9.20
|
||||||
|
|
||||||
|
Only for webapps.
|
||||||
|
|
||||||
|
A path within the webapp to a 32x32 image, e.g. /icon.png
|
||||||
|
Applies to all webapps in the plugin.
|
||||||
|
|
||||||
|
The following properties are used by the plugin installer:
|
||||||
|
|
||||||
|
type
|
||||||
|
app/theme/locale/webapp/...
|
||||||
|
|
||||||
|
(unimplemented, probably not necessary)
|
||||||
|
|
||||||
|
min-i2p-version
|
||||||
|
The minimum version of I2P this plugin requires
|
||||||
|
|
||||||
|
max-i2p-version
|
||||||
|
The maximum version of I2P this plugin will run on
|
||||||
|
|
||||||
|
min-java-version
|
||||||
|
The minimum version of Java this plugin requires
|
||||||
|
|
||||||
|
min-jetty-version
|
||||||
|
supported as of 0.8.13, use 6 for Jetty 6 webapps
|
||||||
|
|
||||||
|
max-jetty-version
|
||||||
|
supported as of 0.8.13, use 5.99999 for Jetty 5 webapps
|
||||||
|
|
||||||
|
required-platform-OS
|
||||||
|
unimplemented - perhaps will be displayed only, not verified
|
||||||
|
|
||||||
|
other-requirements
|
||||||
|
unimplemented
|
||||||
|
|
||||||
|
e.g. python x.y - not verified by the installer, just displayed to the
|
||||||
|
user
|
||||||
|
|
||||||
|
dont-start-at-install=true
|
||||||
|
Default false.
|
||||||
|
|
||||||
|
Won't start the plugin when it is installed or updated. On initial
|
||||||
|
installation, configures the plugin so the user must manually start it.
|
||||||
|
An update will not change the user's preference to start it if they
|
||||||
|
choose to do so.
|
||||||
|
|
||||||
|
router-restart-required=true
|
||||||
|
Default false.
|
||||||
|
|
||||||
|
This does not restart the router or the plugin on an update, it just
|
||||||
|
informs the user that a restart is required. It has no effect on initial
|
||||||
|
plugin installation.
|
||||||
|
|
||||||
|
update-only=true
|
||||||
|
Default false.
|
||||||
|
|
||||||
|
If true, will fail if an installation does not exist.
|
||||||
|
|
||||||
|
install-only=true
|
||||||
|
Default false.
|
||||||
|
If true, will fail if an installation exists.
|
||||||
|
|
||||||
|
min-installed-version
|
||||||
|
to update over, if an installation exists
|
||||||
|
|
||||||
|
max-installed-version
|
||||||
|
to update over, if an installation exists
|
||||||
|
|
||||||
|
depends=plugin1,plugin2,plugin3
|
||||||
|
unimplemented - is this too hard? proposed by sponge
|
||||||
|
|
||||||
|
depends-version=0.3.4,,5.6.7
|
||||||
|
unimplemented
|
||||||
|
|
||||||
|
The following property is used for translation plugins:
|
||||||
|
|
||||||
|
langs=xx,yy,Klingon,...
|
||||||
|
(unimplemented)
|
||||||
|
(yy is the country flag)
|
||||||
|
|
||||||
|
Application Directories and Files
|
||||||
|
`````````````````````````````````
|
||||||
|
Each of the following directories or files is optional, but something must be
|
||||||
|
there or it won't do anything:
|
||||||
|
|
||||||
|
console/
|
||||||
|
locale/
|
||||||
|
Only jars containing new resource bundles (translations) for apps in the
|
||||||
|
base I2P installation. Bundles for this plugin should go inside
|
||||||
|
console/webapp/foo.war or lib/foo.jar
|
||||||
|
|
||||||
|
themes/
|
||||||
|
New themes for the router console
|
||||||
|
Place each theme in a subdirectory.
|
||||||
|
|
||||||
|
webapps/
|
||||||
|
(See important notes below about webapps)
|
||||||
|
|
||||||
|
.wars
|
||||||
|
These will be run at install time unless disabled in webapps.config
|
||||||
|
The war name does not have to be the same as the plugin name.
|
||||||
|
Do not duplicate war names in the base I2P installation.
|
||||||
|
|
||||||
|
webapps.config
|
||||||
|
Same format as router's webapps.config. Also used to specify additional
|
||||||
|
jars in $PLUGIN/lib/ or $I2P/lib for the webapp classpath, with
|
||||||
|
``webapps.warname.classpath=$PLUGIN/lib/foo.jar,$I2P/lib/bar.jar``
|
||||||
|
|
||||||
|
NOTE: Currently, the classpath line is only loaded if the warname is the
|
||||||
|
same as the plugin name.
|
||||||
|
|
||||||
|
NOTE: Prior to router version 0.7.12-9, the router looked for
|
||||||
|
``plugin.warname.startOnLoad`` instead of
|
||||||
|
``webapps.warname.startOnLoad``. For compatibility with older router
|
||||||
|
versions, a plugin wishing to disable a war should include both lines.
|
||||||
|
|
||||||
|
eepsite/
|
||||||
|
(See important notes below about eepsites)
|
||||||
|
|
||||||
|
cgi-bin/
|
||||||
|
|
||||||
|
docroot/
|
||||||
|
|
||||||
|
logs/
|
||||||
|
|
||||||
|
webapps/
|
||||||
|
|
||||||
|
jetty.xml
|
||||||
|
The installer will have to do variable substitution in here to set the
|
||||||
|
path. The location and name of this file doesn't really matter, as long
|
||||||
|
as it is set in clients.config - it may be more convenient to be up one
|
||||||
|
level from here (that's what the zzzot plugin does)
|
||||||
|
|
||||||
|
lib/
|
||||||
|
Put any jars here, and specify them in a classpath line in
|
||||||
|
console/webapps.config and/or clients.config
|
||||||
|
|
||||||
|
clients.config file
|
||||||
|
```````````````````
|
||||||
|
This file is optional, and specifies clients that will be run when a plugin is
|
||||||
|
started. It uses the same format as the router's clients.config file. See the
|
||||||
|
clients.config configuration file specification [CONFIG]_ for more information
|
||||||
|
about the format and important details about how clients are started and
|
||||||
|
stopped.
|
||||||
|
|
||||||
|
property clientApp.0.stopargs=foo bar stop baz
|
||||||
|
If present, the class will be called with these args to stop the client
|
||||||
|
All stop tasks are called with zero delay
|
||||||
|
Note: The router can't tell if your unmanaged clients are running or not.
|
||||||
|
Each should handle stopping an app that isn't running without complaint.
|
||||||
|
That probably goes for starting a client that is already started too.
|
||||||
|
|
||||||
|
property clientApp.0.uninstallargs=foo bar uninstall baz
|
||||||
|
If present, the class will be called with these args just before
|
||||||
|
deleting $PLUGIN. All uninstall tasks are called with zero delay
|
||||||
|
|
||||||
|
property clientApp.0.classpath=$I2P/lib/foo.bar,$PLUGIN/lib/bar.jar
|
||||||
|
The plugin runner will do variable substitution in the args and stopargs
|
||||||
|
lines as follows:
|
||||||
|
|
||||||
|
$I2P
|
||||||
|
I2P base installation dir
|
||||||
|
|
||||||
|
$CONFIG
|
||||||
|
I2P config dir (typically ~/.i2p)
|
||||||
|
|
||||||
|
$PLUGIN
|
||||||
|
this plugin's installation dir (typically ~/.i2p/plugins/appname)
|
||||||
|
|
||||||
|
(See important notes below about running shell scripts or external
|
||||||
|
programs)
|
||||||
|
|
||||||
|
|
||||||
|
Plugin installer tasks
|
||||||
|
======================
|
||||||
|
|
||||||
|
This lists what happens when a plugin is installed by I2P.
|
||||||
|
|
||||||
|
* The .xpi2p file is downloaded.
|
||||||
|
|
||||||
|
* The .sud signature is verified against stored keys. As of release 0.9.14.1,
|
||||||
|
if there is no matching key, the installation fails, unless an advanced
|
||||||
|
router property is set to allow all keys.
|
||||||
|
|
||||||
|
* Verify the integrity of the zip file.
|
||||||
|
|
||||||
|
* Extract the plugin.config file.
|
||||||
|
|
||||||
|
* Verify the I2P version, to make sure the plugin will work.
|
||||||
|
|
||||||
|
* Check that webapps don't duplicate the existing $I2P applications.
|
||||||
|
|
||||||
|
* Stop the existing plugin (if present).
|
||||||
|
|
||||||
|
* Verify that the install directory does not exist yet if update=false, or ask
|
||||||
|
to overwrite.
|
||||||
|
|
||||||
|
* Verify that the install directory does exist if update=true, or ask to
|
||||||
|
create.
|
||||||
|
|
||||||
|
* Unzip the plugin in to appDir/plugins/name/
|
||||||
|
|
||||||
|
* Add the plugin to plugins.config
|
||||||
|
|
||||||
|
|
||||||
|
Plugin starter tasks
|
||||||
|
====================
|
||||||
|
|
||||||
|
This lists what happens when plugins are started.
|
||||||
|
First, plugins.config is checked to see which plugins need to be started.
|
||||||
|
For each plugin:
|
||||||
|
|
||||||
|
* Check clients.config, and load and start each item (add the configured jars
|
||||||
|
to the classpath).
|
||||||
|
|
||||||
|
* Check console/webapp and console/webapp.config. Load and start required items
|
||||||
|
(add the configured jars to the classpath).
|
||||||
|
|
||||||
|
* Add console/locale/foo.jar to the translation classpath if present.
|
||||||
|
|
||||||
|
* Add console/theme to the theme search path if present.
|
||||||
|
|
||||||
|
* Add the summary bar link.
|
||||||
|
|
||||||
|
|
||||||
|
Console webapp notes
|
||||||
|
====================
|
||||||
|
|
||||||
|
Console webapps with background tasks should implement a ServletContextListener
|
||||||
|
(see seedless or i2pbote for examples), or override destroy() in the servlet,
|
||||||
|
so that they can be stopped. As of router version 0.7.12-3, console webapps
|
||||||
|
will always be stopped before they are restarted, so you do not need to worry
|
||||||
|
about multiple instances, as long as you do this. Also as of router version
|
||||||
|
0.7.12-3, console webapps will be stopped at router shutdown.
|
||||||
|
|
||||||
|
Don't bundle library jars in the webapp; put them in lib/ and put a classpath
|
||||||
|
in webapps.config. Then you can make separate install and update plugins,
|
||||||
|
where the update plugin does not contain the library jars.
|
||||||
|
|
||||||
|
Don't include .java or .jsp files; otherwise jetty will recompile them at
|
||||||
|
installation.
|
||||||
|
|
||||||
|
For now, a webapp needing to add classpath files in $PLUGIN must be the same
|
||||||
|
name as the plugin. For example, a webapp in plugin foo must be named foo.war.
|
||||||
|
|
||||||
|
|
||||||
|
Eepsite notes
|
||||||
|
=============
|
||||||
|
|
||||||
|
It isn't clear how to have a plugin install to an existing eepsite. The router
|
||||||
|
has no hook to the eepsite, and it may or may not be running, and there may be
|
||||||
|
more than one. Better is to start your own Jetty instance and I2PTunnel
|
||||||
|
instance, for a brand new eepsite.
|
||||||
|
|
||||||
|
It can instantiate a new I2PTunnel (somewhat like the i2ptunnel CLI does), but
|
||||||
|
it won't appear in the i2ptunnel gui of course, that's a different instance.
|
||||||
|
But that's ok. Then you can start and stop i2ptunnel and jetty together.
|
||||||
|
|
||||||
|
So don't count on the router to automatically merge this with some existing
|
||||||
|
eepsite. It probably won't happen. Start a new I2PTunnel and Jetty from
|
||||||
|
clients.config. The best examples of this are the zzzot and pebble plugins,
|
||||||
|
available at zzz's plugins page [STATS-PLUGINS]_.
|
||||||
|
|
||||||
|
How to get path substitution into jetty.xml? See zzzot and pebble plugins for
|
||||||
|
examples.
|
||||||
|
|
||||||
|
|
||||||
|
Client start/stop notes
|
||||||
|
=======================
|
||||||
|
|
||||||
|
As of release 0.9.4, the router supports "managed" plugin clients. Managed
|
||||||
|
plugin clients are instantiated and started by the ``ClientAppManager``. The
|
||||||
|
ClientAppManager maintains a reference to the client and receives updates on
|
||||||
|
the client's state. Managed plugin client are preferred, as it is much easier
|
||||||
|
to implement state tracking and to start and stop a client. It also is much
|
||||||
|
easier to avoid static references in the client code which could lead to
|
||||||
|
excessive memory usage after a client is stopped. See the clients.config
|
||||||
|
configuration file specification [CONFIG]_ for more information on writing a
|
||||||
|
managed client.
|
||||||
|
|
||||||
|
For "unmanaged" plugin clients, The router has no way to monitor the state of
|
||||||
|
clients started via clients.config. The plugin author should handle multiple
|
||||||
|
start or stop calls gracefully, if at all possible, by keeping a static state
|
||||||
|
table, or using PID files, etc. Avoid logging or exceptions on multiple starts
|
||||||
|
or stops. This also goes for a stop call without a previous start. As of
|
||||||
|
router version 0.7.12-3, plugins will be stopped at router shutdown, which
|
||||||
|
means that all clients with stopargs in clients.config will be called, whether
|
||||||
|
or not they were previously started.
|
||||||
|
|
||||||
|
|
||||||
|
Shell script and external program notes
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
To run shell scripts or other external programs, see [ZZZ-141]_.
|
||||||
|
|
||||||
|
To work on both Windows and Linux, write a small Java class that checks the OS
|
||||||
|
type, then runs ShellCommand on either the .bat or a .sh file you provide.
|
||||||
|
|
||||||
|
External programs won't be stopped when the router stops, and a second copy
|
||||||
|
will fire up when the router starts. To work around this, you could write a
|
||||||
|
wrapper class or shell script that does the usual storage of the PID in a PID
|
||||||
|
file, and check for it on start.
|
||||||
|
|
||||||
|
|
||||||
|
Other plugin guidelines
|
||||||
|
=======================
|
||||||
|
|
||||||
|
* See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p
|
||||||
|
file generator to make it easy.
|
||||||
|
|
||||||
|
* Pack200 of jars and wars is strongly recommended for plugins, it generally
|
||||||
|
shrinks plugins by 60-65%. See any of the sample plugins on zzz's page for
|
||||||
|
an example. Pack200 unpacking is supported on routers 0.7.11-5 or higher,
|
||||||
|
which is essentially all routers that support plugins at all.
|
||||||
|
|
||||||
|
* Plugins should not attempt to write anywhere in $I2P as it may be readonly,
|
||||||
|
and that isn't good policy anyway.
|
||||||
|
|
||||||
|
* Plugins may write to $CONFIG but keeping files in $PLUGIN only is recommended.
|
||||||
|
All files in $PLUGIN will be deleted at uninstall. Files elsewhere will not be
|
||||||
|
deleted at uninstall unless the plugin does it explicitly with a client in
|
||||||
|
clients.config run with uninstallargs. If the user may want to save data after
|
||||||
|
uninstallation, the uninstallargs hook could ask.
|
||||||
|
|
||||||
|
* $CWD may be anywhere; do not assume it is in a particular place, do not
|
||||||
|
attempt to read or write files relative to $CWD.
|
||||||
|
|
||||||
|
* Java programs should find out where they are with the directory getters in
|
||||||
|
I2PAppContext.
|
||||||
|
|
||||||
|
* Plugin directory is
|
||||||
|
``I2PAppContext.getGlobalContext().getAppDir().getAbsolutePath() + "/plugins/" + appname``,
|
||||||
|
or put a $PLUGIN argument in the args line in clients.config. There is no
|
||||||
|
reliable way to find the i2p install or config or plugin directory without
|
||||||
|
using the context API in i2p.jar.
|
||||||
|
|
||||||
|
* See [ZZZ-16]_ for info on generating signing keys and generating/verifying
|
||||||
|
keys and sud files.
|
||||||
|
|
||||||
|
* All config files must be UTF-8.
|
||||||
|
|
||||||
|
* To run in a separate JVM, use ShellCommand with
|
||||||
|
``java -cp foo:bar:baz my.main.class arg1 arg2 arg3``. Of course, it will be a
|
||||||
|
lot harder to stop the plugin then... But with some trickery with PID files it
|
||||||
|
should be possible.
|
||||||
|
|
||||||
|
* As an alternative to stopargs in clients.config, a Java client may register a
|
||||||
|
shutdown hook with I2PAppContext.addShutdownTask(). But this wouldn't shut
|
||||||
|
down a plugin when upgrading, so stopargs is recommended. Also, set all
|
||||||
|
created threads to daemon mode.
|
||||||
|
|
||||||
|
* Do not include classes duplicating those in the standard installation. Extend
|
||||||
|
the classes if necessary.
|
||||||
|
|
||||||
|
* Beware of the different classpath definitions in wrapper.config between old
|
||||||
|
and new installations - see classpath section below.
|
||||||
|
|
||||||
|
* Clients will reject duplicate keys with different keynames, and duplicate
|
||||||
|
keynames with different keys, and different keys or keynames in upgrade
|
||||||
|
packages. Safeguard your keys. Only generate them once.
|
||||||
|
|
||||||
|
* Do not modify the plugin.config file at runtime as it will be overwritten on
|
||||||
|
upgrade. Use a different config file in the directory for storing runtime
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
* In general, plugins should not require access to $I2P/lib/router.jar. Do not
|
||||||
|
access router classes, unless you are doing something special. The router may
|
||||||
|
in the future implement a restricted classpath for plugins that prevents
|
||||||
|
access to router classes.
|
||||||
|
|
||||||
|
* Since each version must be higher than the one before, you could enhance your
|
||||||
|
build script to add a build number to the end of the version. This helps for
|
||||||
|
testing. Most of zzz's plugins have that feature, check build.xml for an example.
|
||||||
|
|
||||||
|
* Plugins must never call ``System.exit()``.
|
||||||
|
|
||||||
|
* Please respect licenses by meeting license requirements for any software you
|
||||||
|
bundle.
|
||||||
|
|
||||||
|
* The router sets the JVM time zone to UTC. If a plugin needs to know the user's
|
||||||
|
actual time zone, it is stored by the router in the I2PAppContext property
|
||||||
|
``i2p.systemTimeZone``.
|
||||||
|
|
||||||
|
|
||||||
|
Classpaths
|
||||||
|
==========
|
||||||
|
|
||||||
|
The following jars in $I2P/lib can be assumed to be in the standard classpath
|
||||||
|
for all I2P installations, no matter how old or how new the original
|
||||||
|
installation::
|
||||||
|
|
||||||
|
i2p.jar, router.jar, jbigi.jar, sam.jar, mstreaming.jar, streaming.jar, i2ptunnel.jar,
|
||||||
|
org.mortbay.jetty.jar, javax.servlet.jar, jasper-compiler.jar, jasper-runtime.jar,
|
||||||
|
commons-logging.jar, commons-el.jar, wrapper.jar, systray.jar, systray4j.jar
|
||||||
|
|
||||||
|
The following jars in $I2P/lib can be assumed to be present for all I2P
|
||||||
|
installations, no matter how old or how new the original installation, but are
|
||||||
|
not necessarily in the classpath::
|
||||||
|
|
||||||
|
jstl.jar, standard.jar
|
||||||
|
|
||||||
|
Anything not listed above may not be present in everybody's classpath, even if
|
||||||
|
you have it in the classpath in YOUR version of i2p. If you need any jar not
|
||||||
|
listed above, add $I2P/lib/foo.jar to the classpath specified in clients.config
|
||||||
|
or webapps.config in your plugin.
|
||||||
|
|
||||||
|
Previously, a classpath entry specified in clients.config was added to the
|
||||||
|
classpath for the entire JVM. However, as of 0.7.13-3, this was fixed using
|
||||||
|
class loaders, and now, as originally intended, the specified classpath in
|
||||||
|
clients.config is only for the particular thread. See the section on JVM
|
||||||
|
crashes below, and [ZZZ-633]_ for background. Therefore, specify the full
|
||||||
|
required classpath for each client.
|
||||||
|
|
||||||
|
|
||||||
|
Java Version Notes
|
||||||
|
==================
|
||||||
|
|
||||||
|
While most I2P users are running a 1.6 (6.0) JVM, we support 1.5 (5.0) and
|
||||||
|
higher JVMs. Unless you require 1.6 features, you should create your plugin so
|
||||||
|
it works on 1.5.
|
||||||
|
|
||||||
|
If your plugin **does not require 1.6**:
|
||||||
|
|
||||||
|
* Ensure that all java and jsp files are compiled with source="1.5"
|
||||||
|
target="1.5".
|
||||||
|
|
||||||
|
* Ensure that all bundled library jars are also for 1.5 or lower.
|
||||||
|
|
||||||
|
* If you are using pack200, any 1.6 classes in a jar will cause pack200 to
|
||||||
|
create a 1.6 pack format, and plugin installation will fail on a 1.5 system
|
||||||
|
with the misleading message "plugin is corrupt".
|
||||||
|
|
||||||
|
If your plugin **requires 1.6**:
|
||||||
|
|
||||||
|
* Note that on your download page.
|
||||||
|
|
||||||
|
* Add min-java-version=1.6 to your plugin.config
|
||||||
|
|
||||||
|
* If you are using pack200, plugin installation will fail on a 1.5 system with
|
||||||
|
the misleading message "plugin is corrupt".
|
||||||
|
|
||||||
|
|
||||||
|
JVM Crashes When Updating
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Note - this should all be fixed now.
|
||||||
|
|
||||||
|
The JVM has a tendency to crash when updating jars in a plugin if that plugin
|
||||||
|
was running since I2P was started (even if the plugin was later stopped). This
|
||||||
|
may have been fixed with the class loader implementation in 0.7.13-3, but it
|
||||||
|
may not. For further testing.
|
||||||
|
|
||||||
|
The safest is to design your plugin with the jar inside the war (for a webapp),
|
||||||
|
or to require a restart after update, or don't update the jars in your plugin.
|
||||||
|
|
||||||
|
Due to the way class loaders work inside a webapp, it _may_ be safe to have
|
||||||
|
external jars if you specify the classpath in webapps.config. More testing is
|
||||||
|
required to verify this. Don't specify the classpath with a 'fake' client in
|
||||||
|
clients.config if it's only needed for a webapp - use webapps.config instead.
|
||||||
|
|
||||||
|
The least safe, and apparently the source of most crashes, is clients with
|
||||||
|
plugin jars specified in the classpath in clients.config.
|
||||||
|
|
||||||
|
None of this should be a problem on initial install - you should not ever have
|
||||||
|
to require a restart for an initial install of a plugin.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [CONFIG]
|
||||||
|
{{ spec_url('configuration') }}
|
||||||
|
|
||||||
|
.. [CRYPTO-DSA]
|
||||||
|
{{ site_url('docs/how/cryptography', True) }}#DSA
|
||||||
|
|
||||||
|
.. [STATS-PLUGINS]
|
||||||
|
http://{{ i2pconv('stats.i2p') }}/i2p/plugins/
|
||||||
|
|
||||||
|
.. [UPDATES]
|
||||||
|
{{ spec_url('updates') }}
|
||||||
|
|
||||||
|
.. [ZZZ-16]
|
||||||
|
http://{{ i2pconv('zzz.i2p') }}/topics/16
|
||||||
|
|
||||||
|
.. [ZZZ-141]
|
||||||
|
http://{{ i2pconv('zzz.i2p') }}/topics/141
|
||||||
|
|
||||||
|
.. [ZZZ-633]
|
||||||
|
http://{{ i2pconv('zzz.i2p') }}/topics/633
|
76
i2p2www/spec/spectags
Normal file
76
i2p2www/spec/spectags
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
||||||
|
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
||||||
|
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
||||||
|
BandwidthLimits i2cp.rst 441;" m
|
||||||
|
Boolean common-structures.rst 110;" t
|
||||||
|
BuildRequestRecord i2np.rst 175;" s
|
||||||
|
BuildResponseRecord i2np.rst 349;" s
|
||||||
|
Certificate common-structures.rst 340;" t
|
||||||
|
CreateLeaseSet i2cp.rst 469;" m
|
||||||
|
CreateSession i2cp.rst 503;" m
|
||||||
|
Data i2np.rst 1098;" m
|
||||||
|
DatabaseLookup i2np.rst 653;" m
|
||||||
|
DatabaseSearchReply i2np.rst 808;" m
|
||||||
|
DatabaseStore i2np.rst 552;" m
|
||||||
|
Date common-structures.rst 80;" t
|
||||||
|
DeliveryInstructions common-structures.rst 1070;" s
|
||||||
|
DeliveryStatus i2np.rst 882;" m
|
||||||
|
DestLookup i2cp.rst 535;" m
|
||||||
|
DestReply i2cp.rst 557;" m
|
||||||
|
Destination common-structures.rst 680;" s
|
||||||
|
DestroySession i2cp.rst 580;" m
|
||||||
|
Disconnect i2cp.rst 599;" m
|
||||||
|
Garlic i2np.rst 925;" m
|
||||||
|
GarlicClove i2np.rst 394;" s
|
||||||
|
GarlicCloveDeliveryInstructions i2np.rst 456;" s
|
||||||
|
GetBandwidthLimits i2cp.rst 619;" m
|
||||||
|
GetDate i2cp.rst 642;" m
|
||||||
|
Hash common-structures.rst 293;" t
|
||||||
|
HostLookup i2cp.rst 675;" m
|
||||||
|
HostReply i2cp.rst 715;" m
|
||||||
|
I2CPMessageHeader i2cp.rst 299;" s
|
||||||
|
I2NPMessageHeader i2np.rst 93;" s
|
||||||
|
Integer common-structures.rst 67;" t
|
||||||
|
KeysAndCert common-structures.rst 580;" s
|
||||||
|
Lease common-structures.rst 713;" s
|
||||||
|
LeaseSet common-structures.rst 761;" s
|
||||||
|
Mapping common-structures.rst 502;" t
|
||||||
|
MessageId i2cp.rst 319;" s
|
||||||
|
MessagePayload i2cp.rst 740;" m
|
||||||
|
MessageStatus i2cp.rst 761;" m
|
||||||
|
Payload i2cp.rst 338;" s
|
||||||
|
PrivateKey common-structures.rst 145;" t
|
||||||
|
PublicKey common-structures.rst 128;" t
|
||||||
|
ReceiveMessageBegin i2cp.rst 903;" m
|
||||||
|
ReceiveMessageEnd i2cp.rst 929;" m
|
||||||
|
ReconfigureSession i2cp.rst 954;" m
|
||||||
|
ReportAbuse i2cp.rst 984;" m
|
||||||
|
RequestLeaseSet i2cp.rst 1012;" m
|
||||||
|
RequestVariableLeaseSet i2cp.rst 1040;" m
|
||||||
|
RouterAddress common-structures.rst 897;" s
|
||||||
|
RouterIdentity common-structures.rst 651;" s
|
||||||
|
RouterInfo common-structures.rst 969;" s
|
||||||
|
SendMessage i2cp.rst 1066;" m
|
||||||
|
SendMessageExpires i2cp.rst 1109;" m
|
||||||
|
SessionConfig i2cp.rst 358;" s
|
||||||
|
SessionId i2cp.rst 385;" s
|
||||||
|
SessionKey common-structures.rst 162;" t
|
||||||
|
SessionStatus i2cp.rst 1252;" m
|
||||||
|
SessionTag common-structures.rst 308;" t
|
||||||
|
SetDate i2cp.rst 1297;" m
|
||||||
|
Signature common-structures.rst 254;" t
|
||||||
|
SigningPrivateKey common-structures.rst 216;" t
|
||||||
|
SigningPublicKey common-structures.rst 177;" t
|
||||||
|
String common-structures.rst 94;" t
|
||||||
|
Tunnel tunnel-message.rst 33;" m
|
||||||
|
TunnelBuild i2np.rst 1127;" m
|
||||||
|
TunnelBuildReply i2np.rst 1162;" m
|
||||||
|
TunnelData i2np.rst 1020;" m
|
||||||
|
TunnelGateway i2np.rst 1063;" m
|
||||||
|
TunnelId common-structures.rst 323;" t
|
||||||
|
TunnelMessageDeliveryInstructions tunnel-message.rst 161;" s
|
||||||
|
VariableTunnelBuild i2np.rst 1180;" m
|
||||||
|
VariableTunnelBuildReply i2np.rst 1213;" m
|
1194
i2p2www/spec/ssu.rst
Normal file
1194
i2p2www/spec/ssu.rst
Normal file
File diff suppressed because it is too large
Load Diff
191
i2p2www/spec/streaming.rst
Normal file
191
i2p2www/spec/streaming.rst
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
===============================
|
||||||
|
Streaming Library Specification
|
||||||
|
===============================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: June 2015
|
||||||
|
:accuratefor: 0.9.20
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
See [STREAMING]_ for an overview of the Streaming Library.
|
||||||
|
|
||||||
|
|
||||||
|
Protocol Specification
|
||||||
|
======================
|
||||||
|
|
||||||
|
Packet Format
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The format of a single packet in the streaming protocol is:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' %}
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| send Stream ID | rcv Stream ID |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| sequence Num | ack Through |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| nc | NACKs ...
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| rd | flags | opt size| opt data
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
... |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| payload ...
|
||||||
|
+----+----+----+-//
|
||||||
|
|
||||||
|
sendStreamId :: 4 byte `Integer`
|
||||||
|
Random number selected by the packet recipient before sending
|
||||||
|
the first SYN reply packet and constant for the life of the
|
||||||
|
connection. 0 in the SYN message sent by the connection
|
||||||
|
originator, and in subsequent messages, until a SYN reply is
|
||||||
|
received, containing the peer's stream ID.
|
||||||
|
|
||||||
|
receiveStreamId :: 4 byte `Integer`
|
||||||
|
Random number selected by the packet originator before
|
||||||
|
sending the first SYN packet and constant for the life of
|
||||||
|
the connection. May be 0 if unknown, for example in a RESET
|
||||||
|
packet.
|
||||||
|
|
||||||
|
sequenceNum :: 4 byte `Integer`
|
||||||
|
The sequence for this message, starting at 0 in the SYN
|
||||||
|
message, and incremented by 1 in each message except for plain
|
||||||
|
ACKs and retransmissions. If the sequenceNum is 0 and the SYN
|
||||||
|
flag is not set, this is a plain ACK packet that should not be
|
||||||
|
ACKed.
|
||||||
|
|
||||||
|
ackThrough :: 4 byte `Integer`
|
||||||
|
The highest packet sequence number that was received on the
|
||||||
|
$receiveStreamId. This field is ignored on the initial
|
||||||
|
connection packet (where $receiveStreamId is the unknown id) or
|
||||||
|
if the NO_ACK flag set. All packets up to and including this
|
||||||
|
sequence number are ACKed, EXCEPT for those listed in NACKs
|
||||||
|
below.
|
||||||
|
|
||||||
|
NACK count :: 1 byte `Integer`
|
||||||
|
The number of 4-byte NACKs in the next field
|
||||||
|
|
||||||
|
NACKs :: $nc * 4 byte `Integer`s
|
||||||
|
Sequence numbers less than ackThrough that are not yet received. Two
|
||||||
|
NACKs of a packet is a request for a 'fast retransmit' of that packet.
|
||||||
|
|
||||||
|
resendDelay :: 1 byte `Integer`
|
||||||
|
How long is the creator of this packet going to wait before
|
||||||
|
resending this packet (if it hasn't yet been ACKed). The value
|
||||||
|
is seconds since the packet was created. Currently ignored on
|
||||||
|
receive.
|
||||||
|
|
||||||
|
flags :: 2 byte value
|
||||||
|
See below.
|
||||||
|
|
||||||
|
option size :: 2 byte `Integer`
|
||||||
|
The number of bytes in the next field
|
||||||
|
|
||||||
|
option data :: 0 or more bytes
|
||||||
|
As specified by the flags. See below.
|
||||||
|
|
||||||
|
payload :: remaining packet size
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Flags and Option Data Fields
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The flags field above specifies some metadata about the packet, and in turn may
|
||||||
|
require certain additional data to be included. The flags are as follows. Any
|
||||||
|
data structures specified must be added to the options area in the given order.
|
||||||
|
|
||||||
|
Bit order: 15....0 (15 is MSB)
|
||||||
|
|
||||||
|
===== ======================== ============ =============== ===============================================================
|
||||||
|
Bit Flag Option Order Option Data Function
|
||||||
|
===== ======================== ============ =============== ===============================================================
|
||||||
|
0 SYNCHRONIZE -- -- Similar to TCP SYN. Set in the initial packet and in the first
|
||||||
|
response. FROM_INCLUDED and SIGNATURE_INCLUDED must also be
|
||||||
|
set.
|
||||||
|
|
||||||
|
1 CLOSE -- -- Similar to TCP FIN. If the response to a SYNCHRONIZE fits in a
|
||||||
|
single message, the response will contain both SYNCHRONIZE and
|
||||||
|
CLOSE. SIGNATURE_INCLUDED must also be set.
|
||||||
|
|
||||||
|
2 RESET -- -- Abnormal close. SIGNATURE_INCLUDED must also be set. Prior to
|
||||||
|
release 0.9.20, due to a bug, FROM_INCLUDED must also be set.
|
||||||
|
|
||||||
|
3 SIGNATURE_INCLUDED 4 variable length Currently sent only with SYNCHRONIZE, CLOSE, and RESET, where
|
||||||
|
[Signature]_ it is required, and with ECHO, where it is required for a
|
||||||
|
ping. The signature uses the Destination's [SigningPrivateKey]_
|
||||||
|
to sign the entire header and payload with the space in the
|
||||||
|
option data field for the signature being set to all zeroes.
|
||||||
|
|
||||||
|
Prior to release 0.9.11, the signature was always 40 bytes. As
|
||||||
|
of release 0.9.11, the signature may be variable-length, see
|
||||||
|
below for details.
|
||||||
|
|
||||||
|
4 SIGNATURE_REQUESTED -- -- Unused. Requests every packet in the other direction to have
|
||||||
|
SIGNATURE_INCLUDED
|
||||||
|
|
||||||
|
5 FROM_INCLUDED 2 387+ byte Currently sent only with SYNCHRONIZE, where it is required, and
|
||||||
|
[Destination]_ with ECHO, where it is required for a ping. Prior to release
|
||||||
|
0.9.20, due to a bug, must also be sent with RESET.
|
||||||
|
|
||||||
|
6 DELAY_REQUESTED 1 2 byte Optional delay. How many milliseconds the sender of this packet
|
||||||
|
[Integer]_ wants the recipient to wait before sending any more data. A
|
||||||
|
value greater than 60000 indicates choking.
|
||||||
|
|
||||||
|
7 MAX_PACKET_SIZE_INCLUDED 3 2 byte Currently sent with SYNCHRONIZE only. Was also sent in
|
||||||
|
[Integer]_ retransmitted packets until release 0.9.1.
|
||||||
|
|
||||||
|
8 PROFILE_INTERACTIVE -- -- Unused or ignored; the interactive profile is unimplemented.
|
||||||
|
|
||||||
|
9 ECHO -- -- Unused except by ping programs. If set, most other options are
|
||||||
|
ignored. See the streaming docs [STREAMING]_.
|
||||||
|
|
||||||
|
10 NO_ACK -- -- This flag simply tells the recipient to ignore the ackThrough
|
||||||
|
field in the header. Currently set in the inital SYN packet,
|
||||||
|
otherwise the ackThrough field is always valid. Note that this
|
||||||
|
does not save any space, the ackThrough field is before the
|
||||||
|
flags and is always present.
|
||||||
|
|
||||||
|
11-15 unused Set to zero for compatibility with future uses.
|
||||||
|
===== ======================== ============ =============== ===============================================================
|
||||||
|
|
||||||
|
Variable Length Signature Notes
|
||||||
|
```````````````````````````````
|
||||||
|
Prior to release 0.9.11, the signature in the option field was always 40 bytes.
|
||||||
|
As of release 0.9.11, the signature is variable length. The Signature type and
|
||||||
|
length are inferred from the type of key used in the FROM_INCLUDED option and
|
||||||
|
the [Signature]_ documentation.
|
||||||
|
|
||||||
|
* When a packet contains both FROM_INCLUDED and SIGNATURE_INCLUDED (as in
|
||||||
|
SYNCHRONIZE), the inference may be made directly.
|
||||||
|
|
||||||
|
* When a packet does not contain FROM_INCLUDED, the inference must be made from
|
||||||
|
a previous SYNCHRONIZE packet.
|
||||||
|
|
||||||
|
* When a packet does not contain FROM_INCLUDED, and there was no previous
|
||||||
|
SYNCHRONIZE packet (for example a stray CLOSE or RESET packet), the inference
|
||||||
|
can be made from the length of the remaining options (since
|
||||||
|
SIGNATURE_INCLUDED is the last option), but the packet will probably be
|
||||||
|
discarded anyway, since there is no FROM available to validate the signature.
|
||||||
|
If more option fields are defined in the future, they must be accounted for.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [Destination]
|
||||||
|
{{ ctags_url('Destination') }}
|
||||||
|
|
||||||
|
.. [Integer]
|
||||||
|
{{ ctags_url('Integer') }}
|
||||||
|
|
||||||
|
.. [Signature]
|
||||||
|
{{ ctags_url('Signature') }}
|
||||||
|
|
||||||
|
.. [SigningPrivateKey]
|
||||||
|
{{ ctags_url('SigningPrivateKey') }}
|
||||||
|
|
||||||
|
.. [STREAMING]
|
||||||
|
{{ site_url('docs/api/streaming', True) }}
|
358
i2p2www/spec/tunnel-creation.rst
Normal file
358
i2p2www/spec/tunnel-creation.rst
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
=============================
|
||||||
|
Tunnel Creation Specification
|
||||||
|
=============================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: September 2014
|
||||||
|
:accuratefor: 0.9.15
|
||||||
|
|
||||||
|
|
||||||
|
.. _tunnelCreate.overview:
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This document specifies the details of the encrypted tunnel build messages used
|
||||||
|
to create tunnels using a "non-interactive telescoping" method. See the tunnel
|
||||||
|
build document [TUNNEL-IMPL]_ for an overview of the process, including peer
|
||||||
|
selection and ordering methods.
|
||||||
|
|
||||||
|
The tunnel creation is accomplished by a single message passed along the path
|
||||||
|
of peers in the tunnel, rewritten in place, and transmitted back to the tunnel
|
||||||
|
creator. This single tunnel message is made up of a variable number of records
|
||||||
|
(up to 8) - one for each potential peer in the tunnel. Individual records are
|
||||||
|
asymmetrically (ElGamal [CRYPTO-ELG]_) encrypted to be read only by a specific
|
||||||
|
peer along the path, while an additional symmetric layer of encryption (AES
|
||||||
|
[CRYPTO-AES]_) is added at each hop so as to expose the asymmetrically
|
||||||
|
encrypted record only at the appropriate time.
|
||||||
|
|
||||||
|
.. _number:
|
||||||
|
|
||||||
|
Number of Records
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Not all records must contain valid data. The build message for a 3-hop tunnel,
|
||||||
|
for example, may contain more records to hide the actual length of the tunnel
|
||||||
|
from the participants. There are two build message types. The original Tunnel
|
||||||
|
Build Message ([TBM]_) contains 8 records, which is more than enough for any
|
||||||
|
practical tunnel length. The newer Variable Tunnel Build Message ([VTBM]_)
|
||||||
|
contains 1 to 8 records. The originator may trade off the size of the message
|
||||||
|
with the desired amount of tunnel length obfuscation.
|
||||||
|
|
||||||
|
In the current network, most tunnels are 2 or 3 hops long. The current
|
||||||
|
implementation uses a 5-record VTBM to build tunnels of 4 hops or less, and the
|
||||||
|
8-record TBM for longer tunnels. The 5-record VTBM (which, when fragmented,
|
||||||
|
fits in three 1KB tunnel messaages) reduces network traffic and increases
|
||||||
|
build sucess rate, because smaller messages are less likely to be dropped.
|
||||||
|
|
||||||
|
The reply message must be the same type and length as the build message.
|
||||||
|
|
||||||
|
.. _tunnelCreate.requestRecord:
|
||||||
|
|
||||||
|
Request Record Specification
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Also specified in the I2NP Specification [BRR]_.
|
||||||
|
|
||||||
|
Cleartext of the record, visible only to the hop being asked::
|
||||||
|
|
||||||
|
bytes 0-3: tunnel ID to receive messages as
|
||||||
|
bytes 4-35: local router identity hash
|
||||||
|
bytes 36-39: next tunnel ID
|
||||||
|
bytes 40-71: next router identity hash
|
||||||
|
bytes 72-103: AES-256 tunnel layer key
|
||||||
|
bytes 104-135: AES-256 tunnel IV key
|
||||||
|
bytes 136-167: AES-256 reply key
|
||||||
|
bytes 168-183: AES-256 reply IV
|
||||||
|
byte 184: flags
|
||||||
|
bytes 185-188: request time (in hours since the epoch, rounded down)
|
||||||
|
bytes 189-192: next message ID
|
||||||
|
bytes 193-221: uninterpreted / random padding
|
||||||
|
|
||||||
|
The next tunnel ID and next router identity hash fields are used to specify the
|
||||||
|
next hop in the tunnel, though for an outbound tunnel endpoint, they specify
|
||||||
|
where the rewritten tunnel creation reply message should be sent. In addition,
|
||||||
|
the next message ID specifies the message ID that the message (or reply) should
|
||||||
|
use.
|
||||||
|
|
||||||
|
The tunnel layer key, tunnel IV key, reply key, and reply IV are each random
|
||||||
|
32-byte values generated by the creator, for use in this build request record
|
||||||
|
only.
|
||||||
|
|
||||||
|
The flags field contains the following::
|
||||||
|
|
||||||
|
Bit order: 76543210 (bit 7 is MSB)
|
||||||
|
bit 7: if set, allow messages from anyone
|
||||||
|
bit 6: if set, allow messages to anyone, and send the reply to the
|
||||||
|
specified next hop in a Tunnel Build Reply Message
|
||||||
|
bits 5-0: Undefined, must set to 0 for compatibility with future options
|
||||||
|
|
||||||
|
Bit 7 indicates that the hop will be an inbound gateway (IBGW). Bit 6
|
||||||
|
indicates that the hop will be an outbound endpoint (OBEP). If neither bit is
|
||||||
|
set, the hop will be an intermediate participant. Both cannot be set at once.
|
||||||
|
|
||||||
|
Request Record Creation
|
||||||
|
```````````````````````
|
||||||
|
Every hop gets a random Tunnel ID.
|
||||||
|
The current and next-hop Tunnel IDs are filled in.
|
||||||
|
Every record gets a random tunnel IV key, reply IV, layer key, and reply key.
|
||||||
|
|
||||||
|
.. _encryption:
|
||||||
|
|
||||||
|
Request Record Encryption
|
||||||
|
`````````````````````````
|
||||||
|
That cleartext record is ElGamal 2048 encrypted [CRYPTO-ELG]_ with the hop's
|
||||||
|
public encryption key and formatted into a 528 byte record::
|
||||||
|
|
||||||
|
bytes 0-15: First 16 bytes of the SHA-256 of the current hop's router identity
|
||||||
|
bytes 16-527: ElGamal-2048 encrypted request record
|
||||||
|
|
||||||
|
In the 512-byte encrypted record, the ElGamal data contains bytes 1-256 and
|
||||||
|
258-513 of the 514-byte ElGamal encrypted block [CRYPTO-ELG]_. The two padding
|
||||||
|
bytes from the block (the zero bytes at locations 0 and 257) are removed.
|
||||||
|
|
||||||
|
Since the cleartext uses the full field, there is no need for additional
|
||||||
|
padding beyond ``SHA256(cleartext) + cleartext``.
|
||||||
|
|
||||||
|
Each 528-byte record is then iteratively encrypted (using AES decryption, with
|
||||||
|
the reply key and reply IV for each hop) so that the router identity will only
|
||||||
|
be in cleartext for the hop in question.
|
||||||
|
|
||||||
|
.. _tunnelCreate.hopProcessing:
|
||||||
|
|
||||||
|
Hop Processing and Encryption
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
When a hop receives a TunnelBuildMessage, it looks through the records
|
||||||
|
contained within it for one starting with their own identity hash (trimmed to
|
||||||
|
16 bytes). It then decrypts the ElGamal block from that record and retrieves
|
||||||
|
the protected cleartext. At that point, they make sure the tunnel request is
|
||||||
|
not a duplicate by feeding the AES-256 reply key into a bloom filter.
|
||||||
|
Duplicates or invalid requests are dropped.
|
||||||
|
|
||||||
|
After deciding whether they will agree to participate in the tunnel or not,
|
||||||
|
they replace the record that had contained the request with an encrypted reply
|
||||||
|
block. All other records are AES-256 encrypted [CRYPTO-AES]_ with the included
|
||||||
|
reply key and IV. Each is AES/CBC encrypted separately with the same reply key
|
||||||
|
and reply IV. The CBC mode is not continued (chained) across records.
|
||||||
|
|
||||||
|
Each hop knows only its own response. If it agrees, it will maintain the
|
||||||
|
tunnel until expiration, even if it will not be used, as it cannot know whether
|
||||||
|
all other hops agreed.
|
||||||
|
|
||||||
|
.. _tunnelCreate.replyRecord:
|
||||||
|
|
||||||
|
Reply Record Specification
|
||||||
|
``````````````````````````
|
||||||
|
After the current hop reads their record, they replace it with a reply record
|
||||||
|
stating whether or not they agree to participate in the tunnel, and if they do
|
||||||
|
not, they classify their reason for rejection. This is simply a 1 byte value,
|
||||||
|
with 0x0 meaning they agree to participate in the tunnel, and higher values
|
||||||
|
meaning higher levels of rejection.
|
||||||
|
|
||||||
|
The following rejection codes are defined:
|
||||||
|
|
||||||
|
* TUNNEL_REJECT_PROBABALISTIC_REJECT = 10
|
||||||
|
* TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20
|
||||||
|
* TUNNEL_REJECT_BANDWIDTH = 30
|
||||||
|
* TUNNEL_REJECT_CRIT = 50
|
||||||
|
|
||||||
|
To hide other causes, such as router shutdown, from peers, the current
|
||||||
|
implementation uses TUNNEL_REJECT_BANDWIDTH for almost all rejections.
|
||||||
|
|
||||||
|
The reply is encrypted with the AES session key delivered to it in the
|
||||||
|
encrypted block, padded with 495 bytes of random data to reach the full record
|
||||||
|
size. The padding is placed before the status byte::
|
||||||
|
|
||||||
|
AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)
|
||||||
|
|
||||||
|
bytes 0-31 : SHA-256 of bytes 32-527
|
||||||
|
bytes 32-526 : Random padding
|
||||||
|
byte 527 : Reply value
|
||||||
|
|
||||||
|
This is also described in the I2NP spec [BRR]_.
|
||||||
|
|
||||||
|
.. _tunnelCreate.requestPreparation:
|
||||||
|
|
||||||
|
Tunnel Build Message Preparation
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
When building a new Tunnel Build Message, all of the Build Request Records must
|
||||||
|
first be built and asymmetrically encrypted using ElGamal [CRYPTO-ELG]_. Each
|
||||||
|
record is then premptively decrypted with the reply keys and IVs of the hops
|
||||||
|
earlier in the path, using AES [CRYPTO-AES]_. That decryption should be run in
|
||||||
|
reverse order so that the asymmetrically encrypted data will show up in the
|
||||||
|
clear at the right hop after their predecessor encrypts it.
|
||||||
|
|
||||||
|
The excess records not needed for individual requests are simply filled with
|
||||||
|
random data by the creator.
|
||||||
|
|
||||||
|
.. _tunnelCreate.requestDelivery:
|
||||||
|
|
||||||
|
Tunnel Build Message Delivery
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
For outbound tunnels, the delivery is done directly from the tunnel creator to
|
||||||
|
the first hop, packaging up the TunnelBuildMessage as if the creator was just
|
||||||
|
another hop in the tunnel. For inbound tunnels, the delivery is done through
|
||||||
|
an existing outbound tunnel. The outbound tunnel is generally from the same
|
||||||
|
pool as the new tunnel being built. If no outbound tunnel is available in that
|
||||||
|
pool, an outbound exploratory tunnel is used. At startup, when no outbound
|
||||||
|
exploratory tunnel exists yet, a fake 0-hop outbound tunnel is used.
|
||||||
|
|
||||||
|
.. _tunnelCreate.endpointHandling:
|
||||||
|
|
||||||
|
Tunnel Build Message Endpoint Handling
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
For creation of an outbound tunnel, when the request reaches an outbound
|
||||||
|
endpoint (as determined by the 'allow messages to anyone' flag), the hop is
|
||||||
|
processed as usual, encrypting a reply in place of the record and encrypting
|
||||||
|
all of the other records, but since there is no 'next hop' to forward the
|
||||||
|
TunnelBuildMessage on to, it instead places the encrypted reply records into a
|
||||||
|
TunnelBuildReplyMessage ([TBRM]_) or VariableTunnelBuildReplyMessage ([VTBRM]_)
|
||||||
|
(the type of message and number of records must match that of the request) and
|
||||||
|
delivers it to the reply tunnel specified within the request record. That
|
||||||
|
reply tunnel forwards the Tunnel Build Reply Message back to the tunnel
|
||||||
|
creator, just as for any other message [TUNNEL-OP]_. The tunnel creator then
|
||||||
|
processes it, as described below.
|
||||||
|
|
||||||
|
The reply tunnel was selected by the creator as follows: Generally it is an
|
||||||
|
inbound tunnel from the same pool as the new outbound tunnel being built. If
|
||||||
|
no inbound tunnel is available in that pool, an inbound exploratory tunnel is
|
||||||
|
used. At startup, when no inbound exploratory tunnel exists yet, a fake 0-hop
|
||||||
|
inbound tunnel is used.
|
||||||
|
|
||||||
|
For creation of an inbound tunnel, when the request reaches the inbound
|
||||||
|
endpoint (also known as the tunnel creator), there is no need to generate an
|
||||||
|
explicit Tunnel Build Reply Message, and the router processes each of the
|
||||||
|
replies, as below.
|
||||||
|
|
||||||
|
.. _tunnelCreate.replyProcessing:
|
||||||
|
|
||||||
|
Tunnel Build Reply Message Processing
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
To process the reply records, the creator simply has to AES decrypt each record
|
||||||
|
individually, using the reply key and IV of each hop in the tunnel after the
|
||||||
|
peer (in reverse order). This then exposes the reply specifying whether they
|
||||||
|
agree to participate in the tunnel or why they refuse. If they all agree, the
|
||||||
|
tunnel is considered created and may be used immediately, but if anyone
|
||||||
|
refuses, the tunnel is discarded.
|
||||||
|
|
||||||
|
The agreements and rejections are noted in each peer's profile
|
||||||
|
[PEER-SELECTION]_, to be used in future assessments of peer tunnel capacity.
|
||||||
|
|
||||||
|
|
||||||
|
.. _tunnelCreate.notes:
|
||||||
|
|
||||||
|
History and Notes
|
||||||
|
=================
|
||||||
|
|
||||||
|
This strategy came about during a discussion on the I2P mailing list between
|
||||||
|
Michael Rogers, Matthew Toseland (toad), and jrandom regarding the predecessor
|
||||||
|
attack. See [TUNBUILD-SUMMARY]_, [TUNBUILD-REASONING]_. It was introduced in
|
||||||
|
release 0.6.1.10 on 2006-02-16, which was the last time a
|
||||||
|
non-backward-compatible change was made in I2P.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
* This design does not prevent two hostile peers within a tunnel from
|
||||||
|
tagging one or more request or reply records to detect that they are within
|
||||||
|
the same tunnel, but doing so can be detected by the tunnel creator when
|
||||||
|
reading the reply, causing the tunnel to be marked as invalid.
|
||||||
|
|
||||||
|
* This design does not include a proof of work on the asymmetrically
|
||||||
|
encrypted section, though the 16 byte identity hash could be cut in half with
|
||||||
|
the latter replaced by a hashcash function of up to 2^64 cost.
|
||||||
|
|
||||||
|
* This design alone does not prevent two hostile peers within a tunnel from
|
||||||
|
using timing information to determine whether they are in the same tunnel.
|
||||||
|
The use of batched and synchronized request delivery could help (batching up
|
||||||
|
requests and sending them off on the (ntp-synchronized) minute). However,
|
||||||
|
doing so lets peers 'tag' the requests by delaying them and detecting the
|
||||||
|
delay later in the tunnel, though perhaps dropping requests not delivered in
|
||||||
|
a small window would work (though doing that would require a high degree of
|
||||||
|
clock synchronization). Alternately, perhaps individual hops could inject a
|
||||||
|
random delay before forwarding on the request?
|
||||||
|
|
||||||
|
* Are there any nonfatal methods of tagging the request?
|
||||||
|
|
||||||
|
* The timestamp with a one-hour resolution is used for replay prevention. The
|
||||||
|
constraint was not enforced until release 0.9.16.
|
||||||
|
|
||||||
|
|
||||||
|
.. _future:
|
||||||
|
|
||||||
|
Future Work
|
||||||
|
===========
|
||||||
|
|
||||||
|
* In the current implementation, the originator leaves one record empty
|
||||||
|
for itself. Thus a message of n records can only build a tunnel of n-1 hops.
|
||||||
|
This appears to be necessary for inbound tunnels (where the next-to-last hop
|
||||||
|
can see the hash prefix for the next hop), but not for outbound tunnels.
|
||||||
|
This is to be researched and verified. If it is possible to use the
|
||||||
|
remaining record without compromising anonymity, we should do so.
|
||||||
|
|
||||||
|
* Further analysis of possible tagging and timing attacks described in the
|
||||||
|
above notes.
|
||||||
|
|
||||||
|
* The Bloom filter rotation time should be evaluated.
|
||||||
|
|
||||||
|
* Use only VTBM; do not select old peers that don't support it.
|
||||||
|
|
||||||
|
* The Build Request Record does not specify a tunnel lifetime or expiration;
|
||||||
|
each hop expires the tunnel after 10 minutes, which is a network-wide
|
||||||
|
hardcoded constant. We could use a bit in the flag field and take 4 (or 8)
|
||||||
|
bytes out of the padding to specify a lifetime or expiration. The requestor
|
||||||
|
would only specify this option if all participants supported it.
|
||||||
|
|
||||||
|
|
||||||
|
.. _ref:
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [BRR]
|
||||||
|
{{ ctags_url('BuildRequestRecord') }}
|
||||||
|
|
||||||
|
.. [CRYPTO-AES]
|
||||||
|
{{ site_url('docs/how/cryptography', True) }}#AES
|
||||||
|
|
||||||
|
.. [CRYPTO-ELG]
|
||||||
|
{{ site_url('docs/how/cryptography', True) }}#elgamal
|
||||||
|
|
||||||
|
.. [HASHING-IT-OUT]
|
||||||
|
http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf
|
||||||
|
|
||||||
|
.. [PEER-SELECTION]
|
||||||
|
{{ site_url('docs/how/peer-selection', True) }}
|
||||||
|
|
||||||
|
.. [PREDECESSOR]
|
||||||
|
http://forensics.umass.edu/pubs/wright-tissec.pdf
|
||||||
|
|
||||||
|
.. [PREDECESSOR-2008]
|
||||||
|
http://forensics.umass.edu/pubs/wright.tissec.2008.pdf
|
||||||
|
|
||||||
|
.. [TBM]
|
||||||
|
{{ ctags_url('TunnelBuild') }}
|
||||||
|
|
||||||
|
.. [TBRM]
|
||||||
|
{{ ctags_url('TunnelBuildReply') }}
|
||||||
|
|
||||||
|
.. [TUNBUILD-REASONING]
|
||||||
|
http://osdir.com/ml/network.i2p/2005-10/msg00129.html
|
||||||
|
|
||||||
|
.. [TUNBUILD-SUMMARY]
|
||||||
|
http://osdir.com/ml/network.i2p/2005-10/msg00138.html
|
||||||
|
|
||||||
|
.. [TUNNEL-IMPL]
|
||||||
|
{{ site_url('docs/tunnels/implementation', True) }}
|
||||||
|
|
||||||
|
.. [TUNNEL-OP]
|
||||||
|
{{ site_url('docs/tunnels/implementation', True) }}#tunnel.operation
|
||||||
|
|
||||||
|
.. [VTBM]
|
||||||
|
{{ ctags_url('VariableTunnelBuild') }}
|
||||||
|
|
||||||
|
.. [VTBRM]
|
||||||
|
{{ ctags_url('VariableTunnelBuildReply') }}
|
351
i2p2www/spec/tunnel-message.rst
Normal file
351
i2p2www/spec/tunnel-message.rst
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
============================
|
||||||
|
Tunnel Message Specification
|
||||||
|
============================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: February 2014
|
||||||
|
:accuratefor: 0.9.11
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This document specifies the format of tunnel messages. For general information
|
||||||
|
about tunnels see the tunnel documentation [TUNNEL-IMPL]_.
|
||||||
|
|
||||||
|
|
||||||
|
Message preprocessing
|
||||||
|
=====================
|
||||||
|
|
||||||
|
A *tunnel gateway* is the entrance, or first hop, of a tunnel. For an outbound
|
||||||
|
tunnel, the gateway is the creator of the tunnel. For an inbound tunnel, the
|
||||||
|
gateway is at the opposite end from the creator of the tunnel.
|
||||||
|
|
||||||
|
A gateway *preprocesses* [I2NP]_ messages by fragmenting and combining them
|
||||||
|
into tunnel messages.
|
||||||
|
|
||||||
|
While I2NP messages are variable size from 0 to almost 64 KB, tunnel messages
|
||||||
|
are fixed-size, approximately 1 KB. Fixed message size restricts several types
|
||||||
|
of attacks that are possible from observing message size.
|
||||||
|
|
||||||
|
After the tunnel messages are created, they are encrypted as described in the
|
||||||
|
tunnel documentation [TUNNEL-IMPL]_.
|
||||||
|
|
||||||
|
.. _msg-Tunnel:
|
||||||
|
|
||||||
|
Tunnel Message (Encrypted)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
These are the contents of a tunnel data message after encryption.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' -%}
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| Tunnel ID | IV |
|
||||||
|
+----+----+----+----+ +
|
||||||
|
| |
|
||||||
|
+ +----+----+----+----+
|
||||||
|
| | |
|
||||||
|
+----+----+----+----+ +
|
||||||
|
| |
|
||||||
|
+ Encrypted Data +
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+ +-------------------+
|
||||||
|
| |
|
||||||
|
+----+----+----+----+
|
||||||
|
|
||||||
|
Tunnel ID :: `TunnelId`
|
||||||
|
4 bytes
|
||||||
|
the ID of the next hop
|
||||||
|
|
||||||
|
IV ::
|
||||||
|
16 bytes
|
||||||
|
the initialization vector
|
||||||
|
|
||||||
|
Encrypted Data ::
|
||||||
|
1008 bytes
|
||||||
|
the encrypted tunnel message
|
||||||
|
|
||||||
|
total size: 1028 Bytes
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Tunnel Message (Decrypted)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
These are the contents of a tunnel data message when decrypted.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' %}
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| Tunnel ID | IV |
|
||||||
|
+----+----+----+----+ +
|
||||||
|
| |
|
||||||
|
+ +----+----+----+----+
|
||||||
|
| | Checksum |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| nonzero padding... |
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+ +----+
|
||||||
|
| |zero|
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| |
|
||||||
|
| Delivery Instructions 1 |
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| |
|
||||||
|
+ I2NP Message Fragment 1 +
|
||||||
|
| |
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| |
|
||||||
|
| Delivery Instructions 2... |
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
| |
|
||||||
|
+ I2NP Message Fragment 2... +
|
||||||
|
| |
|
||||||
|
~ ~
|
||||||
|
| |
|
||||||
|
+ +-------------------+
|
||||||
|
| |
|
||||||
|
+----+----+----+----+
|
||||||
|
|
||||||
|
Tunnel ID :: `TunnelId`
|
||||||
|
4 bytes
|
||||||
|
the ID of the next hop
|
||||||
|
|
||||||
|
IV ::
|
||||||
|
16 bytes
|
||||||
|
the initialization vector
|
||||||
|
|
||||||
|
Checksum ::
|
||||||
|
4 bytes
|
||||||
|
the first 4 bytes of the SHA256 hash of (the contents of the message
|
||||||
|
(after the zero byte) + IV)
|
||||||
|
|
||||||
|
Nonzero padding ::
|
||||||
|
0 or more bytes
|
||||||
|
random nonzero data for padding
|
||||||
|
|
||||||
|
Zero ::
|
||||||
|
1 byte
|
||||||
|
the value 0x00
|
||||||
|
|
||||||
|
Delivery Instructions :: `TunnelMessageDeliveryInstructions`
|
||||||
|
length varies but is typically 7, 39, 43, or 47 bytes
|
||||||
|
Indicates the fragment and the routing for the fragment
|
||||||
|
|
||||||
|
Message Fragment ::
|
||||||
|
1 to 996 bytes, actual maximum depends on delivery instruction size
|
||||||
|
A partial or full I2NP Message
|
||||||
|
|
||||||
|
total size: 1028 Bytes
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Notes
|
||||||
|
`````
|
||||||
|
* The padding, if any, must be before the instruction/message pairs.
|
||||||
|
There is no provision for padding at the end.
|
||||||
|
|
||||||
|
* The checksum does NOT cover the padding or the zero byte.
|
||||||
|
Take the message starting at the first delivery instructions, concatenate the
|
||||||
|
IV, and take the Hash of that.
|
||||||
|
|
||||||
|
|
||||||
|
.. _struct-TunnelMessageDeliveryInstructions:
|
||||||
|
|
||||||
|
Tunnel Message Delivery Instructions
|
||||||
|
====================================
|
||||||
|
|
||||||
|
The instructions are encoded with a single control byte, followed by any
|
||||||
|
necessary additional information. The first bit (MSB) in that control byte
|
||||||
|
determines how the remainder of the header is interpreted - if it is not set,
|
||||||
|
the message is either not fragmented or this is the first fragment in the
|
||||||
|
message. If it is set, this is a follow on fragment.
|
||||||
|
|
||||||
|
This specification is for Delivery Instructions inside Tunnel Messages only.
|
||||||
|
Note that "Delivery Instructions" are also used inside Garlic Cloves
|
||||||
|
[I2NP-GC]_, where the format is significantly different. See the I2NP
|
||||||
|
documentation [I2NP-GCDI]_ for details. Do NOT use the following specification
|
||||||
|
for Garlic Clove Delivery Instructions!
|
||||||
|
|
||||||
|
First Fragment Delivery Instructions
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
If the MSB of the first byte is 0, this is an initial I2NP message fragment,
|
||||||
|
or a complete (unfragmented) I2NP message, and the instructions are:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' %}
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
|flag| Tunnel ID (opt) | |
|
||||||
|
+----+----+----+----+----+ +
|
||||||
|
| |
|
||||||
|
+ +
|
||||||
|
| To Hash (optional) |
|
||||||
|
+ +
|
||||||
|
| |
|
||||||
|
+ +--------------+
|
||||||
|
| |dly | Message
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
ID (opt) |extended opts (opt)| size |
|
||||||
|
+----+----+----+----+----+----+----+----+
|
||||||
|
|
||||||
|
flag ::
|
||||||
|
1 byte
|
||||||
|
Bit order: 76543210
|
||||||
|
bit 7: 0 to specify an initial fragment or an unfragmented message
|
||||||
|
bits 6-5: delivery type
|
||||||
|
0x0 = LOCAL
|
||||||
|
0x01 = TUNNEL
|
||||||
|
0x02 = ROUTER
|
||||||
|
0x03 = unused, invalid
|
||||||
|
Note: LOCAL is used for inbound tunnels only, unimplemented
|
||||||
|
for outbound tunnels
|
||||||
|
bit 4: delay included? Unimplemented, always 0
|
||||||
|
If 1, a delay byte is included
|
||||||
|
bit 3: fragmented? If 0, the message is not fragmented, what follows
|
||||||
|
is the entire message
|
||||||
|
If 1, the message is fragmented, and the
|
||||||
|
instructions contain a Message ID
|
||||||
|
bit 2: extended options? Unimplemented, always 0
|
||||||
|
If 1, extended options are included
|
||||||
|
bits 1-0: reserved, set to 0 for compatibility with future uses
|
||||||
|
|
||||||
|
Tunnel ID :: `TunnelId`
|
||||||
|
4 bytes
|
||||||
|
Optional, present if delivery type is TUNNEL
|
||||||
|
The destination tunnel ID
|
||||||
|
|
||||||
|
To Hash ::
|
||||||
|
32 bytes
|
||||||
|
Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
|
||||||
|
If DESTINATION, the SHA256 Hash of the destination
|
||||||
|
If ROUTER, the SHA256 Hash of the router
|
||||||
|
If TUNNEL, the SHA256 Hash of the gateway router
|
||||||
|
|
||||||
|
Delay ::
|
||||||
|
1 byte
|
||||||
|
Optional, present if delay included flag is set
|
||||||
|
In tunnel messages: Unimplemented, never present; original
|
||||||
|
specification:
|
||||||
|
bit 7: type (0 = strict, 1 = randomized)
|
||||||
|
bits 6-0: delay exponent (2^value minutes)
|
||||||
|
|
||||||
|
Message ID ::
|
||||||
|
4 bytes
|
||||||
|
Optional, present if this message is the first of 2 or more fragments
|
||||||
|
(i.e. if the fragmented bit is 1)
|
||||||
|
An ID that uniquely identifies all fragments as belonging to a single
|
||||||
|
message (the current implementation uses `I2NPMessageHeader.msg_id`)
|
||||||
|
|
||||||
|
Extended Options ::
|
||||||
|
2 or more bytes
|
||||||
|
Optional, present if extend options flag is set
|
||||||
|
Unimplemented, never present; original specification:
|
||||||
|
One byte length and then that many bytes
|
||||||
|
|
||||||
|
size ::
|
||||||
|
2 bytes
|
||||||
|
The length of the fragment that follows
|
||||||
|
Valid values: 1 to approx. 960 in a tunnel message
|
||||||
|
|
||||||
|
Total length: Typical length is:
|
||||||
|
3 bytes for LOCAL delivery (tunnel message);
|
||||||
|
35 bytes for ROUTER / DESTINATION delivery or 39 bytes for TUNNEL
|
||||||
|
delivery (unfragmented tunnel message);
|
||||||
|
39 bytes for ROUTER delivery or 43 bytes for TUNNEL delivery (first
|
||||||
|
fragment)
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Follow-on Fragment Delivery Instructions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
If the MSB of the first byte is 1, this is a follow-on fragment, and the
|
||||||
|
instructions are:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
{% highlight lang='dataspec' %}
|
||||||
|
+----+----+----+----+----+----+----+
|
||||||
|
|frag| Message ID | size |
|
||||||
|
+----+----+----+----+----+----+----+
|
||||||
|
|
||||||
|
frag ::
|
||||||
|
1 byte
|
||||||
|
Bit order: 76543210
|
||||||
|
binary 1nnnnnnd
|
||||||
|
bit 7: 1 to indicate this is a follow-on fragment
|
||||||
|
bits 6-1: nnnnnn is the 6 bit fragment number from 1 to 63
|
||||||
|
bit 0: d is 1 to indicate the last fragment, 0 otherwise
|
||||||
|
|
||||||
|
Message ID ::
|
||||||
|
4 bytes
|
||||||
|
Identifies the fragment sequence that this fragment belongs to.
|
||||||
|
This will match the message ID of an initial fragment (a fragment
|
||||||
|
with flag bit 7 set to 0 and flag bit 3 set to 1).
|
||||||
|
|
||||||
|
size ::
|
||||||
|
2 bytes
|
||||||
|
the length of the fragment that follows
|
||||||
|
valid values: 1 to 996
|
||||||
|
|
||||||
|
total length: 7 bytes
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/DeliveryInstructions.html
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
=====
|
||||||
|
|
||||||
|
I2NP Message Maximum Size
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
While the maximum I2NP message size is nominally 64 KB, the size is further
|
||||||
|
constrained by the method of fragmenting I2NP messages into multiple 1 KB
|
||||||
|
tunnel messages. The maximum number of fragments is 64, and the initial
|
||||||
|
fragment may not be perfectly aligned at the start of a tunnel message. So the
|
||||||
|
message must nominally fit in 63 fragments.
|
||||||
|
|
||||||
|
The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery
|
||||||
|
mode); the maximum size of a follow-on fragment is 996 bytes. Therefore the
|
||||||
|
maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
|
||||||
|
|
||||||
|
Ordering, Batching, Packing
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Tunnel messages may be dropped or reordered. The tunnel gateway, who creates
|
||||||
|
tunnel messages, is free to implement any batching, mixing, or reordering
|
||||||
|
strategy to fragment I2NP messages and efficiently pack fragments into tunnel
|
||||||
|
messages. In general, an optimal packing is not possible (the "packing
|
||||||
|
problem"). The gateways may implement various delay and reordering strategies.
|
||||||
|
|
||||||
|
Cover Traffic
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Tunnel messages may contain only padding (i.e. no delivery instructions or
|
||||||
|
message fragments at all) for cover traffic. This is unimplemented.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [I2NP]
|
||||||
|
{{ site_url('docs/protocol/i2np', True) }}
|
||||||
|
|
||||||
|
.. [I2NP-GC]
|
||||||
|
{{ ctags_url('GarlicClove') }}
|
||||||
|
|
||||||
|
.. [I2NP-GCDI]
|
||||||
|
{{ ctags_url('GarlicCloveDeliveryInstructions') }}
|
||||||
|
|
||||||
|
.. [TUNNEL-IMPL]
|
||||||
|
{{ site_url('docs/tunnels/implementation', True) }}
|
561
i2p2www/spec/updates.rst
Normal file
561
i2p2www/spec/updates.rst
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
=============================
|
||||||
|
Software Update Specification
|
||||||
|
=============================
|
||||||
|
.. meta::
|
||||||
|
:lastupdated: May 2015
|
||||||
|
:accuratefor: 0.9.20
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
I2P uses a simple, yet secure, system for automated software update. The
|
||||||
|
router console periodically pulls a news file from a configurable I2P URL.
|
||||||
|
There is a hardcoded backup URL pointing to the project website, in case the
|
||||||
|
default project news host goes down.
|
||||||
|
|
||||||
|
The contents of the news file are displayed on the home page of the router
|
||||||
|
console. In addition, the news file contains the most recent version number of
|
||||||
|
the software. If the version is higher than the router's version number, it
|
||||||
|
will display an indication to the user that an update is available.
|
||||||
|
|
||||||
|
The router may optionally download, or download and install, the new version if
|
||||||
|
configured to do so.
|
||||||
|
|
||||||
|
Old News File Specification
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
This format is replaced by the su3 news format as of release 0.9.17.
|
||||||
|
|
||||||
|
The news.xml file may contain the following elements::
|
||||||
|
|
||||||
|
<i2p.news date="$Date: 2010-01-22 00:00:00 $" />
|
||||||
|
<i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" />
|
||||||
|
|
||||||
|
Parameters in the i2p.release entry are as follows. All keys are
|
||||||
|
case-insensitive. All values must be enclosed in double quotes.
|
||||||
|
|
||||||
|
date
|
||||||
|
The release date of the router version.
|
||||||
|
|
||||||
|
Unused. Format not specified.
|
||||||
|
|
||||||
|
minJavaVersion
|
||||||
|
The minimum version of Java required to run the current version.
|
||||||
|
|
||||||
|
As of release 0.9.9.
|
||||||
|
|
||||||
|
minVersion
|
||||||
|
The minimum version of the router required to update to the current
|
||||||
|
version. If a router is older than this, the user must (manually?)
|
||||||
|
update to an intermediate version first.
|
||||||
|
|
||||||
|
As of release 0.9.9.
|
||||||
|
|
||||||
|
su3Clearnet
|
||||||
|
One or more HTTP URLs where the .su3 update file may be found on the
|
||||||
|
clearnet (non-I2P). Multiple URLs must be separated by a space or comma.
|
||||||
|
|
||||||
|
As of release 0.9.9.
|
||||||
|
|
||||||
|
su3SSL
|
||||||
|
One or more HTTPS URLs where the .su3 update file may be found on the
|
||||||
|
clearnet (non-I2P). Multiple URLs must be separated by a space or comma.
|
||||||
|
|
||||||
|
As of release 0.9.9.
|
||||||
|
|
||||||
|
sudTorrent
|
||||||
|
The magnet link for the .sud (non-pack200) torrent of the update.
|
||||||
|
|
||||||
|
As of release 0.9.4.
|
||||||
|
|
||||||
|
su2Torrent
|
||||||
|
The magnet link for the .su2 (pack200) torrent of the update.
|
||||||
|
|
||||||
|
As of release 0.9.4.
|
||||||
|
|
||||||
|
su3Torrent
|
||||||
|
The magnet link for the .su3 (new format) torrent of the update.
|
||||||
|
|
||||||
|
As of release 0.9.9.
|
||||||
|
|
||||||
|
version
|
||||||
|
Required.
|
||||||
|
|
||||||
|
The latest current router version available.
|
||||||
|
|
||||||
|
The elements may be included inside XML comments to prevent interpretation by
|
||||||
|
browsers. The i2p.release element and version are required. All others are
|
||||||
|
optional. NOTE: Due to parser limitations an entire element must be on a
|
||||||
|
single line.
|
||||||
|
|
||||||
|
Update File Specification
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
As of release 0.9.9, the signed update file, named i2pupdate.su3, will use the
|
||||||
|
"su3" file format specified below. Approved release signers will use 4096-bit
|
||||||
|
RSA keys. The X.509 public key certificates for these signers are distributed
|
||||||
|
in the router installation packages. The updates may contain certificates for
|
||||||
|
new, approved signers, and/or contain a list of certificates to delete for
|
||||||
|
revocation.
|
||||||
|
|
||||||
|
|
||||||
|
Old Update File Specification
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
This format is obsolete as of release 0.9.9.
|
||||||
|
|
||||||
|
The signed update file, traditionally named i2pupdate.sud, is simply a zip file
|
||||||
|
with a prepended 56 byte header. The header contains:
|
||||||
|
|
||||||
|
* A 40-byte DSA [Signature]_
|
||||||
|
* A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary
|
||||||
|
|
||||||
|
The signature covers only the zip archive - not the prepended version. The
|
||||||
|
signature must match one of the DSA [SigningPublicKey]_ configured into the
|
||||||
|
router, which has a hardcoded default list of keys of the current project
|
||||||
|
release managers.
|
||||||
|
|
||||||
|
For version comparison purposes, version fields contain [0-9]*, field
|
||||||
|
separators are '-', '_', and '.', and all other characters are ignored.
|
||||||
|
|
||||||
|
As of version 0.8.8, the version must also be specified as a zip file comment
|
||||||
|
in UTF-8, without the trailing zeroes. The updating router verifes that the
|
||||||
|
version in the header (not covered by the signature) matches the version in the
|
||||||
|
zip file comment, which is covered by the signature. This prevents spoofing of
|
||||||
|
the version number in the header.
|
||||||
|
|
||||||
|
Download and Installation
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The router first downloads the header of the update file from one in a
|
||||||
|
configurable list of I2P URLs, using the built-in HTTP client and proxy, and
|
||||||
|
checks that the version is newer. This prevents the problem of update hosts
|
||||||
|
that do not have the latest file. The router then downloads the full update
|
||||||
|
file. The router verifies that the update file version is newer before
|
||||||
|
installation. It also, of course, verifies the signature, and verifes that the
|
||||||
|
zip file comment matches the header version, as explained above.
|
||||||
|
|
||||||
|
The zip file is extracted and copied to "i2pupdate.zip" in the I2P
|
||||||
|
configuration directory (~/.i2p on Linux).
|
||||||
|
|
||||||
|
As of release 0.7.12, the router supports Pack200 decompression. Files inside
|
||||||
|
the zip archive with a .jar.pack or .war.pack suffix are transparently
|
||||||
|
decompressed to a .jar or .war file. Update files containing .pack files are
|
||||||
|
traditionally named with a '.su2' suffix. Pack200 shrinks the update files by
|
||||||
|
about 60%.
|
||||||
|
|
||||||
|
As of release 0.8.7, the router will delete the libjbigi.so and libjcpuid.so
|
||||||
|
files if the zip archive contains a lib/jbigi.jar file, so that the new files
|
||||||
|
will be extracted from jbigi.jar.
|
||||||
|
|
||||||
|
As of release 0.8.12, if the zip archive contains a file deletelist.txt, the
|
||||||
|
router will delete the files listed there. The format is:
|
||||||
|
|
||||||
|
* One file name per line
|
||||||
|
|
||||||
|
* All file names are relative to the installation directory; no absolute file
|
||||||
|
names allowed, no files starting with ".."
|
||||||
|
|
||||||
|
* Comments start with '#'
|
||||||
|
|
||||||
|
The router will then delete the deletelist.txt file.
|
||||||
|
|
||||||
|
.. _su3:
|
||||||
|
|
||||||
|
SU3 File Specification
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
This specification is used for router updates as of release 0.9.9, reseed data
|
||||||
|
as of release 0.9.14, plugins as of release 0.9.15, and the news file as of
|
||||||
|
release 0.9.17.
|
||||||
|
|
||||||
|
Issues with the previous .sud/.su2 format
|
||||||
|
`````````````````````````````````````````
|
||||||
|
* No magic number or flags
|
||||||
|
|
||||||
|
* No way to specify compression, pack200 or not, or signing algo
|
||||||
|
|
||||||
|
* Version is not covered by signature, so it is enforced by requiring it to be
|
||||||
|
in the zip file comment (for router files) or in the plugin.config file (for
|
||||||
|
plugins)
|
||||||
|
|
||||||
|
* Signer not specified so verifier must try all known keys
|
||||||
|
|
||||||
|
* Signature-before-data format requires two passes to generate file
|
||||||
|
|
||||||
|
Goals
|
||||||
|
`````
|
||||||
|
* Fix above problems
|
||||||
|
|
||||||
|
* Migrate to more secure signature algorithm
|
||||||
|
|
||||||
|
* Keep version info in same format and offset for compatibility with existing
|
||||||
|
version checkers
|
||||||
|
|
||||||
|
* One-pass signature verification and file extraction
|
||||||
|
|
||||||
|
Specification
|
||||||
|
`````````````
|
||||||
|
|
||||||
|
====== ========================================================================
|
||||||
|
Bytes Contents
|
||||||
|
====== ========================================================================
|
||||||
|
0-5 Magic number "I2Psu3"
|
||||||
|
6 unused = 0
|
||||||
|
7 su3 file format version = 0
|
||||||
|
|
||||||
|
8-9 Signature type
|
||||||
|
|
||||||
|
* 0x0000 = DSA-SHA1
|
||||||
|
* 0x0001 = ECDSA-SHA256-P256
|
||||||
|
* 0x0002 = ECDSA-SHA384-P384
|
||||||
|
* 0x0003 = ECDSA-SHA512-P521
|
||||||
|
* 0x0004 = RSA-SHA256-2048
|
||||||
|
* 0x0005 = RSA-SHA384-3072
|
||||||
|
* 0x0006 = RSA-SHA512-4096
|
||||||
|
|
||||||
|
10-11 Signature length, e.g. 40 (0x0028) for DSA-SHA1. Must match that
|
||||||
|
specified for the [Signature]_ type.
|
||||||
|
12 unused = 0
|
||||||
|
|
||||||
|
13 Version length (in bytes not chars, including padding)
|
||||||
|
|
||||||
|
must be at least 16 (0x10) for compatibility
|
||||||
|
|
||||||
|
14 unused = 0
|
||||||
|
15 Signer ID length (in bytes not chars)
|
||||||
|
16-23 Content length (not including header or sig)
|
||||||
|
24 unused = 0
|
||||||
|
|
||||||
|
25 File type
|
||||||
|
|
||||||
|
* 0x00 = zip file
|
||||||
|
* 0x01 = xml file (as of 0.9.15)
|
||||||
|
* 0x02 = html file (as of 0.9.17)
|
||||||
|
* 0x03 = xml.gz file (as of 0.9.17)
|
||||||
|
|
||||||
|
26 unused = 0
|
||||||
|
|
||||||
|
27 Content type
|
||||||
|
|
||||||
|
* 0x00 = unknown
|
||||||
|
* 0x01 = router update
|
||||||
|
* 0x02 = plugin or plugin update
|
||||||
|
* 0x03 = reseed data
|
||||||
|
* 0x04 = news feed (as of 0.9.15)
|
||||||
|
|
||||||
|
28-39 unused = 0
|
||||||
|
|
||||||
|
40-55+ Version, UTF-8 padded with trailing 0x00, 16 bytes minimum, length
|
||||||
|
specified at byte 13. Do not append 0x00 bytes if the length is 16 or
|
||||||
|
more.
|
||||||
|
|
||||||
|
xx+ ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified
|
||||||
|
at byte 15
|
||||||
|
|
||||||
|
xx+ Content:
|
||||||
|
|
||||||
|
* Length specified in header at bytes 16-23
|
||||||
|
* Format specified in header at byte 25
|
||||||
|
* Content specified in header at byte 27
|
||||||
|
|
||||||
|
xx+ Signature: Length is specified in header at bytes 10-11, covers
|
||||||
|
everything starting at byte 0
|
||||||
|
====== ========================================================================
|
||||||
|
|
||||||
|
All unused fields must be set to 0 for compatibility with future versions.
|
||||||
|
|
||||||
|
Signature Details
|
||||||
|
`````````````````
|
||||||
|
The signature covers the entire header starting at byte 0, through the end of
|
||||||
|
the content. We use raw signatures. Take the hash of the data (using the hash
|
||||||
|
type implied by the signature type at bytes 8-9) and pass that to a "raw" sign
|
||||||
|
or verify function (e.g. "NONEwithRSA" in Java).
|
||||||
|
|
||||||
|
While signature verification and content extraction may be implemented in one
|
||||||
|
pass, an implementation must read and buffer the first 10 bytes to determine
|
||||||
|
the hash type before starting to verify.
|
||||||
|
|
||||||
|
Signature lengths for the various signature types are given in the [Signature]_
|
||||||
|
specification. Pad the signature with leading zeros if necessary. See the
|
||||||
|
cryptography details page [CRYPTO-SIG]_ for parameters of the various signature
|
||||||
|
types.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
`````
|
||||||
|
The content type specifies the trust domain. For each content type, clients
|
||||||
|
maintain a set of X.509 public key certificates for parties trusted to sign
|
||||||
|
that content. Only certificates for the specified content type may be used.
|
||||||
|
The certificate is looked up by the ID of the signer. Clients must verify that
|
||||||
|
the content type is that expected for the application.
|
||||||
|
|
||||||
|
All values are in network byte order (big endian).
|
||||||
|
|
||||||
|
SU3 Router Update File Specification
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
SU3 Details
|
||||||
|
```````````
|
||||||
|
* SU3 Content Type: 1 (ROUTER UPDATE)
|
||||||
|
|
||||||
|
* SU3 File Type: 0 (ZIP)
|
||||||
|
|
||||||
|
* SU3 Version: The router version
|
||||||
|
|
||||||
|
* Jar and war files in the zip are compressed with pack200 as documented above
|
||||||
|
for "su2" files. If the client does not support pack200, it must download the
|
||||||
|
update in a "sud" format.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
`````
|
||||||
|
* For releases, the SU3 version is the "base" router version, e.g. "0.9.20".
|
||||||
|
|
||||||
|
* For development builds, which are supported as of release 0.9.20, the SU3
|
||||||
|
version is the "full" router version, e.g. "0.9.20-5" or "0.9.20-5-rc". See
|
||||||
|
RouterVersion.java [I2P-SRC]_.
|
||||||
|
|
||||||
|
SU3 Reseed File Specification
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
As of 0.9.14, reseed data is delivered in an "su3" file format.
|
||||||
|
|
||||||
|
Goals
|
||||||
|
`````
|
||||||
|
* Signed files with strong signatures and trusted certificates to prevent
|
||||||
|
man-in-the-middle attacks that could boot victims into a separate, untrusted
|
||||||
|
network.
|
||||||
|
|
||||||
|
* Use su3 file format already used for updates, reseeding, and plugins
|
||||||
|
|
||||||
|
* Single compressed file to speed up reseeding, which was slow to fetch 200 files
|
||||||
|
|
||||||
|
Specification
|
||||||
|
`````````````
|
||||||
|
1. The file must be named "i2pseeds.su3".
|
||||||
|
|
||||||
|
2. The file must be in the same directory as the router infos on the web server.
|
||||||
|
|
||||||
|
3. A router will first try to fetch (index URL)/i2pseeds.su3; if that fails it
|
||||||
|
will fetch the index URL and then fetch the individual router info files
|
||||||
|
found in the links.
|
||||||
|
|
||||||
|
SU3 Details
|
||||||
|
```````````
|
||||||
|
* SU3 Content Type: 3 (RESEED)
|
||||||
|
|
||||||
|
* SU3 File Type: 0 (ZIP)
|
||||||
|
|
||||||
|
* SU3 Version: Seconds since the epoch, in ASCII (date +%s)
|
||||||
|
|
||||||
|
* Router info files in the zip file must be at the "top level". No directories
|
||||||
|
are in the zip file.
|
||||||
|
|
||||||
|
* Router info files must be named "routerInfo-(44 character base 64 router
|
||||||
|
hash).dat", as in the old reseed mechanism. The I2P base 64 alphabet must be
|
||||||
|
used.
|
||||||
|
|
||||||
|
SU3 Plugin File Specification
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
As of 0.9.15, plugins may be packaged in an "su3" file format.
|
||||||
|
|
||||||
|
SU3 Details
|
||||||
|
```````````
|
||||||
|
* SU3 Content Type: 2 (PLUGIN)
|
||||||
|
|
||||||
|
* SU3 File Type: 0 (ZIP)
|
||||||
|
|
||||||
|
* See the plugin specification [PLUGIN]_ for details.
|
||||||
|
|
||||||
|
* SU3 Version: The plugin version, must match that in plugin.config.
|
||||||
|
|
||||||
|
* Jar and war files in the zip are compressed with pack200 as documented above
|
||||||
|
for "su2" files.
|
||||||
|
|
||||||
|
SU3 News File Specification
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
As of 0.9.17, the news is delivered in an "su3" file format.
|
||||||
|
|
||||||
|
Goals
|
||||||
|
`````
|
||||||
|
* Signed news with strong signatures and trusted certificates
|
||||||
|
|
||||||
|
* Use su3 file format already used for updates, reseeding, and plugins
|
||||||
|
|
||||||
|
* Standard XML format for use with standard parsers
|
||||||
|
|
||||||
|
* Standard Atom format for use with standard feed readers and generators
|
||||||
|
|
||||||
|
* Sanitization and verification of HTML before displaying on console
|
||||||
|
|
||||||
|
* Suitable for easy implementation on Android and other platforms without an
|
||||||
|
HTML console
|
||||||
|
|
||||||
|
SU3 Details
|
||||||
|
```````````
|
||||||
|
* SU3 Content Type: 4 (NEWS)
|
||||||
|
|
||||||
|
* SU3 File Type: 1 (XML) or 3 (XML.GZ)
|
||||||
|
|
||||||
|
* SU3 Version: Seconds since the epoch, in ASCII (date +%s)
|
||||||
|
|
||||||
|
* File Format: XML or gzipped XML, containing an [RFC-4287]_ (Atom) XML Feed.
|
||||||
|
Charset must be UTF-8.
|
||||||
|
|
||||||
|
Specification
|
||||||
|
`````````````
|
||||||
|
**Atom <feed> Details:**
|
||||||
|
|
||||||
|
The following <feed> elements are used:
|
||||||
|
|
||||||
|
<entry>
|
||||||
|
A news item. See below.
|
||||||
|
|
||||||
|
<i2p:release>
|
||||||
|
I2P update metadata. See below.
|
||||||
|
|
||||||
|
<updated>
|
||||||
|
Required
|
||||||
|
|
||||||
|
Timestamp for the feed (conforming to [RFC-4287]_ (Atom) section 3.3 and
|
||||||
|
[RFC-3339]_.
|
||||||
|
|
||||||
|
**Atom <entry> Details:**
|
||||||
|
|
||||||
|
Each Atom <entry> in the news feed may be parsed and displayed in the router console.
|
||||||
|
The following elements are used:
|
||||||
|
|
||||||
|
<author>
|
||||||
|
Optional
|
||||||
|
|
||||||
|
Containing:
|
||||||
|
|
||||||
|
<name>
|
||||||
|
The name of the entry author
|
||||||
|
|
||||||
|
<content>
|
||||||
|
Required
|
||||||
|
|
||||||
|
Content, must be type="xhtml".
|
||||||
|
|
||||||
|
The XHTML will be sanitized with a whitelist of allowed elements and a
|
||||||
|
blacklist of disallowed attributes. Clients may ignore an element, or
|
||||||
|
the enclosing entry, or the entire feed when a non-whitelisted element
|
||||||
|
is encountered.
|
||||||
|
|
||||||
|
<link>
|
||||||
|
Optional
|
||||||
|
|
||||||
|
Link for further information
|
||||||
|
|
||||||
|
<summary>
|
||||||
|
Optional
|
||||||
|
|
||||||
|
Short summary, suitable for a tooltip
|
||||||
|
|
||||||
|
<title>
|
||||||
|
Required
|
||||||
|
|
||||||
|
Title of the news entry
|
||||||
|
|
||||||
|
<updated>
|
||||||
|
Required
|
||||||
|
|
||||||
|
Timestamp for this entry (conforming to [RFC-4287]_ (Atom) section 3.3
|
||||||
|
and [RFC-3339]_).
|
||||||
|
|
||||||
|
**Atom <i2p:release> Details:**
|
||||||
|
|
||||||
|
There must be at least one <i2p:release> entity in the feed. Each contains the
|
||||||
|
following attributes and entities:
|
||||||
|
|
||||||
|
date (attribute)
|
||||||
|
Required
|
||||||
|
|
||||||
|
Timestamp for this entry (conforming to [RFC-4287]_ (Atom) section 3.3
|
||||||
|
and [RFC-3339]_.
|
||||||
|
|
||||||
|
The date also may be in truncated format yyyy-mm-dd (without the 'T');
|
||||||
|
this is the "full-date" format in [RFC-3339]_. In this format the time
|
||||||
|
is assumed to be 00:00:00 UTC for any processing.
|
||||||
|
|
||||||
|
minJavaVersion (attribute)
|
||||||
|
If present, the minimum version of Java required to run the current
|
||||||
|
version.
|
||||||
|
|
||||||
|
minVersion (attribute)
|
||||||
|
If present, the minimum version of the router required to update to the
|
||||||
|
current version. If a router is older than this, the user must
|
||||||
|
(manually?) update to an intermediate version first.
|
||||||
|
|
||||||
|
<i2p:version>
|
||||||
|
Required
|
||||||
|
|
||||||
|
The latest current router version available.
|
||||||
|
|
||||||
|
<i2p:update>
|
||||||
|
An update file (one or more). It must contain at least one child.
|
||||||
|
|
||||||
|
type (attribute)
|
||||||
|
"sud", "su2", or "su3".
|
||||||
|
|
||||||
|
Must be unique across all <i2p:update> elements.
|
||||||
|
|
||||||
|
<i2p:clearnet>
|
||||||
|
Out-of-network direct download links (zero or more)
|
||||||
|
|
||||||
|
href (attribute)
|
||||||
|
A standard clearnet http link
|
||||||
|
|
||||||
|
<i2p:clearnetssl>
|
||||||
|
Out-of-network direct download links (zero or more)
|
||||||
|
|
||||||
|
href (attribute)
|
||||||
|
A standard clearnet https link
|
||||||
|
|
||||||
|
<i2p:torrent>
|
||||||
|
In-network magnet link
|
||||||
|
|
||||||
|
href (attribute)
|
||||||
|
A magnet link
|
||||||
|
|
||||||
|
<i2p:url>
|
||||||
|
In-network direct download links (zero or more)
|
||||||
|
|
||||||
|
href (attribute)
|
||||||
|
An in-network http .i2p link
|
||||||
|
|
||||||
|
|
||||||
|
Future Work
|
||||||
|
===========
|
||||||
|
|
||||||
|
* The router update mechanism is part of the web router console. There is
|
||||||
|
currently no provision for updates of an embedded router lacking the router
|
||||||
|
console.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [CRYPTO-SIG]
|
||||||
|
{{ site_url('docs/how/cryptography', True) }}#sig
|
||||||
|
|
||||||
|
.. [I2P-SRC]
|
||||||
|
https://github.com/i2p/i2p.i2p
|
||||||
|
|
||||||
|
.. [PLUGIN]
|
||||||
|
{{ spec_url('plugin') }}
|
||||||
|
|
||||||
|
.. [RFC-3339]
|
||||||
|
http://tools.ietf.org/html/rfc3339
|
||||||
|
|
||||||
|
.. [RFC-4287]
|
||||||
|
http://tools.ietf.org/html/rfc4287
|
||||||
|
|
||||||
|
.. [Signature]
|
||||||
|
{{ ctags_url('Signature') }}
|
||||||
|
|
||||||
|
.. [SigningPublicKey]
|
||||||
|
{{ ctags_url('SigningPublicKey') }}
|
90
i2p2www/spec/views.py
Normal file
90
i2p2www/spec/views.py
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import codecs
|
||||||
|
from docutils.core import publish_parts
|
||||||
|
from flask import (
|
||||||
|
abort,
|
||||||
|
g,
|
||||||
|
make_response,
|
||||||
|
redirect,
|
||||||
|
render_template,
|
||||||
|
render_template_string,
|
||||||
|
request,
|
||||||
|
safe_join,
|
||||||
|
url_for,
|
||||||
|
)
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from i2p2www import SPEC_DIR
|
||||||
|
from i2p2www import helpers
|
||||||
|
|
||||||
|
|
||||||
|
SPEC_METATAGS = {
|
||||||
|
'accuratefor': None,
|
||||||
|
'lastupdated': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
SPEC_LIST_METATAGS = [
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def spec_index():
|
||||||
|
specs = []
|
||||||
|
for f in os.listdir(SPEC_DIR):
|
||||||
|
if f.endswith('.rst'):
|
||||||
|
path = safe_join(SPEC_DIR, f)
|
||||||
|
# read file
|
||||||
|
with codecs.open(path, encoding='utf-8') as fd:
|
||||||
|
content = fd.read()
|
||||||
|
parts = publish_parts(source=content, source_path=SPEC_DIR, writer_name="html")
|
||||||
|
meta = get_metadata_from_meta(parts['meta'])
|
||||||
|
|
||||||
|
spec = {
|
||||||
|
'name': f[:-4],
|
||||||
|
'title': parts['title'],
|
||||||
|
}
|
||||||
|
spec.update(meta)
|
||||||
|
specs.append(spec)
|
||||||
|
|
||||||
|
specs.sort(key=lambda s: s['name'])
|
||||||
|
return render_template('spec/index.html', specs=specs)
|
||||||
|
|
||||||
|
def spec_show(name, txt=False):
|
||||||
|
# check if that file actually exists
|
||||||
|
path = safe_join(SPEC_DIR, name + '.rst')
|
||||||
|
if not os.path.exists(path):
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
# read file
|
||||||
|
with codecs.open(path, encoding='utf-8') as fd:
|
||||||
|
content = fd.read()
|
||||||
|
|
||||||
|
if txt:
|
||||||
|
# Strip out RST
|
||||||
|
content = content.replace('.. meta::\n', '')
|
||||||
|
content = content.replace('.. raw:: html\n\n', '')
|
||||||
|
content = content.replace('\n.. [', '\n[')
|
||||||
|
content = content.replace(']_.', '].')
|
||||||
|
content = content.replace(']_', '] ')
|
||||||
|
# Change highlight formatter
|
||||||
|
content = content.replace('{% highlight', "{% highlight formatter='textspec'")
|
||||||
|
|
||||||
|
# render the post with Jinja2 to handle URLs etc.
|
||||||
|
rendered_content = render_template_string(content)
|
||||||
|
rendered_content = rendered_content.replace('</pre></div>', ' </pre></div>')
|
||||||
|
|
||||||
|
if txt:
|
||||||
|
# Send response
|
||||||
|
r = make_response(rendered_content)
|
||||||
|
r.mimetype = 'text/plain'
|
||||||
|
return r
|
||||||
|
|
||||||
|
# publish the post with docutils
|
||||||
|
parts = publish_parts(source=rendered_content, source_path=SPEC_DIR, writer_name="html")
|
||||||
|
meta = get_metadata_from_meta(parts['meta'])
|
||||||
|
|
||||||
|
return render_template('spec/show.html', title=parts['title'], body=parts['fragment'], name=name, meta=meta)
|
||||||
|
|
||||||
|
def spec_show_txt(name):
|
||||||
|
return spec_show(name, True)
|
||||||
|
|
||||||
|
def get_metadata_from_meta(meta):
|
||||||
|
return helpers.get_metadata_from_meta(meta, SPEC_METATAGS, SPEC_LIST_METATAGS)
|
@@ -19,6 +19,29 @@ a:hover {
|
|||||||
color: #f00e0e
|
color: #f00e0e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl p.first {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
min-width: 100px;
|
||||||
|
margin-right: 10px;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: bold;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:after {
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin: 0 0 0 110px;
|
||||||
|
padding: 0 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
div.hide {
|
div.hide {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
|
import ctags
|
||||||
from flask import g, request, safe_join, url_for
|
from flask import g, request, safe_join, url_for
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from i2p2www import CANONICAL_DOMAIN, CURRENT_I2P_VERSION, RTL_LANGS, SUPPORTED_LANGS, SUPPORTED_LANG_NAMES, STATIC_DIR, app
|
from i2p2www import CANONICAL_DOMAIN, CURRENT_I2P_VERSION, RTL_LANGS, SUPPORTED_LANGS, SUPPORTED_LANG_NAMES, SPEC_DIR, STATIC_DIR, app
|
||||||
|
|
||||||
INPROXY = '.xyz' # http://zzz.i2p/topics/1771-i2p-xyz-inproxy
|
INPROXY = '.xyz' # http://zzz.i2p/topics/1771-i2p-xyz-inproxy
|
||||||
|
|
||||||
@@ -20,15 +21,50 @@ I2P_TO_CLEAR = {
|
|||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def utility_processor():
|
def utility_processor():
|
||||||
|
_ctags = ctags.CTags(os.path.join(SPEC_DIR, 'spectags'))
|
||||||
|
kinds = {
|
||||||
|
't': 'type',
|
||||||
|
's': 'struct',
|
||||||
|
'm': 'msg',
|
||||||
|
}
|
||||||
|
|
||||||
# Shorthand for getting a site url
|
# Shorthand for getting a site url
|
||||||
def get_site_url(path=None):
|
def get_site_url(path=None, external=False):
|
||||||
lang = 'en'
|
lang = 'en'
|
||||||
if hasattr(g, 'lang') and g.lang:
|
if hasattr(g, 'lang') and g.lang:
|
||||||
lang = g.lang
|
lang = g.lang
|
||||||
if path:
|
if path:
|
||||||
return url_for('site_show', lang=lang, page=path)
|
return url_for('site_show', lang=lang, page=path, _external=external)
|
||||||
else:
|
else:
|
||||||
return url_for('site_show', lang=lang)
|
return url_for('site_show', lang=lang, _external=external)
|
||||||
|
|
||||||
|
def get_spec_url(name):
|
||||||
|
url = url_for('spec_show', name=name, _external=True)
|
||||||
|
# Remove ?lang=xx
|
||||||
|
if '?' in url:
|
||||||
|
url = url[:url.index('?')]
|
||||||
|
return url
|
||||||
|
|
||||||
|
def get_ctags_url(value):
|
||||||
|
filename, kind = _lookup_ctag(value)
|
||||||
|
# Handle message types
|
||||||
|
if not kind and value.endswith('Message'):
|
||||||
|
value = value[:-7]
|
||||||
|
filename, kind = _lookup_ctag(value)
|
||||||
|
if kind:
|
||||||
|
specname, _ = os.path.splitext(filename)
|
||||||
|
url = get_spec_url(specname)
|
||||||
|
return '%s#%s-%s' % \
|
||||||
|
(url, kinds[kind], value.lower())
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def _lookup_ctag(token):
|
||||||
|
entry = ctags.TagEntry()
|
||||||
|
if _ctags.find(entry, token, 0):
|
||||||
|
return entry['file'], entry['kind']
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
|
||||||
# Shorthand for getting a language-specific url
|
# Shorthand for getting a language-specific url
|
||||||
def get_url_with_lang(endpoint, **args):
|
def get_url_with_lang(endpoint, **args):
|
||||||
@@ -111,6 +147,8 @@ def utility_processor():
|
|||||||
change_theme=change_theme,
|
change_theme=change_theme,
|
||||||
logo_url=get_logo_for_theme,
|
logo_url=get_logo_for_theme,
|
||||||
site_url=get_site_url,
|
site_url=get_site_url,
|
||||||
|
spec_url=get_spec_url,
|
||||||
|
ctags_url=get_ctags_url,
|
||||||
get_url=get_url_with_lang,
|
get_url=get_url_with_lang,
|
||||||
is_rtl=is_rtl_lang,
|
is_rtl=is_rtl_lang,
|
||||||
get_flag=get_flag,
|
get_flag=get_flag,
|
||||||
|
@@ -44,6 +44,10 @@ url('/', 'views.main_index')
|
|||||||
url('/<lang:lang>/', 'views.site_show', defaults={'page': 'index'})
|
url('/<lang:lang>/', 'views.site_show', defaults={'page': 'index'})
|
||||||
url('/<lang:lang>/<path:page>', 'views.site_show')
|
url('/<lang:lang>/<path:page>', 'views.site_show')
|
||||||
|
|
||||||
|
url('/spec', 'spec.views.spec_index')
|
||||||
|
url('/spec/<string:name>', 'spec.views.spec_show')
|
||||||
|
url('/spec/<string:name>.txt', 'spec.views.spec_show_txt')
|
||||||
|
|
||||||
url('/<lang:lang>/papers/', 'anonbib.views.papers_list')
|
url('/<lang:lang>/papers/', 'anonbib.views.papers_list')
|
||||||
url('/<lang:lang>/papers/bibtex', 'anonbib.views.papers_bibtex')
|
url('/<lang:lang>/papers/bibtex', 'anonbib.views.papers_bibtex')
|
||||||
url('/<lang:lang>/papers/by-<string:choice>', 'anonbib.views.papers_list')
|
url('/<lang:lang>/papers/by-<string:choice>', 'anonbib.views.papers_list')
|
||||||
|
Reference in New Issue
Block a user