Virtual Circuits are network connections between PSYC nodes, typically on the Internet and typically using TCP, but we are also thinking about UDP circuits. The term is historically derived from the X.25 definition of Virtual Circuit, but doesn't operate the same way.
Contents |
Circuit establishment
The PSYC protocol and its routing layer open circuits with an empty packet, then a _notice_circuit_established. You are supposed to reply with the same combination as well. Whenever you want to shut down a circuit, you are supposed to send a _request_circuit_shutdown to the other side. When everything is fine the other side will close the socket and let you go. You are not supposed to shut down the socket without asking as you may be losing data the other side was just starting to send.
See Spec:Circuit for a more detailed description.
Circuits are currently being used for all traffic in psyced, although it was the original idea that notices (in particular presence updates) would travel by UDP unless a circuit has already been established to the receiving node.
the Virtual Circuit manager
Most PSYC implementations have a class that manages virtual circuits. In psyced http://www.psyced.org/dist/world/net/circuit.c and http://www.psyced.org/dist/world/net/psyc/circuit.c do that job. The code is not an easy read. What it does is try to keep the circuit (TCP) flowing, and whenever that isn't the case, queue up messages and retry connecting.
Circuits over UDP
One day however we may decide to use circuits over UDP. There is a commonly resounding urban legend that bringing packet safety to UDP equals reinventing TCP. This is underestimating TCP which also provides correct order of packets and has such complex algorithms as "slow start" and the concept of a window.
A lightweight circuit strategy using UDP would ensure that all packets make it safely to the other side, or at least provide a means to find out which ones haven't - but that doesn't mean that they have to arrive in the proper order. In PSYC the order of messages may not be terrifically important, and by the use of Packet Ids the client at the end of the line would still take care of reorganizing output properly.. like inserting a lost line of chat output at the proper spot in the output and replacing a warning message that informed the user of a temporarily missing packet.
In fact with multipeer multicasting the client will need to be able to reorganize the arrival of packets anyway, so it might just aswell be able to do so for unicast over UDP circuits.
The main advantage of a UDP circuit is its immediateness. While a TCP gets stuck in a netlag until missing packets get through, UDP lets you have everything that made it so far. If you like to recover lost packets, we talk about that in recovery.
Circuits over SCTP
SCTP is the Stream Control Transmission Protocol - an alternative to TCP with features that fit the PSYC needs better.
The built-in framing is quite interesting, it would allow PSYC to leave out some dots and to transmit binary without providing a content-length.
Also the Transmission sequence number (TSN) of SCTP has a similar function to PSYC's _counter, I wonder if one could delegate some jobs of PSYC routing and Packet Ids to SCTP.
One thing SCTP will not provide is multicast packet ids - to get to that we'd either have to synchronize TSNs on all transmissions related to a particular context, or not try to optimize the routing layer away just because SCTP does an inbetween job between TCP and PSYC.
I'm not sure if I got the SCTP multiplexing capabilities right, but if that means that you can have sources and targets and each of them has their own TSN, then to synchronize a multicast would mean that all SCTP links, no matter how many in the world, all use the same TSNs when distributing multicasts coming from a particular context, thus implementing the Multicast Sanity Rule on top of SCTP.
Does that make sense? Of course there may be some reason that we are not grasping right now why SCTP would be completely inappropriate. Also the fact that it would de facto turn PSYC into a non-plaintext protocol is quite a minus.
As a side note, XMPP would gain a lot from using this technology: It has a huge framing problem which SCTP would solve. And since XMPP doesn't multicast, it isn't requiring any extras from SCTP.
elmex notifies us of unix API woes concerning SCTP: "recv() and recvfrom() return data from any stream, but the caller can not distinguish the different streams. The system uses stream 0 as the default stream for send() and sendto()." looks like a complicated operation to implement SCTP in practice.
Circuits over HTTP
The classic kludge for web-based applications. In some cases it is just easier to deliver data by HTTP POST rather than a socket or an IP packet.
HTTP circuits would, if anyone cared to implement them, log into a remote web application using a POST to an http: URL, then dump regular PSYC packets to it. Depending on the situation the socket may want to be closed after that. The circuit logic takes care of queuing up new packets until a new connection is ready to push them out. The incoming side would go through the HTTP server implementation, not the circuits.
One could imagine that the same HTTP circuit is capable of outputting other formats than PSYC packets, like format PSYC into JSON, XML, XML-RPC or even - oh dear - SOAP.
Circuit Authentication & Trust
For authentication of circuits we do use SASL in our XMPP implementation and are looking into how to apply that to PSYC as well, but we also have a mechanism for checksums on an MMP packet level, which can be used to raise the trust level of an existing circuit. See checksums.
We also consider applying the web of trust to circuits or even to use the collective social trust of users towards a particular network node as an indicator of trustworthiness. Experimental stuff.