2016-06-27 01:56:23 +00:00
|
|
|
package utils
|
|
|
|
|
2017-05-02 23:33:51 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Error captures various common ricochet errors
|
|
|
|
type Error string
|
|
|
|
|
|
|
|
func (e Error) Error() string { return string(e) }
|
|
|
|
|
|
|
|
// Defining Versions
|
|
|
|
const (
|
|
|
|
VersionNegotiationError = Error("VersionNegotiationError")
|
|
|
|
VersionNegotiationFailed = Error("VersionNegotiationFailed")
|
|
|
|
|
|
|
|
RicochetConnectionClosed = Error("RicochetConnectionClosed")
|
|
|
|
RicochetProtocolError = Error("RicochetProtocolError")
|
|
|
|
|
|
|
|
UnknownChannelTypeError = Error("UnknownChannelTypeError")
|
|
|
|
UnauthorizedChannelTypeError = Error("UnauthorizedChannelTypeError")
|
2018-01-14 16:45:30 +00:00
|
|
|
UnexpectedChannelResultError = Error("UnexpectedChannelResultError")
|
2017-05-02 23:33:51 +00:00
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
// Timeout Errors
|
2017-05-02 23:33:51 +00:00
|
|
|
ActionTimedOutError = Error("ActionTimedOutError")
|
2017-07-04 18:29:11 +00:00
|
|
|
PeerTimedOutError = Error("PeerTimedOutError")
|
2017-05-02 23:33:51 +00:00
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
// Authentication Errors
|
|
|
|
ClientFailedToAuthenticateError = Error("ClientFailedToAuthenticateError")
|
|
|
|
ServerRejectedClientConnectionError = Error("ServerRejectedClientConnectionError")
|
2017-06-27 17:39:33 +00:00
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
UnauthorizedActionError = Error("UnauthorizedActionError")
|
|
|
|
ChannelClosedByPeerError = Error("ChannelClosedByPeerError")
|
2017-06-27 17:39:33 +00:00
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
// Channel Management Errors
|
|
|
|
ServerAttemptedToOpenEvenNumberedChannelError = Error("ServerAttemptedToOpenEvenNumberedChannelError")
|
|
|
|
ClientAttemptedToOpenOddNumberedChannelError = Error("ClientAttemptedToOpenOddNumberedChannelError")
|
|
|
|
ChannelIDIsAlreadyInUseError = Error("ChannelIDIsAlreadyInUseError")
|
|
|
|
AttemptToOpenMoreThanOneSingletonChannelError = Error("AttemptToOpenMoreThanOneSingletonChannelError")
|
|
|
|
|
|
|
|
// Library Use Errors
|
2018-05-01 01:03:06 +00:00
|
|
|
OnionAddressGenerationError = Error("OnionAddressGenerationError")
|
2018-05-09 19:40:07 +00:00
|
|
|
PrivateKeyNotSetError = Error("PrivateKeyNotSet")
|
Prevent deadlocks with Do or Break and closing connections
After the last round of fixes in Do, there was still one major issue
making it impossible to use Do or Break safely: closing connections.
Connections can be closed spontaneously, and this causes Process to
return. At that moment any ongoing call to Do or Break has deadlocked;
nothing will ever read those channels again. To prevent this, we have to
ensure that Do or Break won't try to send to Process' channels once it
has stopped reading from them. Doing that without other races is tricky.
The solution here, briefly, is to acquire a mutex in Do and Break before
checking the `closed` boolean, and hold that mutex for the entire
operation (including any blocking channel operations). When Process is
closing down the connection, it uses a separate goroutine to acquire the
same mutex and change the boolean, while still handling channel reads.
Once the boolean has changed, the mutex guarantees that nothing will try
to send to these channels again.
I've tried to document the problems and solutions in the code, because
it is subtle in some places and this is definitely critical code.
2017-09-16 21:45:07 +00:00
|
|
|
|
|
|
|
// Connection Errors
|
|
|
|
ConnectionClosedError = Error("ConnectionClosedError")
|
2017-05-02 23:33:51 +00:00
|
|
|
)
|
2016-06-27 01:56:23 +00:00
|
|
|
|
2016-11-08 23:04:11 +00:00
|
|
|
// CheckError is a helper function for panicing on errors which we need to handle
|
|
|
|
// but should be very rare e.g. failures deserializing a protobuf object that
|
|
|
|
// should only happen if there was a bug in the underlying library.
|
2016-06-27 01:56:23 +00:00
|
|
|
func CheckError(err error) {
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("%v", err))
|
|
|
|
}
|
|
|
|
}
|