mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 17:40:26 +00:00
Merge pull request #238 from neilalexander/afunix
Use AF_UNIX socket by default for admin API
This commit is contained in:
commit
6901e2fc9a
@ -35,9 +35,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
- Add `-json` command line flag for generating and normalising configuration in plain JSON instead of HJSON
|
- Add `-json` command line flag for generating and normalising configuration in plain JSON instead of HJSON
|
||||||
- Build name and version numbers are now imprinted onto the build, accessible through `yggdrasil -version` and `yggdrasilctl getSelf`
|
- Build name and version numbers are now imprinted onto the build, accessible through `yggdrasil -version` and `yggdrasilctl getSelf`
|
||||||
- Add ability to disable admin socket by setting `AdminListen` to `"none"`
|
- Add ability to disable admin socket by setting `AdminListen` to `"none"`
|
||||||
|
- `yggdrasilctl` now tries to look for the default configuration file to find `AdminListen` if `-endpoint` is not specified
|
||||||
|
- `yggdrasilctl` now returns more useful logging in the event of a fatal error
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Switched to Chord DHT (instead of Kademlia, although still compatible at the protocol level)
|
- Switched to Chord DHT (instead of Kademlia, although still compatible at the protocol level)
|
||||||
|
- The `AdminListen` option and `yggdrasilctl` now default to `unix:///var/run/yggdrasil.sock` on BSDs, macOS and Linux
|
||||||
- Cleaned up some of the parameter naming in the admin socket
|
- Cleaned up some of the parameter naming in the admin socket
|
||||||
- Latency-based parent selection for the switch instead of uptime-based (should help to avoid high latency links somewhat)
|
- Latency-based parent selection for the switch instead of uptime-based (should help to avoid high latency links somewhat)
|
||||||
- Real peering endpoints now shown in the admin socket `getPeers` call to help identify peerings
|
- Real peering endpoints now shown in the admin socket `getPeers` call to help identify peerings
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -12,16 +15,31 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/text/encoding/unicode"
|
||||||
|
|
||||||
|
"github.com/neilalexander/hjson-go"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||||
)
|
)
|
||||||
|
|
||||||
type admin_info map[string]interface{}
|
type admin_info map[string]interface{}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
logbuffer := &bytes.Buffer{}
|
||||||
|
logger := log.New(logbuffer, "", log.Flags())
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
logger.Println("Fatal error:", r)
|
||||||
|
fmt.Print(logbuffer)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
endpoint := defaults.GetDefaults().DefaultAdminListen
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n", os.Args[0])
|
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n", os.Args[0])
|
||||||
fmt.Println("Options:")
|
fmt.Println("Options:")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
fmt.Println("Commands:\n - Use \"list\" for a list of available commands")
|
fmt.Println("Commands:\n - Use \"list\" for a list of available commands")
|
||||||
fmt.Println("Examples:")
|
fmt.Println("Examples:")
|
||||||
fmt.Println(" - ", os.Args[0], "list")
|
fmt.Println(" - ", os.Args[0], "list")
|
||||||
@ -30,7 +48,7 @@ func main() {
|
|||||||
fmt.Println(" - ", os.Args[0], "-endpoint=tcp://localhost:9001 getDHT")
|
fmt.Println(" - ", os.Args[0], "-endpoint=tcp://localhost:9001 getDHT")
|
||||||
fmt.Println(" - ", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getDHT")
|
fmt.Println(" - ", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getDHT")
|
||||||
}
|
}
|
||||||
server := flag.String("endpoint", defaults.GetDefaults().DefaultAdminListen, "Admin socket endpoint")
|
server := flag.String("endpoint", endpoint, "Admin socket endpoint")
|
||||||
injson := flag.Bool("json", false, "Output in JSON format (as opposed to pretty-print)")
|
injson := flag.Bool("json", false, "Output in JSON format (as opposed to pretty-print)")
|
||||||
verbose := flag.Bool("v", false, "Verbose output (includes public keys)")
|
verbose := flag.Bool("v", false, "Verbose output (includes public keys)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -41,23 +59,59 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *server == endpoint {
|
||||||
|
if config, err := ioutil.ReadFile(defaults.GetDefaults().DefaultConfigFile); err == nil {
|
||||||
|
if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
||||||
|
bytes.Compare(config[0:2], []byte{0xFE, 0xFF}) == 0 {
|
||||||
|
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||||
|
decoder := utf.NewDecoder()
|
||||||
|
config, err = decoder.Bytes(config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dat map[string]interface{}
|
||||||
|
if err := hjson.Unmarshal(config, &dat); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if ep, ok := dat["AdminListen"].(string); ok && (ep != "none" && ep != "") {
|
||||||
|
endpoint = ep
|
||||||
|
logger.Println("Found platform default config file", defaults.GetDefaults().DefaultConfigFile)
|
||||||
|
logger.Println("Using endpoint", endpoint, "from AdminListen")
|
||||||
|
} else {
|
||||||
|
logger.Println("Configuration file doesn't contain appropriate AdminListen option")
|
||||||
|
logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Println("Can't open config file from default location", defaults.GetDefaults().DefaultConfigFile)
|
||||||
|
logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Println("Using endpoint", endpoint, "from command line")
|
||||||
|
}
|
||||||
|
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
u, err := url.Parse(*server)
|
u, err := url.Parse(endpoint)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch strings.ToLower(u.Scheme) {
|
switch strings.ToLower(u.Scheme) {
|
||||||
case "unix":
|
case "unix":
|
||||||
conn, err = net.Dial("unix", (*server)[7:])
|
logger.Println("Connecting to UNIX socket", endpoint[7:])
|
||||||
|
conn, err = net.Dial("unix", endpoint[7:])
|
||||||
case "tcp":
|
case "tcp":
|
||||||
|
logger.Println("Connecting to TCP socket", u.Host)
|
||||||
conn, err = net.Dial("tcp", u.Host)
|
conn, err = net.Dial("tcp", u.Host)
|
||||||
default:
|
default:
|
||||||
|
logger.Println("Unknown protocol or malformed address - check your endpoint")
|
||||||
err = errors.New("protocol not supported")
|
err = errors.New("protocol not supported")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
conn, err = net.Dial("tcp", *server)
|
logger.Println("Connecting to TCP socket", u.Host)
|
||||||
|
conn, err = net.Dial("tcp", endpoint)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
logger.Println("Connected")
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
decoder := json.NewDecoder(conn)
|
decoder := json.NewDecoder(conn)
|
||||||
@ -67,11 +121,13 @@ func main() {
|
|||||||
|
|
||||||
for c, a := range args {
|
for c, a := range args {
|
||||||
if c == 0 {
|
if c == 0 {
|
||||||
|
logger.Printf("Sending request: %v\n", a)
|
||||||
send["request"] = a
|
send["request"] = a
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tokens := strings.Split(a, "=")
|
tokens := strings.Split(a, "=")
|
||||||
if i, err := strconv.Atoi(tokens[1]); err == nil {
|
if i, err := strconv.Atoi(tokens[1]); err == nil {
|
||||||
|
logger.Printf("Sending parameter %s: %d\n", tokens[0], i)
|
||||||
send[tokens[0]] = i
|
send[tokens[0]] = i
|
||||||
} else {
|
} else {
|
||||||
switch strings.ToLower(tokens[1]) {
|
switch strings.ToLower(tokens[1]) {
|
||||||
@ -82,28 +138,31 @@ func main() {
|
|||||||
default:
|
default:
|
||||||
send[tokens[0]] = tokens[1]
|
send[tokens[0]] = tokens[1]
|
||||||
}
|
}
|
||||||
|
logger.Printf("Sending parameter %s: %v\n", tokens[0], send[tokens[0]])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := encoder.Encode(&send); err != nil {
|
if err := encoder.Encode(&send); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
logger.Printf("Request sent")
|
||||||
if err := decoder.Decode(&recv); err == nil {
|
if err := decoder.Decode(&recv); err == nil {
|
||||||
|
logger.Printf("Response received")
|
||||||
if recv["status"] == "error" {
|
if recv["status"] == "error" {
|
||||||
if err, ok := recv["error"]; ok {
|
if err, ok := recv["error"]; ok {
|
||||||
fmt.Println("Error:", err)
|
fmt.Println("Admin socket returned an error:", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Unspecified error occured")
|
fmt.Println("Admin socket returned an error but didn't specify any error text")
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if _, ok := recv["request"]; !ok {
|
if _, ok := recv["request"]; !ok {
|
||||||
fmt.Println("Missing request in response (malformed response?)")
|
fmt.Println("Missing request in response (malformed response?)")
|
||||||
return
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if _, ok := recv["response"]; !ok {
|
if _, ok := recv["response"]; !ok {
|
||||||
fmt.Println("Missing response body (malformed response?)")
|
fmt.Println("Missing response body (malformed response?)")
|
||||||
return
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
req := recv["request"].(map[string]interface{})
|
req := recv["request"].(map[string]interface{})
|
||||||
res := recv["response"].(map[string]interface{})
|
res := recv["response"].(map[string]interface{})
|
||||||
@ -243,7 +302,7 @@ func main() {
|
|||||||
queuesize := v.(map[string]interface{})["queue_size"].(float64)
|
queuesize := v.(map[string]interface{})["queue_size"].(float64)
|
||||||
queuepackets := v.(map[string]interface{})["queue_packets"].(float64)
|
queuepackets := v.(map[string]interface{})["queue_packets"].(float64)
|
||||||
queueid := v.(map[string]interface{})["queue_id"].(string)
|
queueid := v.(map[string]interface{})["queue_id"].(string)
|
||||||
portqueues[queueport] += 1
|
portqueues[queueport]++
|
||||||
portqueuesize[queueport] += queuesize
|
portqueuesize[queueport] += queuesize
|
||||||
portqueuepackets[queueport] += queuepackets
|
portqueuepackets[queueport] += queuepackets
|
||||||
queuesizepercent := (100 / maximumqueuesize) * queuesize
|
queuesizepercent := (100 / maximumqueuesize) * queuesize
|
||||||
@ -331,9 +390,11 @@ func main() {
|
|||||||
fmt.Println(string(json))
|
fmt.Println(string(json))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logger.Println("Error receiving response:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := recv["status"]; ok && v == "error" {
|
if v, ok := recv["status"]; ok && v != "success" {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
@ -7,6 +7,9 @@ type platformDefaultParameters struct {
|
|||||||
// Admin socket
|
// Admin socket
|
||||||
DefaultAdminListen string
|
DefaultAdminListen string
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile string
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU int
|
MaximumIfMTU int
|
||||||
DefaultIfMTU int
|
DefaultIfMTU int
|
||||||
|
@ -7,7 +7,10 @@ package defaults
|
|||||||
func GetDefaults() platformDefaultParameters {
|
func GetDefaults() platformDefaultParameters {
|
||||||
return platformDefaultParameters{
|
return platformDefaultParameters{
|
||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "unix:///var/run/yggdrasil.sock",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 65535,
|
MaximumIfMTU: 65535,
|
||||||
|
@ -7,7 +7,10 @@ package defaults
|
|||||||
func GetDefaults() platformDefaultParameters {
|
func GetDefaults() platformDefaultParameters {
|
||||||
return platformDefaultParameters{
|
return platformDefaultParameters{
|
||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "unix:///var/run/yggdrasil.sock",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 32767,
|
MaximumIfMTU: 32767,
|
||||||
|
@ -7,7 +7,10 @@ package defaults
|
|||||||
func GetDefaults() platformDefaultParameters {
|
func GetDefaults() platformDefaultParameters {
|
||||||
return platformDefaultParameters{
|
return platformDefaultParameters{
|
||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "unix:///var/run/yggdrasil.sock",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 65535,
|
MaximumIfMTU: 65535,
|
||||||
|
@ -7,7 +7,10 @@ package defaults
|
|||||||
func GetDefaults() platformDefaultParameters {
|
func GetDefaults() platformDefaultParameters {
|
||||||
return platformDefaultParameters{
|
return platformDefaultParameters{
|
||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "unix:///var/run/yggdrasil.sock",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 9000,
|
MaximumIfMTU: 9000,
|
||||||
|
@ -7,7 +7,10 @@ package defaults
|
|||||||
func GetDefaults() platformDefaultParameters {
|
func GetDefaults() platformDefaultParameters {
|
||||||
return platformDefaultParameters{
|
return platformDefaultParameters{
|
||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "unix:///var/run/yggdrasil.sock",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 16384,
|
MaximumIfMTU: 16384,
|
||||||
|
@ -9,6 +9,9 @@ func GetDefaults() platformDefaultParameters {
|
|||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "tcp://localhost:9001",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "/etc/yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 65535,
|
MaximumIfMTU: 65535,
|
||||||
DefaultIfMTU: 65535,
|
DefaultIfMTU: 65535,
|
||||||
|
@ -9,6 +9,9 @@ func GetDefaults() platformDefaultParameters {
|
|||||||
// Admin
|
// Admin
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "tcp://localhost:9001",
|
||||||
|
|
||||||
|
// Configuration (used for yggdrasilctl)
|
||||||
|
DefaultConfigFile: "C:\\Program Files\\Yggdrasil\\yggdrasil.conf",
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 65535,
|
MaximumIfMTU: 65535,
|
||||||
DefaultIfMTU: 65535,
|
DefaultIfMTU: 65535,
|
||||||
|
@ -343,7 +343,19 @@ func (a *admin) listen() {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
switch strings.ToLower(u.Scheme) {
|
switch strings.ToLower(u.Scheme) {
|
||||||
case "unix":
|
case "unix":
|
||||||
|
if _, err := os.Stat(a.listenaddr[7:]); err == nil {
|
||||||
|
a.core.log.Println("WARNING:", a.listenaddr[7:], "already exists and may be in use by another process")
|
||||||
|
}
|
||||||
a.listener, err = net.Listen("unix", a.listenaddr[7:])
|
a.listener, err = net.Listen("unix", a.listenaddr[7:])
|
||||||
|
if err == nil {
|
||||||
|
switch a.listenaddr[7:8] {
|
||||||
|
case "@": // maybe abstract namespace
|
||||||
|
default:
|
||||||
|
if err := os.Chmod(a.listenaddr[7:], 0660); err != nil {
|
||||||
|
a.core.log.Println("WARNING:", a.listenaddr[:7], "may have unsafe permissions!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case "tcp":
|
case "tcp":
|
||||||
a.listener, err = net.Listen("tcp", u.Host)
|
a.listener, err = net.Listen("tcp", u.Host)
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user