diff --git a/Gopkg.lock b/Gopkg.lock index 8ddcccf8..bd28eebe 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -27,7 +27,7 @@ [[projects]] branch = "master" - digest = "1:c309b41787813f80ec393023471014b0be16346bba6e16bf5fa01ce1d310a4ea" + digest = "1:a2c142e6c2aa1c71796c748bbe42d224e23d6638fd5b3ae153e70a4b08a8da4e" name = "github.com/bettercap/gatt" packages = [ ".", @@ -40,7 +40,7 @@ "xpc", ] pruneopts = "UT" - revision = "1353e80bee488dc02d1f7e42759c1352492bf18b" + revision = "277ee0d0ef94d26e3190252c59fa34dde0df4f26" [[projects]] branch = "master" diff --git a/modules/ble/ble_recon.go b/modules/ble/ble_recon.go index 1c54bff5..1bea0d99 100644 --- a/modules/ble/ble_recon.go +++ b/modules/ble/ble_recon.go @@ -6,7 +6,6 @@ package ble import ( "encoding/hex" "fmt" - "io/ioutil" golog "log" "time" @@ -15,6 +14,8 @@ import ( "github.com/bettercap/bettercap/session" "github.com/bettercap/gatt" + + "github.com/evilsocket/islazy/str" ) type BLERecon struct { @@ -126,15 +127,25 @@ func (mod *BLERecon) isEnumerating() bool { return mod.currDevice != nil } +type dummyWriter struct { + mod *BLERecon +} + +func (w dummyWriter) Write(p []byte) (n int, err error) { + w.mod.Debug("[gatt.log] %s", str.Trim(string(p))) + return len(p), nil +} + func (mod *BLERecon) Configure() (err error) { if mod.Running() { return session.ErrAlreadyStarted } else if mod.gattDevice == nil { mod.Debug("initializing device ...") - // hey Paypal GATT library, could you please just STFU?! - golog.SetOutput(ioutil.Discard) + golog.SetFlags(0) + golog.SetOutput(dummyWriter{mod}) if mod.gattDevice, err = gatt.NewDevice(defaultBLEClientOptions...); err != nil { + mod.Debug("error while creating new gatt device: %v", err) return err } @@ -162,7 +173,17 @@ func (mod *BLERecon) Start() error { mod.Info("stopping scan ...") - mod.gattDevice.StopScanning() + if mod.currDevice != nil && mod.currDevice.Device != nil && mod.gattDevice != nil { + mod.Debug("resetting connection with %v", mod.currDevice.Device) + mod.gattDevice.CancelConnection(mod.currDevice.Device) + } + + mod.Debug("stopping device") + if err := mod.gattDevice.Stop(); err != nil { + mod.Warning("error while stopping device: %v", err) + } else { + mod.Debug("gatt device closed") + } mod.done <- true }) @@ -172,6 +193,9 @@ func (mod *BLERecon) Stop() error { return mod.SetRunning(false, func() { mod.quit <- true <-mod.done + mod.Debug("module stopped, cleaning state") + mod.gattDevice = nil + mod.setCurrentDevice(nil) }) } diff --git a/modules/ble/ble_recon_events.go b/modules/ble/ble_recon_events.go index 883527c8..25c63ebb 100644 --- a/modules/ble/ble_recon_events.go +++ b/modules/ble/ble_recon_events.go @@ -15,8 +15,12 @@ func (mod *BLERecon) onStateChanged(dev gatt.Device, s gatt.State) { if mod.currDevice == nil { mod.Info("starting discovery ...") dev.Scan([]gatt.UUID{}, true) + } else { + mod.Debug("current device was not cleaned: %v", mod.currDevice) } case gatt.StatePoweredOff: + mod.Debug("resetting device instance") + mod.gattDevice.StopScanning() mod.setCurrentDevice(nil) mod.gattDevice = nil @@ -51,6 +55,7 @@ func (mod *BLERecon) onPeriphConnected(p gatt.Peripheral, err error) { defer func(per gatt.Peripheral) { mod.Info("disconnecting from %s ...", per.ID()) per.Device().CancelConnection(per) + mod.setCurrentDevice(nil) }(p) mod.Session.Events.Add("ble.device.connected", mod.currDevice) diff --git a/vendor/github.com/bettercap/gatt/linux/device.go b/vendor/github.com/bettercap/gatt/linux/device.go index e2ca3e4e..5f2a234e 100644 --- a/vendor/github.com/bettercap/gatt/linux/device.go +++ b/vendor/github.com/bettercap/gatt/linux/device.go @@ -22,6 +22,7 @@ type device struct { func newDevice(n int, chk bool) (*device, error) { fd, err := socket.Socket(socket.AF_BLUETOOTH, syscall.SOCK_RAW, socket.BTPROTO_HCI) if err != nil { + log.Printf("could not create AF_BLUETOOTH raw socket") return nil, err } if n != -1 { @@ -30,13 +31,17 @@ func newDevice(n int, chk bool) (*device, error) { req := devListRequest{devNum: hciMaxDevices} if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceList, uintptr(unsafe.Pointer(&req))); err != nil { + log.Printf("hciGetDeviceList failed") return nil, err } + log.Printf("got %d devices", req.devNum) for i := 0; i < int(req.devNum); i++ { d, err := newSocket(fd, i, chk) if err == nil { log.Printf("dev: %s opened", d.name) return d, err + } else { + log.Printf("error while opening device %d: %v", i, err) } } return nil, errors.New("no supported devices available") @@ -45,6 +50,7 @@ func newDevice(n int, chk bool) (*device, error) { func newSocket(fd, n int, chk bool) (*device, error) { i := hciDevInfo{id: uint16(n)} if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceInfo, uintptr(unsafe.Pointer(&i))); err != nil { + log.Printf("hciGetDeviceInfo failed") return nil, err } name := string(i.name[:]) @@ -61,6 +67,7 @@ func newSocket(fd, n int, chk bool) (*device, error) { } log.Printf("dev: %s reset", name) if err := gioctl.Ioctl(uintptr(fd), hciResetDevice, uintptr(n)); err != nil { + log.Printf("hciResetDevice failed") return nil, err } } @@ -105,5 +112,6 @@ func (d device) Write(b []byte) (int, error) { } func (d device) Close() error { + log.Printf("linux.device.Close()") return syscall.Close(d.fd) } diff --git a/vendor/github.com/bettercap/gatt/linux/hci.go b/vendor/github.com/bettercap/gatt/linux/hci.go index dc3f58b7..ac2f73ef 100644 --- a/vendor/github.com/bettercap/gatt/linux/hci.go +++ b/vendor/github.com/bettercap/gatt/linux/hci.go @@ -26,7 +26,8 @@ type HCI struct { bufCnt chan struct{} bufSize int - pool *util.BytePool + pool *util.BytePool + loopDone chan bool maxConn int connsmu *sync.Mutex @@ -68,7 +69,8 @@ func NewHCI(devID int, chk bool, maxConn int) (*HCI, error) { bufCnt: make(chan struct{}, 15-1), bufSize: 27, - pool: util.NewBytePool(4096, 16), + pool: util.NewBytePool(4096, 16), + loopDone: make(chan bool), maxConn: maxConn, connsmu: &sync.Mutex{}, @@ -89,9 +91,15 @@ func NewHCI(devID int, chk bool, maxConn int) (*HCI, error) { } func (h *HCI) Close() error { + log.Printf("hci.Close()") + h.pool.Put(nil) + <-h.loopDone + log.Printf("mainLoop exited") for _, c := range h.conns { + log.Printf("closing connection %v", c) c.Close() } + log.Printf("closing %v", h.d) return h.d.Close() } @@ -151,7 +159,10 @@ func (h *HCI) Connect(pd *PlatData) error { } func (h *HCI) CancelConnection(pd *PlatData) error { - return pd.Conn.Close() + if pd != nil && pd.Conn != nil { + return pd.Conn.Close() + } + return nil } func (h *HCI) SendRawCommand(c cmd.CmdParam) ([]byte, error) { @@ -166,19 +177,33 @@ func btoi(b bool) uint8 { } func (h *HCI) mainLoop() { + log.Printf("hci.mainLoop started") + defer func() { + h.loopDone <- true + }() + for { + // log.Printf("hci.mainLoop pool.Get") b := h.pool.Get() + if b == nil { + log.Printf("got nil buffer, breaking mainLoop") + break + } + // log.Printf("hci.mainLoop Read(%d)", len(b)) n, err := h.d.Read(b) if err != nil { - fmt.Sprintf("mainloop err: %v\n", err) + log.Printf("mainloop err: %v", err) return } if n == 0 { - println("mainLoop failed to read") + log.Printf("mainLoop failed to read") return } + + // log.Printf("hci.mainLoop -> handlePacket") h.handlePacket(b, n) } + log.Printf("hci.mainLoop stopped") } func (h *HCI) handlePacket(buf []byte, n int) { diff --git a/vendor/github.com/bettercap/gatt/linux/l2cap.go b/vendor/github.com/bettercap/gatt/linux/l2cap.go index 1a8e9d85..a4f1c5de 100644 --- a/vendor/github.com/bettercap/gatt/linux/l2cap.go +++ b/vendor/github.com/bettercap/gatt/linux/l2cap.go @@ -156,7 +156,7 @@ func (c *conn) Close() error { defer h.connsmu.Unlock() _, found := h.conns[hh] if !found { - // log.Printf("l2conn: 0x%04x already disconnected", hh) + log.Printf("l2conn: 0x%04x already disconnected", hh) return nil } if err, _ := h.c.Send(cmd.Disconnect{ConnectionHandle: hh, Reason: 0x13}); err != nil { diff --git a/vendor/github.com/bettercap/gatt/peripheral_linux.go b/vendor/github.com/bettercap/gatt/peripheral_linux.go index f3fc530d..b31cb9b4 100644 --- a/vendor/github.com/bettercap/gatt/peripheral_linux.go +++ b/vendor/github.com/bettercap/gatt/peripheral_linux.go @@ -407,7 +407,6 @@ func (p *peripheral) loop() { if rspOp == attRspFor[reqOp] || (rspOp == attOpError && r[1] == reqOp) { req.rspc <- r break - } log.Printf("Request 0x%02x got a mismatched response: 0x%02x", reqOp, rspOp) p.l2c.Write(attErrorRsp(rspOp, 0x0000, AttEcodeReqNotSupp)) @@ -434,6 +433,7 @@ func (p *peripheral) loop() { copy(b, buf) if (b[0] != attOpHandleNotify) && (b[0] != attOpHandleInd) { + log.Printf("response 0x%x", b[0]) rspc <- b continue }