| package main |
| |
| import ( |
| "encoding/hex" |
| "log" |
| "sync" |
| |
| "mojo/public/go/application" |
| "mojo/public/go/bindings" |
| "mojo/public/go/system" |
| |
| "mojom/v.io/x/ref/services/discovery/ble/ble" |
| "v.io/x/ref/services/discovery/ble/internal/lib" |
| ) |
| |
| //#include "mojo/public/c/system/types.h" |
| import "C" |
| |
| type bleImpl struct { |
| n *lib.BleNeighborHood |
| d *delegate |
| } |
| |
| func (b *bleImpl) Advertise(adv ble.Advertisement) (ble.PluginStopper_Pointer, error) { |
| uuid := hex.EncodeToString(adv.ServiceId) |
| b.n.AddService(uuid, adv.Service) |
| return b.createHandleFor(&stopAdvertingImpl{uuid: uuid, n: b.n}), nil |
| } |
| |
| func (b *bleImpl) Scan(uuid *[]uint8, attr map[string]string, handler ble.PluginScanHandler_Pointer) (ble.PluginStopper_Pointer, error) { |
| ch := make(chan *update, 10) |
| proxy := ble.NewPluginScanHandlerProxy(handler, bindings.GetAsyncWaiter()) |
| go func() { |
| for v := range ch { |
| if v.found { |
| proxy.Found(v.adv) |
| } else { |
| proxy.Lost(v.adv) |
| } |
| } |
| }() |
| id := b.n.AddScanner(uuid, attr, ch) |
| return b.createHandleFor(&stopScanImpl{id: id, n: b.n}), nil |
| } |
| |
| func (b *bleImpl) createHandleFor(h ble.PluginStopper) ble.PluginStopper_Pointer { |
| req, ptr := ble.CreateMessagePipeForPluginStopper() |
| stub := ble.NewPluginStopperStub(req, h, bindings.GetAsyncWaiter()) |
| b.d.addStub(stub) |
| go func() { |
| for { |
| if err := stub.ServeRequest(); err != nil { |
| connErr, ok := err.(*bindings.ConnectionError) |
| if !ok || !connErr.Closed() { |
| log.Println(err) |
| } |
| break |
| } |
| } |
| }() |
| |
| return ptr |
| } |
| |
| type stopAdvertingImpl struct { |
| uuid string |
| n *bleNeighborHood |
| } |
| |
| func (s *stopAdvertingImpl) Stop() error { |
| s.n.removeService(s.uuid) |
| return nil |
| } |
| |
| type stopScanImpl struct { |
| id int64 |
| n *bleNeighborHood |
| } |
| |
| func (s *stopScanImpl) Stop() error { |
| s.n.removeScanner(s.id) |
| return nil |
| } |
| |
| type delegate struct { |
| mu sync.Mutex |
| n *bleNeighborHood |
| stubs []*bindings.Stub |
| } |
| |
| func (d *delegate) Initialize(ctx application.Context) { |
| args := ctx.Args() |
| if len(args) < 2 { |
| log.Println("Device name needs to be passed in") |
| ctx.Close() |
| } |
| name := ctx.Args()[1] |
| n, err := newBleNeighborhood(name) |
| if err != nil { |
| log.Println("Failed to start neighborhood", err) |
| ctx.Close() |
| } |
| d.n = n |
| } |
| |
| func (d *delegate) Create(req ble.V23Ble_Request) { |
| stub := ble.NewV23BleStub(req, &bleImpl{n: d.n, d: d}, bindings.GetAsyncWaiter()) |
| d.addStub(stub) |
| go func() { |
| for { |
| if err := stub.ServeRequest(); err != nil { |
| connErr, ok := err.(*bindings.ConnectionError) |
| if !ok || !connErr.Closed() { |
| log.Println(err) |
| } |
| break |
| } |
| } |
| }() |
| } |
| |
| func (d *delegate) addStub(s *bindings.Stub) { |
| d.mu.Lock() |
| d.stubs = append(d.stubs, s) |
| d.mu.Unlock() |
| } |
| func (d *delegate) AcceptConnection(conn *application.Connection) { |
| conn.ProvideServices(&ble.V23Ble_ServiceFactory{d}) |
| } |
| |
| func (d *delegate) Quit() { |
| for _, stub := range d.stubs { |
| stub.Close() |
| } |
| if d.n != nil { |
| d.n.Stop() |
| } |
| } |
| |
| //export MojoMain |
| func MojoMain(handle C.MojoHandle) C.MojoResult { |
| application.Run(&delegate{}, system.MojoHandle(handle)) |
| return C.MOJO_RESULT_OK |
| } |
| |
| func main() {} |