forked from lug/matterbridge
Use upstream whatsapp again (#809)
This commit is contained in:
111
vendor/github.com/Rhymen/go-whatsapp/read.go
generated
vendored
Normal file
111
vendor/github.com/Rhymen/go-whatsapp/read.go
generated
vendored
Normal file
@@ -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
|
||||
}
|
Reference in New Issue
Block a user