2021-04-04 17:06:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"chat2/pb"
|
2021-04-28 20:28:45 +00:00
|
|
|
"context"
|
2021-06-10 13:00:16 +00:00
|
|
|
"crypto/sha256"
|
2021-04-04 17:06:17 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
"github.com/status-im/go-waku/waku/v2/node"
|
2021-06-28 14:14:28 +00:00
|
|
|
"github.com/status-im/go-waku/waku/v2/protocol"
|
|
|
|
"github.com/status-im/go-waku/waku/v2/protocol/filter"
|
2021-04-22 00:12:51 +00:00
|
|
|
wpb "github.com/status-im/go-waku/waku/v2/protocol/pb"
|
2021-06-28 14:14:28 +00:00
|
|
|
"github.com/status-im/go-waku/waku/v2/protocol/relay"
|
2021-06-10 13:00:16 +00:00
|
|
|
"golang.org/x/crypto/pbkdf2"
|
2021-04-04 17:06:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Chat represents a subscription to a single PubSub topic. Messages
|
|
|
|
// can be published to the topic with Chat.Publish, and received
|
|
|
|
// messages are pushed to the Messages channel.
|
|
|
|
type Chat struct {
|
|
|
|
// Messages is a channel of messages received from other peers in the chat room
|
|
|
|
Messages chan *pb.Chat2Message
|
|
|
|
|
|
|
|
sub *node.Subscription
|
2021-06-28 14:14:28 +00:00
|
|
|
C chan *protocol.Envelope
|
2021-04-04 17:06:17 +00:00
|
|
|
node *node.WakuNode
|
|
|
|
|
2021-06-10 13:00:16 +00:00
|
|
|
self peer.ID
|
|
|
|
contentTopic string
|
|
|
|
useV1Payload bool
|
|
|
|
nick string
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewChat tries to subscribe to the PubSub topic for the room name, returning
|
|
|
|
// a ChatRoom on success.
|
2021-06-28 14:14:28 +00:00
|
|
|
func NewChat(ctx context.Context, n *node.WakuNode, selfID peer.ID, contentTopic string, useV1Payload bool, useLightPush bool, nickname string) (*Chat, error) {
|
2021-04-04 17:06:17 +00:00
|
|
|
// join the default waku topic and subscribe to it
|
|
|
|
|
2021-06-28 14:14:28 +00:00
|
|
|
chat := &Chat{
|
2021-06-10 13:00:16 +00:00
|
|
|
node: n,
|
|
|
|
self: selfID,
|
|
|
|
contentTopic: contentTopic,
|
|
|
|
nick: nickname,
|
|
|
|
useV1Payload: useV1Payload,
|
|
|
|
Messages: make(chan *pb.Chat2Message, 1024),
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
|
2021-06-28 14:14:28 +00:00
|
|
|
if useLightPush {
|
|
|
|
chat.C = make(filter.ContentFilterChan)
|
|
|
|
|
|
|
|
filterRequest := wpb.FilterRequest{
|
2021-10-09 18:18:53 +00:00
|
|
|
ContentFilters: []*wpb.FilterRequest_ContentFilter{{ContentTopic: contentTopic}},
|
2021-06-28 14:14:28 +00:00
|
|
|
Topic: string(relay.GetTopic(nil)),
|
|
|
|
Subscribe: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
n.SubscribeFilter(ctx, filterRequest, chat.C)
|
|
|
|
} else {
|
|
|
|
sub, err := n.Subscribe(nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
chat.C = sub.C
|
|
|
|
}
|
|
|
|
|
2021-04-04 17:06:17 +00:00
|
|
|
// start reading messages from the subscription in a loop
|
2021-06-28 14:14:28 +00:00
|
|
|
go chat.readLoop()
|
2021-04-04 17:06:17 +00:00
|
|
|
|
2021-06-28 14:14:28 +00:00
|
|
|
return chat, nil
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
|
2021-06-10 13:00:16 +00:00
|
|
|
func generateSymKey(password string) []byte {
|
|
|
|
// AesKeyLength represents the length (in bytes) of an private key
|
|
|
|
AESKeyLength := 256 / 8
|
|
|
|
return pbkdf2.Key([]byte(password), nil, 65356, AESKeyLength, sha256.New)
|
|
|
|
}
|
|
|
|
|
2021-04-04 17:06:17 +00:00
|
|
|
// Publish sends a message to the pubsub topic.
|
2021-04-28 20:28:45 +00:00
|
|
|
func (cr *Chat) Publish(ctx context.Context, message string) error {
|
2021-04-04 17:06:17 +00:00
|
|
|
|
|
|
|
msg := &pb.Chat2Message{
|
|
|
|
Timestamp: uint64(time.Now().Unix()),
|
|
|
|
Nick: cr.nick,
|
|
|
|
Payload: []byte(message),
|
|
|
|
}
|
|
|
|
|
|
|
|
msgBytes, err := proto.Marshal(msg)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-06-10 13:00:16 +00:00
|
|
|
var version uint32
|
2021-10-09 18:18:53 +00:00
|
|
|
var timestamp float64 = float64(time.Now().Unix())
|
2021-06-10 13:00:16 +00:00
|
|
|
var keyInfo *node.KeyInfo = &node.KeyInfo{}
|
|
|
|
|
|
|
|
if cr.useV1Payload { // Use WakuV1 encryption
|
|
|
|
keyInfo.Kind = node.Symmetric
|
|
|
|
keyInfo.SymKey = generateSymKey(cr.contentTopic)
|
|
|
|
version = 1
|
|
|
|
} else {
|
|
|
|
keyInfo.Kind = node.None
|
|
|
|
version = 0
|
|
|
|
}
|
2021-04-06 23:27:54 +00:00
|
|
|
|
|
|
|
p := new(node.Payload)
|
|
|
|
p.Data = msgBytes
|
|
|
|
p.Key = keyInfo
|
2021-04-04 17:06:17 +00:00
|
|
|
|
2021-06-10 13:00:16 +00:00
|
|
|
payload, err := p.Encode(version)
|
2021-04-04 17:06:17 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-04-22 00:12:51 +00:00
|
|
|
wakuMsg := &wpb.WakuMessage{
|
2021-04-04 17:06:17 +00:00
|
|
|
Payload: payload,
|
2021-04-07 21:19:39 +00:00
|
|
|
Version: version,
|
2021-06-10 13:00:16 +00:00
|
|
|
ContentTopic: cr.contentTopic,
|
2021-04-07 21:19:39 +00:00
|
|
|
Timestamp: timestamp,
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
|
2021-04-28 20:28:45 +00:00
|
|
|
_, err = cr.node.Publish(ctx, wakuMsg, nil)
|
2021-04-11 23:45:42 +00:00
|
|
|
|
|
|
|
return err
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 00:12:51 +00:00
|
|
|
func (cr *Chat) decodeMessage(wakumsg *wpb.WakuMessage) {
|
2021-06-10 13:00:16 +00:00
|
|
|
var keyInfo *node.KeyInfo = &node.KeyInfo{}
|
|
|
|
if cr.useV1Payload { // Use WakuV1 encryption
|
|
|
|
keyInfo.Kind = node.Symmetric
|
|
|
|
keyInfo.SymKey = generateSymKey(cr.contentTopic)
|
|
|
|
} else {
|
|
|
|
keyInfo.Kind = node.None
|
|
|
|
}
|
|
|
|
|
|
|
|
payload, err := node.DecodePayload(wakumsg, keyInfo)
|
2021-04-12 18:03:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
msg := &pb.Chat2Message{}
|
|
|
|
if err := proto.Unmarshal(payload.Data, msg); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// send valid messages onto the Messages channel
|
|
|
|
cr.Messages <- msg
|
|
|
|
}
|
|
|
|
|
2021-04-04 17:06:17 +00:00
|
|
|
// readLoop pulls messages from the pubsub topic and pushes them onto the Messages channel.
|
|
|
|
func (cr *Chat) readLoop() {
|
2021-06-28 14:14:28 +00:00
|
|
|
for value := range cr.C {
|
2021-04-12 18:03:58 +00:00
|
|
|
cr.decodeMessage(value.Message())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-22 00:12:51 +00:00
|
|
|
func (cr *Chat) displayMessages(messages []*wpb.WakuMessage) {
|
2021-04-12 18:03:58 +00:00
|
|
|
for _, msg := range messages {
|
|
|
|
cr.decodeMessage(msg)
|
2021-04-04 17:06:17 +00:00
|
|
|
}
|
|
|
|
}
|