core: Handle response to outbound contact requests
This commit is contained in:
parent
b6fd295ac1
commit
6f7e030811
|
@ -33,6 +33,8 @@ type Contact struct {
|
||||||
connChannel chan *protocol.OpenConnection
|
connChannel chan *protocol.OpenConnection
|
||||||
connClosedChannel chan struct{}
|
connClosedChannel chan struct{}
|
||||||
|
|
||||||
|
outboundConnAuthKnown bool
|
||||||
|
|
||||||
conversation *Conversation
|
conversation *Conversation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,10 +249,9 @@ func (c *Contact) connectOutbound(ctx context.Context, connChannel chan *protoco
|
||||||
oc, err := protocol.Open(conn, hostname[0:16])
|
oc, err := protocol.Open(conn, hostname[0:16])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Contact connection protocol failure: %s", err)
|
log.Printf("Contact connection protocol failure: %s", err)
|
||||||
|
if oc != nil {
|
||||||
oc.Close()
|
oc.Close()
|
||||||
// XXX These failures are probably not worth retrying so much,
|
}
|
||||||
// but that would need to be investigated. For now, just do the
|
|
||||||
// same backoff behavior.
|
|
||||||
if err := connector.Backoff(ctx); err != nil {
|
if err := connector.Backoff(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -303,6 +304,14 @@ func (c *Contact) setConnection(conn *protocol.OpenConnection) error {
|
||||||
return fmt.Errorf("Connection hostname %s doesn't match contact hostname %s when assigning connection", conn.OtherHostname, c.data.Hostname[0:16])
|
return fmt.Errorf("Connection hostname %s doesn't match contact hostname %s when assigning connection", conn.OtherHostname, c.data.Hostname[0:16])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conn.Client && !c.outboundConnAuthKnown && !c.data.Request.Pending {
|
||||||
|
log.Printf("Outbound connection to contact says we are not a known contact for %v", c)
|
||||||
|
// XXX Should move to rejected status, stop attempting connections.
|
||||||
|
c.mutex.Unlock()
|
||||||
|
conn.Close()
|
||||||
|
return fmt.Errorf("Outbound connection says we are not a known contact")
|
||||||
|
}
|
||||||
|
|
||||||
if c.connection != nil {
|
if c.connection != nil {
|
||||||
if c.shouldReplaceConnection(conn) {
|
if c.shouldReplaceConnection(conn) {
|
||||||
// XXX Signal state change for connection loss?
|
// XXX Signal state change for connection loss?
|
||||||
|
@ -324,17 +333,17 @@ func (c *Contact) setConnection(conn *protocol.OpenConnection) error {
|
||||||
log.Printf("Assigned connection %v to contact %v", c.connection, c)
|
log.Printf("Assigned connection %v to contact %v", c.connection, c)
|
||||||
|
|
||||||
if c.data.Request.Pending {
|
if c.data.Request.Pending {
|
||||||
if conn.Client {
|
if conn.Client && !c.outboundConnAuthKnown {
|
||||||
// XXX Need to check knownContact flag in authentication and implicit accept also
|
|
||||||
// Outbound connection for contact request; send request message
|
// Outbound connection for contact request; send request message
|
||||||
// XXX hardcoded channel ID
|
// XXX hardcoded channel ID
|
||||||
log.Printf("Sending outbound contact request to %v", c)
|
log.Printf("Sending outbound contact request to %v", c)
|
||||||
conn.SendContactRequest(5, c.data.Request.MyNickname, c.data.Request.Message)
|
conn.SendContactRequest(5, c.data.Request.MyNickname, c.data.Request.Message)
|
||||||
} else {
|
} else {
|
||||||
// Inbound connection for contact request; implicitly accept request
|
// Inbound connection or outbound connection with a positive
|
||||||
// and continue as contact
|
// 'isKnownContact' response implicitly accepts the contact request
|
||||||
log.Printf("Contact request implicitly accepted by incoming connection for contact %v", c)
|
// and can continue as a contact
|
||||||
c.requestAccepted()
|
log.Printf("Contact request implicitly accepted by contact %v", c)
|
||||||
|
c.updateContactRequest("Accepted")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.status = ricochet.Contact_ONLINE
|
c.status = ricochet.Contact_ONLINE
|
||||||
|
@ -428,22 +437,72 @@ func (c *Contact) shouldReplaceConnection(conn *protocol.OpenConnection) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes mutex is held, and assumes the caller will send the UPDATE event
|
// Update the status of a contact request from a protocol event. Returns
|
||||||
func (c *Contact) requestAccepted() {
|
// true if the contact request channel should remain open.
|
||||||
config := c.core.Config.OpenWrite()
|
func (c *Contact) UpdateContactRequest(status string) bool {
|
||||||
c.data.Request = ConfigContactRequest{}
|
c.mutex.Lock()
|
||||||
config.Contacts[strconv.Itoa(c.id)] = c.data
|
defer c.mutex.Unlock()
|
||||||
config.Save()
|
|
||||||
|
|
||||||
|
if !c.data.Request.Pending {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
re := c.updateContactRequest(status)
|
||||||
|
|
||||||
|
event := ricochet.ContactEvent{
|
||||||
|
Type: ricochet.ContactEvent_UPDATE,
|
||||||
|
Subject: &ricochet.ContactEvent_Contact{
|
||||||
|
Contact: c.Data(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.events.Publish(event)
|
||||||
|
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as above, but assumes the mutex is already held and that the caller
|
||||||
|
// will send an UPDATE event
|
||||||
|
func (c *Contact) updateContactRequest(status string) bool {
|
||||||
|
config := c.core.Config.OpenWrite()
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
// Whether to keep the channel open
|
||||||
|
var re bool
|
||||||
|
|
||||||
|
switch status {
|
||||||
|
case "Pending":
|
||||||
|
c.data.Request.WhenDelivered = now
|
||||||
|
re = true
|
||||||
|
|
||||||
|
case "Accepted":
|
||||||
|
c.data.Request = ConfigContactRequest{}
|
||||||
if c.connection != nil {
|
if c.connection != nil {
|
||||||
c.status = ricochet.Contact_ONLINE
|
c.status = ricochet.Contact_ONLINE
|
||||||
} else {
|
} else {
|
||||||
c.status = ricochet.Contact_UNKNOWN
|
c.status = ricochet.Contact_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "Rejected":
|
||||||
|
c.data.Request.WhenRejected = now
|
||||||
|
|
||||||
|
case "Error":
|
||||||
|
c.data.Request.WhenRejected = now
|
||||||
|
c.data.Request.RemoteError = "error occurred"
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Printf("Unknown contact request status '%s'", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Contacts[strconv.Itoa(c.id)] = c.data
|
||||||
|
config.Save()
|
||||||
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX also will go away during protocol API rework
|
// XXX also will go away during protocol API rework
|
||||||
func (c *Contact) OnConnectionAuthenticated(conn *protocol.OpenConnection) {
|
func (c *Contact) OnConnectionAuthenticated(conn *protocol.OpenConnection, knownContact bool) {
|
||||||
|
// XXX this is ugly
|
||||||
|
if conn.Client {
|
||||||
|
c.outboundConnAuthKnown = knownContact
|
||||||
|
}
|
||||||
c.connChannel <- conn
|
c.connChannel <- conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (pc *ProtocolConnection) OnAuthenticationProof(channelID int32, publicKey [
|
||||||
|
|
||||||
log.Printf("protocol: OnAuthenticationProof, result: %v, contact: %v", result, pc.Contact)
|
log.Printf("protocol: OnAuthenticationProof, result: %v, contact: %v", result, pc.Contact)
|
||||||
if result && pc.Contact != nil {
|
if result && pc.Contact != nil {
|
||||||
pc.Contact.OnConnectionAuthenticated(pc.Conn)
|
pc.Contact.OnConnectionAuthenticated(pc.Conn, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,16 +87,9 @@ func (pc *ProtocolConnection) OnAuthenticationResult(channelID int32, result boo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Contact request, removed cases
|
|
||||||
if !isKnownContact {
|
|
||||||
log.Printf("protocol: Outbound connection authentication to %s succeeded, but we are not a known contact", pc.Conn.OtherHostname)
|
|
||||||
pc.Conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("protocol: Outbound connection to %s authenticated", pc.Conn.OtherHostname)
|
log.Printf("protocol: Outbound connection to %s authenticated", pc.Conn.OtherHostname)
|
||||||
if pc.Contact != nil {
|
if pc.Contact != nil {
|
||||||
pc.Contact.OnConnectionAuthenticated(pc.Conn)
|
pc.Contact.OnConnectionAuthenticated(pc.Conn, isKnownContact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +98,15 @@ func (pc *ProtocolConnection) OnContactRequest(channelID int32, nick string, mes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc *ProtocolConnection) OnContactRequestAck(channelID int32, status string) {
|
func (pc *ProtocolConnection) OnContactRequestAck(channelID int32, status string) {
|
||||||
|
if !pc.Conn.Client || pc.Contact == nil {
|
||||||
|
pc.Conn.CloseChannel(channelID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pc.Contact.UpdateContactRequest(status) {
|
||||||
|
pc.Conn.CloseChannel(channelID)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Managing Channels
|
// Managing Channels
|
||||||
|
|
Loading…
Reference in New Issue