{"action":"created","issue":{"url":"https://api.github.com/repos/python-trio/trio/issues/275","repository_url":"https://api.github.com/repos/python-trio/trio","labels_url":"https://api.github.com/repos/python-trio/trio/issues/275/labels{/name}","comments_url":"https://api.github.com/repos/python-trio/trio/issues/275/comments","events_url":"https://api.github.com/repos/python-trio/trio/issues/275/events","html_url":"https://github.com/python-trio/trio/issues/275","id":249195050,"number":275,"title":"Allow setting source interface in open_tcp_stream","user":{"login":"njsmith","id":609896,"avatar_url":"https://avatars0.githubusercontent.com/u/609896?v=4","gravatar_id":"","url":"https://api.github.com/users/njsmith","html_url":"https://github.com/njsmith","followers_url":"https://api.github.com/users/njsmith/followers","following_url":"https://api.github.com/users/njsmith/following{/other_user}","gists_url":"https://api.github.com/users/njsmith/gists{/gist_id}","starred_url":"https://api.github.com/users/njsmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/njsmith/subscriptions","organizations_url":"https://api.github.com/users/njsmith/orgs","repos_url":"https://api.github.com/users/njsmith/repos","events_url":"https://api.github.com/users/njsmith/events{/privacy}","received_events_url":"https://api.github.com/users/njsmith/received_events","type":"User","site_admin":false},"labels":[{"id":772783575,"url":"https://api.github.com/repos/python-trio/trio/labels/asyncio%20feature%20parity","name":"asyncio feature parity","color":"bfd4f2","default":false},{"id":523593177,"url":"https://api.github.com/repos/python-trio/trio/labels/polish","name":"polish","color":"f9d0c4","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2017-08-09T23:56:06Z","updated_at":"2018-05-05T22:38:52Z","closed_at":null,"author_association":"OWNER","body":"Right now `open_tcp_stream` has no option to control which outgoing interface the connections are made from. We should make this possible.\r\n\r\nSubtleties:\r\n\r\n* It needs to be possible to set this separately for AF_INET and AF_INET6\r\n* We can't support setting the actual outgoing port, because we might need to make multiple outgoing connections in parallel\r\n\r\nOn Linux 4.2+, there's `sock.setsockopt(IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, 1); sock.bind((address, 0))` which means \"use this host, but delay picking the port until I call `connect`\". We should use this if available. We should *not* use `SO_REUSEADDR`, because then it's possible to bind to a port that will fail when we actually call `connect` (because there might be a TIME_WAIT with the same 4-tuple).\r\n\r\nSo maybe something like: `source_host={AF_INET: \"...\", AF_INET6: \"...\"}`?\r\n\r\nShould we also allow `source_host=\"1.2.3.4\"` and auto-expand it into `{AF_INET: \"1.2.3.4\"}`?\r\n\r\nIf one is not specified, what happens? Maybe we should treat `INADDR_ANY` as meaning \"you can use this protocol, and I don't care what host you originate from\", and missing as meaning \"don't use this protocol\"? That could be nice since it would also give a way to say \"I just want you to use IPv6\", albeit not an obvious one."},"comment":{"url":"https://api.github.com/repos/python-trio/trio/issues/comments/386840035","html_url":"https://github.com/python-trio/trio/issues/275#issuecomment-386840035","issue_url":"https://api.github.com/repos/python-trio/trio/issues/275","id":386840035,"user":{"login":"njsmith","id":609896,"avatar_url":"https://avatars0.githubusercontent.com/u/609896?v=4","gravatar_id":"","url":"https://api.github.com/users/njsmith","html_url":"https://github.com/njsmith","followers_url":"https://api.github.com/users/njsmith/followers","following_url":"https://api.github.com/users/njsmith/following{/other_user}","gists_url":"https://api.github.com/users/njsmith/gists{/gist_id}","starred_url":"https://api.github.com/users/njsmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/njsmith/subscriptions","organizations_url":"https://api.github.com/users/njsmith/orgs","repos_url":"https://api.github.com/users/njsmith/repos","events_url":"https://api.github.com/users/njsmith/events{/privacy}","received_events_url":"https://api.github.com/users/njsmith/received_events","type":"User","site_admin":false},"created_at":"2018-05-05T22:38:52Z","updated_at":"2018-05-05T22:38:52Z","author_association":"OWNER","body":"Here's a possible API that might be a bit simpler to use: allow specifying a list of source addresses, and each socket walks down the list and uses the first one that it can.\r\n\r\nSo `[\"1.2.3.4\", \"1:2:3::4\"]` would use `1.2.3.4` for outgoing IPv4 connections, and `1:2:3::4` for outgoing IPv6 connections, with random ports. (Using `IP_BIND_ADDRESS_NO_PORT` if available, otherwise falling back on port 0.) Specifying `[\"1.2.3.4\"]` would force the use of IPv4 for this connection.\r\n\r\nDo people need the ability to control the outgoing port? We could also allow `[(\"1.2.3.4\", 5678)]` to specify the source port, and this would even allow folks to write silly things like `[(\"1.2.3.4\", 5678), (\"1.2.3.4\", 9012)]` if they wanted to specify a set of allowable source ports (so the first attempt would use 5678, then the second one would try to bind that and fail if the first one was still using it, and then move on to try binding 9012 instead). But possibly this is something we should defer until someone actually needs it."}}
{"actor":{"display_login":"njsmith"}}