summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Rhymen/go-whatsapp/read.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2019-05-30 12:20:56 +0200
committerGitHub <noreply@github.com>2019-05-30 12:20:56 +0200
commit3418e8c9afbdf3e94ab26a20d8f12c042ae29fc4 (patch)
treec5358b971a95749bece9469e959041d4f2e54cc3 /vendor/github.com/Rhymen/go-whatsapp/read.go
parent9619dff33417548a50e51a4f75f41b9de4a73327 (diff)
downloadmatterbridge-msglm-3418e8c9afbdf3e94ab26a20d8f12c042ae29fc4.tar.gz
matterbridge-msglm-3418e8c9afbdf3e94ab26a20d8f12c042ae29fc4.tar.bz2
matterbridge-msglm-3418e8c9afbdf3e94ab26a20d8f12c042ae29fc4.zip
Use upstream whatsapp again (#809)
Diffstat (limited to 'vendor/github.com/Rhymen/go-whatsapp/read.go')
-rw-r--r--vendor/github.com/Rhymen/go-whatsapp/read.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/read.go b/vendor/github.com/Rhymen/go-whatsapp/read.go
new file mode 100644
index 00000000..7281ccff
--- /dev/null
+++ b/vendor/github.com/Rhymen/go-whatsapp/read.go
@@ -0,0 +1,111 @@
+package whatsapp
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "github.com/Rhymen/go-whatsapp/binary"
+ "github.com/Rhymen/go-whatsapp/crypto/cbc"
+ "github.com/gorilla/websocket"
+ "github.com/pkg/errors"
+ "io"
+ "io/ioutil"
+ "strings"
+)
+
+func (wac *Conn) readPump() {
+ defer wac.wg.Done()
+
+ var readErr error
+ var msgType int
+ var reader io.Reader
+
+ for {
+ readerFound := make(chan struct{})
+ go func() {
+ msgType, reader, readErr = wac.ws.conn.NextReader()
+ close(readerFound)
+ }()
+ select {
+ case <-readerFound:
+ if readErr != nil {
+ wac.handle(&ErrConnectionFailed{Err: readErr})
+ _, _ = wac.Disconnect()
+ return
+ }
+ msg, err := ioutil.ReadAll(reader)
+ if err != nil {
+ wac.handle(errors.Wrap(err, "error reading message from Reader"))
+ continue
+ }
+ err = wac.processReadData(msgType, msg)
+ if err != nil {
+ wac.handle(errors.Wrap(err, "error processing data"))
+ }
+ case <-wac.ws.close:
+ return
+ }
+ }
+}
+
+func (wac *Conn) processReadData(msgType int, msg []byte) error {
+ data := strings.SplitN(string(msg), ",", 2)
+
+ if data[0][0] == '!' { //Keep-Alive Timestamp
+ data = append(data, data[0][1:]) //data[1]
+ data[0] = "!"
+ }
+
+ if len(data) != 2 || len(data[1]) == 0 {
+ return ErrInvalidWsData
+ }
+
+ wac.listener.RLock()
+ listener, hasListener := wac.listener.m[data[0]]
+ wac.listener.RUnlock()
+
+ if hasListener {
+ // listener only exists for TextMessages query messages out of contact.go
+ // If these binary query messages can be handled another way,
+ // then the TextMessages, which are all JSON encoded, can directly
+ // be unmarshalled. The listener chan could then be changed from type
+ // chan string to something like chan map[string]interface{}. The unmarshalling
+ // in several places, especially in session.go, would then be gone.
+ listener <- data[1]
+
+ wac.listener.Lock()
+ delete(wac.listener.m, data[0])
+ wac.listener.Unlock()
+ } else if msgType == websocket.BinaryMessage && wac.loggedIn {
+ message, err := wac.decryptBinaryMessage([]byte(data[1]))
+ if err != nil {
+ return errors.Wrap(err, "error decoding binary")
+ }
+ wac.dispatch(message)
+ } else { //RAW json status updates
+ wac.handle(string(data[1]))
+ }
+ return nil
+}
+
+func (wac *Conn) decryptBinaryMessage(msg []byte) (*binary.Node, error) {
+ //message validation
+ h2 := hmac.New(sha256.New, wac.session.MacKey)
+ h2.Write([]byte(msg[32:]))
+ if !hmac.Equal(h2.Sum(nil), msg[:32]) {
+ return nil, ErrInvalidHmac
+ }
+
+ // message decrypt
+ d, err := cbc.Decrypt(wac.session.EncKey, nil, msg[32:])
+ if err != nil {
+ return nil, errors.Wrap(err, "decrypting message with AES-CBC failed")
+ }
+
+ // message unmarshal
+ message, err := binary.Unmarshal(d)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not decode binary")
+ }
+
+ return message, nil
+}