From aed2271bf7f795ef395367ce13a2dcc02d02c7dc Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Fri, 5 Oct 2018 16:12:07 +0200 Subject: [PATCH] Continuing work on JSON-RPC API ! --- cmd/server/rpc/server.go | 99 +++++++++++++++++++++++++- openwrt/uci.go | 26 +++++-- openwrt/uci_wireless_conf.go | 6 +- openwrt/uci_wireless_interface.go | 27 ++++++- openwrt/uci_wireless_interface_test.go | 10 ++- 5 files changed, 154 insertions(+), 14 deletions(-) diff --git a/cmd/server/rpc/server.go b/cmd/server/rpc/server.go index 98a14e9..47bc890 100644 --- a/cmd/server/rpc/server.go +++ b/cmd/server/rpc/server.go @@ -1,7 +1,9 @@ package rpc import ( + "fmt" "net/http" + "time" "forge.cadoles.com/Pyxis/orion/openwrt" "github.com/gorilla/rpc" @@ -52,11 +54,106 @@ func (o *OrionService) OwrtListWifiInterfaces(r *http.Request, args *ListIfaceAr return nil } +// CreateIfaceArgs argument structure for exported method OwrtCreateWifiInterface +type CreateIfaceArgs struct { + Iface *openwrt.UCIWirelessInterface + Cleanup bool +} + +// CreateIfaceResponse argument structure for exported method OwrtCreateWifiInterface +type CreateIfaceResponse struct { + Iface *openwrt.UCIWirelessInterface + Errors []*openwrt.Action +} + +// OwrtCreateWifiInterface Create a WifiInterface in openwrt +func (o *OrionService) OwrtCreateWifiInterface(r *http.Request, args *CreateIfaceArgs, reply *CreateIfaceResponse) error { + reply.Iface = nil + if args.Cleanup == true { + o.UCI.LoadWirelessConf() + w := o.UCI.GetWifiIfaces() + for _, iface := range w { + iface.Delete(o.UCI) + } + o.UCI.Commit() + o.UCI.Reload() + time.Sleep(3 * time.Second) + } + + o.UCI.LoadWirelessConf() + create := args.Iface.Create(o.UCI) + if create.ReturnCode != 0 { + reply.Errors = append(reply.Errors, create) + return nil + } + create = args.Iface.SysAdd(o.UCI) + if create.ReturnCode == 233 { + delete := args.Iface.SysDel(o.UCI) + if delete.ReturnCode != 0 { + reply.Errors = append(reply.Errors, delete) + return nil + } + create = args.Iface.SysAdd(o.UCI) + if create.ReturnCode != 0 { + reply.Errors = append(reply.Errors, create) + return nil + } + } + create = args.Iface.Up(o.UCI) + if create.ReturnCode != 0 { + reply.Errors = append(reply.Errors, create) + return nil + } + create = args.Iface.Save(o.UCI) + if create.ReturnCode != 0 { + reply.Errors = append(reply.Errors, create) + return nil + } + reply.Iface = args.Iface + return nil +} + +// ConnectIfaceArgs argument structure for exported method OwrtCreateWifiInterface +type ConnectIfaceArgs struct { + Iface *openwrt.UCIWirelessInterface + SSID string + Key string +} + +// ConnectIfaceResponse argument structure for exported method OwrtCreateWifiInterface +type ConnectIfaceResponse struct { + status int + Errors []string +} + +// OwrtConnectWifiInterface connects a given Wifi Interface to a given SSID +func (o *OrionService) OwrtConnectWifiInterface(r *http.Request, args *ConnectIfaceArgs, reply *ConnectIfaceResponse) error { + o.UCI.LoadWirelessConf() + iface := o.UCI.GetWifiIface(args.Iface.Index) + cells := iface.Scan() + + for _, cell := range cells { + if cell.Ssid == args.SSID { + cn := iface.Connect(o.UCI, cell, args.Key) + if cn.ReturnCode != 0 { + reply.status = cn.ReturnCode + reply.Errors = append(reply.Errors, cn.Stdout, cn.Stderr, cn.Command) + } + reply.status = 0 + return nil + } + } + reply.status = 1 + msg := fmt.Sprintf("Wifi Cell with SSID %s is not available !", args.SSID) + reply.Errors = append(reply.Errors, msg) + return nil +} + // NewServer returns a new configured JSON-RPC server func NewServer() *rpc.Server { server := rpc.NewServer() server.RegisterCodec(json.NewCodec(), "application/json") - if err := server.RegisterService(new(OrionService), "Orion"); err != nil { + if err := server.RegisterService(NewOrionService(), "Orion"); err != nil { panic(err) } return server diff --git a/openwrt/uci.go b/openwrt/uci.go index 6aff080..108fd5a 100644 --- a/openwrt/uci.go +++ b/openwrt/uci.go @@ -8,6 +8,7 @@ import ( // Action is the result of an UCI action output and return code type Action struct { *CommandResult + Command string } // UCI "Object" @@ -34,13 +35,14 @@ func NewUCIWithExecutor(exec Executor) *UCI { func (u *UCI) uciRun(param ...string) *Action { cmd := "/sbin/uci" res := u.exec.Run(cmd, param...) - return &Action{res} + return &Action{res, fmt.Sprintf("%s %s", cmd, param)} } // Add add an entry to UCI configuration, specify the Module and the value func (u *UCI) Add(module string, name string) *Action { - commandRes := u.exec.Run("uci add", module, name) - return &Action{commandRes} + cmd := "uci add" + commandRes := u.exec.Run(cmd, module, name) + return &Action{commandRes, fmt.Sprintf("%s %s %s", cmd, module, name)} } // Delete delete an entry from UCI configuration specify the entry name @@ -65,7 +67,7 @@ func (u *UCI) Reload() *Action { time.Sleep(5 * time.Second) - return &Action{cmdResult} + return &Action{cmdResult, "reload_config"} } // Show returns the output of uci show command @@ -86,7 +88,7 @@ func (u *UCI) LoadWirelessConf() { u.Wireless.Load() } -// GetWifiIface returns the system name of the Interface +// GetWifiIface returns the wifi Interface by Index func (u *UCI) GetWifiIface(idx int) *UCIWirelessInterface { ifaces := u.Wireless.Interfaces if len(ifaces) < idx { @@ -95,6 +97,20 @@ func (u *UCI) GetWifiIface(idx int) *UCIWirelessInterface { return ifaces[idx] } +// GetWifiIfaceByName returns the wifi Interface by Index +func (u *UCI) GetWifiIfaceByName(name string) *UCIWirelessInterface { + ifaces := u.Wireless.Interfaces + if len(ifaces) <= 0 { + return nil + } + for _, ifa := range ifaces { + if ifa.Name == name { + return ifa + } + } + return nil +} + // GetWifiIfaces wifi interfaces in configuration func (u *UCI) GetWifiIfaces() []*UCIWirelessInterface { return u.Wireless.Interfaces diff --git a/openwrt/uci_wireless_conf.go b/openwrt/uci_wireless_conf.go index a91b8b6..bad8aeb 100644 --- a/openwrt/uci_wireless_conf.go +++ b/openwrt/uci_wireless_conf.go @@ -84,6 +84,10 @@ func (wc *UCIWirelessConf) parseInterfaces(lines []string) int { } if key == "Device" { wc.Interfaces[idx].Device = value + //FIXME + //dev := fmt.Sprintf("wireless.%s", value) + //path := wc.uciClient.Show(dev) + //wc.Interfaces[idx].DevicePath = strings.Split(path.Stdout, "=")[1] } if key == "Mode" { wc.Interfaces[idx].Mode = value @@ -167,10 +171,8 @@ func grep(lines string, pattern string) []string { func (wc *UCIWirelessConf) Load() *UCIWirelessConf { conf := wc.uciClient.Show("wireless") - fmt.Println(conf.Stdout) wc.parseDevicesConf(grep(conf.Stdout, "wireless.radio")) wc.parseDefaultInterface(grep(conf.Stdout, "wireless.default_radio0")) - fmt.Println(grep(conf.Stdout, "wireless.@wifi-iface")) wc.parseInterfaces(grep(conf.Stdout, "wireless.@wifi-iface")) return wc diff --git a/openwrt/uci_wireless_interface.go b/openwrt/uci_wireless_interface.go index eef77a8..b7b6edf 100644 --- a/openwrt/uci_wireless_interface.go +++ b/openwrt/uci_wireless_interface.go @@ -47,8 +47,6 @@ func (wi *UCIWirelessInterface) GetSysDevName(sysDir string) string { filepath.Walk(sysDir, func(path string, f os.FileInfo, _ error) error { patt := fmt.Sprintf("%s/%s/.*/address", wi.DevicePath, "net") - fmt.Println(wi.DevicePath) - fmt.Println(patt) r, err := regexp.MatchString(patt, path) if err == nil && r { fmt.Println(path) @@ -65,11 +63,16 @@ func (wi *UCIWirelessInterface) GetSysDevName(sysDir string) string { // Create add a new entry for wifi interface in UCI Configuration func (wi *UCIWirelessInterface) Create(uci *UCI) *Action { + var confPrefix string addRes := uci.AddWireless() if addRes.ReturnCode != 0 { return addRes } - confPrefix := fmt.Sprintf("wireless.@wifi-iface[%d]", wi.Index) + if wi.Index <= 0 { + confPrefix = fmt.Sprintf("wireless.@wifi-iface[%d]", wi.Index) + } else { + confPrefix = fmt.Sprintf("wireless.@wifi-iface[%d]", len(uci.Wireless.Interfaces)) + } conf := make(map[string][]string) conf["network"] = append(conf["network"], fmt.Sprintf("%s.network", confPrefix), wi.Network) @@ -125,6 +128,24 @@ func (wi *UCIWirelessInterface) SysAdd(uci *UCI) *Action { res := uci.exec.Run(cmd, opt, phydev, what, act, wi.SysDevName, "type", tpe) return &Action{ CommandResult: res, + Command: fmt.Sprintf("%s %s %s %s %s %s %s %s", cmd, opt, phydev, what, act, wi.SysDevName, "type", tpe), + } +} + +// SysDel deletes the interface in the system using iw command +func (wi *UCIWirelessInterface) SysDel(uci *UCI) *Action { + cmd := "iw" + opt := "dev" + act := "del" + + if wi.SysDevName == "" { + wi.SysDevName = fmt.Sprintf("tmp.radio%d", wi.Index) + } + + res := uci.exec.Run(cmd, opt, wi.SysDevName, act) + return &Action{ + CommandResult: res, + Command: fmt.Sprintf("%s %s %s %s", cmd, opt, wi.SysDevName, act), } } diff --git a/openwrt/uci_wireless_interface_test.go b/openwrt/uci_wireless_interface_test.go index ff68798..e27ce73 100644 --- a/openwrt/uci_wireless_interface_test.go +++ b/openwrt/uci_wireless_interface_test.go @@ -10,7 +10,6 @@ func TestGetSysDevName(t *testing.T) { iface.Index = 1 iface.Device = "radioX" iface.DevicePath = "soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0" - iface.SysDevName = "wlanX" iface.Mode = "ap" iface.Ssid = "PyxisWifi" iface.Bssid = "00:00:00:00:00" @@ -18,8 +17,13 @@ func TestGetSysDevName(t *testing.T) { iface.Encryption = "psk" iface.Key = "qsmdflkjqslmdfkjqslmfkdj" - if iface.GetSysDevName("testdata/sys/") != "wlan1" { - t.Fatalf("UCIWirelessInterface.GetDeviceSysName() failed !") + if g, e := iface.GetSysDevName("testdata/sys/"), "wlan1"; g != e { + t.Fatalf("UCIWirelessInterface.GetDeviceSysName() failed ! Got: %s Expect: %s", g, e) + } + + iface.SysDevName = "wlanX" + if g, e := iface.GetSysDevName("testdata/sys/"), "wlanX"; g != e { + t.Fatalf("UCIWirelessInterface.GetDeviceSysName() failed ! Got: %s Expect: %s", g, e) } }