go-ricochet/messagebuilder.go

200 lines
6.5 KiB
Go

package goricochet
import (
"github.com/golang/protobuf/proto"
"github.com/s-rah/go-ricochet/auth"
"github.com/s-rah/go-ricochet/chat"
"github.com/s-rah/go-ricochet/contact"
"github.com/s-rah/go-ricochet/control"
"github.com/s-rah/go-ricochet/utils"
)
// 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.
func (mb *MessageBuilder) OpenChannel(channelID int32, channelType string) ([]byte, error) {
oc := &Protocol_Data_Control.OpenChannel{
ChannelIdentifier: proto.Int32(channelID),
ChannelType: proto.String(channelType),
}
pc := &Protocol_Data_Control.Packet{
OpenChannel: oc,
}
return proto.Marshal(pc)
}
// AckOpenChannel constructs a message to acknowledge a previous open channel operation.
func (mb *MessageBuilder) AckOpenChannel(channelID int32) ([]byte, error) {
cr := &Protocol_Data_Control.ChannelResult{
ChannelIdentifier: proto.Int32(channelID),
Opened: proto.Bool(true),
}
pc := &Protocol_Data_Control.Packet{
ChannelResult: cr,
}
return proto.Marshal(pc)
}
// RejectOpenChannel constructs a channel result message, stating the channel failed to open and a reason
func (mb *MessageBuilder) RejectOpenChannel(channelID int32, error string) ([]byte, error) {
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,
}
return proto.Marshal(pc)
}
// ConfirmAuthChannel constructs a message to acknowledge a previous open channel operation.
func (mb *MessageBuilder) ConfirmAuthChannel(channelID int32, serverCookie [16]byte) ([]byte, error) {
cr := &Protocol_Data_Control.ChannelResult{
ChannelIdentifier: proto.Int32(channelID),
Opened: proto.Bool(true),
}
err := proto.SetExtension(cr, Protocol_Data_AuthHiddenService.E_ServerCookie, serverCookie[:])
utils.CheckError(err)
pc := &Protocol_Data_Control.Packet{
ChannelResult: cr,
}
return proto.Marshal(pc)
}
// 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.
func (mb *MessageBuilder) OpenContactRequestChannel(channelID int32, nick string, message string) ([]byte, error) {
// 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)
utils.CheckError(err)
pc := &Protocol_Data_Control.Packet{
OpenChannel: oc,
}
return proto.Marshal(pc)
}
// ReplyToContactRequestOnResponse constructs a message to acknowledge contact request
func (mb *MessageBuilder) ReplyToContactRequestOnResponse(channelID int32, status string) ([]byte, error) {
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)
utils.CheckError(err)
pc := &Protocol_Data_Control.Packet{
ChannelResult: cr,
}
return proto.Marshal(pc)
}
// ReplyToContactRequest constructs a message to acknowledge a contact request
func (mb *MessageBuilder) ReplyToContactRequest(channelID int32, status string) ([]byte, error) {
statusNum := Protocol_Data_ContactRequest.Response_Status_value[status]
responseStatus := Protocol_Data_ContactRequest.Response_Status(statusNum)
contactRequest := &Protocol_Data_ContactRequest.Response{
Status: &responseStatus,
}
return proto.Marshal(contactRequest)
}
// OpenAuthenticationChannel constructs a message which will reuqest to open a channel for
// authentication on the given channelID, with the given cookie
func (mb *MessageBuilder) OpenAuthenticationChannel(channelID int32, clientCookie [16]byte) ([]byte, error) {
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[:])
utils.CheckError(err)
pc := &Protocol_Data_Control.Packet{
OpenChannel: oc,
}
return proto.Marshal(pc)
}
// Proof constructs a proof message with the given public key and signature.
func (mb *MessageBuilder) Proof(publicKeyBytes []byte, signatureBytes []byte) ([]byte, error) {
proof := &Protocol_Data_AuthHiddenService.Proof{
PublicKey: publicKeyBytes,
Signature: signatureBytes,
}
ahsPacket := &Protocol_Data_AuthHiddenService.Packet{
Proof: proof,
Result: nil,
}
return proto.Marshal(ahsPacket)
}
// AuthResult constructs a response to a Proof
func (mb *MessageBuilder) AuthResult(accepted bool, isKnownContact bool) ([]byte, error) {
// 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,
}
return proto.Marshal(ahsPacket)
}
// ChatMessage constructs a chat message with the given content.
func (mb *MessageBuilder) ChatMessage(message string, messageID int32) ([]byte, error) {
cm := &Protocol_Data_Chat.ChatMessage{
MessageId: proto.Uint32(uint32(messageID)),
MessageText: proto.String(message),
}
chatPacket := &Protocol_Data_Chat.Packet{
ChatMessage: cm,
}
return proto.Marshal(chatPacket)
}
// AckChatMessage constructs a chat message acknowledgement.
func (mb *MessageBuilder) AckChatMessage(messageID int32) ([]byte, error) {
cr := &Protocol_Data_Chat.ChatAcknowledge{
MessageId: proto.Uint32(uint32(messageID)),
Accepted: proto.Bool(true),
}
pc := &Protocol_Data_Chat.Packet{
ChatAcknowledge: cr,
}
return proto.Marshal(pc)
}