WiFi: reworked RPC, CLI, WebClient data structures

This commit is contained in:
MaMe82 2018-09-11 17:43:04 +02:00
parent c7df6b3d01
commit 4a29298b3c
14 changed files with 2074 additions and 1601 deletions

View File

@ -12,15 +12,13 @@ import (
//Empty settings used to store cobra flags //Empty settings used to store cobra flags
var ( var (
tmpWifiStrReg string = ""
tmpWifiStrReg string = "" tmpWifiStrChannel uint8 = 0
tmpWifiStrChannel uint8 = 0 tmpWifiHideSSID bool = false
tmpWifiHideSSID bool = false tmpWifiDisabled bool = false
tmpWifiDisabled bool = false tmpWifiDisableNexmon bool = false
tmpWifiDisableNexmon bool = false tmpWifiSSID string = ""
tmpWifiSSID string = "" tmpWifiPSK string = ""
tmpWifiPSK string = ""
) )
/* /*
@ -40,29 +38,28 @@ var wifiCmd = &cobra.Command{
var wifiSetCmd = &cobra.Command{ var wifiSetCmd = &cobra.Command{
Use: "set", Use: "set",
Short: "set WiFi settings", Short: "set WiFi settings",
Long: ``, Long: ``,
} }
var wifiSetAPCmd = &cobra.Command{ var wifiSetAPCmd = &cobra.Command{
Use: "ap", Use: "ap",
Short: "Configure WiFi interface as access point", Short: "Configure WiFi interface as access point",
Long: ``, Long: ``,
Run: cobraWifiSetAP, Run: cobraWifiSetAP,
} }
var wifiSetStaCmd = &cobra.Command{ var wifiSetStaCmd = &cobra.Command{
Use: "sta", Use: "sta",
Short: "Configure WiFi interface to join a network as station", Short: "Configure WiFi interface to join a network as station",
Long: ``, Long: ``,
Run: cobraWifiSetSta, Run: cobraWifiSetSta,
} }
var wifiGetCmd = &cobra.Command{ var wifiGetCmd = &cobra.Command{
Use: "get", Use: "get",
Short: "get WiFi settings", Short: "get WiFi settings",
Long: ``, Long: ``,
Run: cobraWifiGet, Run: cobraWifiGet,
} }
func cobraWifiGet(cmd *cobra.Command, args []string) { func cobraWifiGet(cmd *cobra.Command, args []string) {
@ -78,16 +75,15 @@ func cobraWifiSetAP(cmd *cobra.Command, args []string) {
return return
} }
fmt.Printf("Deploying WiFi inteface settings:\n\t%v\n", settings) fmt.Printf("Deploying WiFi inteface settings:\n\t%v\n", settings)
err = ClientDeployWifiSettings(StrRemoteHost, StrRemotePort, settings) state, err := ClientDeployWifiSettings(StrRemoteHost, StrRemotePort, settings)
if err != nil { if err != nil {
fmt.Println(status.Convert(err).Message()) fmt.Println(status.Convert(err).Message())
os.Exit(-1) //exit with error os.Exit(-1) //exit with error
} else {
fmt.Printf("%+v\n", state)
} }
return return
} }
@ -101,86 +97,92 @@ func cobraWifiSetSta(cmd *cobra.Command, args []string) {
return return
} }
fmt.Printf("Deploying WiFi inteface settings:\n\t%v\n", settings) fmt.Printf("Deploying WiFi inteface settings:\n\t%v\n", settings)
err = ClientDeployWifiSettings(StrRemoteHost, StrRemotePort, settings) state,err := ClientDeployWifiSettings(StrRemoteHost, StrRemotePort, settings)
if err != nil { if err != nil {
fmt.Println(status.Convert(err).Message()) fmt.Println(status.Convert(err).Message())
os.Exit(-1) //exit with error os.Exit(-1) //exit with error
} else {
fmt.Printf("%+v\n", state)
} }
return return
} }
func createWifiAPSettings(channel uint8, reg string, strSSID string, strPSK string, hideSsid bool, nonexmon bool, disabled bool) (settings *pb.WiFiSettings, err error) { func createWifiAPSettings(channel uint8, reg string, strSSID string, strPSK string, hideSsid bool, nonexmon bool, disabled bool) (settings *pb.WiFi2Settings, err error) {
if channel < 1 || channel > 14 { if channel < 1 || channel > 14 {
return nil,errors.New(fmt.Sprintf("Only 2.4GHz channels between 1 and 14 are supported, but '%d' was given\n", channel)) return nil, errors.New(fmt.Sprintf("Only 2.4GHz channels between 1 and 14 are supported, but '%d' was given\n", channel))
} }
if len(reg) != 2 { if len(reg) != 2 {
return nil,errors.New(fmt.Sprintf("Regulatory domain has to consist of two uppercase letters (ISO/IEC 3166-1 alpha2), but '%s' was given\n", reg)) return nil, errors.New(fmt.Sprintf("Regulatory domain has to consist of two uppercase letters (ISO/IEC 3166-1 alpha2), but '%s' was given\n", reg))
} }
reg = strings.ToUpper(reg) reg = strings.ToUpper(reg)
if len(strSSID) < 1 || len(strSSID) > 32 { if len(strSSID) < 1 || len(strSSID) > 32 {
return nil,errors.New(fmt.Sprintf("SSID has to consist of 1 to 32 ASCII letters (even if hidden), but '%s' was given\n", strSSID)) return nil, errors.New(fmt.Sprintf("SSID has to consist of 1 to 32 ASCII letters (even if hidden), but '%s' was given\n", strSSID))
} }
if len(strPSK) > 0 && len(strPSK) < 8 { if len(strPSK) > 0 && len(strPSK) < 8 {
return nil,errors.New(fmt.Sprintf("A non-empty PSK implies WPA2 and has to have a minimum of 8 characters, but given PSK has '%d' charactres\n", len(strPSK))) return nil, errors.New(fmt.Sprintf("A non-empty PSK implies WPA2 and has to have a minimum of 8 characters, but given PSK has '%d' charactres\n", len(strPSK)))
} }
settings = &pb.WiFiSettings{ settings = &pb.WiFi2Settings{
Mode: pb.WiFiSettings_AP, WorkingMode: pb.WiFi2WorkingMode_AP,
AuthMode: pb.WiFiSettings_OPEN, AuthMode: pb.WiFi2AuthMode_OPEN,
Disabled: disabled, Disabled: disabled,
Reg: reg, Regulatory: reg,
ApChannel: uint32(channel), Channel: uint32(channel),
ApHideSsid: hideSsid, HideSsid: hideSsid,
BssCfgAP: &pb.BSSCfg{ Ap_BSS: &pb.WiFi2BSSCfg{
SSID: strSSID, SSID: strSSID,
PSK: strPSK, PSK: strPSK,
}, },
DisableNexmon: nonexmon, Client_BSSList: []*pb.WiFi2BSSCfg{},
BssCfgClient: nil, //not needed Nexmon: !nonexmon,
Name: "default",
} }
if len(strPSK) > 0 { if len(strPSK) > 0 {
settings.AuthMode = pb.WiFiSettings_WPA2_PSK //if PSK is given use WPA2 settings.AuthMode = pb.WiFi2AuthMode_WPA2_PSK //if PSK is given use WPA2
} }
return settings, err return settings, err
} }
func createWifiStaSettings(reg string, strSSID string, strPSK string, nonexmon bool, disabled bool) (settings *pb.WiFiSettings, err error) { func createWifiStaSettings(reg string, strSSID string, strPSK string, nonexmon bool, disabled bool) (settings *pb.WiFi2Settings, err error) {
if len(reg) != 2 { if len(reg) != 2 {
return nil,errors.New(fmt.Sprintf("Regulatory domain has to consist of two uppercase letters (ISO/IEC 3166-1 alpha2), but '%s' was given\n", reg)) return nil, errors.New(fmt.Sprintf("Regulatory domain has to consist of two uppercase letters (ISO/IEC 3166-1 alpha2), but '%s' was given\n", reg))
} }
reg = strings.ToUpper(reg) reg = strings.ToUpper(reg)
if len(strSSID) < 1 || len(strSSID) > 32 { if len(strSSID) < 1 || len(strSSID) > 32 {
return nil,errors.New(fmt.Sprintf("SSID has to consist of 1 to 32 ASCII letters (even if hidden), but '%s' was given\n", strSSID)) return nil, errors.New(fmt.Sprintf("SSID has to consist of 1 to 32 ASCII letters (even if hidden), but '%s' was given\n", strSSID))
} }
if len(strPSK) > 0 && len(strPSK) < 8 { if len(strPSK) > 0 && len(strPSK) < 8 {
return nil,errors.New(fmt.Sprintf("A non-empty PSK implies WPA2 and has to have a minimum of 8 characters, but given PSK has '%d' charactres\n", len(strPSK))) return nil, errors.New(fmt.Sprintf("A non-empty PSK implies WPA2 and has to have a minimum of 8 characters, but given PSK has '%d' charactres\n", len(strPSK)))
} }
settings = &pb.WiFiSettings{ settings = &pb.WiFi2Settings{
Mode: pb.WiFiSettings_STA, WorkingMode: pb.WiFi2WorkingMode_STA,
AuthMode: pb.WiFiSettings_OPEN, AuthMode: pb.WiFi2AuthMode_OPEN,
Disabled: disabled, Disabled: disabled,
Reg: reg, Regulatory: reg,
BssCfgClient: &pb.BSSCfg{ Client_BSSList: []*pb.WiFi2BSSCfg{
SSID: strSSID, &pb.WiFi2BSSCfg{
PSK: strPSK, SSID: strSSID,
PSK: strPSK,
},
}, },
DisableNexmon: nonexmon, Nexmon: !nonexmon,
BssCfgAP: nil, //not needed Ap_BSS: &pb.WiFi2BSSCfg{}, //not needed
Name: "default",
HideSsid: false,
} }
if len(strPSK) > 0 { if len(strPSK) > 0 {
settings.AuthMode = pb.WiFiSettings_WPA2_PSK //if PSK is given use WPA2 settings.AuthMode = pb.WiFi2AuthMode_WPA2_PSK //if PSK is given use WPA2
} }
return settings, err return settings, err
@ -193,12 +195,12 @@ func init() {
wifiSetCmd.AddCommand(wifiSetAPCmd) wifiSetCmd.AddCommand(wifiSetAPCmd)
wifiSetCmd.AddCommand(wifiSetStaCmd) wifiSetCmd.AddCommand(wifiSetStaCmd)
wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiStrReg, "reg","r", "US", "Sets the regulatory domain according to ISO/IEC 3166-1 alpha2") wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiStrReg, "reg", "r", "US", "Sets the regulatory domain according to ISO/IEC 3166-1 alpha2")
wifiSetCmd.PersistentFlags().BoolVarP(&tmpWifiDisabled, "disable","d", false, "The flag disables the WiFi interface (omitting the flag enables the interface") wifiSetCmd.PersistentFlags().BoolVarP(&tmpWifiDisabled, "disable", "d", false, "The flag disables the WiFi interface (omitting the flag enables the interface")
wifiSetCmd.PersistentFlags().BoolVarP(&tmpWifiDisableNexmon, "nonexmon","n", false, "Don't use the modified nexmon firmware") wifiSetCmd.PersistentFlags().BoolVarP(&tmpWifiDisableNexmon, "nonexmon", "n", false, "Don't use the modified nexmon firmware")
wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiSSID, "ssid","s", "", "The SSID to use for an Access Point or to join as station") wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiSSID, "ssid", "s", "", "The SSID to use for an Access Point or to join as station")
wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiPSK, "psk","k", "", "The Pre-Shared-Key to use for the Access Point (if empty, an OPEN AP is created) or for the network") wifiSetCmd.PersistentFlags().StringVarP(&tmpWifiPSK, "psk", "k", "", "The Pre-Shared-Key to use for the Access Point (if empty, an OPEN AP is created) or for the network")
wifiSetAPCmd.Flags().Uint8VarP(&tmpWifiStrChannel, "channel","c", 1, "The WiFi channel to use for the Access Point") wifiSetAPCmd.Flags().Uint8VarP(&tmpWifiStrChannel, "channel", "c", 1, "The WiFi channel to use for the Access Point")
wifiSetAPCmd.Flags().BoolVarP(&tmpWifiHideSSID, "hide","x", false, "Hide the SSID of the Access Point") wifiSetAPCmd.Flags().BoolVarP(&tmpWifiHideSSID, "hide", "x", false, "Hide the SSID of the Access Point")
} }

View File

@ -258,7 +258,7 @@ func ClientDeployEthernetInterfaceSettings(host string, port string, settings *p
} }
func ClientDeployWifiSettings(host string, port string, settings *pb.WiFiSettings) (err error) { func ClientDeployWifiSettings(host string, port string, settings *pb.WiFi2Settings) (state *pb.WiFi2State, err error) {
// Set up a connection to the server. // Set up a connection to the server.
address := host + ":" + port address := host + ":" + port
//log.Printf("Connecting %s ...", address) //log.Printf("Connecting %s ...", address)
@ -274,10 +274,8 @@ func ClientDeployWifiSettings(host string, port string, settings *pb.WiFiSetting
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30) ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
defer cancel() defer cancel()
_,err = rpcClient.DeployWifiSettings(ctx, settings) state,err = rpcClient.DeployWiFiSettings2(ctx, settings)
return
return err
} }
func ClientHIDRunScript(host string, port string, scriptPath string, timeoutSeconds uint32) (scriptRes *pb.HIDScriptResult, err error) { func ClientHIDRunScript(host string, port string, scriptPath string, timeoutSeconds uint32) (scriptRes *pb.HIDScriptResult, err error) {

1
ntest.go Normal file
View File

@ -0,0 +1 @@
package main

View File

@ -8,6 +8,9 @@
grpc.proto grpc.proto
It has these top-level messages: It has these top-level messages:
WiFi2Settings
WiFi2State
WiFi2BSSCfg
StringMessage StringMessage
EventRequest EventRequest
EventValue EventValue
@ -33,8 +36,6 @@
DHCPServerSettings DHCPServerSettings
DHCPServerRange DHCPServerRange
DHCPServerStaticHost DHCPServerStaticHost
WiFiSettings
BSSCfg
Empty Empty
*/ */
package P4wnP1_grpc package P4wnP1_grpc
@ -51,6 +52,53 @@ import (
// is compatible with the jspb package it is being compiled against. // is compatible with the jspb package it is being compiled against.
const _ = jspb.JspbPackageIsVersion2 const _ = jspb.JspbPackageIsVersion2
// WiFi2 (distinguish state and settings)
type WiFi2WorkingMode int
const (
WiFi2WorkingMode_UNKNOWN WiFi2WorkingMode = 0
WiFi2WorkingMode_AP WiFi2WorkingMode = 1
WiFi2WorkingMode_STA WiFi2WorkingMode = 2
WiFi2WorkingMode_STA_FAILOVER_AP WiFi2WorkingMode = 3
)
var WiFi2WorkingMode_name = map[int]string{
0: "UNKNOWN",
1: "AP",
2: "STA",
3: "STA_FAILOVER_AP",
}
var WiFi2WorkingMode_value = map[string]int{
"UNKNOWN": 0,
"AP": 1,
"STA": 2,
"STA_FAILOVER_AP": 3,
}
func (x WiFi2WorkingMode) String() string {
return WiFi2WorkingMode_name[int(x)]
}
type WiFi2AuthMode int
const (
WiFi2AuthMode_WPA2_PSK WiFi2AuthMode = 0
WiFi2AuthMode_OPEN WiFi2AuthMode = 1
)
var WiFi2AuthMode_name = map[int]string{
0: "WPA2_PSK",
1: "OPEN",
}
var WiFi2AuthMode_value = map[string]int{
"WPA2_PSK": 0,
"OPEN": 1,
}
func (x WiFi2AuthMode) String() string {
return WiFi2AuthMode_name[int(x)]
}
type EthernetInterfaceSettings_Mode int type EthernetInterfaceSettings_Mode int
const ( const (
@ -77,47 +125,476 @@ func (x EthernetInterfaceSettings_Mode) String() string {
return EthernetInterfaceSettings_Mode_name[int(x)] return EthernetInterfaceSettings_Mode_name[int(x)]
} }
type WiFiSettings_Mode int type WiFi2Settings struct {
// Generic
const ( Name string
WiFiSettings_AP WiFiSettings_Mode = 0 Disabled bool
WiFiSettings_STA WiFiSettings_Mode = 1 Regulatory string
WiFiSettings_STA_FAILOVER_AP WiFiSettings_Mode = 2 WorkingMode WiFi2WorkingMode
) AuthMode WiFi2AuthMode
Channel uint32
var WiFiSettings_Mode_name = map[int]string{ Ap_BSS *WiFi2BSSCfg
0: "AP", Client_BSSList []*WiFi2BSSCfg
1: "STA", HideSsid bool
2: "STA_FAILOVER_AP", Nexmon bool
}
var WiFiSettings_Mode_value = map[string]int{
"AP": 0,
"STA": 1,
"STA_FAILOVER_AP": 2,
} }
func (x WiFiSettings_Mode) String() string { // GetName gets the Name of the WiFi2Settings.
return WiFiSettings_Mode_name[int(x)] func (m *WiFi2Settings) GetName() (x string) {
if m == nil {
return x
}
return m.Name
} }
type WiFiSettings_APAuthMode int // GetDisabled gets the Disabled of the WiFi2Settings.
func (m *WiFi2Settings) GetDisabled() (x bool) {
const ( if m == nil {
WiFiSettings_WPA2_PSK WiFiSettings_APAuthMode = 0 return x
WiFiSettings_OPEN WiFiSettings_APAuthMode = 1 }
) return m.Disabled
var WiFiSettings_APAuthMode_name = map[int]string{
0: "WPA2_PSK",
1: "OPEN",
}
var WiFiSettings_APAuthMode_value = map[string]int{
"WPA2_PSK": 0,
"OPEN": 1,
} }
func (x WiFiSettings_APAuthMode) String() string { // GetRegulatory gets the Regulatory of the WiFi2Settings.
return WiFiSettings_APAuthMode_name[int(x)] func (m *WiFi2Settings) GetRegulatory() (x string) {
if m == nil {
return x
}
return m.Regulatory
}
// GetWorkingMode gets the WorkingMode of the WiFi2Settings.
func (m *WiFi2Settings) GetWorkingMode() (x WiFi2WorkingMode) {
if m == nil {
return x
}
return m.WorkingMode
}
// GetAuthMode gets the AuthMode of the WiFi2Settings.
func (m *WiFi2Settings) GetAuthMode() (x WiFi2AuthMode) {
if m == nil {
return x
}
return m.AuthMode
}
// GetChannel gets the Channel of the WiFi2Settings.
func (m *WiFi2Settings) GetChannel() (x uint32) {
if m == nil {
return x
}
return m.Channel
}
// GetAp_BSS gets the Ap_BSS of the WiFi2Settings.
func (m *WiFi2Settings) GetAp_BSS() (x *WiFi2BSSCfg) {
if m == nil {
return x
}
return m.Ap_BSS
}
// GetClient_BSSList gets the Client_BSSList of the WiFi2Settings.
func (m *WiFi2Settings) GetClient_BSSList() (x []*WiFi2BSSCfg) {
if m == nil {
return x
}
return m.Client_BSSList
}
// GetHideSsid gets the HideSsid of the WiFi2Settings.
func (m *WiFi2Settings) GetHideSsid() (x bool) {
if m == nil {
return x
}
return m.HideSsid
}
// GetNexmon gets the Nexmon of the WiFi2Settings.
func (m *WiFi2Settings) GetNexmon() (x bool) {
if m == nil {
return x
}
return m.Nexmon
}
// MarshalToWriter marshals WiFi2Settings to the provided writer.
func (m *WiFi2Settings) MarshalToWriter(writer jspb.Writer) {
if m == nil {
return
}
if len(m.Name) > 0 {
writer.WriteString(1, m.Name)
}
if m.Disabled {
writer.WriteBool(2, m.Disabled)
}
if len(m.Regulatory) > 0 {
writer.WriteString(3, m.Regulatory)
}
if int(m.WorkingMode) != 0 {
writer.WriteEnum(4, int(m.WorkingMode))
}
if int(m.AuthMode) != 0 {
writer.WriteEnum(5, int(m.AuthMode))
}
if m.Channel != 0 {
writer.WriteUint32(6, m.Channel)
}
if m.Ap_BSS != nil {
writer.WriteMessage(7, func() {
m.Ap_BSS.MarshalToWriter(writer)
})
}
for _, msg := range m.Client_BSSList {
writer.WriteMessage(8, func() {
msg.MarshalToWriter(writer)
})
}
if m.HideSsid {
writer.WriteBool(9, m.HideSsid)
}
if m.Nexmon {
writer.WriteBool(13, m.Nexmon)
}
return
}
// Marshal marshals WiFi2Settings to a slice of bytes.
func (m *WiFi2Settings) Marshal() []byte {
writer := jspb.NewWriter()
m.MarshalToWriter(writer)
return writer.GetResult()
}
// UnmarshalFromReader unmarshals a WiFi2Settings from the provided reader.
func (m *WiFi2Settings) UnmarshalFromReader(reader jspb.Reader) *WiFi2Settings {
for reader.Next() {
if m == nil {
m = &WiFi2Settings{}
}
switch reader.GetFieldNumber() {
case 1:
m.Name = reader.ReadString()
case 2:
m.Disabled = reader.ReadBool()
case 3:
m.Regulatory = reader.ReadString()
case 4:
m.WorkingMode = WiFi2WorkingMode(reader.ReadEnum())
case 5:
m.AuthMode = WiFi2AuthMode(reader.ReadEnum())
case 6:
m.Channel = reader.ReadUint32()
case 7:
reader.ReadMessage(func() {
m.Ap_BSS = m.Ap_BSS.UnmarshalFromReader(reader)
})
case 8:
reader.ReadMessage(func() {
m.Client_BSSList = append(m.Client_BSSList, new(WiFi2BSSCfg).UnmarshalFromReader(reader))
})
case 9:
m.HideSsid = reader.ReadBool()
case 13:
m.Nexmon = reader.ReadBool()
default:
reader.SkipField()
}
}
return m
}
// Unmarshal unmarshals a WiFi2Settings from a slice of bytes.
func (m *WiFi2Settings) Unmarshal(rawBytes []byte) (*WiFi2Settings, error) {
reader := jspb.NewReader(rawBytes)
m = m.UnmarshalFromReader(reader)
if err := reader.Err(); err != nil {
return nil, err
}
return m, nil
}
type WiFi2State struct {
Name string
Regulatory string
WorkingMode WiFi2WorkingMode
AuthMode WiFi2AuthMode
Channel uint32
Bss *WiFi2BSSCfg
HideSsid bool
Nexmon bool
Disabled bool
}
// GetName gets the Name of the WiFi2State.
func (m *WiFi2State) GetName() (x string) {
if m == nil {
return x
}
return m.Name
}
// GetRegulatory gets the Regulatory of the WiFi2State.
func (m *WiFi2State) GetRegulatory() (x string) {
if m == nil {
return x
}
return m.Regulatory
}
// GetWorkingMode gets the WorkingMode of the WiFi2State.
func (m *WiFi2State) GetWorkingMode() (x WiFi2WorkingMode) {
if m == nil {
return x
}
return m.WorkingMode
}
// GetAuthMode gets the AuthMode of the WiFi2State.
func (m *WiFi2State) GetAuthMode() (x WiFi2AuthMode) {
if m == nil {
return x
}
return m.AuthMode
}
// GetChannel gets the Channel of the WiFi2State.
func (m *WiFi2State) GetChannel() (x uint32) {
if m == nil {
return x
}
return m.Channel
}
// GetBss gets the Bss of the WiFi2State.
func (m *WiFi2State) GetBss() (x *WiFi2BSSCfg) {
if m == nil {
return x
}
return m.Bss
}
// GetHideSsid gets the HideSsid of the WiFi2State.
func (m *WiFi2State) GetHideSsid() (x bool) {
if m == nil {
return x
}
return m.HideSsid
}
// GetNexmon gets the Nexmon of the WiFi2State.
func (m *WiFi2State) GetNexmon() (x bool) {
if m == nil {
return x
}
return m.Nexmon
}
// GetDisabled gets the Disabled of the WiFi2State.
func (m *WiFi2State) GetDisabled() (x bool) {
if m == nil {
return x
}
return m.Disabled
}
// MarshalToWriter marshals WiFi2State to the provided writer.
func (m *WiFi2State) MarshalToWriter(writer jspb.Writer) {
if m == nil {
return
}
if len(m.Name) > 0 {
writer.WriteString(1, m.Name)
}
if len(m.Regulatory) > 0 {
writer.WriteString(2, m.Regulatory)
}
if int(m.WorkingMode) != 0 {
writer.WriteEnum(3, int(m.WorkingMode))
}
if int(m.AuthMode) != 0 {
writer.WriteEnum(4, int(m.AuthMode))
}
if m.Channel != 0 {
writer.WriteUint32(5, m.Channel)
}
if m.Bss != nil {
writer.WriteMessage(6, func() {
m.Bss.MarshalToWriter(writer)
})
}
if m.HideSsid {
writer.WriteBool(7, m.HideSsid)
}
if m.Nexmon {
writer.WriteBool(8, m.Nexmon)
}
if m.Disabled {
writer.WriteBool(9, m.Disabled)
}
return
}
// Marshal marshals WiFi2State to a slice of bytes.
func (m *WiFi2State) Marshal() []byte {
writer := jspb.NewWriter()
m.MarshalToWriter(writer)
return writer.GetResult()
}
// UnmarshalFromReader unmarshals a WiFi2State from the provided reader.
func (m *WiFi2State) UnmarshalFromReader(reader jspb.Reader) *WiFi2State {
for reader.Next() {
if m == nil {
m = &WiFi2State{}
}
switch reader.GetFieldNumber() {
case 1:
m.Name = reader.ReadString()
case 2:
m.Regulatory = reader.ReadString()
case 3:
m.WorkingMode = WiFi2WorkingMode(reader.ReadEnum())
case 4:
m.AuthMode = WiFi2AuthMode(reader.ReadEnum())
case 5:
m.Channel = reader.ReadUint32()
case 6:
reader.ReadMessage(func() {
m.Bss = m.Bss.UnmarshalFromReader(reader)
})
case 7:
m.HideSsid = reader.ReadBool()
case 8:
m.Nexmon = reader.ReadBool()
case 9:
m.Disabled = reader.ReadBool()
default:
reader.SkipField()
}
}
return m
}
// Unmarshal unmarshals a WiFi2State from a slice of bytes.
func (m *WiFi2State) Unmarshal(rawBytes []byte) (*WiFi2State, error) {
reader := jspb.NewReader(rawBytes)
m = m.UnmarshalFromReader(reader)
if err := reader.Err(); err != nil {
return nil, err
}
return m, nil
}
type WiFi2BSSCfg struct {
SSID string
PSK string
}
// GetSSID gets the SSID of the WiFi2BSSCfg.
func (m *WiFi2BSSCfg) GetSSID() (x string) {
if m == nil {
return x
}
return m.SSID
}
// GetPSK gets the PSK of the WiFi2BSSCfg.
func (m *WiFi2BSSCfg) GetPSK() (x string) {
if m == nil {
return x
}
return m.PSK
}
// MarshalToWriter marshals WiFi2BSSCfg to the provided writer.
func (m *WiFi2BSSCfg) MarshalToWriter(writer jspb.Writer) {
if m == nil {
return
}
if len(m.SSID) > 0 {
writer.WriteString(1, m.SSID)
}
if len(m.PSK) > 0 {
writer.WriteString(2, m.PSK)
}
return
}
// Marshal marshals WiFi2BSSCfg to a slice of bytes.
func (m *WiFi2BSSCfg) Marshal() []byte {
writer := jspb.NewWriter()
m.MarshalToWriter(writer)
return writer.GetResult()
}
// UnmarshalFromReader unmarshals a WiFi2BSSCfg from the provided reader.
func (m *WiFi2BSSCfg) UnmarshalFromReader(reader jspb.Reader) *WiFi2BSSCfg {
for reader.Next() {
if m == nil {
m = &WiFi2BSSCfg{}
}
switch reader.GetFieldNumber() {
case 1:
m.SSID = reader.ReadString()
case 2:
m.PSK = reader.ReadString()
default:
reader.SkipField()
}
}
return m
}
// Unmarshal unmarshals a WiFi2BSSCfg from a slice of bytes.
func (m *WiFi2BSSCfg) Unmarshal(rawBytes []byte) (*WiFi2BSSCfg, error) {
reader := jspb.NewReader(rawBytes)
m = m.UnmarshalFromReader(reader)
if err := reader.Err(); err != nil {
return nil, err
}
return m, nil
} }
// Alive check // Alive check
@ -2598,276 +3075,6 @@ func (m *DHCPServerStaticHost) Unmarshal(rawBytes []byte) (*DHCPServerStaticHost
return m, nil return m, nil
} }
// WiFi
type WiFiSettings struct {
Disabled bool
Reg string
Mode WiFiSettings_Mode
AuthMode WiFiSettings_APAuthMode
ApChannel uint32
BssCfgAP *BSSCfg
BssCfgClient *BSSCfg
ApHideSsid bool
DisableNexmon bool
}
// GetDisabled gets the Disabled of the WiFiSettings.
func (m *WiFiSettings) GetDisabled() (x bool) {
if m == nil {
return x
}
return m.Disabled
}
// GetReg gets the Reg of the WiFiSettings.
func (m *WiFiSettings) GetReg() (x string) {
if m == nil {
return x
}
return m.Reg
}
// GetMode gets the Mode of the WiFiSettings.
func (m *WiFiSettings) GetMode() (x WiFiSettings_Mode) {
if m == nil {
return x
}
return m.Mode
}
// GetAuthMode gets the AuthMode of the WiFiSettings.
func (m *WiFiSettings) GetAuthMode() (x WiFiSettings_APAuthMode) {
if m == nil {
return x
}
return m.AuthMode
}
// GetApChannel gets the ApChannel of the WiFiSettings.
func (m *WiFiSettings) GetApChannel() (x uint32) {
if m == nil {
return x
}
return m.ApChannel
}
// GetBssCfgAP gets the BssCfgAP of the WiFiSettings.
func (m *WiFiSettings) GetBssCfgAP() (x *BSSCfg) {
if m == nil {
return x
}
return m.BssCfgAP
}
// GetBssCfgClient gets the BssCfgClient of the WiFiSettings.
func (m *WiFiSettings) GetBssCfgClient() (x *BSSCfg) {
if m == nil {
return x
}
return m.BssCfgClient
}
// GetApHideSsid gets the ApHideSsid of the WiFiSettings.
func (m *WiFiSettings) GetApHideSsid() (x bool) {
if m == nil {
return x
}
return m.ApHideSsid
}
// GetDisableNexmon gets the DisableNexmon of the WiFiSettings.
func (m *WiFiSettings) GetDisableNexmon() (x bool) {
if m == nil {
return x
}
return m.DisableNexmon
}
// MarshalToWriter marshals WiFiSettings to the provided writer.
func (m *WiFiSettings) MarshalToWriter(writer jspb.Writer) {
if m == nil {
return
}
if m.Disabled {
writer.WriteBool(1, m.Disabled)
}
if len(m.Reg) > 0 {
writer.WriteString(2, m.Reg)
}
if int(m.Mode) != 0 {
writer.WriteEnum(3, int(m.Mode))
}
if int(m.AuthMode) != 0 {
writer.WriteEnum(4, int(m.AuthMode))
}
if m.ApChannel != 0 {
writer.WriteUint32(5, m.ApChannel)
}
if m.BssCfgAP != nil {
writer.WriteMessage(6, func() {
m.BssCfgAP.MarshalToWriter(writer)
})
}
if m.BssCfgClient != nil {
writer.WriteMessage(7, func() {
m.BssCfgClient.MarshalToWriter(writer)
})
}
if m.ApHideSsid {
writer.WriteBool(8, m.ApHideSsid)
}
if m.DisableNexmon {
writer.WriteBool(10, m.DisableNexmon)
}
return
}
// Marshal marshals WiFiSettings to a slice of bytes.
func (m *WiFiSettings) Marshal() []byte {
writer := jspb.NewWriter()
m.MarshalToWriter(writer)
return writer.GetResult()
}
// UnmarshalFromReader unmarshals a WiFiSettings from the provided reader.
func (m *WiFiSettings) UnmarshalFromReader(reader jspb.Reader) *WiFiSettings {
for reader.Next() {
if m == nil {
m = &WiFiSettings{}
}
switch reader.GetFieldNumber() {
case 1:
m.Disabled = reader.ReadBool()
case 2:
m.Reg = reader.ReadString()
case 3:
m.Mode = WiFiSettings_Mode(reader.ReadEnum())
case 4:
m.AuthMode = WiFiSettings_APAuthMode(reader.ReadEnum())
case 5:
m.ApChannel = reader.ReadUint32()
case 6:
reader.ReadMessage(func() {
m.BssCfgAP = m.BssCfgAP.UnmarshalFromReader(reader)
})
case 7:
reader.ReadMessage(func() {
m.BssCfgClient = m.BssCfgClient.UnmarshalFromReader(reader)
})
case 8:
m.ApHideSsid = reader.ReadBool()
case 10:
m.DisableNexmon = reader.ReadBool()
default:
reader.SkipField()
}
}
return m
}
// Unmarshal unmarshals a WiFiSettings from a slice of bytes.
func (m *WiFiSettings) Unmarshal(rawBytes []byte) (*WiFiSettings, error) {
reader := jspb.NewReader(rawBytes)
m = m.UnmarshalFromReader(reader)
if err := reader.Err(); err != nil {
return nil, err
}
return m, nil
}
type BSSCfg struct {
SSID string
PSK string
}
// GetSSID gets the SSID of the BSSCfg.
func (m *BSSCfg) GetSSID() (x string) {
if m == nil {
return x
}
return m.SSID
}
// GetPSK gets the PSK of the BSSCfg.
func (m *BSSCfg) GetPSK() (x string) {
if m == nil {
return x
}
return m.PSK
}
// MarshalToWriter marshals BSSCfg to the provided writer.
func (m *BSSCfg) MarshalToWriter(writer jspb.Writer) {
if m == nil {
return
}
if len(m.SSID) > 0 {
writer.WriteString(1, m.SSID)
}
if len(m.PSK) > 0 {
writer.WriteString(2, m.PSK)
}
return
}
// Marshal marshals BSSCfg to a slice of bytes.
func (m *BSSCfg) Marshal() []byte {
writer := jspb.NewWriter()
m.MarshalToWriter(writer)
return writer.GetResult()
}
// UnmarshalFromReader unmarshals a BSSCfg from the provided reader.
func (m *BSSCfg) UnmarshalFromReader(reader jspb.Reader) *BSSCfg {
for reader.Next() {
if m == nil {
m = &BSSCfg{}
}
switch reader.GetFieldNumber() {
case 1:
m.SSID = reader.ReadString()
case 2:
m.PSK = reader.ReadString()
default:
reader.SkipField()
}
}
return m
}
// Unmarshal unmarshals a BSSCfg from a slice of bytes.
func (m *BSSCfg) Unmarshal(rawBytes []byte) (*BSSCfg, error) {
reader := jspb.NewReader(rawBytes)
m = m.UnmarshalFromReader(reader)
if err := reader.Err(); err != nil {
return nil, err
}
return m, nil
}
type Empty struct { type Empty struct {
} }
@ -2939,9 +3146,6 @@ type P4WNP1Client interface {
DeployEthernetInterfaceSettings(ctx context.Context, in *EthernetInterfaceSettings, opts ...grpcweb.CallOption) (*Empty, error) DeployEthernetInterfaceSettings(ctx context.Context, in *EthernetInterfaceSettings, opts ...grpcweb.CallOption) (*Empty, error)
GetAllDeployedEthernetInterfaceSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*DeployedEthernetInterfaceSettings, error) GetAllDeployedEthernetInterfaceSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*DeployedEthernetInterfaceSettings, error)
GetDeployedEthernetInterfaceSettings(ctx context.Context, in *StringMessage, opts ...grpcweb.CallOption) (*EthernetInterfaceSettings, error) GetDeployedEthernetInterfaceSettings(ctx context.Context, in *StringMessage, opts ...grpcweb.CallOption) (*EthernetInterfaceSettings, error)
// WiFi
DeployWifiSettings(ctx context.Context, in *WiFiSettings, opts ...grpcweb.CallOption) (*Empty, error)
GetDeployedWifiSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFiSettings, error)
// HIDScript / job management // HIDScript / job management
HIDRunScript(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptResult, error) HIDRunScript(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptResult, error)
HIDRunScriptJob(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptJob, error) HIDRunScriptJob(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptJob, error)
@ -2959,6 +3163,9 @@ type P4WNP1Client interface {
EventListen(ctx context.Context, in *EventRequest, opts ...grpcweb.CallOption) (P4WNP1_EventListenClient, error) EventListen(ctx context.Context, in *EventRequest, opts ...grpcweb.CallOption) (P4WNP1_EventListenClient, error)
// Alive check // Alive check
EchoRequest(ctx context.Context, in *StringMessage, opts ...grpcweb.CallOption) (*StringMessage, error) EchoRequest(ctx context.Context, in *StringMessage, opts ...grpcweb.CallOption) (*StringMessage, error)
DeployWiFiSettings2(ctx context.Context, in *WiFi2Settings, opts ...grpcweb.CallOption) (*WiFi2State, error)
GetWiFiState2(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFi2State, error)
ListenWiFiStateChanges2(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFi2State, error)
} }
type p4WNP1Client struct { type p4WNP1Client struct {
@ -3062,24 +3269,6 @@ func (c *p4WNP1Client) GetDeployedEthernetInterfaceSettings(ctx context.Context,
return new(EthernetInterfaceSettings).Unmarshal(resp) return new(EthernetInterfaceSettings).Unmarshal(resp)
} }
func (c *p4WNP1Client) DeployWifiSettings(ctx context.Context, in *WiFiSettings, opts ...grpcweb.CallOption) (*Empty, error) {
resp, err := c.client.RPCCall(ctx, "DeployWifiSettings", in.Marshal(), opts...)
if err != nil {
return nil, err
}
return new(Empty).Unmarshal(resp)
}
func (c *p4WNP1Client) GetDeployedWifiSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFiSettings, error) {
resp, err := c.client.RPCCall(ctx, "GetDeployedWifiSettings", in.Marshal(), opts...)
if err != nil {
return nil, err
}
return new(WiFiSettings).Unmarshal(resp)
}
func (c *p4WNP1Client) HIDRunScript(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptResult, error) { func (c *p4WNP1Client) HIDRunScript(ctx context.Context, in *HIDScriptRequest, opts ...grpcweb.CallOption) (*HIDScriptResult, error) {
resp, err := c.client.RPCCall(ctx, "HIDRunScript", in.Marshal(), opts...) resp, err := c.client.RPCCall(ctx, "HIDRunScript", in.Marshal(), opts...)
if err != nil { if err != nil {
@ -3219,3 +3408,30 @@ func (c *p4WNP1Client) EchoRequest(ctx context.Context, in *StringMessage, opts
return new(StringMessage).Unmarshal(resp) return new(StringMessage).Unmarshal(resp)
} }
func (c *p4WNP1Client) DeployWiFiSettings2(ctx context.Context, in *WiFi2Settings, opts ...grpcweb.CallOption) (*WiFi2State, error) {
resp, err := c.client.RPCCall(ctx, "DeployWiFiSettings2", in.Marshal(), opts...)
if err != nil {
return nil, err
}
return new(WiFi2State).Unmarshal(resp)
}
func (c *p4WNP1Client) GetWiFiState2(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFi2State, error) {
resp, err := c.client.RPCCall(ctx, "GetWiFiState2", in.Marshal(), opts...)
if err != nil {
return nil, err
}
return new(WiFi2State).Unmarshal(resp)
}
func (c *p4WNP1Client) ListenWiFiStateChanges2(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*WiFi2State, error) {
resp, err := c.client.RPCCall(ctx, "ListenWiFiStateChanges2", in.Marshal(), opts...)
if err != nil {
return nil, err
}
return new(WiFi2State).Unmarshal(resp)
}

File diff suppressed because it is too large Load Diff

View File

@ -3,256 +3,281 @@ syntax = "proto3";
package P4wnP1_grpc; package P4wnP1_grpc;
service P4WNP1 { service P4WNP1 {
//USB gadget //USB gadget
rpc GetDeployedGadgetSetting (Empty) returns (GadgetSettings) {} rpc GetDeployedGadgetSetting (Empty) returns (GadgetSettings) { }
rpc DeployGadgetSetting (Empty) returns (GadgetSettings) {} rpc DeployGadgetSetting (Empty) returns (GadgetSettings) { }
rpc GetGadgetSettings (Empty) returns (GadgetSettings) {} rpc GetGadgetSettings (Empty) returns (GadgetSettings) { }
rpc SetGadgetSettings (GadgetSettings) returns (GadgetSettings) {} rpc SetGadgetSettings (GadgetSettings) returns (GadgetSettings) { }
rpc GetLEDSettings (Empty) returns (LEDSettings) {} rpc GetLEDSettings (Empty) returns (LEDSettings) { }
rpc SetLEDSettings (LEDSettings) returns (Empty) {} rpc SetLEDSettings (LEDSettings) returns (Empty) { }
rpc MountUMSFile (GadgetSettingsUMS) returns (Empty) {} rpc MountUMSFile (GadgetSettingsUMS) returns (Empty) { }
//Ethernet //Ethernet
rpc DeployEthernetInterfaceSettings(EthernetInterfaceSettings) returns (Empty) {} rpc DeployEthernetInterfaceSettings (EthernetInterfaceSettings) returns (Empty) { }
rpc GetAllDeployedEthernetInterfaceSettings(Empty) returns (DeployedEthernetInterfaceSettings) {} rpc GetAllDeployedEthernetInterfaceSettings (Empty) returns (DeployedEthernetInterfaceSettings) { }
rpc GetDeployedEthernetInterfaceSettings(StringMessage) returns (EthernetInterfaceSettings) {} //StringMessage has to contain the interface name rpc GetDeployedEthernetInterfaceSettings (StringMessage) returns (EthernetInterfaceSettings) { } //StringMessage has to contain the interface name
// WiFi /*
rpc DeployWifiSettings(WiFiSettings) returns (Empty) {} // WiFi
rpc GetDeployedWifiSettings(Empty) returns (WiFiSettings) {} rpc DeployWifiSettings (WiFiSettings) returns (WiFiConnectionState) {}
rpc GetDeployedWifiSettings (Empty) returns (WiFiSettings) {}
*/
//HIDScript / job management
rpc HIDRunScript (HIDScriptRequest) returns (HIDScriptResult) { }
rpc HIDRunScriptJob (HIDScriptRequest) returns (HIDScriptJob) { }
rpc HIDGetScriptJobResult (HIDScriptJob) returns (HIDScriptResult) { }
rpc HIDCancelScriptJob (HIDScriptJob) returns (Empty) { }
rpc HIDGetRunningScriptJobs (Empty) returns (HIDScriptJobList) { }
rpc HIDCancelAllScriptJobs (Empty) returns (Empty) { }
rpc HIDGetRunningJobState (HIDScriptJob) returns (HIDRunningJobStateResult) { }
//HIDScript / job management //FileSystem
rpc HIDRunScript(HIDScriptRequest) returns (HIDScriptResult) {} rpc FSWriteFile (WriteFileRequest) returns (Empty) { }
rpc HIDRunScriptJob(HIDScriptRequest) returns (HIDScriptJob) {} rpc FSReadFile (ReadFileRequest) returns (ReadFileResponse) { }
rpc HIDGetScriptJobResult(HIDScriptJob) returns (HIDScriptResult) {} rpc FSGetFileInfo (FileInfoRequest) returns (FileInfoResponse) { }
rpc HIDCancelScriptJob(HIDScriptJob) returns (Empty) {} rpc FSCreateTempDirOrFile (TempDirOrFileRequest) returns (TempDirOrFileResponse) { }
rpc HIDGetRunningScriptJobs(Empty) returns (HIDScriptJobList) {}
rpc HIDCancelAllScriptJobs(Empty) returns (Empty) {}
rpc HIDGetRunningJobState(HIDScriptJob) returns (HIDRunningJobStateResult) {}
//FileSystem //Events
rpc FSWriteFile(WriteFileRequest) returns (Empty) {} rpc EventListen (EventRequest) returns (stream Event) { }
rpc FSReadFile(ReadFileRequest) returns (ReadFileResponse) {}
rpc FSGetFileInfo(FileInfoRequest) returns (FileInfoResponse) {}
rpc FSCreateTempDirOrFile(TempDirOrFileRequest) returns (TempDirOrFileResponse) {}
//Events //Alive check
rpc EventListen(EventRequest) returns (stream Event) {} rpc EchoRequest (StringMessage) returns (StringMessage) { }
//Alive check rpc DeployWiFiSettings2 (WiFi2Settings) returns (WiFi2State) {}
rpc EchoRequest(StringMessage) returns (StringMessage) {} rpc GetWiFiState2 (Empty) returns (WiFi2State) {}
rpc ListenWiFiStateChanges2 (Empty) returns (WiFi2State) {}
// ToDo: Template requests (store, load, listStored)
} }
/* WiFi2 (distinguish state and settings) */
enum WiFi2WorkingMode {
UNKNOWN = 0;
AP = 1; //acts as access point
STA = 2; //acts as station for an existing access point
STA_FAILOVER_AP = 3; //acts as station, if connection to the given AP isn't possible spawns an own AP
}
enum WiFi2AuthMode {
WPA2_PSK = 0; //AP uses WPA2 pre-shared key
OPEN = 1; //Open System Authentication (no authentication)
}
message WiFi2Settings {
/* Generic */
string name = 1; //for template storage
bool disabled = 2; //disabled means neither hostapd, nor wpa_supplicant are running, the interface could still be enabled
string regulatory = 3; //Regulatory domain per ISO/IEC 3166-1 alpha2
WiFi2WorkingMode working_mode = 4;
WiFi2AuthMode auth_mode = 5;
uint32 channel = 6;
WiFi2BSSCfg ap_BSS = 7; //SSID of AP to spawn + PSK if needed
repeated WiFi2BSSCfg client_BSS_list = 8; //SSID of Infra to join + PSK if needed
bool hide_ssid = 9; //if true, SSID gets hidden for spawned AP
bool nexmon = 13;
}
message WiFi2State {
string name = 1; //name of template in use
string regulatory = 2; //Regulatory domain per ISO/IEC 3166-1 alpha2
WiFi2WorkingMode working_mode = 3;
WiFi2AuthMode auth_mode = 4;
uint32 channel = 5;
WiFi2BSSCfg bss = 6; //SSID currently connected (STA) or spawned (AP)
bool hide_ssid = 7;
bool nexmon = 8;
bool disabled = 9;
}
message WiFi2BSSCfg {
string SSID = 1;
string PSK = 2;
}
/* Alive check */ /* Alive check */
message StringMessage { message StringMessage {
string msg = 1; string msg = 1;
} }
/* Events */ /* Events */
message EventRequest { message EventRequest {
int64 listenType = 1; int64 listenType = 1;
} }
message EventValue { message EventValue {
oneof val { oneof val {
string tstring = 1; string tstring = 1;
bool tbool = 2; bool tbool = 2;
int64 tint64 = 3; int64 tint64 = 3;
} }
} }
message Event { message Event {
int64 type = 1; int64 type = 1;
repeated EventValue values = 2; repeated EventValue values = 2;
} }
/* File System */ /* File System */
message TempDirOrFileRequest { message TempDirOrFileRequest {
string dir = 1; string dir = 1;
string prefix = 2; string prefix = 2;
bool onlyFolder = 3; bool onlyFolder = 3;
} }
message TempDirOrFileResponse { message TempDirOrFileResponse {
string resultPath = 1; string resultPath = 1;
} }
message ReadFileRequest { message ReadFileRequest {
string path = 1; string path = 1;
int64 start = 2; int64 start = 2;
bytes data = 3; bytes data = 3;
} }
message ReadFileResponse { message ReadFileResponse {
int64 readCount = 1; int64 readCount = 1;
} }
message WriteFileRequest { message WriteFileRequest {
string path = 1; string path = 1;
bool append = 2; bool append = 2;
bool mustNotExist = 3; bool mustNotExist = 3;
bytes data = 4; bytes data = 4;
} }
message FileInfoRequest { message FileInfoRequest {
string path = 1; string path = 1;
} }
message FileInfoResponse { message FileInfoResponse {
string name = 1; string name = 1;
int64 size = 2; int64 size = 2;
uint32 mode = 3; uint32 mode = 3;
int64 modTime = 4; //unused int64 modTime = 4; //unused
bool isDir = 5; bool isDir = 5;
} }
/* HID */ /* HID */
message HIDScriptRequest { message HIDScriptRequest {
string scriptPath = 1; string scriptPath = 1;
uint32 timeoutSeconds = 2; //a timeout > 0 interrupts the HIDScript when reached, meassurement in seconds uint32 timeoutSeconds = 2; //a timeout > 0 interrupts the HIDScript when reached, meassurement in seconds
} }
message HIDScriptJob { message HIDScriptJob {
uint32 id = 1; uint32 id = 1;
} }
message HIDScriptJobList { message HIDScriptJobList {
repeated uint32 ids = 1; repeated uint32 ids = 1;
} }
message HIDRunningJobStateResult { message HIDRunningJobStateResult {
int64 id = 1; int64 id = 1;
int64 vmId = 2; int64 vmId = 2;
string source = 3; string source = 3;
} }
message HIDScriptResult { message HIDScriptResult {
HIDScriptJob job = 1; HIDScriptJob job = 1;
bool isFinished = 2; bool isFinished = 2;
string resultJson = 3; string resultJson = 3;
//string logOutput = 4; //will be used to retrieve log output of unfinished scripts, better implemented in dedicated method with stream //string logOutput = 4; //will be used to retrieve log output of unfinished scripts, better implemented in dedicated method with stream
} }
/* LED */ /* LED */
message LEDSettings { message LEDSettings {
uint32 blink_count = 1; uint32 blink_count = 1;
} }
/* End LED */ /* End LED */
/* USB Gadget */ /* USB Gadget */
message GadgetSettings { message GadgetSettings {
bool enabled = 1; bool enabled = 1;
string vid = 2; string vid = 2;
string pid = 3; string pid = 3;
string manufacturer = 4; string manufacturer = 4;
string product = 5; string product = 5;
string serial = 6; string serial = 6;
bool use_CDC_ECM = 7; bool use_CDC_ECM = 7;
bool use_RNDIS = 8; bool use_RNDIS = 8;
bool use_HID_KEYBOARD = 9; bool use_HID_KEYBOARD = 9;
bool use_HID_MOUSE = 10; bool use_HID_MOUSE = 10;
bool use_HID_RAW = 11; bool use_HID_RAW = 11;
bool use_UMS = 12; bool use_UMS = 12;
bool use_SERIAL = 13; bool use_SERIAL = 13;
GadgetSettingsEthernet rndis_settings = 14; //Only applicable if RNDIS on GadgetSettingsEthernet rndis_settings = 14; //Only applicable if RNDIS on
GadgetSettingsEthernet cdc_ecm_settings = 15; //Only applicable if CDC ECM on GadgetSettingsEthernet cdc_ecm_settings = 15; //Only applicable if CDC ECM on
GadgetSettingsUMS ums_settings = 16; GadgetSettingsUMS ums_settings = 16;
//EthernetInterfaceSettings ethernet_settings = 17; //only applicable if RNDIS or CDC ECM on //EthernetInterfaceSettings ethernet_settings = 17; //only applicable if RNDIS or CDC ECM on
} }
message GadgetSettingsEthernet { message GadgetSettingsEthernet {
string host_addr = 1; string host_addr = 1;
string dev_addr = 2; string dev_addr = 2;
} }
message GadgetSettingsUMS { message GadgetSettingsUMS {
bool cdrom = 1; bool cdrom = 1;
string file = 2; string file = 2;
} }
/* End USB Gadget */ /* End USB Gadget */
/* Ethernet Interface Settings */ /* Ethernet Interface Settings */
message DeployedEthernetInterfaceSettings { message DeployedEthernetInterfaceSettings {
repeated EthernetInterfaceSettings list = 1; repeated EthernetInterfaceSettings list = 1;
} }
message EthernetInterfaceSettings { message EthernetInterfaceSettings {
string name = 1; string name = 1;
enum Mode { enum Mode {
MANUAL = 0; MANUAL = 0;
DHCP_CLIENT = 1; DHCP_CLIENT = 1;
DHCP_SERVER = 2; DHCP_SERVER = 2;
UNMANAGED = 3; // Indicates that the settings aren't known, as they aren't managed by the service UNMANAGED = 3; // Indicates that the settings aren't known, as they aren't managed by the service
} }
Mode mode = 2; Mode mode = 2;
string ipAddress4 = 3; string ipAddress4 = 3;
string netmask4 = 4; string netmask4 = 4;
bool enabled = 5; bool enabled = 5;
DHCPServerSettings dhcpServerSettings = 6; DHCPServerSettings dhcpServerSettings = 6;
bool settingsInUse = 7; //indicates if the given settings are applied to the interface bool settingsInUse = 7; //indicates if the given settings are applied to the interface
} }
/* DHCP */ /* DHCP */
message DHCPServerSettings { message DHCPServerSettings {
uint32 listenPort = 1; //if a port other thaan 0 is provided, a DNS server is bound to this port in addition to DHCP uint32 listenPort = 1; //if a port other thaan 0 is provided, a DNS server is bound to this port in addition to DHCP
string listenInterface = 2; string listenInterface = 2;
string leaseFile = 3; string leaseFile = 3;
bool notAuthoritative = 4; bool notAuthoritative = 4;
bool doNotBindInterface = 5; //if true, DHCP server binds to 0.0.0.0, no matter which interface is given (no restart needed on interface up/down) bool doNotBindInterface = 5; //if true, DHCP server binds to 0.0.0.0, no matter which interface is given (no restart needed on interface up/down)
string callbackScript = 6; //Script executes when lease is added/deleted `scriptname <add|del> <MAC> <IP> <HOSTNAME>` string callbackScript = 6; //Script executes when lease is added/deleted `scriptname <add|del> <MAC> <IP> <HOSTNAME>`
repeated DHCPServerRange ranges = 7; repeated DHCPServerRange ranges = 7;
//repeated DHCPServerOption options = 8; //repeated DHCPServerOption options = 8;
map<uint32, string> options = 8; //Replaced by map (dealing with key duplicates is ONLY PARTIALY handled by proto3), See RFC 2132 for details of available options map<uint32, string> options = 8; //Replaced by map (dealing with key duplicates is ONLY PARTIALY handled by proto3), See RFC 2132 for details of available options
repeated DHCPServerStaticHost staticHosts = 9; repeated DHCPServerStaticHost staticHosts = 9;
} }
//Could be used for IPv4 or IPv6 (refer dnsmasq docs), nor field for prefix length (default is 64) //Could be used for IPv4 or IPv6 (refer dnsmasq docs), nor field for prefix length (default is 64)
message DHCPServerRange { message DHCPServerRange {
string rangeLower = 1; //Lowest IP of DHCP range string rangeLower = 1; //Lowest IP of DHCP range
string rangeUpper = 2; //Highest IP of DHCP range string rangeUpper = 2; //Highest IP of DHCP range
string leaseTime = 3; string leaseTime = 3;
} }
//Used for static leases //Used for static leases
message DHCPServerStaticHost { message DHCPServerStaticHost {
string mac = 1; string mac = 1;
string ip = 2; string ip = 2;
} }
/* End DHCP */
/* WiFi */ message Empty {
message WiFiSettings {
enum Mode {
AP = 0; //acts as access point
STA = 1; //acts as station for an existing access point
STA_FAILOVER_AP = 2; //acts as station, if connection to the given AP isn't possible spawns an own AP
}
enum APAuthMode {
WPA2_PSK = 0; //AP uses WPA2 pre-shared key
OPEN = 1; //Open System Authentication (no authentication)
}
bool disabled = 1;
string reg = 2; //Regulatory domain per ISO/IEC 3166-1 alpha2
Mode mode = 3;
APAuthMode auth_mode = 4;
uint32 ap_channel = 5;
BSSCfg BssCfgAP = 6; //SSID of AP to spawn + PSK if needed
BSSCfg BssCfgClient = 7; //SSID of Infra to join + PSK if needed
bool ap_hide_ssid = 8; //if true, SSID gets hidden for spawned AP
bool disable_nexmon = 10; //if true, legacy driver / firmware is used instead of nexmon
} }
message BSSCfg {
string SSID = 1;
string PSK = 2;
}
/* End WiFI */
message Empty {}

View File

@ -2,59 +2,400 @@ package service
import ( import (
pb "github.com/mame82/P4wnP1_go/proto" pb "github.com/mame82/P4wnP1_go/proto"
"log" "sync"
"github.com/mame82/P4wnP1_go/netlink" "os/exec"
"github.com/mame82/P4wnP1_go/service/util" "github.com/mame82/P4wnP1_go/service/util"
"net"
"errors" "errors"
"fmt" "fmt"
"os/exec"
"strings" "strings"
"os" "log"
"io/ioutil"
"syscall"
"time" "time"
"sync" "syscall"
"net"
"io/ioutil"
"os"
"regexp" "regexp"
"strconv" "strconv"
) )
const ( const (
wifi_if_name string = "wlan0" wifi_if_name string = "wlan0"
)
//ToDo: big to do ... move all the shitty command tool line wrapping/parsing (iw, hostapd, wpa_supplicant etc.) to dedicated netlink/nl80211 implementation
//VERY LOW PRIORITY, as this basically means reimplementing the whole toolset for a way too small benefit
type WiFiAuthMode int
const (
WiFiAuthMode_OPEN WiFiAuthMode = iota
//WiFiAuthMode_WEP
WiFiAuthMode_WPA_PSK
WiFiAuthMode_WPA2_PSK
WiFiAuthMode_UNSUPPORTED
)
const (
WPA_SUPPLICANT_CONNECT_TIMEOUT = time.Second * 20 WPA_SUPPLICANT_CONNECT_TIMEOUT = time.Second * 20
) )
type WifiState struct {
mutexSettings *sync.Mutex func wifiCheckExternalBinaries() error {
Settings *pb.WiFiSettings if !binaryAvailable("wpa_supplicant") {
CmdWpaSupplicant *exec.Cmd return errors.New("wpa_supplicant seems to be missing, please install it")
mutexWpaSupplicant *sync.Mutex }
CmdHostapd *exec.Cmd // to create wpa_supplicant.conf
mutexHostapd *sync.Mutex if !binaryAvailable("wpa_passphrase") {
IfaceName string return errors.New("wpa_passphrase seems to be missing, please install it")
PathWpaSupplicantConf string }
PathHostapdConf string if !binaryAvailable("hostapd") {
LoggerHostapd *util.TeeLogger return errors.New("hostapd seems to be missing, please install it")
LoggerWpaSupplicant *util.TeeLogger }
OutMonitorWpaSupplicant *wpaSupplicantOutMonitor // for wifiScan
if !binaryAvailable("iw") {
return errors.New("The tool 'iw' seems to be missing, please install it")
}
return nil
} }
type WiFiService struct {
State *pb.WiFi2State
Settings *pb.WiFi2Settings
mutexSettings *sync.Mutex // Lock settings on change
CmdWpaSupplicant *exec.Cmd //Manages wpa-supplicant process
mutexWpaSupplicant *sync.Mutex //mutex for wpa-supplicant proc
CmdHostapd *exec.Cmd //Manages hostapd process
mutexHostapd *sync.Mutex //hostapd proc lock
IfaceName string //Name of WiFi interface
PathWpaSupplicantConf string // path to config file for wpa-supplicant
PathHostapdConf string // path to config file for hostapd
LoggerHostapd *util.TeeLogger //logger for hostapd
LoggerWpaSupplicant *util.TeeLogger //logger for WPA supplicant
OutMonitorWpaSupplicant *wpaSupplicantOutMonitor //Monitors wpa_supplicant output and sets signals where needed
}
func (wSvc *WiFiService) StartHostapd() (err error) {
log.Printf("Starting hostapd for interface '%s'...\n", wSvc.IfaceName)
wSvc.mutexHostapd.Lock()
defer wSvc.mutexHostapd.Unlock()
//stop hostapd if already running
if wSvc.CmdHostapd != nil {
// avoid deadlock
wSvc.mutexHostapd.Unlock()
wSvc.StopHostapd()
wSvc.mutexHostapd.Lock()
}
wSvc.CmdHostapd = exec.Command("/usr/sbin/hostapd", wSvc.PathHostapdConf)
wSvc.CmdHostapd.Stdout = wSvc.LoggerHostapd.LogWriter
wSvc.CmdHostapd.Stderr = wSvc.LoggerHostapd.LogWriter
err = wSvc.CmdHostapd.Start()
if err != nil {
wSvc.CmdHostapd.Wait()
return errors.New(fmt.Sprintf("Error starting hostapd '%v'", err))
}
log.Printf("... hostapd for interface '%s' started\n", wSvc.IfaceName)
return nil
}
func (wSvc *WiFiService) StopHostapd() (err error) {
eSuccess := fmt.Sprintf("... hostapd for interface '%s' stopped", wSvc.IfaceName)
eCantStop := fmt.Sprintf("... couldn't terminate hostapd for interface '%s'", wSvc.IfaceName)
wSvc.mutexHostapd.Lock()
defer wSvc.mutexHostapd.Unlock()
if wSvc.CmdHostapd == nil {
log.Printf("... hostapd for interface '%s' isn't running, no need to stop it\n", wSvc.IfaceName)
return nil
}
wSvc.CmdHostapd.Process.Signal(syscall.SIGTERM)
wSvc.CmdHostapd.Wait()
if !wSvc.CmdHostapd.ProcessState.Exited() {
log.Printf("... hostapd didn't react on SIGTERM for interface '%s', trying SIGKILL\n", wSvc.IfaceName)
wSvc.CmdHostapd.Process.Kill()
time.Sleep(500 * time.Millisecond)
if wSvc.CmdHostapd.ProcessState.Exited() {
wSvc.CmdHostapd = nil
log.Println(eSuccess)
return nil
} else {
log.Println(eCantStop)
return errors.New(eCantStop)
}
}
wSvc.CmdHostapd = nil
log.Println(eSuccess)
return nil
}
func (wSvc *WiFiService) StopWpaSupplicant() (err error) {
eSuccess := fmt.Sprintf("... wpa_supplicant for interface '%s' stopped", wSvc.IfaceName)
eCantStop := fmt.Sprintf("... couldn't terminate wpa_supplicant for interface '%s'", wSvc.IfaceName)
log.Printf("... stop running wpa_supplicant processes for interface '%s'\n", wSvc.IfaceName)
wSvc.mutexWpaSupplicant.Lock()
defer wSvc.mutexWpaSupplicant.Unlock()
if wSvc.CmdWpaSupplicant == nil {
log.Printf("... wpa_supplicant for interface '%s' wasn't running, no need to stop it\n", wSvc.IfaceName)
return nil
}
log.Printf("... sending SIGTERM for wpa_supplicant on interface '%s' with PID\n", wSvc.IfaceName, wSvc.CmdWpaSupplicant.Process.Pid)
wSvc.CmdWpaSupplicant.Process.Signal(syscall.SIGTERM)
wSvc.CmdWpaSupplicant.Wait()
if !wSvc.CmdWpaSupplicant.ProcessState.Exited() {
log.Printf("... wpa_supplicant didn't react on SIGTERM for interface '%s', trying SIGKILL\n", wSvc.IfaceName)
wSvc.CmdWpaSupplicant.Process.Kill()
time.Sleep(500 * time.Millisecond)
if wSvc.CmdWpaSupplicant.ProcessState.Exited() {
wSvc.CmdWpaSupplicant = nil
log.Println(eSuccess)
return nil
} else {
log.Println(eCantStop)
return errors.New(eCantStop)
}
}
wSvc.CmdWpaSupplicant = nil
log.Println(eSuccess)
return nil
}
func (wSvc *WiFiService) StartWpaSupplicant(timeout time.Duration) (err error) {
log.Printf("Starting wpa_supplicant for interface '%s'...\n", wSvc.IfaceName)
wSvc.mutexWpaSupplicant.Lock()
defer wSvc.mutexWpaSupplicant.Unlock()
//stop wpa_supplicant if already running
if wSvc.CmdWpaSupplicant != nil {
// avoid dead lock
wSvc.mutexWpaSupplicant.Unlock()
wSvc.StopWpaSupplicant()
wSvc.mutexWpaSupplicant.Lock()
}
//we monitor output of wpa_supplicant till we are connected, fail due to wrong PSK or timeout is reached
//Note: PID file creation doesn't work when not started as daemon, so we do it manually, later on
wSvc.CmdWpaSupplicant = exec.Command("/sbin/wpa_supplicant", "-c", wSvc.PathWpaSupplicantConf, "-i", wSvc.IfaceName)
wSvc.CmdWpaSupplicant.Stdout = wSvc.LoggerWpaSupplicant.LogWriter
err = wSvc.CmdWpaSupplicant.Start()
if err != nil {
return err
}
//wait for result in output
connected, errcon := wSvc.OutMonitorWpaSupplicant.WaitConnectResultOnce(timeout)
if errcon != nil {
log.Printf("... wpa_supplicant reached timeout of '%v' without beeing able to connect to given network\n", timeout)
log.Println("... killing wpa_supplicant")
// avoid dead lock
wSvc.mutexWpaSupplicant.Unlock()
wSvc.StopWpaSupplicant()
wSvc.mutexWpaSupplicant.Lock()
return errors.New("TIMEOUT REACHED")
}
if connected {
//We could return success and keep wpa_supplicant running
log.Println("... connected to given WiFi network, wpa_supplicant running")
return nil
} else {
//we stop wpa_supplicant and return err
log.Println("... seems the wrong PSK was provided for the given WiFi network, stopping wpa_supplicant ...")
//wifiStopWpaSupplicant(nameIface)
log.Println("... killing wpa_supplicant")
// avoid dead lock
wSvc.mutexWpaSupplicant.Unlock()
wSvc.StopWpaSupplicant()
wSvc.mutexWpaSupplicant.Lock()
return errors.New("Wrong PSK")
}
return nil
}
func (wSvc *WiFiService) GetState() pb.WiFi2State {
return *wSvc.State
}
func MatchGivenBBSToScanResult(scanRes []BSS, targets []*pb.WiFi2BSSCfg) (matches []*pb.WiFi2BSSCfg) {
for _,bssCfgTarget := range targets {
for _,bssCfgScan := range scanRes {
if bssCfgScan.SSID == bssCfgTarget.SSID {
// SSID match, possible candidate
matches = append(matches, bssCfgTarget)
}
}
}
return
}
func (wSvc *WiFiService) runStaMode(newWifiSettings *pb.WiFi2Settings) (err error) {
if len(newWifiSettings.Client_BSSList) == 0 {
return errors.New("Error: WiFi mode set to station (STA) but no BSS configurations provided")
}
//scan for provided wifi
scanres, err := WifiScan(wSvc.IfaceName)
if err != nil {
return errors.New(fmt.Sprintf("Scanning for existing WiFi networks failed: %v", err))
}
matchingBssList := MatchGivenBBSToScanResult(scanres, newWifiSettings.Client_BSSList)
if len(matchingBssList) == 0 {
return errors.New(fmt.Sprintf("Non of the given SSIDs found during scan\n"))
}
// Create config for the remaining networks
confstr, err := wifiCreateWpaSupplicantConfStringList(matchingBssList)
if err != nil { return err }
// store config to file
log.Printf("Creating wpa_supplicant configuration file at '%s'\n", wSvc.PathWpaSupplicantConf)
err = ioutil.WriteFile(wSvc.PathWpaSupplicantConf, []byte(confstr), os.ModePerm)
if err != nil { return err }
//ToDo: proper error handling, in case connection not possible
err = wSvc.StartWpaSupplicant(WPA_SUPPLICANT_CONNECT_TIMEOUT)
if err != nil { return err }
wSvc.State.Bss.SSID = "unknown SSID"
wSvc.State.Channel = newWifiSettings.Channel
wSvc.State.Regulatory = newWifiSettings.Regulatory
wSvc.State.HideSsid = newWifiSettings.HideSsid
wSvc.State.WorkingMode = pb.WiFi2WorkingMode_STA
wSvc.State.Disabled = false
return nil
}
// ToDo: Output monitor for AP-ENABLED (same approach as for wpa_supplicant)
func (wSvc *WiFiService) runAPMode(newWifiSettings *pb.WiFi2Settings) (err error) {
//generate hostapd.conf (overwrite old one)
hostapdCreateConfigFile2(newWifiSettings, wSvc.PathHostapdConf)
//start hostapd
err = wSvc.StartHostapd()
if err != nil {
wSvc.State.WorkingMode = pb.WiFi2WorkingMode_UNKNOWN
return err
}
// update Connection wSvc
wSvc.State.Bss.SSID = newWifiSettings.Ap_BSS.SSID
wSvc.State.Channel = newWifiSettings.Channel
wSvc.State.Regulatory = newWifiSettings.Regulatory
wSvc.State.HideSsid = newWifiSettings.HideSsid
wSvc.State.WorkingMode = pb.WiFi2WorkingMode_AP
wSvc.State.Disabled = false
return nil
}
func (wSvc *WiFiService) DeploySettings(newWifiSettings *pb.WiFi2Settings) (wstate *pb.WiFi2State, err error) {
log.Println("Deploying new WiFi settings...")
log.Printf("Settings: %+v\n", newWifiSettings)
wSvc.mutexSettings.Lock()
defer wSvc.mutexSettings.Unlock()
// Reset wSvc to unknown, if something goes wrong, there's no wpa_supplicant or hostapd
wSvc.State.WorkingMode = pb.WiFi2WorkingMode_UNKNOWN
//ToDo: Dis/Enable nexmon if needed
//stop wpa_supplicant if needed
err = wSvc.StopWpaSupplicant()
if err != nil { return wSvc.State, err}
//kill hostapd in case it is still running
err = wSvc.StopHostapd()
if err != nil { return wSvc.State, err}
wSvc.State.Disabled = true
if !newWifiSettings.Disabled {
switch newWifiSettings.WorkingMode {
case pb.WiFi2WorkingMode_AP:
err = wSvc.runAPMode(newWifiSettings)
case pb.WiFi2WorkingMode_STA, pb.WiFi2WorkingMode_STA_FAILOVER_AP:
errSta := wSvc.runStaMode(newWifiSettings)
if errSta != nil {
//in failover mode, we try to enable AP first
if newWifiSettings.WorkingMode == pb.WiFi2WorkingMode_STA_FAILOVER_AP {
log.Println(errSta)
log.Printf("Trying to fail over to Access Point Mode...")
err = wSvc.runAPMode(newWifiSettings)
} else {
err = errSta
}
}
default:
// None allowed working mode, so we leave wSvc as UNKNOWN
err = errors.New("Unknown working mode")
}
}
if err == nil {
log.Printf("... WiFi settings deployed successfully\n")
} else {
log.Printf("... deploying WiFi settings failed: %s\n", err.Error())
}
// update settings (wSvc is updated by runAPMode/runStaMode)
wSvc.Settings = newWifiSettings
return wSvc.State, nil
}
func NewWifiService() (res *WiFiService) {
ifName := wifi_if_name
err := wifiCheckExternalBinaries()
if err != nil { panic(err) }
//Check interface existence
if exists,_ := CheckInterfaceExistence(ifName); !exists {
panic(errors.New(fmt.Sprintf("WiFi interface '%s' not present")))
}
res = &WiFiService{
mutexSettings: &sync.Mutex{},
CmdWpaSupplicant: nil,
mutexWpaSupplicant: &sync.Mutex{},
CmdHostapd: nil,
mutexHostapd: &sync.Mutex{},
IfaceName: ifName,
PathWpaSupplicantConf: fmt.Sprintf("/tmp/wpa_supplicant_%s.conf", ifName),
PathHostapdConf: fmt.Sprintf("/tmp/hostapd_%s.conf", ifName),
}
res.OutMonitorWpaSupplicant = NewWpaSupplicantOutMonitor()
res.LoggerHostapd = util.NewTeeLogger(true)
res.LoggerHostapd.SetPrefix("hostapd: ")
res.LoggerWpaSupplicant = util.NewTeeLogger(true)
res.LoggerWpaSupplicant.SetPrefix("wpa_supplicant: ")
res.LoggerWpaSupplicant.AddOutput(res.OutMonitorWpaSupplicant) // add watcher too tee'ed output writers
// Initial settings and state on service start
res.Settings = &pb.WiFi2Settings{
Disabled: false,
WorkingMode: pb.WiFi2WorkingMode_AP,
Client_BSSList: []*pb.WiFi2BSSCfg{},
Ap_BSS: &pb.WiFi2BSSCfg{},
}
res.State = &pb.WiFi2State{
Disabled: true,
WorkingMode: pb.WiFi2WorkingMode_UNKNOWN,
Bss: &pb.WiFi2BSSCfg{},
}
return res
}
type wpaSupplicantOutMonitor struct { type wpaSupplicantOutMonitor struct {
resultReceived *util.Signal resultReceived *util.Signal
result bool result bool
@ -108,422 +449,26 @@ func NewWpaSupplicantOutMonitor() *wpaSupplicantOutMonitor {
} }
} }
func NewWifiState(startupSettings *pb.WiFiSettings, ifName string) (res *WifiState) {
if !binaryAvailable("wpa_supplicant") {
panic("wpa_supplicant seems to be missing, please install it")
}
// to create wpa_supplicant.conf
if !binaryAvailable("wpa_passphrase") {
panic("wpa_passphrase seems to be missing, please install it")
}
if !binaryAvailable("hostapd") {
panic("hostapd seems to be missing, please install it")
}
// for wifiScan
if !binaryAvailable("iw") {
panic("The tool 'iw' seems to be missing, please install it")
}
res = &WifiState{ type WiFiAuthMode int
mutexSettings: &sync.Mutex{},
IfaceName: ifName,
Settings: startupSettings,
CmdWpaSupplicant: nil,
mutexWpaSupplicant: &sync.Mutex{},
CmdHostapd: nil,
mutexHostapd: &sync.Mutex{},
PathWpaSupplicantConf: fmt.Sprintf("/tmp/wpa_supplicant_%s.conf", ifName),
PathHostapdConf: fmt.Sprintf("/tmp/hostapd_%s.conf", ifName),
}
res.OutMonitorWpaSupplicant = NewWpaSupplicantOutMonitor() const (
res.LoggerHostapd = util.NewTeeLogger(true) WiFiAuthMode_OPEN WiFiAuthMode = iota
res.LoggerHostapd.SetPrefix("hostapd: ") //WiFiAuthMode_WEP
res.LoggerWpaSupplicant = util.NewTeeLogger(true) WiFiAuthMode_WPA_PSK
res.LoggerWpaSupplicant.SetPrefix("wpa_supplicant: ") WiFiAuthMode_WPA2_PSK
res.LoggerWpaSupplicant.AddOutput(res.OutMonitorWpaSupplicant) // add watcher too tee'ed output writers WiFiAuthMode_UNSUPPORTED
)
return
}
func (wifiState *WifiState) StartHostapd() (err error) {
log.Printf("Starting hostapd for interface '%s'...\n", wifiState.IfaceName)
wifiState.mutexHostapd.Lock()
defer wifiState.mutexHostapd.Unlock()
//check if interface is valid
if_exists, _ := CheckInterfaceExistence(wifiState.IfaceName)
if !if_exists {
return errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", wifiState.IfaceName))
}
//stop hostapd if already running
if wifiState.CmdHostapd != nil {
// avoid deadlock
wifiState.mutexHostapd.Unlock()
wifiState.StopHostapd()
wifiState.mutexHostapd.Lock()
}
//We use the run command and allow hostapd to daemonize
//wifiState.CmdHostapd = exec.Command("/usr/sbin/hostapd", "-f", logFileHostapd(wifiState.IfaceName), wifiState.PathHostapdConf)
wifiState.CmdHostapd = exec.Command("/usr/sbin/hostapd", wifiState.PathHostapdConf)
wifiState.CmdHostapd.Stdout = wifiState.LoggerHostapd.LogWriter
wifiState.CmdHostapd.Stderr = wifiState.LoggerHostapd.LogWriter
err = wifiState.CmdHostapd.Start()
if err != nil {
//bytes, _ := wifiState.CmdHostapd.CombinedOutput()
//println(string(bytes))
wifiState.CmdHostapd.Wait()
return errors.New(fmt.Sprintf("Error starting hostapd '%v'", err))
}
log.Printf("... hostapd for interface '%s' started\n", wifiState.IfaceName)
return nil
}
func (wifiState *WifiState) StopHostapd() (err error) {
eSuccess := fmt.Sprintf("... hostapd for interface '%s' stopped", wifiState.IfaceName)
eCantStop := fmt.Sprintf("... couldn't terminate hostapd for interface '%s'", wifiState.IfaceName)
wifiState.mutexHostapd.Lock()
defer wifiState.mutexHostapd.Unlock()
if wifiState.CmdHostapd == nil {
log.Printf("... hostapd for interface '%s' isn't running, no need to stop it\n", wifiState.IfaceName)
return nil
}
wifiState.CmdHostapd.Process.Signal(syscall.SIGTERM)
wifiState.CmdHostapd.Wait()
if !wifiState.CmdHostapd.ProcessState.Exited() {
log.Printf("... hostapd didn't react on SIGTERM for interface '%s', trying SIGKILL\n", wifiState.IfaceName)
wifiState.CmdHostapd.Process.Kill()
time.Sleep(500 * time.Millisecond)
if wifiState.CmdHostapd.ProcessState.Exited() {
wifiState.CmdHostapd = nil
log.Println(eSuccess)
return nil
} else {
log.Println(eCantStop)
return errors.New(eCantStop)
}
}
wifiState.CmdHostapd = nil
log.Println(eSuccess)
return nil
}
func (wifiState *WifiState) StopWpaSupplicant() (err error) {
eSuccess := fmt.Sprintf("... wpa_supplicant for interface '%s' stopped", wifiState.IfaceName)
eCantStop := fmt.Sprintf("... couldn't terminate wpa_supplicant for interface '%s'", wifiState.IfaceName)
log.Printf("... stop running wpa_supplicant processes for interface '%s'\n", wifiState.IfaceName)
wifiState.mutexWpaSupplicant.Lock()
defer wifiState.mutexWpaSupplicant.Unlock()
if wifiState.CmdWpaSupplicant == nil {
log.Printf("... wpa_supplicant for interface '%s' wasn't running, no need to stop it\n", wifiState.IfaceName)
return nil
}
log.Printf("... sending SIGTERM for wpa_supplicant on interface '%s' with PID\n", wifiState.IfaceName, wifiState.CmdWpaSupplicant.Process.Pid)
wifiState.CmdWpaSupplicant.Process.Signal(syscall.SIGTERM)
wifiState.CmdWpaSupplicant.Wait()
if !wifiState.CmdWpaSupplicant.ProcessState.Exited() {
log.Printf("... wpa_supplicant didn't react on SIGTERM for interface '%s', trying SIGKILL\n", wifiState.IfaceName)
wifiState.CmdWpaSupplicant.Process.Kill()
time.Sleep(500 * time.Millisecond)
if wifiState.CmdWpaSupplicant.ProcessState.Exited() {
wifiState.CmdWpaSupplicant = nil
log.Println(eSuccess)
return nil
} else {
log.Println(eCantStop)
return errors.New(eCantStop)
}
}
wifiState.CmdWpaSupplicant = nil
log.Println(eSuccess)
return nil
}
func (wifiState *WifiState) StartWpaSupplicant(timeout time.Duration) (err error) {
log.Printf("Starting wpa_supplicant for interface '%s'...\n", wifiState.IfaceName)
wifiState.mutexWpaSupplicant.Lock()
defer wifiState.mutexWpaSupplicant.Unlock()
//check if interface is valid
if_exists, _ := CheckInterfaceExistence(wifiState.IfaceName)
if !if_exists {
return errors.New(fmt.Sprintf("The given interface '%s' doesn't exist", wifiState.IfaceName))
}
//stop wpa_supplicant if already running
if wifiState.CmdWpaSupplicant != nil {
// avoid dead lock
wifiState.mutexWpaSupplicant.Unlock()
wifiState.StopWpaSupplicant()
wifiState.mutexWpaSupplicant.Lock()
}
//we monitor output of wpa_supplicant till we are connected, fail due to wrong PSK or timeout is reached
//Note: PID file creation doesn't work when not started as daemon, so we do it manually, later on
wifiState.CmdWpaSupplicant = exec.Command("/sbin/wpa_supplicant", "-c", wifiState.PathWpaSupplicantConf, "-i", wifiState.IfaceName)
wifiState.CmdWpaSupplicant.Stdout = wifiState.LoggerWpaSupplicant.LogWriter
err = wifiState.CmdWpaSupplicant.Start()
if err != nil {
return err
}
//wait for result in output
connected, errcon := wifiState.OutMonitorWpaSupplicant.WaitConnectResultOnce(timeout)
if errcon != nil {
log.Printf("... wpa_supplicant reached timeout of '%v' without beeing able to connect to given network\n", timeout)
log.Println("... killing wpa_supplicant")
// avoid dead lock
wifiState.mutexWpaSupplicant.Unlock()
wifiState.StopWpaSupplicant()
wifiState.mutexWpaSupplicant.Lock()
return errors.New("TIMEOUT REACHED")
}
if connected {
//We could return success and keep wpa_supplicant running
log.Println("... connected to given WiFi network, wpa_supplicant running")
return nil
} else {
//we stop wpa_supplicant and return err
log.Println("... seems the wrong PSK was provided for the given WiFi network, stopping wpa_supplicant ...")
//wifiStopWpaSupplicant(nameIface)
log.Println("... killing wpa_supplicant")
// avoid dead lock
wifiState.mutexWpaSupplicant.Unlock()
wifiState.StopWpaSupplicant()
wifiState.mutexWpaSupplicant.Lock()
return errors.New("Wrong PSK")
}
return nil
}
type BSS struct { type BSS struct {
SSID string SSID string
BSSID net.HardwareAddr BSSID net.HardwareAddr
Frequency int Frequency int
BeaconInterval time.Duration //carefull, on IE level beacon interval isn't meassured in milliseconds BeaconInterval time.Duration //carefull, on IE level beacon interval isn't measured in milliseconds
AuthMode WiFiAuthMode AuthMode WiFiAuthMode
Signal float32 //Signal strength in dBm Signal float32 //Signal strength in dBm
} }
func (state WifiState) GetDeployWifiSettings() (ws *pb.WiFiSettings, err error) {
return state.Settings, nil
}
func (state *WifiState) DeployWifiSettings(newWifiSettings *pb.WiFiSettings) (err error) {
log.Printf("Trying to deploy WiFi settings:\n%v\n", newWifiSettings)
ifName := wifi_if_name
state.mutexSettings.Lock()
defer state.mutexSettings.Unlock()
//Get Interface
iface, err := net.InterfaceByName(ifName)
if err != nil {
return errors.New(fmt.Sprintf("No WiFi interface present: %v\n", err))
}
firmwareChange := false
if newWifiSettings.DisableNexmon {
//load legacy driver + firmware
if wifiIsNexmonLoaded() {
err = wifiLoadLegacy()
if err != nil {
return
}
firmwareChange = true
}
} else {
//load nexmon driver + firmware
if !wifiIsNexmonLoaded() {
err = wifiLoadNexmon()
if err != nil {
return
}
firmwareChange = true
}
}
if firmwareChange {
ReInitNetworkInterface(ifName)
}
linkStateChange := false
currentlyEnabled, errstate := netlink.NetworkLinkGetStateUp(iface)
if errstate != nil {
linkStateChange = true
} // current link state couldn't be retireved, regard as changed
if currentlyEnabled == newWifiSettings.Disabled {
linkStateChange = true
} //Is disabled and should be enabled, or the other way around
if linkStateChange || firmwareChange { // Enable/Disable if only if needed
// ToDo: the new interface state isn't reflected to respective ethernet settings
if newWifiSettings.Disabled {
log.Printf("Setting WiFi interface %s to DOWN\n", iface.Name)
err = netlink.NetworkLinkDown(iface)
} else {
log.Printf("Setting WiFi interface %s to UP\n", iface.Name)
err = netlink.NetworkLinkUp(iface)
}
}
//set proper regulatory dom
err = wifiSetReg(newWifiSettings.Reg)
if err != nil {
log.Printf("Error setting WiFi regulatory domain '%s': %v\n", newWifiSettings.Reg, err) //we don't abort on error here
}
//stop wpa_supplicant if needed
state.StopWpaSupplicant()
//kill hostapd in case it is still running
err = state.StopHostapd()
if err != nil {
return err // ToDo: returning at this point is a bit harsh
}
switch newWifiSettings.Mode {
case pb.WiFiSettings_AP:
err = state.runAPMode(newWifiSettings)
if err != nil {
return err
}
case pb.WiFiSettings_STA, pb.WiFiSettings_STA_FAILOVER_AP:
if newWifiSettings.BssCfgClient == nil {
return state.apFailoverOrError(
newWifiSettings,
errors.New("Error: WiFi mode set to station (STA) but no BSS configuration for target WiFi provided"),
)
}
if len(newWifiSettings.BssCfgClient.SSID) == 0 {
return state.apFailoverOrError(
newWifiSettings,
errors.New("Error: WiFi mode set to station (STA) but no SSID provided to identify BSS to join"),
)
}
//scan for provided wifi
scanres, err := WifiScan(ifName)
if err != nil {
return state.apFailoverOrError(
newWifiSettings,
errors.New(fmt.Sprintf("Scanning for existing WiFi networks failed: %v", err)),
)
}
var matchingBss *BSS = nil
for _, bss := range scanres {
if bss.SSID == newWifiSettings.BssCfgClient.SSID {
matchingBss = &bss
break
}
}
if matchingBss == nil {
return state.apFailoverOrError(
newWifiSettings,
errors.New(fmt.Sprintf("SSID not found during scan: '%s'", newWifiSettings.BssCfgClient.SSID)),
)
}
if len(newWifiSettings.BssCfgClient.PSK) == 0 && matchingBss.AuthMode != WiFiAuthMode_OPEN {
//seems we try to connect an OPEN AUTHENTICATION network, but the existing BSS isn't OPEN AUTH
return state.apFailoverOrError(
newWifiSettings,
errors.New(fmt.Sprintf("WiFi SSID '%s' found during scan, but authentication mode isn't OPEN and no PSK was provided", newWifiSettings.BssCfgClient.SSID)),
)
} else {
err = WifiCreateWpaSupplicantConfigFile(newWifiSettings.BssCfgClient.SSID, newWifiSettings.BssCfgClient.PSK, state.PathWpaSupplicantConf)
if err != nil {
return state.apFailoverOrError(
newWifiSettings,
err,
)
}
//ToDo: proper error handling, in case connection not possible
err = state.StartWpaSupplicant(WPA_SUPPLICANT_CONNECT_TIMEOUT)
if err != nil {
return state.apFailoverOrError(
newWifiSettings,
err,
)
}
}
}
log.Printf("... WiFi settings deployed successfully, checking for stored interface configuration...\n")
// store new state
state.Settings = newWifiSettings
return nil
}
func (state *WifiState) runAPMode(newWifiSettings *pb.WiFiSettings) (err error) {
//generate hostapd.conf (overwrite old one)
hostapdCreateConfigFile(newWifiSettings, state.PathHostapdConf)
//start hostapd
return state.StartHostapd()
}
func (state *WifiState) apFailoverOrError(newWifiSettings *pb.WiFiSettings, givenErr error) (err error) {
if newWifiSettings.Mode == pb.WiFiSettings_STA_FAILOVER_AP {
log.Println(givenErr)
log.Printf("Trying to fail over to Access Point Mode...")
return state.runAPMode(newWifiSettings)
} else {
return givenErr
}
}
//check if nexmon driver + firmware is active is loaded
func wifiIsNexmonLoaded() bool {
return true
}
func wifiLoadNexmon() error {
log.Println("Loading nexmon WiFi firmware")
return nil
}
func wifiLoadLegacy() error {
log.Println("Loading leagcy WiFi firmware")
return nil
}
func wifiSetReg(reg string) (err error) {
if len(reg) == 0 {
reg = "US" //default
log.Printf("No ISO/IEC 3166-1 alpha2 regulatory domain provided, defaulting to '%s'\n", reg)
}
reg = strings.ToUpper(reg)
proc := exec.Command("/sbin/iw", "reg", "set", reg)
err = proc.Run()
if err != nil {
return err
}
log.Printf("Notified kernel to use ISO/IEC 3166-1 alpha2 regulatory domain '%s'\n", reg)
return nil
}
func WifiScan(ifName string) (result []BSS, err error) { func WifiScan(ifName string) (result []BSS, err error) {
proc := exec.Command("/sbin/iw", ifName, "scan") proc := exec.Command("/sbin/iw", ifName, "scan")
res, err := proc.CombinedOutput() res, err := proc.CombinedOutput()
@ -536,34 +481,30 @@ func WifiScan(ifName string) (result []BSS, err error) {
return return
} }
func WifiCreateWpaSupplicantConfigFile(ssid string, psk string, filename string) (err error) { func wifiCreateWpaSupplicantConfStringList(bsslist []*pb.WiFi2BSSCfg) (config string, err error) {
log.Printf("Creating wpa_suuplicant configuration file at '%s'\n", filename) // if a PSK is provided, we assume it is needed, otherwise we assume OPEN AUTHENTICATION
fileContent, err := wifiCreateWpaSupplicantConfString(ssid, psk) for _,bss := range bsslist {
if err != nil { ssid := bss.SSID
return psk := bss.PSK
} if len(psk) > 0 {
err = ioutil.WriteFile(filename, []byte(fileContent), os.ModePerm) fmt.Println("Connecting WiFi with PSK")
return proc := exec.Command("/usr/bin/wpa_passphrase", ssid, psk)
} cres, err := proc.CombinedOutput()
func wifiCreateWpaSupplicantConfString(ssid string, psk string) (config string, err error) { if err != nil {
// if a PSK is provided, we assume it is needed, otherwise we assum OPEN AUTHENTICATION return "", errors.New(fmt.Sprintf("Error craeting wpa_supplicant.conf for SSID '%s' with PSK '%s': %s", ssid, psk, string(cres)))
if len(psk) > 0 { }
fmt.Println("Connecting WiFi with PSK") config += string(cres)
proc := exec.Command("/usr/bin/wpa_passphrase", ssid, psk) } else {
cres, err := proc.CombinedOutput() fmt.Println("Connecting WiFi with OPEN AUTH")
config += fmt.Sprintf(
if err != nil { `network={
return "", errors.New(fmt.Sprintf("Error craeting wpa_supplicant.conf for SSID '%s' with PSK '%s': %s", ssid, psk, string(cres)))
}
config = string(cres)
} else {
fmt.Println("Connecting WiFi with OPEN AUTH")
config = fmt.Sprintf(
`network={
ssid="%s" ssid="%s"
key_mgmt=NONE key_mgmt=NONE
}`, ssid) }
`, ssid)
}
} }
@ -572,12 +513,13 @@ func wifiCreateWpaSupplicantConfString(ssid string, psk string) (config string,
return return
} }
func wifiCreateHostapdConfString(ws *pb.WiFiSettings) (config string, err error) {
if ws.Mode != pb.WiFiSettings_STA_FAILOVER_AP && ws.Mode != pb.WiFiSettings_AP { func wifiCreateHostapdConfString2(ws *pb.WiFi2Settings) (config string, err error) {
return "", errors.New("WiFiSettings don't use an AP") if ws.WorkingMode != pb.WiFi2WorkingMode_AP && ws.WorkingMode != pb.WiFi2WorkingMode_STA_FAILOVER_AP {
return "", errors.New("Couldn't create hostapd configuration, the settings don't include an AP")
} }
if ws.BssCfgAP == nil { if ws.Ap_BSS == nil {
return "", errors.New("WiFiSettings don't contain a BSS configuration for an AP") return "", errors.New("WiFiSettings don't contain a BSS configuration for an AP")
} }
@ -590,22 +532,22 @@ func wifiCreateHostapdConfString(ws *pb.WiFiSettings) (config string, err error)
config += fmt.Sprintf("ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]\n") // 40MHz channels with 20ns guard interval config += fmt.Sprintf("ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]\n") // 40MHz channels with 20ns guard interval
config += fmt.Sprintf("macaddr_acl=0\n") //Accept all MAC addresses config += fmt.Sprintf("macaddr_acl=0\n") //Accept all MAC addresses
config += fmt.Sprintf("ssid=%s\n", ws.BssCfgAP.SSID) config += fmt.Sprintf("ssid=%s\n", ws.Ap_BSS.SSID)
config += fmt.Sprintf("channel=%d\n", ws.ApChannel) config += fmt.Sprintf("channel=%d\n", ws.Channel)
if ws.AuthMode == pb.WiFiSettings_WPA2_PSK { if ws.AuthMode == pb.WiFi2AuthMode_WPA2_PSK {
config += fmt.Sprintf("auth_algs=1\n") //Use WPA authentication config += fmt.Sprintf("auth_algs=1\n") //Use WPA authentication
config += fmt.Sprintf("wpa=2\n") //Use WPA2 config += fmt.Sprintf("wpa=2\n") //Use WPA2
//ToDo: check if PSK could be provided encrypted //ToDo: check if PSK could be provided encrypted
config += fmt.Sprintf("wpa_key_mgmt=WPA-PSK\n") //Use a pre-shared key config += fmt.Sprintf("wpa_key_mgmt=WPA-PSK\n") //Use a pre-shared key
config += fmt.Sprintf("wpa_passphrase=%s\n", ws.BssCfgAP.PSK) //Set PSK config += fmt.Sprintf("wpa_passphrase=%s\n", ws.Ap_BSS.PSK) //Set PSK
config += fmt.Sprintf("rsn_pairwise=CCMP\n") //Use Use AES, instead of TKIP config += fmt.Sprintf("rsn_pairwise=CCMP\n") //Use Use AES, instead of TKIP
} else { } else {
config += fmt.Sprintf("auth_algs=3\n") //Both, open and shared auth config += fmt.Sprintf("auth_algs=3\n") //Both, open and shared auth
} }
if ws.ApHideSsid { if ws.HideSsid {
config += fmt.Sprintf("ignore_broadcast_ssid=2\n") //Require clients to know the SSID config += fmt.Sprintf("ignore_broadcast_ssid=2\n") //Require clients to know the SSID
} else { } else {
config += fmt.Sprintf("ignore_broadcast_ssid=0\n") //Send beacons + probes config += fmt.Sprintf("ignore_broadcast_ssid=0\n") //Send beacons + probes
@ -614,9 +556,9 @@ func wifiCreateHostapdConfString(ws *pb.WiFiSettings) (config string, err error)
return return
} }
func hostapdCreateConfigFile(s *pb.WiFiSettings, filename string) (err error) { func hostapdCreateConfigFile2(s *pb.WiFi2Settings, filename string) (err error) {
log.Printf("Creating hostapd configuration file at '%s'\n", filename) log.Printf("Creating hostapd configuration file at '%s'\n", filename)
fileContent, err := wifiCreateHostapdConfString(s) fileContent, err := wifiCreateHostapdConfString2(s)
if err != nil { if err != nil {
return return
} }

View File

@ -118,6 +118,7 @@ func GetDefaultGadgetSettings() (res pb.GadgetSettings) {
return res return res
} }
/*
func GetDefaultWiFiSettings() (res *pb.WiFiSettings) { func GetDefaultWiFiSettings() (res *pb.WiFiSettings) {
res = &pb.WiFiSettings{ res = &pb.WiFiSettings{
Mode: pb.WiFiSettings_AP, Mode: pb.WiFiSettings_AP,
@ -135,3 +136,4 @@ func GetDefaultWiFiSettings() (res *pb.WiFiSettings) {
} }
return return
} }
*/

View File

@ -1,3 +1,5 @@
// +build linux
package service package service
import ( import (
@ -28,20 +30,34 @@ var (
type server struct {} type server struct {}
func (s *server) DeployWiFiSettings2(ctx context.Context, wset *pb.WiFi2Settings) (wstate *pb.WiFi2State, err error) {
return ServiceState.WifiSvc.DeploySettings(wset)
}
func (s *server) GetWiFiState2(ctx context.Context, empty *pb.Empty) (wstate *pb.WiFi2State, err error) {
st := ServiceState.WifiSvc.GetState()
return &st, nil
}
func (s *server) ListenWiFiStateChanges2(ctx context.Context, empty *pb.Empty) (wstate *pb.WiFi2State, err error) {
panic("implement me")
}
/*
func (s *server) GetDeployedWifiSettings(ctx context.Context, req *pb.Empty) (resp *pb.WiFiSettings, err error) { func (s *server) GetDeployedWifiSettings(ctx context.Context, req *pb.Empty) (resp *pb.WiFiSettings, err error) {
return ServiceState.Wifi.GetDeployWifiSettings() return ServiceState.Wifi.GetDeployWifiSettings()
} }
func (s *server) DeployWifiSettings(ctx context.Context, ws *pb.WiFiSettings) (empty *pb.Empty, err error) { func (s *server) DeployWifiSettings(ctx context.Context, ws *pb.WiFiSettings) (wifiConState *pb.WiFiConnectionState, err error) {
log.Printf("Trying to deploy WiFi settings %v", ws) log.Printf("Trying to deploy WiFi settings %v", ws)
empty = &pb.Empty{}
err = ServiceState.Wifi.DeployWifiSettings(ws) err = ServiceState.Wifi.DeployWifiSettings(ws)
if err != nil { if err != nil {
log.Printf("Error deploying WiFi settings settings %v", err) log.Printf("Error deploying WiFi settings settings %v", err)
} }
return return ServiceState.Wifi.ConState, err
} }
*/
func (s *server) GetDeployedEthernetInterfaceSettings(ctx context.Context, req *pb.StringMessage) (resp *pb.EthernetInterfaceSettings, err error) { func (s *server) GetDeployedEthernetInterfaceSettings(ctx context.Context, req *pb.StringMessage) (resp *pb.EthernetInterfaceSettings, err error) {
if settings,exist := ServiceState.StoredNetworkSetting[req.Msg]; exist && settings.SettingsInUse { if settings,exist := ServiceState.StoredNetworkSetting[req.Msg]; exist && settings.SettingsInUse {

View File

@ -12,7 +12,8 @@ type GlobalServiceState struct {
Led *LedState Led *LedState
HidDevPath map[string]string //stores device path for HID devices HidDevPath map[string]string //stores device path for HID devices
StoredNetworkSetting map[string]*pb.EthernetInterfaceSettings StoredNetworkSetting map[string]*pb.EthernetInterfaceSettings
Wifi *WifiState // Wifi *WifiState
WifiSvc *WiFiService
} }
func InitGlobalServiceState() (err error) { func InitGlobalServiceState() (err error) {
@ -40,7 +41,9 @@ func InitGlobalServiceState() (err error) {
IpAddress4: "172.24.0.1", IpAddress4: "172.24.0.1",
Netmask4: "255.255.255.0", Netmask4: "255.255.255.0",
} }
state.Wifi = NewWifiState(GetDefaultWiFiSettings(), wifi_if_name) // state.Wifi = NewWifiState(GetDefaultWiFiSettings(), wifi_if_name)
state.WifiSvc = NewWifiService()
state.HidDevPath = make(map[string]string) //should be initialized BEFORE UsbGadgetManager uses it state.HidDevPath = make(map[string]string) //should be initialized BEFORE UsbGadgetManager uses it
state.EvMgr = NewEventManager(20) state.EvMgr = NewEventManager(20)
@ -53,7 +56,6 @@ func InitGlobalServiceState() (err error) {
return nil return nil
} }
func (state *GlobalServiceState) StartService() { func (state *GlobalServiceState) StartService() {
state.EvMgr.Start() state.EvMgr.Start()
} }

View File

@ -41,10 +41,10 @@ func InitComponentsWiFi() {
Value int `js:"value"` Value int `js:"value"`
}{Object:O()} }{Object:O()}
mode.Value = val mode.Value = val
switch pb.WiFiSettings_APAuthMode(val) { switch pb.WiFi2AuthMode(val) {
case pb.WiFiSettings_WPA2_PSK: case pb.WiFi2AuthMode_WPA2_PSK:
mode.Label = "WPA2" mode.Label = "WPA2"
case pb.WiFiSettings_OPEN: case pb.WiFi2AuthMode_OPEN:
mode.Label = "Open" mode.Label = "Open"
default: default:
mode.Label = "Unknown" mode.Label = "Unknown"
@ -55,27 +55,30 @@ func InitComponentsWiFi() {
}), }),
hvue.Computed("wifiModes", func(vm *hvue.VM) interface{} { hvue.Computed("wifiModes", func(vm *hvue.VM) interface{} {
modes := js.Global.Get("Array").New() modes := js.Global.Get("Array").New()
for val,_ := range pb.WiFiSettings_Mode_name { for val,_ := range pb.WiFi2WorkingMode_name {
mode := struct { mode := struct {
*js.Object *js.Object
Label string `js:"label"` Label string `js:"label"`
Value int `js:"value"` Value int `js:"value"`
}{Object:O()} }{Object:O()}
mode.Value = val mode.Value = val
switch pb.WiFiSettings_Mode(val) { switch pb.WiFi2WorkingMode(val) {
case pb.WiFiSettings_AP: case pb.WiFi2WorkingMode_AP:
mode.Label = "Access Point (AP)" mode.Label = "Access Point (AP)"
case pb.WiFiSettings_STA: case pb.WiFi2WorkingMode_STA:
mode.Label = "Station (Client)" mode.Label = "Station (Client)"
case pb.WiFiSettings_STA_FAILOVER_AP: case pb.WiFi2WorkingMode_STA_FAILOVER_AP:
mode.Label = "Client with Failover to AP" mode.Label = "Client with Failover to AP"
default: default:
mode.Label = "Unknown" continue
} }
modes.Call("push", mode) modes.Call("push", mode)
} }
return modes return modes
}), }),
hvue.Computed("mode_ap", func(vm *hvue.VM) interface{} {return pb.WiFi2WorkingMode_AP}),
hvue.Computed("mode_sta", func(vm *hvue.VM) interface{} {return pb.WiFi2WorkingMode_STA_FAILOVER_AP}),
hvue.Computed("mode_failover", func(vm *hvue.VM) interface{} {return pb.WiFi2WorkingMode_STA_FAILOVER_AP}),
hvue.Method("reset", hvue.Method("reset",
func(vm *hvue.VM) { func(vm *hvue.VM) {
vm.Get("$store").Call("dispatch", VUEX_ACTION_UPDATE_WIFI_SETTINGS_FROM_DEPLOYED) vm.Get("$store").Call("dispatch", VUEX_ACTION_UPDATE_WIFI_SETTINGS_FROM_DEPLOYED)
@ -145,7 +148,7 @@ const templateWiFi = `
</q-card> </q-card>
</div> </div>
<div class="col-lg-4" v-if="settings.mode != 0"> <div class="col-lg-4" v-if="settings.mode == mode_sta || settings.mode == mode_failover">
<q-card class="full-height"> <q-card class="full-height">
<q-card-title> <q-card-title>
WiFi client settings WiFi client settings
@ -172,7 +175,7 @@ const templateWiFi = `
</q-item-main> </q-item-main>
</q-item> </q-item>
<template v-if="settings.mode == 2"> <template v-if="settings.mode == mode_failover">
<q-item> <q-item>
<q-item-main> <q-item-main>
<q-alert type="warning"> <q-alert type="warning">
@ -185,7 +188,7 @@ const templateWiFi = `
</q-card> </q-card>
</div> </div>
<div class="col-lg-4" v-if="settings.mode != 1"> <div class="col-lg-4" v-if="settings.mode == mode_ap || settings.mode == mode_failover">
<q-card class="full-height"> <q-card class="full-height">
<q-card-title> <q-card-title>
WiFi Access Point settings WiFi Access Point settings
@ -247,6 +250,17 @@ const templateWiFi = `
</q-list> </q-list>
</q-card> </q-card>
</div> </div>
<div class="col-lg-12">
<q-card class="full-height">
<q-card-title>
<q-icon name="alarm" /><q-icon name="alarm" />
</q-card-title>
WiFiState {{ $store.state.wifiConnectionState }}
</q-card>
</div>
</div> </div>
</q-page> </q-page>

View File

@ -18,22 +18,22 @@ var eNoHidEvent = errors.New("No HID event")
type jsGadgetSettings struct { type jsGadgetSettings struct {
*js.Object *js.Object
Enabled bool `js:"Enabled"` Enabled bool `js:"Enabled"`
Vid string `js:"Vid"` Vid string `js:"Vid"`
Pid string `js:"Pid"` Pid string `js:"Pid"`
Manufacturer string `js:"Manufacturer"` Manufacturer string `js:"Manufacturer"`
Product string `js:"Product"` Product string `js:"Product"`
Serial string `js:"Serial"` Serial string `js:"Serial"`
Use_CDC_ECM bool `js:"Use_CDC_ECM"` Use_CDC_ECM bool `js:"Use_CDC_ECM"`
Use_RNDIS bool `js:"Use_RNDIS"` Use_RNDIS bool `js:"Use_RNDIS"`
Use_HID_KEYBOARD bool `js:"Use_HID_KEYBOARD"` Use_HID_KEYBOARD bool `js:"Use_HID_KEYBOARD"`
Use_HID_MOUSE bool `js:"Use_HID_MOUSE"` Use_HID_MOUSE bool `js:"Use_HID_MOUSE"`
Use_HID_RAW bool `js:"Use_HID_RAW"` Use_HID_RAW bool `js:"Use_HID_RAW"`
Use_UMS bool `js:"Use_UMS"` Use_UMS bool `js:"Use_UMS"`
Use_SERIAL bool `js:"Use_SERIAL"` Use_SERIAL bool `js:"Use_SERIAL"`
RndisSettings *VGadgetSettingsEthernet `js:"RndisSettings"` RndisSettings *VGadgetSettingsEthernet `js:"RndisSettings"`
CdcEcmSettings *VGadgetSettingsEthernet `js:"CdcEcmSettings"` CdcEcmSettings *VGadgetSettingsEthernet `js:"CdcEcmSettings"`
UmsSettings *VGadgetSettingsUMS `js:"UmsSettings"` UmsSettings *VGadgetSettingsUMS `js:"UmsSettings"`
} }
type VGadgetSettingsEthernet struct { type VGadgetSettingsEthernet struct {
@ -42,10 +42,9 @@ type VGadgetSettingsEthernet struct {
DevAddr string `js:"DevAddr"` DevAddr string `js:"DevAddr"`
} }
type VGadgetSettingsUMS struct { type VGadgetSettingsUMS struct {
*js.Object *js.Object
Cdrom bool `js:"Cdrom"` Cdrom bool `js:"Cdrom"`
File string `js:"File"` File string `js:"File"`
} }
@ -121,7 +120,6 @@ func (jsGS *jsGadgetSettings) fromGS(gs *pb.GadgetSettings) {
} }
} }
func NewUSBGadgetSettings() *jsGadgetSettings { func NewUSBGadgetSettings() *jsGadgetSettings {
gs := &jsGadgetSettings{ gs := &jsGadgetSettings{
Object: O(), Object: O(),
@ -135,18 +133,17 @@ func NewUSBGadgetSettings() *jsGadgetSettings {
type jsEvent struct { type jsEvent struct {
*js.Object *js.Object
Type int64 `js:"type"` Type int64 `js:"type"`
Values []interface{} Values []interface{}
JSValues *js.Object `js:"values"` JSValues *js.Object `js:"values"`
} }
func NewJsEventFromNative(event *pb.Event) (res *jsEvent) { func NewJsEventFromNative(event *pb.Event) (res *jsEvent) {
res = &jsEvent{Object:O()} res = &jsEvent{Object: O()}
res.JSValues = js.Global.Get("Array").New() res.JSValues = js.Global.Get("Array").New()
res.Type = event.Type res.Type = event.Type
res.Values = make([]interface{}, len(event.Values)) res.Values = make([]interface{}, len(event.Values))
for idx,val := range event.Values { for idx, val := range event.Values {
switch valT := val.Val.(type) { switch valT := val.Val.(type) {
case *pb.EventValue_Tint64: case *pb.EventValue_Tint64:
res.Values[idx] = valT.Tint64 res.Values[idx] = valT.Tint64
@ -170,89 +167,115 @@ func NewJsEventFromNative(event *pb.Event) (res *jsEvent) {
type jsLogEvent struct { type jsLogEvent struct {
*js.Object *js.Object
EvLogSource string `js:"source"` EvLogSource string `js:"source"`
EvLogLevel int `js:"level"` EvLogLevel int `js:"level"`
EvLogMessage string `js:"message"` EvLogMessage string `js:"message"`
EvLogTime string `js:"time"` EvLogTime string `js:"time"`
} }
//HID event //HID event
type jsHidEvent struct { type jsHidEvent struct {
*js.Object *js.Object
EvType int64 `js:"evtype"` EvType int64 `js:"evtype"`
VMId int64 `js:"vmId"` VMId int64 `js:"vmId"`
JobId int64 `js:"jobId"` JobId int64 `js:"jobId"`
HasError bool `js:"hasError"` HasError bool `js:"hasError"`
Result string `js:"result"` Result string `js:"result"`
Error string `js:"error"` Error string `js:"error"`
Message string `js:"message"` Message string `js:"message"`
EvLogTime string `js:"time"` EvLogTime string `js:"time"`
} }
func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) { func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) {
if jsEv.Type != common_web.EVT_LOG || len(jsEv.Values) != 4 { return nil,eNoLogEvent} if jsEv.Type != common_web.EVT_LOG || len(jsEv.Values) != 4 {
res = &jsLogEvent{Object:O()} return nil, eNoLogEvent
}
res = &jsLogEvent{Object: O()}
var ok bool var ok bool
res.EvLogSource,ok = jsEv.Values[0].(string) res.EvLogSource, ok = jsEv.Values[0].(string)
if !ok { return nil,eNoLogEvent } if !ok {
return nil, eNoLogEvent
}
ll,ok := jsEv.Values[1].(int64) ll, ok := jsEv.Values[1].(int64)
if !ok { return nil,eNoLogEvent} if !ok {
return nil, eNoLogEvent
}
res.EvLogLevel = int(ll) res.EvLogLevel = int(ll)
res.EvLogMessage,ok = jsEv.Values[2].(string) res.EvLogMessage, ok = jsEv.Values[2].(string)
if !ok { return nil,eNoLogEvent} if !ok {
return nil, eNoLogEvent
}
res.EvLogTime,ok = jsEv.Values[3].(string) res.EvLogTime, ok = jsEv.Values[3].(string)
if !ok { return nil,eNoLogEvent} if !ok {
return nil, eNoLogEvent
}
return res,nil return res, nil
} }
func (jsEv *jsEvent) toHidEvent() (res *jsHidEvent, err error) { func (jsEv *jsEvent) toHidEvent() (res *jsHidEvent, err error) {
if jsEv.Type != common_web.EVT_HID || len(jsEv.Values) != 8 { return nil,eNoHidEvent} if jsEv.Type != common_web.EVT_HID || len(jsEv.Values) != 8 {
res = &jsHidEvent{Object:O()} return nil, eNoHidEvent
}
res = &jsHidEvent{Object: O()}
var ok bool var ok bool
res.EvType,ok = jsEv.Values[0].(int64) res.EvType, ok = jsEv.Values[0].(int64)
if !ok { return nil,eNoHidEvent } if !ok {
return nil, eNoHidEvent
}
res.VMId,ok = jsEv.Values[1].(int64) res.VMId, ok = jsEv.Values[1].(int64)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.JobId,ok = jsEv.Values[2].(int64) res.JobId, ok = jsEv.Values[2].(int64)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.HasError,ok = jsEv.Values[3].(bool) res.HasError, ok = jsEv.Values[3].(bool)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.Result,ok = jsEv.Values[4].(string) res.Result, ok = jsEv.Values[4].(string)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.Error,ok = jsEv.Values[5].(string) res.Error, ok = jsEv.Values[5].(string)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.Message,ok = jsEv.Values[6].(string) res.Message, ok = jsEv.Values[6].(string)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
res.EvLogTime,ok = jsEv.Values[7].(string) res.EvLogTime, ok = jsEv.Values[7].(string)
if !ok { return nil,eNoHidEvent} if !ok {
return nil, eNoHidEvent
}
return res, nil
return res,nil
} }
/* HIDJobList */ /* HIDJobList */
type jsHidJobState struct { type jsHidJobState struct {
*js.Object *js.Object
Id int64 `js:"id"` Id int64 `js:"id"`
VmId int64 `js:"vmId"` VmId int64 `js:"vmId"`
HasFailed bool `js:"hasFailed"` HasFailed bool `js:"hasFailed"`
HasSucceeded bool `js:"hasSucceeded"` HasSucceeded bool `js:"hasSucceeded"`
LastMessage string `js:"lastMessage"` LastMessage string `js:"lastMessage"`
TextResult string `js:"textResult"` TextResult string `js:"textResult"`
// TextError string `js:"textError"` // TextError string `js:"textError"`
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
ScriptSource string `js:"textSource"` ScriptSource string `js:"textSource"`
} }
@ -263,7 +286,7 @@ type jsHidJobStateList struct {
} }
func NewHIDJobStateList() *jsHidJobStateList { func NewHIDJobStateList() *jsHidJobStateList {
jl := &jsHidJobStateList{Object:O()} jl := &jsHidJobStateList{Object: O()}
jl.Jobs = O() jl.Jobs = O()
/* /*
@ -309,10 +332,10 @@ func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded
//Check if job exists, update existing one if already present //Check if job exists, update existing one if already present
var j *jsHidJobState var j *jsHidJobState
if res := jl.Jobs.Get(key);res == js.Undefined { if res := jl.Jobs.Get(key); res == js.Undefined {
j = &jsHidJobState{Object:O()} j = &jsHidJobState{Object: O()}
} else { } else {
j = &jsHidJobState{Object:res} j = &jsHidJobState{Object: res}
} }
//Create job object //Create job object
@ -324,7 +347,9 @@ func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded
j.LastMessage = message j.LastMessage = message
j.TextResult = textResult j.TextResult = textResult
j.LastUpdateTime = lastUpdateTime j.LastUpdateTime = lastUpdateTime
if len(scriptSource) > 0 {j.ScriptSource = scriptSource} if len(scriptSource) > 0 {
j.ScriptSource = scriptSource
}
//jl.Jobs.Set(strconv.Itoa(int(j.Id)), j) //jobs["j.ID"]=j <--Property addition/update can't be detected by Vue.js, see https://vuejs.org/v2/guide/list.html#Object-Change-Detection-Caveats //jl.Jobs.Set(strconv.Itoa(int(j.Id)), j) //jobs["j.ID"]=j <--Property addition/update can't be detected by Vue.js, see https://vuejs.org/v2/guide/list.html#Object-Change-Detection-Caveats
hvue.Set(jl.Jobs, key, j) hvue.Set(jl.Jobs, key, j)
} }
@ -335,34 +360,85 @@ func (jl *jsHidJobStateList) DeleteEntry(id int64) {
} }
/* WiFi settings */ /* WiFi settings */
/*
type WiFiSettings struct { type jsWiFiConnectionState struct {
Disabled bool *js.Object
Reg string Mode int `js:"mode"`
Mode WiFiSettings_Mode Reg string `js:"reg"`
AuthMode WiFiSettings_APAuthMode Channel uint32 `js:"channel"`
ApChannel uint32 SSID string `js:"SSID"`
BssCfgAP *BSSCfg Hidden bool `js:"hidden"`
BssCfgClient *BSSCfg Nexmon bool `js:"nexmon"`
ApHideSsid bool Disabled bool `js:"disabled"`
DisableNexmon bool }
func (target *jsWiFiConnectionState) fromGo(src *pb.WiFi2State) {
target.Mode = int(src.WorkingMode)
target.Reg = src.Regulatory
target.Channel = src.Channel
target.SSID = src.Bss.SSID
target.Hidden = src.HideSsid
target.Nexmon = src.Nexmon
target.Disabled = src.Disabled
return
}
func (src *jsWiFiConnectionState) toGo() (target *pb.WiFi2State) {
target = &pb.WiFi2State{
Regulatory: src.Reg,
Channel: src.Channel,
Bss: &pb.WiFi2BSSCfg{
SSID: src.SSID,
PSK: "",
},
HideSsid: src.Hidden,
Nexmon: src.Nexmon,
WorkingMode: pb.WiFi2WorkingMode(src.Mode),
Disabled: src.Disabled,
Name: "",
}
return
}
func (src jsWiFiConnectionState) ModeString() (strMode string) {
switch src.Mode {
case 1:
return "Access Point"
case 2:
return "Station"
default:
return "UNKNOWN"
}
}
func NewWiFiConnectionState() *jsWiFiConnectionState {
res := &jsWiFiConnectionState{Object: O()}
res.SSID = "Unknown SSID"
res.Channel = 0
res.Mode = 0
res.Hidden = false
res.Reg = "Unknown reg"
res.Nexmon = false
return res
} }
*/
type jsWiFiSettings struct { type jsWiFiSettings struct {
*js.Object *js.Object
Disabled bool `js:"disabled"` Disabled bool `js:"disabled"`
Reg string `js:"reg"` Reg string `js:"reg"`
Mode int `js:"mode"` //AP, STA, Failover Mode int `js:"mode"` //AP, STA, Failover
AuthMode int `js:"authMode"` //WPA2_PSK, OPEN AuthMode int `js:"authMode"` //WPA2_PSK, OPEN
Channel int `js:"channel"` Channel int `js:"channel"`
// next two fields are interpreted as BssCfgAp or BssCfgClient, depending on Mode // next two fields are interpreted as BssCfgAp or BssCfgClient, depending on Mode
AP_SSID string `js:"apSsid"` AP_SSID string `js:"apSsid"`
AP_PSK string `js:"apPsk"` AP_PSK string `js:"apPsk"`
STA_SSID string `js:"staSsid"` STA_SSID string `js:"staSsid"`
STA_PSK string `js:"staPsk"` STA_PSK string `js:"staPsk"`
HideSsid bool `js:"hideSsid"` HideSsid bool `js:"hideSsid"`
DisableNexmon bool `js:"disableNexmon"` DisableNexmon bool `js:"disableNexmon"`
} }
func (target *jsWiFiSettings) fromGo(src *pb.WiFiSettings) { func (target *jsWiFiSettings) fromGo(src *pb.WiFiSettings) {
@ -397,22 +473,47 @@ func (src *jsWiFiSettings) toGo() (target *pb.WiFiSettings) {
// assure undefined strings end up as empty strings // assure undefined strings end up as empty strings
target = &pb.WiFiSettings{ target = &pb.WiFiSettings{
Disabled: src.Disabled, Disabled: src.Disabled,
Reg: src.Reg, Reg: src.Reg,
Mode: pb.WiFiSettings_Mode(src.Mode), Mode: pb.WiFiSettings_Mode(src.Mode),
AuthMode: pb.WiFiSettings_APAuthMode(src.AuthMode), AuthMode: pb.WiFiSettings_APAuthMode(src.AuthMode),
DisableNexmon: src.DisableNexmon, DisableNexmon: src.DisableNexmon,
ApChannel: uint32(src.Channel), ApChannel: uint32(src.Channel),
ApHideSsid: src.HideSsid, ApHideSsid: src.HideSsid,
BssCfgClient: &pb.BSSCfg{ BssCfgClient: &pb.BSSCfg{
SSID: src.STA_SSID, SSID: src.STA_SSID,
PSK: src.STA_PSK, PSK: src.STA_PSK,
}, },
BssCfgAP: &pb.BSSCfg{ BssCfgAP: &pb.BSSCfg{
SSID: src.AP_SSID, SSID: src.AP_SSID,
PSK: src.AP_PSK, PSK: src.AP_PSK,
}, },
}
return target
}
func (src *jsWiFiSettings) toGo2() (target *pb.WiFi2Settings) {
// assure undefined strings end up as empty strings
target = &pb.WiFi2Settings{
Name: "mainconfig",
Disabled: src.Disabled,
Regulatory: src.Reg,
WorkingMode: pb.WiFi2WorkingMode(src.Mode),
AuthMode: pb.WiFi2AuthMode(src.AuthMode),
Nexmon: !src.DisableNexmon,
Channel: uint32(src.Channel),
HideSsid: src.HideSsid,
Ap_BSS: &pb.WiFi2BSSCfg{
SSID: src.AP_SSID,
PSK: src.AP_PSK,
},
Client_BSSList: []*pb.WiFi2BSSCfg{
&pb.WiFi2BSSCfg{
SSID: src.STA_SSID,
PSK: src.STA_PSK,
},
},
} }
return target return target
} }
@ -427,7 +528,7 @@ func (isl *jsEthernetSettingsList) fromGo(src *pb.DeployedEthernetInterfaceSetti
//Options array (converted from map) //Options array (converted from map)
isl.Interfaces = js.Global.Get("Array").New() isl.Interfaces = js.Global.Get("Array").New()
for _, ifSets := range src.List { for _, ifSets := range src.List {
jsIfSets := &jsEthernetInterfaceSettings{Object:O()} jsIfSets := &jsEthernetInterfaceSettings{Object: O()}
jsIfSets.fromGo(ifSets) jsIfSets.fromGo(ifSets)
isl.Interfaces.Call("push", jsIfSets) isl.Interfaces.Call("push", jsIfSets)
} }
@ -436,13 +537,13 @@ func (isl *jsEthernetSettingsList) fromGo(src *pb.DeployedEthernetInterfaceSetti
type jsEthernetInterfaceSettings struct { type jsEthernetInterfaceSettings struct {
*js.Object *js.Object
Name string `js:"name"` Name string `js:"name"`
Mode int `js:"mode"` Mode int `js:"mode"`
IpAddress4 string `js:"ipAddress4"` IpAddress4 string `js:"ipAddress4"`
Netmask4 string `js:"netmask4"` Netmask4 string `js:"netmask4"`
Enabled bool `js:"enabled"` Enabled bool `js:"enabled"`
DhcpServerSettings *jsDHCPServerSettings `js:"dhcpServerSettings"` DhcpServerSettings *jsDHCPServerSettings `js:"dhcpServerSettings"`
SettingsInUse bool `js:"settingsInUse"` SettingsInUse bool `js:"settingsInUse"`
} }
func (target *jsEthernetInterfaceSettings) fromGo(src *pb.EthernetInterfaceSettings) { func (target *jsEthernetInterfaceSettings) fromGo(src *pb.EthernetInterfaceSettings) {
@ -454,18 +555,18 @@ func (target *jsEthernetInterfaceSettings) fromGo(src *pb.EthernetInterfaceSetti
target.SettingsInUse = src.SettingsInUse target.SettingsInUse = src.SettingsInUse
if src.DhcpServerSettings != nil { if src.DhcpServerSettings != nil {
target.DhcpServerSettings = &jsDHCPServerSettings{Object:O()} target.DhcpServerSettings = &jsDHCPServerSettings{Object: O()}
target.DhcpServerSettings.fromGo(src.DhcpServerSettings) target.DhcpServerSettings.fromGo(src.DhcpServerSettings)
} }
} }
func (src *jsEthernetInterfaceSettings) toGo() (target *pb.EthernetInterfaceSettings) { func (src *jsEthernetInterfaceSettings) toGo() (target *pb.EthernetInterfaceSettings) {
target = &pb.EthernetInterfaceSettings{ target = &pb.EthernetInterfaceSettings{
Name: src.Name, Name: src.Name,
Mode: pb.EthernetInterfaceSettings_Mode(src.Mode), Mode: pb.EthernetInterfaceSettings_Mode(src.Mode),
IpAddress4: src.IpAddress4, IpAddress4: src.IpAddress4,
Netmask4: src.Netmask4, Netmask4: src.Netmask4,
Enabled: src.Enabled, Enabled: src.Enabled,
SettingsInUse: src.SettingsInUse, SettingsInUse: src.SettingsInUse,
} }
@ -480,7 +581,7 @@ func (src *jsEthernetInterfaceSettings) toGo() (target *pb.EthernetInterfaceSett
func (iface *jsEthernetInterfaceSettings) CreateDhcpSettingsForInterface() { func (iface *jsEthernetInterfaceSettings) CreateDhcpSettingsForInterface() {
//create dhcp server settings //create dhcp server settings
settings := &jsDHCPServerSettings{Object:O()} settings := &jsDHCPServerSettings{Object: O()}
settings.ListenInterface = iface.Name settings.ListenInterface = iface.Name
settings.ListenPort = 0 // 0 means DNS is disabled settings.ListenPort = 0 // 0 means DNS is disabled
settings.LeaseFile = common_web.NameLeaseFileDHCPSrv(iface.Name) settings.LeaseFile = common_web.NameLeaseFileDHCPSrv(iface.Name)
@ -489,38 +590,37 @@ func (iface *jsEthernetInterfaceSettings) CreateDhcpSettingsForInterface() {
settings.CallbackScript = "" settings.CallbackScript = ""
//ToDo: add missing fields //ToDo: add missing fields
//Ranges array //Ranges array
settings.Ranges = js.Global.Get("Array").New() settings.Ranges = js.Global.Get("Array").New()
settings.Options = js.Global.Get("Array").New() settings.Options = js.Global.Get("Array").New()
settings.StaticHosts = js.Global.Get("Array").New() settings.StaticHosts = js.Global.Get("Array").New()
//add empty option for router and DNS to prevent netmask from promoting itself via DHCP //add empty option for router and DNS to prevent netmask from promoting itself via DHCP
optNoRouter := &jsDHCPServerOption{Object:O()} optNoRouter := &jsDHCPServerOption{Object: O()}
optNoRouter.Option = 3 optNoRouter.Option = 3
optNoRouter.Value = "" optNoRouter.Value = ""
settings.AddOption(optNoRouter) settings.AddOption(optNoRouter)
optNoDNS := &jsDHCPServerOption{Object:O()} optNoDNS := &jsDHCPServerOption{Object: O()}
optNoDNS.Option = 6 optNoDNS.Option = 6
optNoDNS.Value = "" optNoDNS.Value = ""
settings.AddOption(optNoDNS) settings.AddOption(optNoDNS)
//iface.DhcpServerSettings = settings //iface.DhcpServerSettings = settings
// Update the field with Vue in order to have proper setters in place // Update the field with Vue in order to have proper setters in place
hvue.Set(iface,"dhcpServerSettings", settings) hvue.Set(iface, "dhcpServerSettings", settings)
} }
type jsDHCPServerSettings struct { type jsDHCPServerSettings struct {
*js.Object *js.Object
ListenPort int `js:"listenPort"` ListenPort int `js:"listenPort"`
ListenInterface string `js:"listenInterface"` ListenInterface string `js:"listenInterface"`
LeaseFile string `js:"leaseFile"` LeaseFile string `js:"leaseFile"`
NotAuthoritative bool `js:"nonAuthoritative"` NotAuthoritative bool `js:"nonAuthoritative"`
DoNotBindInterface bool `js:"doNotBindInterface"` DoNotBindInterface bool `js:"doNotBindInterface"`
CallbackScript string `js:"callbackScript"` CallbackScript string `js:"callbackScript"`
Ranges *js.Object `js:"ranges"`//[]*DHCPServerRange Ranges *js.Object `js:"ranges"` //[]*DHCPServerRange
Options *js.Object `js:"options"` //map[uint32]string Options *js.Object `js:"options"` //map[uint32]string
StaticHosts *js.Object `js:"staticHosts"`//[]*DHCPServerStaticHost StaticHosts *js.Object `js:"staticHosts"` //[]*DHCPServerStaticHost
} }
func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) { func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) {
@ -535,13 +635,12 @@ func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) {
println("jsRanges", src.Ranges) println("jsRanges", src.Ranges)
//Check if ranges are present //Check if ranges are present
if src.Ranges != js.Undefined { if src.Ranges != js.Undefined {
if numRanges := src.Ranges.Length(); numRanges > 0 { if numRanges := src.Ranges.Length(); numRanges > 0 {
target.Ranges = make([]*pb.DHCPServerRange, numRanges) target.Ranges = make([]*pb.DHCPServerRange, numRanges)
//iterate over JS array //iterate over JS array
for i:= 0; i < numRanges; i++ { for i := 0; i < numRanges; i++ {
jsRange := &jsDHCPServerRange{Object: src.Ranges.Index(i)} jsRange := &jsDHCPServerRange{Object: src.Ranges.Index(i)}
target.Ranges[i] = &pb.DHCPServerRange{} target.Ranges[i] = &pb.DHCPServerRange{}
target.Ranges[i].RangeUpper = jsRange.RangeUpper target.Ranges[i].RangeUpper = jsRange.RangeUpper
@ -556,7 +655,7 @@ func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) {
if numOptions := src.Options.Length(); numOptions > 0 { if numOptions := src.Options.Length(); numOptions > 0 {
target.Options = make(map[uint32]string) target.Options = make(map[uint32]string)
//iterate over JS array //iterate over JS array
for i:= 0; i < numOptions; i++ { for i := 0; i < numOptions; i++ {
jsOption := &jsDHCPServerOption{Object: src.Options.Index(i)} jsOption := &jsDHCPServerOption{Object: src.Options.Index(i)}
target.Options[uint32(jsOption.Option)] = jsOption.Value target.Options[uint32(jsOption.Option)] = jsOption.Value
} }
@ -568,7 +667,7 @@ func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) {
if numStaticHosts := src.StaticHosts.Length(); numStaticHosts > 0 { if numStaticHosts := src.StaticHosts.Length(); numStaticHosts > 0 {
target.StaticHosts = make([]*pb.DHCPServerStaticHost, numStaticHosts) target.StaticHosts = make([]*pb.DHCPServerStaticHost, numStaticHosts)
//iterate over JS array //iterate over JS array
for i:= 0; i < numStaticHosts; i++ { for i := 0; i < numStaticHosts; i++ {
jsStaticHost := &jsDHCPServerStaticHost{Object: src.StaticHosts.Index(i)} jsStaticHost := &jsDHCPServerStaticHost{Object: src.StaticHosts.Index(i)}
target.StaticHosts[i] = &pb.DHCPServerStaticHost{} target.StaticHosts[i] = &pb.DHCPServerStaticHost{}
target.StaticHosts[i].Mac = jsStaticHost.Mac target.StaticHosts[i].Mac = jsStaticHost.Mac
@ -579,7 +678,6 @@ func (src *jsDHCPServerSettings) toGo() (target *pb.DHCPServerSettings) {
return target return target
} }
func (settings *jsDHCPServerSettings) AddRange(dhcpRange *jsDHCPServerRange) { func (settings *jsDHCPServerSettings) AddRange(dhcpRange *jsDHCPServerRange) {
if settings.Ranges == js.Undefined { if settings.Ranges == js.Undefined {
settings.Ranges = js.Global.Get("Array").New() settings.Ranges = js.Global.Get("Array").New()
@ -588,7 +686,9 @@ func (settings *jsDHCPServerSettings) AddRange(dhcpRange *jsDHCPServerRange) {
} }
func (settings *jsDHCPServerSettings) RemoveRange(dhcpRange *jsDHCPServerRange) { func (settings *jsDHCPServerSettings) RemoveRange(dhcpRange *jsDHCPServerRange) {
if settings.Ranges == js.Undefined { return } if settings.Ranges == js.Undefined {
return
}
//Check if in array //Check if in array
if idx := settings.Ranges.Call("indexOf", dhcpRange).Int(); idx > -1 { if idx := settings.Ranges.Call("indexOf", dhcpRange).Int(); idx > -1 {
@ -596,7 +696,6 @@ func (settings *jsDHCPServerSettings) RemoveRange(dhcpRange *jsDHCPServerRange)
} }
} }
func (settings *jsDHCPServerSettings) AddOption(dhcpOption *jsDHCPServerOption) { func (settings *jsDHCPServerSettings) AddOption(dhcpOption *jsDHCPServerOption) {
if settings.Options == js.Undefined { if settings.Options == js.Undefined {
settings.Options = js.Global.Get("Array").New() settings.Options = js.Global.Get("Array").New()
@ -604,9 +703,10 @@ func (settings *jsDHCPServerSettings) AddOption(dhcpOption *jsDHCPServerOption)
settings.Options.Call("push", dhcpOption) settings.Options.Call("push", dhcpOption)
} }
func (settings *jsDHCPServerSettings) RemoveOption(dhcpOption *jsDHCPServerOption) { func (settings *jsDHCPServerSettings) RemoveOption(dhcpOption *jsDHCPServerOption) {
if settings.Options == js.Undefined { return } if settings.Options == js.Undefined {
return
}
//Check if in array //Check if in array
if idx := settings.Options.Call("indexOf", dhcpOption).Int(); idx > -1 { if idx := settings.Options.Call("indexOf", dhcpOption).Int(); idx > -1 {
@ -621,9 +721,10 @@ func (settings *jsDHCPServerSettings) AddStaticHost(dhcpStaticHost *jsDHCPServer
settings.StaticHosts.Call("push", dhcpStaticHost) settings.StaticHosts.Call("push", dhcpStaticHost)
} }
func (settings *jsDHCPServerSettings) RemoveStaticHost(dhcpStaticHost *jsDHCPServerStaticHost) { func (settings *jsDHCPServerSettings) RemoveStaticHost(dhcpStaticHost *jsDHCPServerStaticHost) {
if settings.StaticHosts == js.Undefined { return } if settings.StaticHosts == js.Undefined {
return
}
//Check if in array //Check if in array
if idx := settings.StaticHosts.Call("indexOf", dhcpStaticHost).Int(); idx > -1 { if idx := settings.StaticHosts.Call("indexOf", dhcpStaticHost).Int(); idx > -1 {
@ -631,7 +732,6 @@ func (settings *jsDHCPServerSettings) RemoveStaticHost(dhcpStaticHost *jsDHCPSer
} }
} }
func (target *jsDHCPServerSettings) fromGo(src *pb.DHCPServerSettings) { func (target *jsDHCPServerSettings) fromGo(src *pb.DHCPServerSettings) {
target.ListenPort = int(src.ListenPort) target.ListenPort = int(src.ListenPort)
target.ListenInterface = src.ListenInterface target.ListenInterface = src.ListenInterface
@ -641,25 +741,25 @@ func (target *jsDHCPServerSettings) fromGo(src *pb.DHCPServerSettings) {
target.CallbackScript = src.CallbackScript target.CallbackScript = src.CallbackScript
//Ranges array //Ranges array
target.Ranges = js.Global.Get("Array").New( ) target.Ranges = js.Global.Get("Array").New()
for _,dhcpRange := range src.Ranges { for _, dhcpRange := range src.Ranges {
jsRange := &jsDHCPServerRange{Object:O()} jsRange := &jsDHCPServerRange{Object: O()}
jsRange.fromGo(dhcpRange) jsRange.fromGo(dhcpRange)
target.Ranges.Call("push", jsRange) target.Ranges.Call("push", jsRange)
} }
//Options array (converted from map) //Options array (converted from map)
target.Options = js.Global.Get("Array").New( ) target.Options = js.Global.Get("Array").New()
for optId, optVal := range src.Options { for optId, optVal := range src.Options {
jsOption := &jsDHCPServerOption{Object:O()} jsOption := &jsDHCPServerOption{Object: O()}
jsOption.fromGo(optId, optVal) jsOption.fromGo(optId, optVal)
target.Options.Call("push", jsOption) target.Options.Call("push", jsOption)
} }
//StaticHosts array //StaticHosts array
target.StaticHosts = js.Global.Get("Array").New( ) target.StaticHosts = js.Global.Get("Array").New()
for _,staticHost := range src.StaticHosts { for _, staticHost := range src.StaticHosts {
jsStaticHost := &jsDHCPServerStaticHost{Object:O()} jsStaticHost := &jsDHCPServerStaticHost{Object: O()}
jsStaticHost.fromGo(staticHost) jsStaticHost.fromGo(staticHost)
target.Ranges.Call("push", jsStaticHost) target.Ranges.Call("push", jsStaticHost)
} }
@ -678,11 +778,10 @@ func (target *jsDHCPServerRange) fromGo(src *pb.DHCPServerRange) {
target.LeaseTime = src.LeaseTime target.LeaseTime = src.LeaseTime
} }
type jsDHCPServerOption struct { type jsDHCPServerOption struct {
*js.Object *js.Object
Option int `js:"option"` Option int `js:"option"`
Value string `js:"value"` Value string `js:"value"`
} }
func (target *jsDHCPServerOption) fromGo(srcID uint32, srcVal string) { func (target *jsDHCPServerOption) fromGo(srcID uint32, srcVal string) {
@ -693,7 +792,7 @@ func (target *jsDHCPServerOption) fromGo(srcID uint32, srcVal string) {
type jsDHCPServerStaticHost struct { type jsDHCPServerStaticHost struct {
*js.Object *js.Object
Mac string `js:"mac"` Mac string `js:"mac"`
Ip string `js:"ip"` Ip string `js:"ip"`
} }
func (target *jsDHCPServerStaticHost) fromGo(src *pb.DHCPServerStaticHost) { func (target *jsDHCPServerStaticHost) fromGo(src *pb.DHCPServerStaticHost) {
@ -704,9 +803,9 @@ func (target *jsDHCPServerStaticHost) fromGo(src *pb.DHCPServerStaticHost) {
/* EVENT LOGGER */ /* EVENT LOGGER */
type jsEventReceiver struct { type jsEventReceiver struct {
*js.Object *js.Object
LogArray *js.Object `js:"logArray"` LogArray *js.Object `js:"logArray"`
HidEventArray *js.Object `js:"eventHidArray"` HidEventArray *js.Object `js:"eventHidArray"`
MaxEntries int `js:"maxEntries"` MaxEntries int `js:"maxEntries"`
JobList *jsHidJobStateList `js:"jobList"` //Needs to be exposed to JS in order to use JobList.UpdateEntry() from this JS object JobList *jsHidJobStateList `js:"jobList"` //Needs to be exposed to JS in order to use JobList.UpdateEntry() from this JS object
} }
@ -723,15 +822,15 @@ func NewEventReceiver(maxEntries int, jobList *jsHidJobStateList) *jsEventReceiv
return eventReceiver return eventReceiver
} }
func (data *jsEventReceiver) handleHidEvent(hEv *jsHidEvent ) { func (data *jsEventReceiver) handleHidEvent(hEv *jsHidEvent) {
println("Received HID EVENT", hEv) println("Received HID EVENT", hEv)
switch hEv.EvType { switch hEv.EvType {
case common_web.HidEventType_JOB_STARTED: case common_web.HidEventType_JOB_STARTED:
// Note: the JOB_STARTED event carries the script source in the message field, (no need to re-request the job // Note: the JOB_STARTED event carries the script source in the message field, (no need to re-request the job
// state in order to retrieve the source code of the job, when adding it to the job state list) // state in order to retrieve the source code of the job, when adding it to the job state list)
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, "Script started", "", hEv.EvLogTime,hEv.Message) data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, "Script started", "", hEv.EvLogTime, hEv.Message)
case common_web.HidEventType_JOB_FAILED: case common_web.HidEventType_JOB_FAILED:
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, hEv.Message, hEv.Error, hEv.EvLogTime,"") data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, hEv.Message, hEv.Error, hEv.EvLogTime, "")
notification := &QuasarNotification{Object: O()} notification := &QuasarNotification{Object: O()}
notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " failed" notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " failed"
@ -741,7 +840,7 @@ func (data *jsEventReceiver) handleHidEvent(hEv *jsHidEvent ) {
notification.Timeout = 5000 notification.Timeout = 5000
QuasarNotify(notification) QuasarNotify(notification)
case common_web.HidEventType_JOB_SUCCEEDED: case common_web.HidEventType_JOB_SUCCEEDED:
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, true, hEv.Message, hEv.Result, hEv.EvLogTime,"") data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, true, hEv.Message, hEv.Result, hEv.EvLogTime, "")
notification := &QuasarNotification{Object: O()} notification := &QuasarNotification{Object: O()}
notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " succeeded" notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " succeeded"
@ -752,29 +851,28 @@ func (data *jsEventReceiver) handleHidEvent(hEv *jsHidEvent ) {
QuasarNotify(notification) QuasarNotify(notification)
case common_web.HidEventType_JOB_CANCELLED: case common_web.HidEventType_JOB_CANCELLED:
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, true, false, hEv.Message, hEv.Message, hEv.EvLogTime,"") data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, true, false, hEv.Message, hEv.Message, hEv.EvLogTime, "")
default: default:
println("unhandled hid event " + common_web.EventType_name[hEv.EvType], hEv) println("unhandled hid event "+common_web.EventType_name[hEv.EvType], hEv)
} }
} }
/* This method gets internalized and therefor the mutex won't be accessible*/ /* This method gets internalized and therefor the mutex won't be accessible*/
func (data *jsEventReceiver) HandleEvent(ev *pb.Event ) { func (data *jsEventReceiver) HandleEvent(ev *pb.Event) {
go func() { go func() {
jsEv := NewJsEventFromNative(ev) jsEv := NewJsEventFromNative(ev)
switch jsEv.Type { switch jsEv.Type {
//if LOG event add to logArray //if LOG event add to logArray
case common_web.EVT_LOG: case common_web.EVT_LOG:
if logEv,err := jsEv.toLogEvent(); err == nil { if logEv, err := jsEv.toLogEvent(); err == nil {
data.LogArray.Call("push", logEv) data.LogArray.Call("push", logEv)
} else { } else {
println("couldn't convert to LogEvent: ", jsEv) println("couldn't convert to LogEvent: ", jsEv)
} }
//if HID event add to eventHidArray //if HID event add to eventHidArray
case common_web.EVT_HID: case common_web.EVT_HID:
if hidEv,err := jsEv.toHidEvent(); err == nil { if hidEv, err := jsEv.toHidEvent(); err == nil {
data.HidEventArray.Call("push", hidEv) data.HidEventArray.Call("push", hidEv)
//handle event //handle event

View File

@ -63,6 +63,7 @@ type GlobalState struct {
FailedConnectionAttempts int `js:"failedConnectionAttempts"` FailedConnectionAttempts int `js:"failedConnectionAttempts"`
InterfaceSettings *jsEthernetSettingsList `js:"InterfaceSettings"` InterfaceSettings *jsEthernetSettingsList `js:"InterfaceSettings"`
WiFiSettings *jsWiFiSettings `js:"wifiSettings"` WiFiSettings *jsWiFiSettings `js:"wifiSettings"`
WiFiState *jsWiFiConnectionState `js:"wifiConnectionState"`
} }
func createGlobalStateStruct() GlobalState { func createGlobalStateStruct() GlobalState {
@ -89,7 +90,7 @@ func createGlobalStateStruct() GlobalState {
panic("Couldn't retrieve WiFi settings") panic("Couldn't retrieve WiFi settings")
} }
state.WiFiSettings = wifiSettings state.WiFiSettings = wifiSettings
state.WiFiState = NewWiFiConnectionState()
return state return state
} }
@ -128,16 +129,32 @@ func actionUpdateWifiSettingsFromDeployed(store *mvuex.Store, context *mvuex.Act
return return
} }
/*
func actionDeployWifiSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, settings *jsWiFiSettings) { func actionDeployWifiSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, settings *jsWiFiSettings) {
go func() { go func() {
println("Vuex dispatch deploy WiFi settings") println("Vuex dispatch deploy WiFi settings")
// convert to Go type // convert to Go type
goSettings := settings.toGo() goSettings := settings.toGo()
err := RpcClient.DeployeWifiSettings(time.Second*3, goSettings) wstate, err := RpcClient.DeployWifiSettings(time.Second*20, goSettings)
if err != nil { if err != nil {
Alert(err) QuasarNotifyError("Error deploying WiFi Settings", err.Error(), QUASAR_NOTIFICATION_POSITION_BOTTOM)
} }
state.WiFiState.fromGo(wstate)
}()
}
*/
func actionDeployWifiSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, settings *jsWiFiSettings) {
go func() {
println("Vuex dispatch deploy WiFi settings")
// convert to Go type
goSettings := settings.toGo2()
wstate, err := RpcClient.DeployWifiSettings2(time.Second*20, goSettings)
if err != nil {
QuasarNotifyError("Error deploying WiFi Settings", err.Error(), QUASAR_NOTIFICATION_POSITION_BOTTOM)
}
state.WiFiState.fromGo(wstate)
}() }()
} }
@ -251,7 +268,7 @@ func initMVuex() *mvuex.Store {
}), }),
mvuex.Getter("hidjobsRunning", func(state *GlobalState) interface{} { mvuex.Getter("hidjobsRunning", func(state *GlobalState) interface{} {
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool { filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
return !(job.HasSucceeded || job.HasFailed) return !(job.HasSucceeded || job.HasFailed)
@ -260,7 +277,7 @@ func initMVuex() *mvuex.Store {
}), }),
mvuex.Getter("hidjobsFailed", func(state *GlobalState) interface{} { mvuex.Getter("hidjobsFailed", func(state *GlobalState) interface{} {
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool { filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
return job.HasFailed return job.HasFailed
@ -269,7 +286,7 @@ func initMVuex() *mvuex.Store {
}), }),
mvuex.Getter("hidjobsSucceeded", func(state *GlobalState) interface{} { mvuex.Getter("hidjobsSucceeded", func(state *GlobalState) interface{} {
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool { filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
return job.HasSucceeded return job.HasSucceeded

View File

@ -39,15 +39,24 @@ func (rpc *Rpc) DeployedEthernetInterfaceSettings(timeout time.Duration, setting
return return
} }
func (rpc *Rpc) DeployeWifiSettings(timeout time.Duration, settings *pb.WiFiSettings) (err error) { func (rpc *Rpc) DeployWifiSettings(timeout time.Duration, settings *pb.WiFiSettings) (state *pb.WiFiConnectionState, err error) {
// ToDo: The RPC call has to return an error in case deployment fails // ToDo: The RPC call has to return an error in case deployment fails
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel() defer cancel()
_, err = rpc.Client.DeployWifiSettings(ctx, settings) state, err = rpc.Client.DeployWifiSettings(ctx, settings)
return return
} }
func (rpc *Rpc) DeployWifiSettings2(timeout time.Duration, settings *pb.WiFi2Settings) (state *pb.WiFi2State, err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
state, err = rpc.Client.DeployWiFiSettings2(ctx, settings)
return
}
func (rpc *Rpc) GetDeployedWiFiSettings(timeout time.Duration) (settingsList *jsWiFiSettings, err error) { func (rpc *Rpc) GetDeployedWiFiSettings(timeout time.Duration) (settingsList *jsWiFiSettings, err error) {
/* /*
//ToDo: Only placeholder, replace with real "get deployed" RPC //ToDo: Only placeholder, replace with real "get deployed" RPC