nmxact/nmble/dispatch.go (207 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package nmble import ( "encoding/json" "fmt" "sync" "mynewt.apache.org/newtmgr/nmxact/nmxutil" log "github.com/sirupsen/logrus" ) type MsgBase struct { // Header Op MsgOp `json:"op"` Type MsgType `json:"type"` Seq BleSeq `json:"seq"` // Optional ConnHandle int `json:"conn_handle" json:",omitempty"` } type OpTypePair struct { Op MsgOp Type MsgType } // The dispatcher is the owner of the listeners it points to. Only the // dispatcher writes to these listeners. type Dispatcher struct { lm *ListenerMap mtx sync.Mutex } type msgCtor func() Msg func errRspCtor() Msg { return &BleErrRsp{} } func syncRspCtor() Msg { return &BleSyncRsp{} } func connectRspCtor() Msg { return &BleConnectRsp{} } func terminateRspCtor() Msg { return &BleTerminateRsp{} } func discAllSvcsRspCtor() Msg { return &BleDiscAllSvcsRsp{} } func discSvcUuidRspCtor() Msg { return &BleDiscSvcUuidRsp{} } func discAllChrsRspCtor() Msg { return &BleDiscAllChrsRsp{} } func discChrUuidRspCtor() Msg { return &BleDiscChrUuidRsp{} } func discAllDscsRspCtor() Msg { return &BleDiscAllDscsRsp{} } func writeRspCtor() Msg { return &BleWriteRsp{} } func writeCmdRspCtor() Msg { return &BleWriteCmdRsp{} } func exchangeMtuRspCtor() Msg { return &BleExchangeMtuRsp{} } func genRandAddrRspCtor() Msg { return &BleGenRandAddrRsp{} } func setRandAddrRspCtor() Msg { return &BleSetRandAddrRsp{} } func connCancelRspCtor() Msg { return &BleConnCancelRsp{} } func scanRspCtor() Msg { return &BleScanRsp{} } func scanCancelRspCtor() Msg { return &BleScanCancelRsp{} } func setPreferredMtuRspCtor() Msg { return &BleSetPreferredMtuRsp{} } func securityInitiateRspCtor() Msg { return &BleSecurityInitiateRsp{} } func connFindRspCtor() Msg { return &BleConnFindRsp{} } func resetRspCtor() Msg { return &BleResetRsp{} } func advStartRspCtor() Msg { return &BleAdvStartRsp{} } func advStopRspCtor() Msg { return &BleAdvStopRsp{} } func advSetDataRspCtor() Msg { return &BleAdvSetDataRsp{} } func advRspSetDataRspCtor() Msg { return &BleAdvRspSetDataRsp{} } func advFieldsRspCtor() Msg { return &BleAdvFieldsRsp{} } func clearSvcsRspCtor() Msg { return &BleClearSvcsRsp{} } func addSvcsRspCtor() Msg { return &BleAddSvcsRsp{} } func commitSvcsRspCtor() Msg { return &BleCommitSvcsRsp{} } func accessStatusRspCtor() Msg { return &BleAccessStatusRsp{} } func notifyRspCtor() Msg { return &BleNotifyRsp{} } func findChrRspCtor() Msg { return &BleFindChrRsp{} } func oobSecDataRspCtor() Msg { return &BleSmInjectIoRsp{} } func syncEvtCtor() Msg { return &BleSyncEvt{} } func connectEvtCtor() Msg { return &BleConnectEvt{} } func connCancelEvtCtor() Msg { return &BleConnCancelEvt{} } func disconnectEvtCtor() Msg { return &BleDisconnectEvt{} } func discSvcEvtCtor() Msg { return &BleDiscSvcEvt{} } func discChrEvtCtor() Msg { return &BleDiscChrEvt{} } func discDscEvtCtor() Msg { return &BleDiscDscEvt{} } func writeAckEvtCtor() Msg { return &BleWriteAckEvt{} } func notifyRxEvtCtor() Msg { return &BleNotifyRxEvt{} } func mtuChangeEvtCtor() Msg { return &BleMtuChangeEvt{} } func scanEvtCtor() Msg { return &BleScanEvt{} } func scanTmoEvtCtor() Msg { return &BleScanCompleteEvt{} } func advCompleteEvtCtor() Msg { return &BleAdvCompleteEvt{} } func encChangeEvtCtor() Msg { return &BleEncChangeEvt{} } func resetEvtCtor() Msg { return &BleResetEvt{} } func accessEvtCtor() Msg { return &BleAccessEvt{} } func passkeyEvtCtor() Msg { return &BlePasskeyEvt{} } var msgCtorMap = map[OpTypePair]msgCtor{ {MSG_OP_RSP, MSG_TYPE_ERR}: errRspCtor, {MSG_OP_RSP, MSG_TYPE_SYNC}: syncRspCtor, {MSG_OP_RSP, MSG_TYPE_CONNECT}: connectRspCtor, {MSG_OP_RSP, MSG_TYPE_TERMINATE}: terminateRspCtor, {MSG_OP_RSP, MSG_TYPE_DISC_ALL_SVCS}: discAllSvcsRspCtor, {MSG_OP_RSP, MSG_TYPE_DISC_SVC_UUID}: discSvcUuidRspCtor, {MSG_OP_RSP, MSG_TYPE_DISC_ALL_CHRS}: discAllChrsRspCtor, {MSG_OP_RSP, MSG_TYPE_DISC_CHR_UUID}: discChrUuidRspCtor, {MSG_OP_RSP, MSG_TYPE_DISC_ALL_DSCS}: discAllDscsRspCtor, {MSG_OP_RSP, MSG_TYPE_WRITE}: writeRspCtor, {MSG_OP_RSP, MSG_TYPE_WRITE_CMD}: writeCmdRspCtor, {MSG_OP_RSP, MSG_TYPE_EXCHANGE_MTU}: exchangeMtuRspCtor, {MSG_OP_RSP, MSG_TYPE_GEN_RAND_ADDR}: genRandAddrRspCtor, {MSG_OP_RSP, MSG_TYPE_SET_RAND_ADDR}: setRandAddrRspCtor, {MSG_OP_RSP, MSG_TYPE_CONN_CANCEL}: connCancelRspCtor, {MSG_OP_RSP, MSG_TYPE_SCAN}: scanRspCtor, {MSG_OP_RSP, MSG_TYPE_SCAN_CANCEL}: scanCancelRspCtor, {MSG_OP_RSP, MSG_TYPE_SET_PREFERRED_MTU}: setPreferredMtuRspCtor, {MSG_OP_RSP, MSG_TYPE_SECURITY_INITIATE}: securityInitiateRspCtor, {MSG_OP_RSP, MSG_TYPE_CONN_FIND}: connFindRspCtor, {MSG_OP_RSP, MSG_TYPE_RESET}: resetRspCtor, {MSG_OP_RSP, MSG_TYPE_ADV_START}: advStartRspCtor, {MSG_OP_RSP, MSG_TYPE_ADV_STOP}: advStopRspCtor, {MSG_OP_RSP, MSG_TYPE_ADV_SET_DATA}: advSetDataRspCtor, {MSG_OP_RSP, MSG_TYPE_ADV_RSP_SET_DATA}: advRspSetDataRspCtor, {MSG_OP_RSP, MSG_TYPE_ADV_FIELDS}: advFieldsRspCtor, {MSG_OP_RSP, MSG_TYPE_CLEAR_SVCS}: clearSvcsRspCtor, {MSG_OP_RSP, MSG_TYPE_ADD_SVCS}: addSvcsRspCtor, {MSG_OP_RSP, MSG_TYPE_COMMIT_SVCS}: commitSvcsRspCtor, {MSG_OP_RSP, MSG_TYPE_ACCESS_STATUS}: accessStatusRspCtor, {MSG_OP_RSP, MSG_TYPE_NOTIFY}: notifyRspCtor, {MSG_OP_RSP, MSG_TYPE_FIND_CHR}: findChrRspCtor, {MSG_OP_RSP, MSG_TYPE_SM_INJECT_IO}: oobSecDataRspCtor, {MSG_OP_EVT, MSG_TYPE_SYNC_EVT}: syncEvtCtor, {MSG_OP_EVT, MSG_TYPE_CONNECT_EVT}: connectEvtCtor, {MSG_OP_EVT, MSG_TYPE_CONN_CANCEL_EVT}: connCancelEvtCtor, {MSG_OP_EVT, MSG_TYPE_DISCONNECT_EVT}: disconnectEvtCtor, {MSG_OP_EVT, MSG_TYPE_DISC_SVC_EVT}: discSvcEvtCtor, {MSG_OP_EVT, MSG_TYPE_DISC_CHR_EVT}: discChrEvtCtor, {MSG_OP_EVT, MSG_TYPE_DISC_DSC_EVT}: discDscEvtCtor, {MSG_OP_EVT, MSG_TYPE_WRITE_ACK_EVT}: writeAckEvtCtor, {MSG_OP_EVT, MSG_TYPE_NOTIFY_RX_EVT}: notifyRxEvtCtor, {MSG_OP_EVT, MSG_TYPE_MTU_CHANGE_EVT}: mtuChangeEvtCtor, {MSG_OP_EVT, MSG_TYPE_SCAN_EVT}: scanEvtCtor, {MSG_OP_EVT, MSG_TYPE_SCAN_COMPLETE_EVT}: scanTmoEvtCtor, {MSG_OP_EVT, MSG_TYPE_ADV_COMPLETE_EVT}: advCompleteEvtCtor, {MSG_OP_EVT, MSG_TYPE_ENC_CHANGE_EVT}: encChangeEvtCtor, {MSG_OP_EVT, MSG_TYPE_RESET_EVT}: resetEvtCtor, {MSG_OP_EVT, MSG_TYPE_ACCESS_EVT}: accessEvtCtor, {MSG_OP_EVT, MSG_TYPE_PASSKEY_EVT}: passkeyEvtCtor, } func NewDispatcher() *Dispatcher { return &Dispatcher{ lm: NewListenerMap(), } } func (d *Dispatcher) AddListener(key ListenerKey, listener *Listener) error { d.mtx.Lock() defer d.mtx.Unlock() return d.lm.AddListener(key, listener) } func (d *Dispatcher) RemoveListener(listener *Listener) *ListenerKey { d.mtx.Lock() defer d.mtx.Unlock() key := d.lm.RemoveListener(listener) if key == nil { return nil } listener.Close() return key } func (d *Dispatcher) RemoveKey(key ListenerKey) *Listener { d.mtx.Lock() defer d.mtx.Unlock() listener := d.lm.RemoveKey(key) if listener == nil { return nil } listener.Close() return listener } func (d *Dispatcher) ErrorAll(err error) { nmxutil.Assert(err != nil) d.mtx.Lock() listeners := d.lm.ExtractAll() d.mtx.Unlock() for _, listener := range listeners { listener.ErrChan <- err listener.Close() } } func decodeBleBase(data []byte) (MsgBase, error) { base := MsgBase{} if err := json.Unmarshal(data, &base); err != nil { return base, err } return base, nil } func decodeMsg(data []byte) (MsgBase, Msg, error) { base, err := decodeBleBase(data) if err != nil { return base, nil, err } opTypePair := OpTypePair{base.Op, base.Type} cb := msgCtorMap[opTypePair] if cb == nil { return base, nil, fmt.Errorf( "Unrecognized op+type pair: %s, %s", MsgOpToString(base.Op), MsgTypeToString(base.Type)) } msg := cb() if err := json.Unmarshal(data, msg); err != nil { return base, nil, err } return base, msg, nil } func (d *Dispatcher) Dispatch(data []byte) { base, msg, err := decodeMsg(data) if err != nil { log.Warnf("BLE dispatch error: %s", err.Error()) return } d.mtx.Lock() defer d.mtx.Unlock() _, listener := d.lm.FindListener(base.Seq, base.Type, base.ConnHandle) if listener == nil { log.Debugf( "No BLE listener for op=%d type=%d seq=%d connHandle=%d", base.Op, base.Type, base.Seq, base.ConnHandle) return } listener.MsgChan <- msg }