[dcc2] Other comments
myndzi
myndzi at gmail.com
Sun Jun 27 19:45:05 EDT 2004
Here's another take on this stuff that came to mind.
Each client should (must?) take every opportunity possible to bind a
port to establish the connection. Do this parallel to negotiation such
that all the other client has to do to finalize things is connect.
This has the effect of reducing the number of back-and-forth
transactions as far as possible.
My "latest" idea goes about like this...
Note some comments on extra tokens at the bottom.
1) ClientA initiating a connection uses the following tokens:
Application=(what is going to handle the connection when it's established)
SID=unique number
MID=1 (using Szymon's name)
Publish="Publish tokens for supported layers and protocols"
Connect="tokens describing the port I am listening on now (optional
but recommended)"
Apptokens="data to pass to the application"
2) ClientB receives the data
Ask whatever module is designated to handle the Application token
(say, IRCChat) if it wants to establish the connection; provide
Apptokens in case the code needs some of that data to decide (example,
filename in IRCFile connections)
no -> we're done
If a Connect section was specified -> decide if we can connect to that or not.
yes -> try
succeeded?
yes -> done; notify the application handler and provide Apptokens for data
No to any of the above:
Select a subset of the provided Publish tokens to use.
Send back a ctcp with the following:
(Application is redundant and thus excluded)
SID=same as before
MID=2
Select="selected subset of publish tokens given by ClientA (optional,
only include if we can specify a solution)"
Publish="optionally we can include our own Publish section to specify
ports and listen capability"
Connect="if we can establish a listening connection based on the
Select params, do so and provide this section"
(Apptokens is redundant and thus excluded)
3) ClientA receives a response
If we opened a listening socket for the first message, close it now.
If ClientB provided a Connect section -> decide if we can connect to
that or not.
yes -> try
succeeded?
yes -> done, pass apptokens along to the Application handler etc.
No to these:
If ClientB specified that it MUST listen (more on that later), decide
if we can connect using the parameters in message 2's Publish section.
yes -> Send back a message including SID, Select="", and MID=3
no -> error, we're done here.
If ClientB specified a Select section:
Using the Select tokens given by ClientB, bind a listening socket.
Send a message like so:
GoAhead SID=<same> MID=3
4) ClientB receives response
Close any listening sockets
Message 3 will either tell us what to listen on, or will be an
acknowledgement that ClientA is listening on the interface we
selected.
If the former, listen on that interface and send a GoAhead message as
per the last group. (MID=4)
If the latter, attempt to connect.
Anything else -> error, done
MIDs higher than 4 = error, done
Always increment the MID in a reply
----
Acceptible Publish tokens as follows:
Network=<network types>
Transport=<transport types>
Ports=<port range>
<listen capability>
All lists should be given in order of preference.
Acceptible Select tokens:
Network=<one network selected from the other end's Publish group>
Transport=<one transport selected from the other end's Publish group>
Ports=<one or more ports selected from the other end's port group>
Acceptible Connect tokens:
<network type>=address
<transport type> (not really needed)
Port=<port>
Note that you will not have to parse the group of Connect tokens to
"find out" what is there. It will either be specified by Select, or by
the first item in the appropriate Publish token. (I.E. if Publish
contains Network=IPv4,IPv6 in the first message, it is assumed that
IPv4= will be specified in the Connect section if provided. IPv6= will
be ignored.) Connect section should only be included when "WillListen
or MustListen" is specified.
Acceptible Application tokens:
Any. Must escape any quotes, etc since it's encapsulated as a quoted string.
"listen capability" may be one of the following:
CanListen - indicates the ability to accept a listening connection;
indicates that the client is not taking the initiative (not listening,
no Connect group).
CannotListen - indicates the inability to accept a listening connection
WillListen - indicates the ability and initiative
MustListen - same as WillListen, but indicates the inability to
establish an outgoing connection to the other side (in any combination
of the other side's provided data).
MustListen would only be used in response to a message from a client
that indicated WillListen, in order to tell it to drop the initiative.
CanListen should be avoided if not left out altogether, but would
indicate a preference for outgoing connections even though the ability
for incoming ones is there.
I forgot to work in compression and/or encryption or any of that kind
of thing. It should be able to fit in the same 'style' with the
exception of assumed Connect tokens. Perhaps the default offered
choice should be indicated specifically.
Put all that crap together in a few examples now!
Shortest possible connection:
ClientA: DCC2 Application=IRCChat SID=69 MID=1
Publish="Network=IPv4,IPv6 Transport=TCP,UDP Ports=1024-5000,8080
WillListen" Connect="IPv4=192.168.0.3 TCP Port=1036"
Apptokens="Nick=myndzi"
ClientB connects.
Longest possible connection (a bit silly/contrived, but illustrative):
ClientA: DCC2 Application=IRCChat SID=69 MID=1
Publish="Network=IPv4,IPv6 Transport=TCP,UDP Ports=1024-5000,8080
WillListen" Connect="IPv4=192.168.0.3 TCP Port=1036"
Apptokens="Nick=myndzi"
ClientB: DCC2 SID=69 MID=2 Publish="Ports=7000-7010 MustListen"
Select="Network=IPv4 Transport=TCP" Connect="IPv4=192.168.0.2 TCP
Port=7001"
ClientA: DCC2 SID=69 MID=3 Select="Ports=7005"
ClientB: DCC2 SID=69 MID=4 GoAhead
ClientA connects.
An instance where all this crap would be useful:
ClientA: DCC2 Application=IRCChat SID=69 MID=1
Publish="Network=IPv4,IPv6 Transport=TCP,UDP Ports=80 CanListen"
Apptokens="Nick=myndzi"
ClientB: DCC2 SID=69 MID=2 Publish="Ports=7000-7010 MustListen"
Select="Network=IPv4 Transport=TCP" Connect="IPv4=192.168.0.2 TCP
Port=7001"
ClientA connects.
Alternately:
ClientA: DCC2 Application=IRCChat SID=69 MID=1
Publish="Network=IPv4,IPv6 Transport=TCP,UDP Ports=80 CanListen"
Apptokens="Nick=myndzi"
ClientB: DCC2 SID=69 MID=2 Select="Network=IPv4 Transport=TCP Ports=80"
ClientA: DCC2 SID=69 MID=3 GoAhead
ClientB connects.
-myndzi
More information about the dcc2
mailing list