2017-08-12 00:10:41 +00:00
|
|
|
package utils
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/golang/protobuf/proto"
|
2017-08-12 00:10:41 +00:00
|
|
|
"github.com/s-rah/go-ricochet/wire/auth"
|
|
|
|
"github.com/s-rah/go-ricochet/wire/chat"
|
|
|
|
"github.com/s-rah/go-ricochet/wire/contact"
|
|
|
|
"github.com/s-rah/go-ricochet/wire/control"
|
2016-12-04 00:34:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// MessageBuilder allows a client to construct specific data packets for the
|
|
|
|
// ricochet protocol.
|
|
|
|
type MessageBuilder struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// OpenChannel contructs a message which will request to open a channel for
|
|
|
|
// chat on the given channelID.
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) OpenChannel(channelID int32, channelType string) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
oc := &Protocol_Data_Control.OpenChannel{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
ChannelType: proto.String(channelType),
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
OpenChannel: oc,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AckOpenChannel constructs a message to acknowledge a previous open channel operation.
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) AckOpenChannel(channelID int32) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
cr := &Protocol_Data_Control.ChannelResult{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
Opened: proto.Bool(true),
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
ChannelResult: cr,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RejectOpenChannel constructs a channel result message, stating the channel failed to open and a reason
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) RejectOpenChannel(channelID int32, error string) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
errorNum := Protocol_Data_Control.ChannelResult_CommonError_value[error]
|
|
|
|
commonError := Protocol_Data_Control.ChannelResult_CommonError(errorNum)
|
|
|
|
|
|
|
|
cr := &Protocol_Data_Control.ChannelResult{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
Opened: proto.Bool(false),
|
|
|
|
CommonError: &commonError,
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
ChannelResult: cr,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ConfirmAuthChannel constructs a message to acknowledge a previous open channel operation.
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) ConfirmAuthChannel(channelID int32, serverCookie [16]byte) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
cr := &Protocol_Data_Control.ChannelResult{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
Opened: proto.Bool(true),
|
|
|
|
}
|
|
|
|
|
|
|
|
err := proto.SetExtension(cr, Protocol_Data_AuthHiddenService.E_ServerCookie, serverCookie[:])
|
2017-08-12 00:10:41 +00:00
|
|
|
CheckError(err)
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
ChannelResult: cr,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// OpenContactRequestChannel contructs a message which will reuqest to open a channel for
|
|
|
|
// a contact request on the given channelID, with the given nick and message.
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) OpenContactRequestChannel(channelID int32, nick string, message string) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
// Construct a Contact Request Channel
|
|
|
|
oc := &Protocol_Data_Control.OpenChannel{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
ChannelType: proto.String("im.ricochet.contact.request"),
|
|
|
|
}
|
|
|
|
|
|
|
|
contactRequest := &Protocol_Data_ContactRequest.ContactRequest{
|
|
|
|
Nickname: proto.String(nick),
|
|
|
|
MessageText: proto.String(message),
|
|
|
|
}
|
|
|
|
|
|
|
|
err := proto.SetExtension(oc, Protocol_Data_ContactRequest.E_ContactRequest, contactRequest)
|
2017-08-12 00:10:41 +00:00
|
|
|
CheckError(err)
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
OpenChannel: oc,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ReplyToContactRequestOnResponse constructs a message to acknowledge contact request
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) ReplyToContactRequestOnResponse(channelID int32, status string) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
cr := &Protocol_Data_Control.ChannelResult{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
Opened: proto.Bool(true),
|
|
|
|
}
|
|
|
|
|
|
|
|
statusNum := Protocol_Data_ContactRequest.Response_Status_value[status]
|
|
|
|
responseStatus := Protocol_Data_ContactRequest.Response_Status(statusNum)
|
|
|
|
contactRequest := &Protocol_Data_ContactRequest.Response{
|
|
|
|
Status: &responseStatus,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := proto.SetExtension(cr, Protocol_Data_ContactRequest.E_Response, contactRequest)
|
2017-08-12 00:10:41 +00:00
|
|
|
CheckError(err)
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
ChannelResult: cr,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ReplyToContactRequest constructs a message to acknowledge a contact request
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) ReplyToContactRequest(channelID int32, status string) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
statusNum := Protocol_Data_ContactRequest.Response_Status_value[status]
|
|
|
|
responseStatus := Protocol_Data_ContactRequest.Response_Status(statusNum)
|
|
|
|
contactRequest := &Protocol_Data_ContactRequest.Response{
|
|
|
|
Status: &responseStatus,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
|
|
|
|
ret, err := proto.Marshal(contactRequest)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// OpenAuthenticationChannel constructs a message which will reuqest to open a channel for
|
|
|
|
// authentication on the given channelID, with the given cookie
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) OpenAuthenticationChannel(channelID int32, clientCookie [16]byte) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
oc := &Protocol_Data_Control.OpenChannel{
|
|
|
|
ChannelIdentifier: proto.Int32(channelID),
|
|
|
|
ChannelType: proto.String("im.ricochet.auth.hidden-service"),
|
|
|
|
}
|
|
|
|
err := proto.SetExtension(oc, Protocol_Data_AuthHiddenService.E_ClientCookie, clientCookie[:])
|
2017-08-12 00:10:41 +00:00
|
|
|
CheckError(err)
|
2016-12-04 00:34:58 +00:00
|
|
|
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
OpenChannel: oc,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Proof constructs a proof message with the given public key and signature.
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) Proof(publicKeyBytes []byte, signatureBytes []byte) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
proof := &Protocol_Data_AuthHiddenService.Proof{
|
|
|
|
PublicKey: publicKeyBytes,
|
|
|
|
Signature: signatureBytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
ahsPacket := &Protocol_Data_AuthHiddenService.Packet{
|
|
|
|
Proof: proof,
|
|
|
|
Result: nil,
|
|
|
|
}
|
|
|
|
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(ahsPacket)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AuthResult constructs a response to a Proof
|
2017-08-12 00:10:41 +00:00
|
|
|
func (mb *MessageBuilder) AuthResult(accepted bool, isKnownContact bool) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
// Construct a Result Message
|
|
|
|
result := &Protocol_Data_AuthHiddenService.Result{
|
|
|
|
Accepted: proto.Bool(accepted),
|
|
|
|
IsKnownContact: proto.Bool(isKnownContact),
|
|
|
|
}
|
|
|
|
|
|
|
|
ahsPacket := &Protocol_Data_AuthHiddenService.Packet{
|
|
|
|
Proof: nil,
|
|
|
|
Result: result,
|
|
|
|
}
|
|
|
|
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(ahsPacket)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ChatMessage constructs a chat message with the given content.
|
2017-09-25 20:24:10 +00:00
|
|
|
func (mb *MessageBuilder) ChatMessage(message string, messageID uint32, timeDelta int64) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
cm := &Protocol_Data_Chat.ChatMessage{
|
2017-08-12 00:10:41 +00:00
|
|
|
MessageId: proto.Uint32(messageID),
|
2016-12-04 00:34:58 +00:00
|
|
|
MessageText: proto.String(message),
|
2017-09-25 20:24:10 +00:00
|
|
|
TimeDelta: proto.Int64(timeDelta),
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
chatPacket := &Protocol_Data_Chat.Packet{
|
|
|
|
ChatMessage: cm,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(chatPacket)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AckChatMessage constructs a chat message acknowledgement.
|
2017-09-25 20:24:10 +00:00
|
|
|
func (mb *MessageBuilder) AckChatMessage(messageID uint32, accepted bool) []byte {
|
2016-12-04 00:34:58 +00:00
|
|
|
cr := &Protocol_Data_Chat.ChatAcknowledge{
|
2017-08-12 00:10:41 +00:00
|
|
|
MessageId: proto.Uint32(messageID),
|
2017-09-25 20:24:10 +00:00
|
|
|
Accepted: proto.Bool(accepted),
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Chat.Packet{
|
|
|
|
ChatAcknowledge: cr,
|
|
|
|
}
|
2017-08-12 00:10:41 +00:00
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// KeepAlive ...
|
|
|
|
func (mb *MessageBuilder) KeepAlive(responseRequested bool) []byte {
|
|
|
|
ka := &Protocol_Data_Control.KeepAlive{
|
|
|
|
ResponseRequested: proto.Bool(responseRequested),
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
KeepAlive: ka,
|
|
|
|
}
|
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnableFeatures ...
|
|
|
|
func (mb *MessageBuilder) EnableFeatures(features []string) []byte {
|
|
|
|
ef := &Protocol_Data_Control.EnableFeatures{
|
|
|
|
Feature: features,
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
EnableFeatures: ef,
|
|
|
|
}
|
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// FeaturesEnabled ...
|
|
|
|
func (mb *MessageBuilder) FeaturesEnabled(features []string) []byte {
|
|
|
|
fe := &Protocol_Data_Control.FeaturesEnabled{
|
|
|
|
Feature: features,
|
|
|
|
}
|
|
|
|
pc := &Protocol_Data_Control.Packet{
|
|
|
|
FeaturesEnabled: fe,
|
|
|
|
}
|
|
|
|
ret, err := proto.Marshal(pc)
|
|
|
|
CheckError(err)
|
|
|
|
return ret
|
2016-12-04 00:34:58 +00:00
|
|
|
}
|