2016-10-05 21:38:18 +00:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/special/notricochet/core/utils"
|
|
|
|
"github.com/special/notricochet/rpc"
|
|
|
|
"log"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// XXX threading model.. this one isn't great
|
|
|
|
|
|
|
|
// XXX Should probably be under core or identity
|
|
|
|
var conversationStream *utils.Publisher = utils.CreatePublisher()
|
|
|
|
|
|
|
|
type Conversation struct {
|
|
|
|
Core *Ricochet
|
|
|
|
Contact *Contact
|
|
|
|
|
|
|
|
mutex sync.Mutex
|
|
|
|
|
|
|
|
localEntity *ricochet.Entity
|
|
|
|
remoteEntity *ricochet.Entity
|
|
|
|
messages []*ricochet.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewConversation(core *Ricochet, contact *Contact, remoteEntity *ricochet.Entity) *Conversation {
|
|
|
|
return &Conversation{
|
|
|
|
Core: core,
|
|
|
|
Contact: contact,
|
|
|
|
localEntity: &ricochet.Entity{IsSelf: true},
|
|
|
|
remoteEntity: remoteEntity,
|
|
|
|
messages: make([]*ricochet.Message, 0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ConversationEventMonitor() utils.Subscribable {
|
|
|
|
return conversationStream
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conversation) Receive(id uint64, timestamp int64, text string) {
|
|
|
|
message := &ricochet.Message{
|
|
|
|
Sender: c.remoteEntity,
|
|
|
|
Recipient: c.localEntity,
|
|
|
|
Timestamp: timestamp,
|
|
|
|
Identifier: id,
|
|
|
|
Status: ricochet.Message_RECEIVED,
|
|
|
|
Text: text,
|
|
|
|
}
|
|
|
|
// XXX container
|
|
|
|
// XXX limit backlog/etc
|
|
|
|
c.mutex.Lock()
|
|
|
|
c.messages = append(c.messages, message)
|
|
|
|
log.Printf("Conversation received message: %v", message)
|
|
|
|
c.mutex.Unlock()
|
|
|
|
|
|
|
|
// XXX Technically these aren't guaranteed to be in order (because
|
|
|
|
// the lock has been released) or to all arrive (because of publisher's
|
|
|
|
// dropping behavior)...
|
|
|
|
event := ricochet.ConversationEvent{
|
|
|
|
Type: ricochet.ConversationEvent_RECEIVE,
|
|
|
|
Msg: message,
|
|
|
|
}
|
|
|
|
conversationStream.Publish(event)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Conversation) UpdateSentStatus(id uint64, success bool) {
|
|
|
|
c.mutex.Lock()
|
|
|
|
for _, message := range c.messages {
|
|
|
|
if message.Status != ricochet.Message_SENDING || message.Identifier != id {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if success {
|
|
|
|
message.Status = ricochet.Message_DELIVERED
|
|
|
|
} else {
|
|
|
|
message.Status = ricochet.Message_ERROR
|
|
|
|
}
|
|
|
|
|
|
|
|
c.mutex.Unlock()
|
|
|
|
event := ricochet.ConversationEvent{
|
|
|
|
Type: ricochet.ConversationEvent_UPDATE,
|
|
|
|
Msg: message,
|
|
|
|
}
|
|
|
|
conversationStream.Publish(event)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.mutex.Unlock()
|
|
|
|
}
|
|
|
|
|
2016-10-06 23:50:07 +00:00
|
|
|
func (c *Conversation) Send(text string) (*ricochet.Message, error) {
|
2016-10-05 21:38:18 +00:00
|
|
|
// XXX protocol
|
|
|
|
// XXX check that text is ok, get identifier, etc
|
|
|
|
// XXX decide whether sending or queued based on state
|
|
|
|
message := &ricochet.Message{
|
|
|
|
Sender: c.localEntity,
|
|
|
|
Recipient: c.remoteEntity,
|
|
|
|
Timestamp: time.Now().Unix(),
|
2016-10-06 23:50:07 +00:00
|
|
|
Identifier: 0, // XXX
|
|
|
|
Status: ricochet.Message_QUEUED,
|
2016-10-05 21:38:18 +00:00
|
|
|
Text: text,
|
|
|
|
}
|
2016-10-06 23:50:07 +00:00
|
|
|
|
|
|
|
// XXX witness thread disaster
|
|
|
|
conn := c.Contact.Connection()
|
|
|
|
if conn != nil {
|
|
|
|
// XXX hardcoded channel IDs, also channel IDs shouldn't be exposed
|
|
|
|
channelId := int32(7)
|
|
|
|
if !conn.Client {
|
|
|
|
channelId++
|
|
|
|
}
|
|
|
|
// XXX no error handling
|
|
|
|
if conn.GetChannelType(channelId) != "im.ricochet.chat" {
|
|
|
|
conn.OpenChatChannel(channelId)
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX no message IDs, no acks
|
|
|
|
conn.SendMessage(channelId, text)
|
|
|
|
message.Status = ricochet.Message_SENDING
|
|
|
|
}
|
|
|
|
|
2016-10-05 21:38:18 +00:00
|
|
|
c.mutex.Lock()
|
|
|
|
c.messages = append(c.messages, message)
|
|
|
|
log.Printf("Conversation sent message: %v", message)
|
|
|
|
c.mutex.Unlock()
|
|
|
|
|
|
|
|
event := ricochet.ConversationEvent{
|
|
|
|
Type: ricochet.ConversationEvent_SEND,
|
|
|
|
Msg: message,
|
|
|
|
}
|
|
|
|
conversationStream.Publish(event)
|
2016-10-06 23:50:07 +00:00
|
|
|
|
|
|
|
return message, nil
|
2016-10-05 21:38:18 +00:00
|
|
|
}
|