RequestOpenChannel is the primary API to open a new outbound channel. It
was written to take a connection.Handler and use OnOpenChannelRequest
to get a channels.Handler to represent the new channel, which is the
same path that inbound channels will take.
Going through the global OnOpenChannelRequest method makes this much
less flexible and prevents passing parameters to the new channel handler
during creation. This also requires users of the API to know/find the
connection handler, or worse, to boilerplate one into existence for their
channel creation.
Instead, I think this function should take a channels.Handler directly,
so that the caller gets full control over the handler for their new
channel.
As part of that change, I've also moved the authentication logic in
AutoConnectionHandler to be contained entirely within
{In,Out}boundConnectionHandler.
ChatChannel didn't return the message ID for sent messages, which made
using the returned ACKs impossible. The SendMessage method now returns
the uin32 messageID.
Also, SendMessage didn't support the TimeDelta field for messages, which
is used for queued or resent messages. This is now available as
SendMessageWithTime.
And finally, the ChatMessageAck callback didn't indicate if mesasges
were accepted or not, which is part of the protocol. That was added as a
field, which is unfortunately a breaking API change, but I've made
enough of those lately to not feel guilty about it.
There are few situations where a pointer to an interface is useful in
Go, and this isn't one. Interfaces can hold types by value or pointer,
so long as that type fulfills the interface.
This is needed to allow creating a Connection for an arbitrary
application-provided io.ReadWriteCloser, instead of doing network logic
inside of go-ricochet. ricochet-go does its own connection management.
I would rather rework this API so that Connection has two construct
methods, inbound and outbound, that do version negotiation and are
always used. The methods that do networking and construct a Connection
would then be a separate (and non-root) package building on top of that.
This is a rework of some parts of the API to make connection management
for applications more sane and reliable.
- The RicochetService interface is split into the ServiceHandler and
ConnectionHandler interfaces. ServiceHandler is implemented by the
application to handle inbound connections to a listener.
ConnectionHandler is implemented to handle events for a single
OpenConnection. Handler instances should no longer be shared for
different listeners or connections.
- Instead of automatically starting a processConnection goroutine, the
application is now responsible for calling OpenConnection.Process in a
goroutine to act on the connection. This function blocks until the
connection is closed. This change allows a better application pattern
for setting the handler of a connection and reacting to connection
loss.
- It is no longer necessary to have started a listener in order to make
outbound connections.
- The Ricochet type is removed, because it no longer served any purpose,
and this avoids having any shared state between different listeners or
connections.
SendRicochetPacket now has error handling, correctly encodes channel
ids, accepts any io.Writer, and ensures that all data is written. All
callers should be changed at some point to handle errors also.
RecvRicochetPackets is refactored to return only one packet per call and
avoid reading more data than it will consume, which simplifies the logic
and fixes a number of problems with short reads or large packets. Also
fixed an error in bounds checking that caused a remote panic for invalid
packet sizes. It also now accepts any io.Reader.
Tests are updated and expanded, and now pass.
Changes to Ricochet.processConnection are whitespace-only, because of
the removal of the inner packets loop.
The service-side version negotiation had a buffer overread that would
cause remotely triggerable panic.
Refactor that code to resolve that issue, follow the spec more exactly,
and avoid reading more data from the socket than is used for version
negotiation, in case clients write optimistically.