1package otr_client 2 3import ( 4 "fmt" 5 "log" 6 7 "github.com/coyim/coyim/xmpp/jid" 8 "github.com/coyim/otr3" 9) 10 11var ( 12 // ErrorPrefix can be used to make an OTR error by appending an error message 13 // to it. 14 ErrorPrefix = "?OTR Error:" 15) 16 17// EventHandler is used to contain information pertaining to the events of a specific OTR interaction 18type EventHandler struct { 19 SmpQuestion string 20 securityChange SecurityChange 21 WaitingForSecret bool 22 account string 23 peer jid.Any 24 notifications chan<- string 25 delayedMessageSent chan<- int 26 delays map[int]bool 27 pendingDelays int 28} 29 30// ConsumeDelayedState returns whether the given trace has been delayed or not, blanking out that status as a side effect 31func (e *EventHandler) ConsumeDelayedState(trace int) bool { 32 val, ok := e.delays[trace] 33 delete(e.delays, trace) 34 return ok && val 35} 36 37func (e *EventHandler) notify(s string) { 38 e.notifications <- s 39} 40 41// HandleErrorMessage is called when asked to handle a specific error message 42func (e *EventHandler) HandleErrorMessage(error otr3.ErrorCode) []byte { 43 log.Printf("[%s] HandleErrorMessage(%s)", e.account, error.String()) 44 45 switch error { 46 case otr3.ErrorCodeEncryptionError: 47 return []byte("Error occurred encrypting message.") 48 case otr3.ErrorCodeMessageUnreadable: 49 return []byte("You transmitted an unreadable encrypted message.") 50 case otr3.ErrorCodeMessageMalformed: 51 return []byte("You transmitted a malformed data message.") 52 case otr3.ErrorCodeMessageNotInPrivate: 53 return []byte("You sent encrypted data to a peer, who wasn't expecting it.") 54 } 55 56 return nil 57} 58 59// HandleSecurityEvent is called to handle a specific security event 60func (e *EventHandler) HandleSecurityEvent(event otr3.SecurityEvent) { 61 log.Printf("[%s] HandleSecurityEvent(%s)", e.account, event.String()) 62 switch event { 63 case otr3.GoneSecure: 64 e.pendingDelays = 0 65 e.securityChange = NewKeys 66 case otr3.StillSecure: 67 e.securityChange = RenewedKeys 68 case otr3.GoneInsecure: 69 e.securityChange = ConversationEnded 70 } 71} 72 73// HandleSMPEvent is called to handle a specific SMP event 74func (e *EventHandler) HandleSMPEvent(event otr3.SMPEvent, progressPercent int, question string) { 75 log.Printf("[%s] HandleSMPEvent(%s, %d, %s)", e.account, event.String(), progressPercent, question) 76 switch event { 77 case otr3.SMPEventAskForSecret, otr3.SMPEventAskForAnswer: 78 e.securityChange = SMPSecretNeeded 79 e.SmpQuestion = question 80 e.WaitingForSecret = true 81 case otr3.SMPEventSuccess: 82 if progressPercent == 100 { 83 e.securityChange = SMPComplete 84 } 85 case otr3.SMPEventAbort, otr3.SMPEventFailure, otr3.SMPEventCheated: 86 e.securityChange = SMPFailed 87 } 88} 89 90// HandleMessageEvent is called to handle a specific message event 91func (e *EventHandler) HandleMessageEvent(event otr3.MessageEvent, message []byte, err error, trace ...interface{}) { 92 switch event { 93 case otr3.MessageEventLogHeartbeatReceived: 94 log.Printf("[%s] Heartbeat received from %s.", e.account, e.peer) 95 case otr3.MessageEventLogHeartbeatSent: 96 log.Printf("[%s] Heartbeat sent to %s.", e.account, e.peer) 97 case otr3.MessageEventReceivedMessageUnrecognized: 98 log.Printf("[%s] Unrecognized OTR message received from %s.", e.account, e.peer) 99 case otr3.MessageEventEncryptionRequired: 100 e.delays[trace[0].(int)] = true 101 e.pendingDelays++ 102 if e.pendingDelays == 1 { 103 e.notify("Attempting to start a private conversation...") 104 } 105 case otr3.MessageEventEncryptionError: 106 // This happens when something goes wrong putting together a new data packet in OTR 107 e.notify("An error occurred when encrypting your message. The message was not sent.") 108 case otr3.MessageEventConnectionEnded: 109 // This happens when we have finished a conversation and tries to send a message afterwards 110 e.notify("Your message was not sent, since the other person has already closed their private connection to you.") 111 case otr3.MessageEventMessageReflected: 112 e.notify("We are receiving our own OTR messages. You are either trying to talk to yourself, or someone is reflecting your messages back at you.") 113 case otr3.MessageEventSetupError: 114 e.notify("Error setting up private conversation.") 115 if err != nil { 116 log.Printf("[%s] Error setting up private conversation with %s: %s.", e.account, e.peer, err.Error()) 117 } 118 case otr3.MessageEventMessageSent: 119 if len(trace) > 0 { 120 e.delayedMessageSent <- trace[0].(int) 121 } 122 case otr3.MessageEventMessageResent: 123 e.notify("The last message to the other person was resent, since we couldn't deliver the message previously.") 124 case otr3.MessageEventReceivedMessageUnreadable: 125 // This happens when the authenticator is wrong, message counters are out of whack 126 // or several other things that indicate tampering or attack 127 e.notify("We received an unreadable encrypted message. It has probably been tampered with, or was sent from an older client.") 128 case otr3.MessageEventReceivedMessageMalformed: 129 // This happens when the OTR header is malformed, or different deserialization issues 130 e.notify("We received a malformed data message.") 131 case otr3.MessageEventReceivedMessageGeneralError: 132 // This happens when we receive an error from the other party 133 e.notify(fmt.Sprintf("We received this error from the other person: %s.", string(message))) 134 case otr3.MessageEventReceivedMessageNotInPrivate: 135 // This happens when we receive what looks like a data message, but we're not in encrypted state 136 // TODO: this should open conversation window 137 e.notify("We received an encrypted message which can't be read, since private communication is not currently turned on. You should ask your peer to repeat what they said.") 138 case otr3.MessageEventReceivedMessageUnencrypted: 139 // This happens when we receive a non-OTR message, even though we have require encryption turned on 140 e.notify("We received a message that was transferred without encryption") 141 case otr3.MessageEventReceivedMessageForOtherInstance: 142 // We ignore this message on purpose, for now it would be too noisy to notify about it 143 default: 144 log.Printf("[%s] Unhandled OTR3 Message Event(%s, %s, %v)", e.account, event.String(), message, err) 145 } 146} 147 148// ConsumeSecurityChange is called to get the current security change and forget the old one 149func (e *EventHandler) ConsumeSecurityChange() SecurityChange { 150 ret := e.securityChange 151 e.securityChange = NoChange 152 return ret 153} 154