﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	launchpad_bug
2889	i2p options, `tub.port = listen:i2p`	warner		"[https://github.com/tahoe-lafs/tahoe-lafs/pull/415 PR 415] adds a `--i2p-i2cp-options=` flag to the `tahoe create-node` CLI command, and stores these options in the tahoe.cfg file under `[i2p] i2cp.options=`, and arranges to use these options when creating the SAM socket.

It must also store these options in the `[node] tub.port=` field, since the SAM socket might be created by the Tub listener *or* the outbound connection handler, and the I2P server will stick with the options requested by whichever one arrives first. So to avoid a race, we must use exactly the same options in both places.

This is complicated by the fact that `tub.port` is first parsed as a comma-joined list of listener descriptors, then each element is parsed as an Endpoint descriptor (which means splitting on colons). Since the I2CP options are a dictionary, encoded with colons and commas, there's a lot of escaping and de-escaping going on.

In yesterday's devchat, we decided that it would be cleaner to put these options solely in the `[i2p] i2cp.options=` field (where they don't need escaping), and not try to put them in `tub.port`. This  DRY (Don't Repeat Yourself) approach avoids the question of what happens if the two option-setting keys disagree, and removes the quoting/escaping concern.

To accomplish this, we decided to change the `tub.port` semantics slightly. It normally contains a comma-separated list of Endpoint descriptors, each of which starts with a `TYPE:` prefix and then a list of colon-separated arguments for that type of endpoint. We're comandeering the `listen:` ""type"" to mean ""ask the tahoe 'provider' for that type to contribute some Server Endpoints"". The provider will also be asked for one or more Foolscap connection hints, to add to `tub.location`.

So `tub.port = listen:i2p` means ""ask the i2p_provider for an endpoint"". `tub.port = tcp:12345,listen:i2p,listen:tor` will get one static TCP endpoint, plus whatever I2P wants to use, plus whatever Tor wants to use.

The code in `Node.create_main_tub()` that handles `tub.port` will look for the `listen:` prefix and call out to the provider, rather than passing the raw string into `tub.listenOn()`. Once the provider returns a list of Endpoints, they'll be passed one-at-a-time into `tub.listenOn()`.

If Twisted (or any active plugins) add an endpoint type named ""listen"", this will prevent them from being used, but that doesn't seem too likely. We could pick a tahoe-specific name to avoid this, but I think that would be harder to read (e.g. `tub.port = tahoe-listen:i2p`). I'm not sure, though.

The `i2p_provider` will then have a method to return a fully-formed Endpoint, with the I2CP options baked in, instead of trying to shoehorn these options into a string that's then passed to `endpoints.serverFromString`.

We'll close PR415 in favor of a different one that adds these changes.
"	defect	closed	normal	1.13.0	code-network	1.12.1	fixed			
