Factor access point and switch out into their own 'network' package.

This commit is contained in:
Patrick Fairbank
2018-10-06 13:28:16 -07:00
parent 465034fbb6
commit 45be632b52
8 changed files with 51 additions and 44 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/Team254/cheesy-arena/game"
"github.com/Team254/cheesy-arena/led"
"github.com/Team254/cheesy-arena/model"
"github.com/Team254/cheesy-arena/network"
"github.com/Team254/cheesy-arena/partner"
"github.com/Team254/cheesy-arena/plc"
"github.com/Team254/cheesy-arena/vaultled"
@@ -44,8 +45,8 @@ const (
type Arena struct {
Database *model.Database
EventSettings *model.EventSettings
accessPoint *AccessPoint
networkSwitch *NetworkSwitch
accessPoint *network.AccessPoint
networkSwitch *network.Switch
Plc plc.Plc
TbaClient *partner.TbaClient
AllianceStations map[string]*AllianceStation
@@ -142,9 +143,9 @@ func (arena *Arena) LoadSettings() error {
arena.EventSettings = settings
// Initialize the components that depend on settings.
arena.accessPoint = NewAccessPoint(settings.ApAddress, settings.ApUsername, settings.ApPassword,
arena.accessPoint = network.NewAccessPoint(settings.ApAddress, settings.ApUsername, settings.ApPassword,
settings.ApTeamChannel, settings.ApAdminChannel, settings.ApAdminWpaKey)
arena.networkSwitch = NewNetworkSwitch(settings.SwitchAddress, settings.SwitchPassword)
arena.networkSwitch = network.NewSwitch(settings.SwitchAddress, settings.SwitchPassword)
arena.Plc.SetAddress(settings.PlcAddress)
arena.TbaClient = partner.NewTbaClient(settings.TbaEventCode, settings.TbaSecretId, settings.TbaSecret)

View File

@@ -473,8 +473,10 @@ func TestSetupNetwork(t *testing.T) {
// Verify the setup ran by checking the log for the expected failure messages.
arena.EventSettings.NetworkSecurityEnabled = true
arena.accessPoint.port = 10022
arena.networkSwitch.port = 10023
arena.EventSettings.ApAddress = "invalid"
arena.EventSettings.SwitchAddress = "invalid"
arena.Database.SaveEventSettings(arena.EventSettings)
arena.LoadSettings()
arena.LoadMatch(&model.Match{Type: "test"})
var writer bytes.Buffer
log.SetOutput(&writer)

View File

@@ -9,6 +9,7 @@ import (
"fmt"
"github.com/Team254/cheesy-arena/game"
"github.com/Team254/cheesy-arena/model"
"github.com/Team254/cheesy-arena/network"
"log"
"net"
"regexp"
@@ -50,7 +51,6 @@ type DriverStationConnection struct {
}
var allianceStationPositionMap = map[string]byte{"R1": 0, "R2": 1, "R3": 2, "B1": 3, "B2": 4, "B3": 5}
var driverStationTcpListenAddress = "10.0.100.5" // The DS will try to connect to this address only.
// Opens a UDP connection for communicating to the driver station.
func newDriverStationConnection(teamId int, allianceStation string, tcpConn net.Conn) (*DriverStationConnection, error) {
@@ -271,10 +271,10 @@ func (dsConn *DriverStationConnection) decodeStatusPacket(data [36]byte) {
// Listens for TCP connection requests to Cheesy Arena from driver stations.
func (arena *Arena) listenForDriverStations() {
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", driverStationTcpListenAddress, driverStationTcpListenPort))
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", network.ServerIpAddress, driverStationTcpListenPort))
if err != nil {
log.Printf("Error opening driver station TCP socket: %v", err.Error())
log.Printf("Change IP address to %s and restart Cheesy Arena to fix.", driverStationTcpListenAddress)
log.Printf("Change IP address to %s and restart Cheesy Arena to fix.", network.ServerIpAddress)
return
}
defer l.Close()

View File

@@ -4,6 +4,7 @@
package field
import (
"github.com/Team254/cheesy-arena/network"
"github.com/stretchr/testify/assert"
"net"
"testing"
@@ -162,11 +163,11 @@ func TestDecodeStatusPacket(t *testing.T) {
func TestListenForDriverStations(t *testing.T) {
arena := setupTestArena(t)
oldAddress := driverStationTcpListenAddress
driverStationTcpListenAddress = "127.0.0.1"
oldAddress := network.ServerIpAddress
network.ServerIpAddress = "127.0.0.1"
go arena.listenForDriverStations()
time.Sleep(time.Millisecond * 10)
driverStationTcpListenAddress = oldAddress // Put it back to avoid affecting other tests.
network.ServerIpAddress = oldAddress // Put it back to avoid affecting other tests.
// Connect with an invalid initial packet.
tcpConn, err := net.Dial("tcp", "127.0.0.1:1750")

View File

@@ -3,7 +3,7 @@
//
// Methods for configuring a Linksys WRT1900ACS access point running OpenWRT for team SSIDs and VLANs.
package field
package network
import (
"fmt"
@@ -30,7 +30,8 @@ type AccessPoint struct {
mutex sync.Mutex
}
func NewAccessPoint(address, username, password string, teamChannel, adminChannel int, adminWpaKey string) *AccessPoint {
func NewAccessPoint(address, username, password string, teamChannel, adminChannel int,
adminWpaKey string) *AccessPoint {
return &AccessPoint{address: address, port: accessPointSshPort, username: username, password: password,
teamChannel: teamChannel, adminChannel: adminChannel, adminWpaKey: adminWpaKey}
}

View File

@@ -1,7 +1,7 @@
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
package field
package network
import (
"github.com/Team254/cheesy-arena/model"

View File

@@ -3,7 +3,7 @@
//
// Methods for configuring a Cisco Switch 3500-series switch for team VLANs.
package field
package network
import (
"bufio"
@@ -27,25 +27,27 @@ const (
blue3Vlan = 60
)
type NetworkSwitch struct {
type Switch struct {
address string
port int
password string
mutex sync.Mutex
}
func NewNetworkSwitch(address, password string) *NetworkSwitch {
return &NetworkSwitch{address: address, port: switchTelnetPort, password: password}
var ServerIpAddress = "10.0.100.5" // The DS will try to connect to this address only.
func NewSwitch(address, password string) *Switch {
return &Switch{address: address, port: switchTelnetPort, password: password}
}
// Sets up wired networks for the given set of teams.
func (ns *NetworkSwitch) ConfigureTeamEthernet(red1, red2, red3, blue1, blue2, blue3 *model.Team) error {
func (sw *Switch) ConfigureTeamEthernet(red1, red2, red3, blue1, blue2, blue3 *model.Team) error {
// Make sure multiple configurations aren't being set at the same time.
ns.mutex.Lock()
defer ns.mutex.Unlock()
sw.mutex.Lock()
defer sw.mutex.Unlock()
// Determine what new team VLANs are needed and build the commands to set them up.
oldTeamVlans, err := ns.getTeamVlans()
oldTeamVlans, err := sw.getTeamVlans()
if err != nil {
return err
}
@@ -69,8 +71,8 @@ func (ns *NetworkSwitch) ConfigureTeamEthernet(red1, red2, red3, blue1, blue2, b
"access-list 1%d permit udp any eq bootpc any eq bootps\n"+
"interface Vlan%d\nip address 10.%d.%d.61 255.255.255.0\n",
team.Id/100, team.Id%100, team.Id/100, team.Id%100, vlan, vlan, team.Id/100, team.Id%100, team.Id/100,
team.Id%100, vlan, vlan, team.Id/100, team.Id%100, driverStationTcpListenAddress, vlan, vlan,
team.Id/100, team.Id%100)
team.Id%100, vlan, vlan, team.Id/100, team.Id%100, ServerIpAddress, vlan, vlan, team.Id/100,
team.Id%100)
}
}
replaceTeamVlan(red1, red1Vlan)
@@ -89,7 +91,7 @@ func (ns *NetworkSwitch) ConfigureTeamEthernet(red1, red2, red3, blue1, blue2, b
// Build and run the overall command to do everything in a single telnet session.
command := removeTeamVlansCommand + addTeamVlansCommand
if len(command) > 0 {
_, err = ns.runConfigCommand(removeTeamVlansCommand + addTeamVlansCommand)
_, err = sw.runConfigCommand(removeTeamVlansCommand + addTeamVlansCommand)
if err != nil {
return err
}
@@ -99,9 +101,9 @@ func (ns *NetworkSwitch) ConfigureTeamEthernet(red1, red2, red3, blue1, blue2, b
}
// Returns a map of currently-configured teams to VLANs.
func (ns *NetworkSwitch) getTeamVlans() (map[int]int, error) {
func (sw *Switch) getTeamVlans() (map[int]int, error) {
// Get the entire config dump.
config, err := ns.runCommand("show running-config\n")
config, err := sw.runCommand("show running-config\n")
if err != nil {
return nil, err
}
@@ -128,9 +130,9 @@ func (ns *NetworkSwitch) getTeamVlans() (map[int]int, error) {
// Logs into the switch via Telnet and runs the given command in user exec mode. Reads the output and
// returns it as a string.
func (ns *NetworkSwitch) runCommand(command string) (string, error) {
func (sw *Switch) runCommand(command string) (string, error) {
// Open a Telnet connection to the switch.
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ns.address, ns.port))
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", sw.address, sw.port))
if err != nil {
return "", err
}
@@ -138,7 +140,7 @@ func (ns *NetworkSwitch) runCommand(command string) (string, error) {
// Login to the AP, send the command, and log out all at once.
writer := bufio.NewWriter(conn)
_, err = writer.WriteString(fmt.Sprintf("%s\nenable\n%s\nterminal length 0\n%sexit\n", ns.password, ns.password,
_, err = writer.WriteString(fmt.Sprintf("%s\nenable\n%s\nterminal length 0\n%sexit\n", sw.password, sw.password,
command))
if err != nil {
return "", err
@@ -159,6 +161,6 @@ func (ns *NetworkSwitch) runCommand(command string) (string, error) {
// Logs into the switch via Telnet and runs the given command in global configuration mode. Reads the output
// and returns it as a string.
func (ns *NetworkSwitch) runConfigCommand(command string) (string, error) {
return ns.runCommand(fmt.Sprintf("config terminal\n%send\ncopy running-config startup-config\n\n", command))
func (sw *Switch) runConfigCommand(command string) (string, error) {
return sw.runCommand(fmt.Sprintf("config terminal\n%send\ncopy running-config startup-config\n\n", command))
}

View File

@@ -1,7 +1,7 @@
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
package field
package network
import (
"bytes"
@@ -14,27 +14,27 @@ import (
)
func TestConfigureSwitch(t *testing.T) {
ns := NewNetworkSwitch("127.0.0.1", "password")
ns.port = 9050
sw := NewSwitch("127.0.0.1", "password")
sw.port = 9050
var command string
// Should do nothing if current configuration is blank.
mockTelnet(t, ns.port, "", &command)
assert.Nil(t, ns.ConfigureTeamEthernet(nil, nil, nil, nil, nil, nil))
mockTelnet(t, sw.port, "", &command)
assert.Nil(t, sw.ConfigureTeamEthernet(nil, nil, nil, nil, nil, nil))
assert.Equal(t, "", command)
// Should remove any existing teams but not other SSIDs.
ns.port += 1
mockTelnet(t, ns.port,
sw.port += 1
mockTelnet(t, sw.port,
"interface Vlan100\nip address 10.0.100.2\ninterface Vlan50\nip address 10.2.54.61\n", &command)
assert.Nil(t, ns.ConfigureTeamEthernet(nil, nil, nil, nil, nil, nil))
assert.Nil(t, sw.ConfigureTeamEthernet(nil, nil, nil, nil, nil, nil))
assert.Equal(t, "password\nenable\npassword\nterminal length 0\nconfig terminal\ninterface Vlan50\nno ip"+
" address\nno access-list 150\nend\ncopy running-config startup-config\n\nexit\n", command)
// Should configure new teams and leave existing ones alone if still needed.
ns.port += 1
mockTelnet(t, ns.port, "interface Vlan50\nip address 10.2.54.61\n", &command)
assert.Nil(t, ns.ConfigureTeamEthernet(nil, &model.Team{Id: 1114}, nil, nil, &model.Team{Id: 254}, nil))
sw.port += 1
mockTelnet(t, sw.port, "interface Vlan50\nip address 10.2.54.61\n", &command)
assert.Nil(t, sw.ConfigureTeamEthernet(nil, &model.Team{Id: 1114}, nil, nil, &model.Team{Id: 254}, nil))
assert.Equal(t, "password\nenable\npassword\nterminal length 0\nconfig terminal\n"+
"ip dhcp excluded-address 10.11.14.1 10.11.14.100\nno ip dhcp pool dhcp20\nip dhcp pool dhcp20\n"+
"network 10.11.14.0 255.255.255.0\ndefault-router 10.11.14.61\nlease 7\nno access-list 120\n"+