Implement conversation with the new protocol API
Conversation now acts as a ChatChannelHandler, so a Conversation is able to directly recieve messages on the associated ChatChannel.
This commit is contained in:
		
							parent
							
								
									0c187e72a0
								
							
						
					
					
						commit
						0b19ae4b66
					
				|  | @ -3,8 +3,6 @@ package core | |||
| import ( | ||||
| 	"github.com/s-rah/go-ricochet/channels" | ||||
| 	"github.com/s-rah/go-ricochet/connection" | ||||
| 	"log" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type ContactProtocolHandler struct { | ||||
|  | @ -18,32 +16,14 @@ func NewContactProtocolHandler(contact *Contact, conn *connection.Connection) *C | |||
| 		conn:    conn, | ||||
| 		contact: contact, | ||||
| 	} | ||||
| 	handler.Init(nil, conn.RemoteHostname) | ||||
| 	handler.Init() | ||||
| 
 | ||||
| 	handler.RegisterChannelHandler("im.ricochet.chat", func() channels.Handler { | ||||
| 		chat := new(channels.ChatChannel) | ||||
| 		chat.Handler = handler | ||||
| 		chat := &channels.ChatChannel{ | ||||
| 			Handler: contact.Conversation(), | ||||
| 		} | ||||
| 		return chat | ||||
| 	}) | ||||
| 
 | ||||
| 	// XXX Somebody needs to be calling Process, nobody is yet, need that rework in contact
 | ||||
| 	return handler | ||||
| } | ||||
| 
 | ||||
| // Implement ChatChannelHandler for im.ricochet.chat
 | ||||
| func (handler *ContactProtocolHandler) ChatMessage(messageID uint32, when time.Time, message string) bool { | ||||
| 	// XXX sanity checks, message contents, etc
 | ||||
| 	log.Printf("chat message: %d %d %v %s", messageID, when, message) | ||||
| 
 | ||||
| 	conversation := handler.contact.Conversation() | ||||
| 	conversation.Receive(uint64(messageID), when.Unix(), message) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (handler *ContactProtocolHandler) ChatMessageAck(messageID uint32) { | ||||
| 	// XXX no success field
 | ||||
| 	log.Printf("chat ack: %d", messageID) | ||||
| 
 | ||||
| 	conversation := handler.contact.Conversation() | ||||
| 	conversation.UpdateSentStatus(uint64(messageID), true) | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import ( | |||
| 	"errors" | ||||
| 	"github.com/ricochet-im/ricochet-go/core/utils" | ||||
| 	"github.com/ricochet-im/ricochet-go/rpc" | ||||
| 	connection "github.com/s-rah/go-ricochet/connection" | ||||
| 	"github.com/s-rah/go-ricochet/channels" | ||||
| 	"log" | ||||
| 	"math/rand" | ||||
| 	"sync" | ||||
|  | @ -129,10 +129,13 @@ func (c *Conversation) Send(text string) (*ricochet.Message, error) { | |||
| 		Text:       text, | ||||
| 	} | ||||
| 
 | ||||
| 	// XXX threading mess, and probably deadlockable. Need better API for conn.
 | ||||
| 	conn := c.Contact.Connection() | ||||
| 	if conn != nil { | ||||
| 		sendMessageToConnection(conn, message) | ||||
| 	if online, err := c.sendMessageToConnection(message); err != nil { | ||||
| 		if online { | ||||
| 			message.Status = ricochet.Message_ERROR | ||||
| 		} else { | ||||
| 			message.Status = ricochet.Message_QUEUED | ||||
| 		} | ||||
| 	} else { | ||||
| 		// XXX go-ricochet doesn't support message IDs & ack properly yet, so skip SENDING
 | ||||
| 		//message.Status = ricochet.Message_SENDING
 | ||||
| 		message.Status = ricochet.Message_DELIVERED | ||||
|  | @ -166,11 +169,19 @@ func (c *Conversation) SendQueuedMessages() int { | |||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		sendMessageToConnection(conn, message) | ||||
| 		if online, err := c.sendMessageToConnection(message); err != nil { | ||||
| 			if online { | ||||
| 				message.Status = ricochet.Message_ERROR | ||||
| 			} else { | ||||
| 				// Offline again?
 | ||||
| 				break | ||||
| 			} | ||||
| 		} else { | ||||
| 			// XXX go-ricochet doesn't support message IDs & ack properly yet, so skip SENDING
 | ||||
| 			//message.Status = ricochet.Message_SENDING
 | ||||
| 			message.Status = ricochet.Message_DELIVERED | ||||
| 			sent++ | ||||
| 		} | ||||
| 
 | ||||
| 		event := ricochet.ConversationEvent{ | ||||
| 			Type: ricochet.ConversationEvent_UPDATE, | ||||
|  | @ -182,25 +193,6 @@ func (c *Conversation) SendQueuedMessages() int { | |||
| 	return sent | ||||
| } | ||||
| 
 | ||||
| func sendMessageToConnection(conn *connection.Connection, message *ricochet.Message) { | ||||
| 	// XXX
 | ||||
| 	panic("sendMessageToConnection needs implementing for new protocol API") | ||||
| 	/* | ||||
| 		// XXX hardcoded channel IDs, also channel IDs shouldn't be exposed
 | ||||
| 		channelId := int32(7) | ||||
| 		if conn.IsInbound { | ||||
| 			channelId++ | ||||
| 		} | ||||
| 		// XXX no error handling
 | ||||
| 		if conn.GetChannelType(channelId) != "im.ricochet.chat" { | ||||
| 			conn.OpenChatChannel(channelId) | ||||
| 		} | ||||
| 
 | ||||
| 		// XXX no message IDs
 | ||||
| 		conn.SendMessage(channelId, message.Text) | ||||
| 	*/ | ||||
| } | ||||
| 
 | ||||
| // XXX This is inefficient -- it'll usually only be marking the last message
 | ||||
| // or few messages. Need a better way to know what's unread.
 | ||||
| func (c *Conversation) MarkReadBeforeMessage(msgId uint64) int { | ||||
|  | @ -227,3 +219,53 @@ func (c *Conversation) MarkReadBeforeMessage(msgId uint64) int { | |||
| 
 | ||||
| 	return marked | ||||
| } | ||||
| 
 | ||||
| // Implement ChatChannelHandler (im.ricochet.chat)
 | ||||
| func (c *Conversation) ChatMessage(messageID uint32, when time.Time, message string) bool { | ||||
| 	// XXX sanity checks, message contents, etc
 | ||||
| 	log.Printf("chat message: %d %d %v %s", messageID, when, message) | ||||
| 
 | ||||
| 	c.Receive(uint64(messageID), when.Unix(), message) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (c *Conversation) ChatMessageAck(messageID uint32) { | ||||
| 	// XXX no success field
 | ||||
| 	log.Printf("chat ack: %d", messageID) | ||||
| 
 | ||||
| 	c.UpdateSentStatus(uint64(messageID), true) | ||||
| } | ||||
| 
 | ||||
| func (c *Conversation) sendMessageToConnection(message *ricochet.Message) (connected bool, err error) { | ||||
| 	conn := c.Contact.Connection() | ||||
| 	if conn == nil { | ||||
| 		err = errors.New("not connected") | ||||
| 		return | ||||
| 	} | ||||
| 	connected = true | ||||
| 
 | ||||
| 	err = conn.Do(func() error { | ||||
| 		channel := conn.Channel("im.ricochet.chat", channels.Outbound) | ||||
| 		if channel == nil { | ||||
| 			if ch, err := conn.RequestOpenChannel("im.ricochet.chat", &channels.ChatChannel{Handler: c}); err != nil { | ||||
| 				return err | ||||
| 			} else { | ||||
| 				channel = ch | ||||
| 			} | ||||
| 		} | ||||
| 		chat, ok := channel.Handler.(*channels.ChatChannel) | ||||
| 		if !ok { | ||||
| 			channel.CloseChannel() | ||||
| 			return errors.New("invalid chat channel") | ||||
| 		} | ||||
| 
 | ||||
| 		// XXX message id and all of that
 | ||||
| 		chat.SendMessage(message.Text) | ||||
| 		return nil | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		log.Printf("chat send failed: %s", err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue