Files

85 lines
2.4 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package speech
import (
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"
)
type serverAddress struct {
network string
address string
}
// DefaultSocketAddress follows the default used by the Python speechd client.
func DefaultSocketAddress() string {
runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR")
if runtimeDirectory == "" {
runtimeDirectory = os.Getenv("XDG_CACHE_HOME")
}
if runtimeDirectory == "" {
cacheDirectory, err := os.UserCacheDir()
if err == nil {
runtimeDirectory = cacheDirectory
}
}
return filepath.Join(runtimeDirectory, "speech-dispatcher", "speechd.sock")
}
// resolveServerAddress gives an explicit CLI socket priority over speechd's
// standard address variables. SPEECHD_SOCKET is the older Unix-only setting.
func resolveServerAddress(socket string) (serverAddress, error) {
if socket != "" {
return serverAddress{network: "unix", address: socket}, nil
}
if address := os.Getenv("SPEECHD_ADDRESS"); address != "" {
return parseServerAddress(address)
}
if socket := os.Getenv("SPEECHD_SOCKET"); socket != "" {
return serverAddress{network: "unix", address: socket}, nil
}
return serverAddress{network: "unix", address: DefaultSocketAddress()}, nil
}
func parseServerAddress(address string) (serverAddress, error) {
method, value, _ := strings.Cut(address, ":")
switch method {
case "unix_socket":
if value == "" {
value = DefaultSocketAddress()
}
if !filepath.IsAbs(value) {
return serverAddress{}, fmt.Errorf("Speech Dispatcher Unix socket must be an absolute path: %q", value)
}
return serverAddress{network: "unix", address: value}, nil
case "inet_socket":
host, port := "127.0.0.1", 6560
if value != "" {
parts := strings.Split(value, ":")
if len(parts) > 2 {
return serverAddress{}, fmt.Errorf("invalid Speech Dispatcher address %q", address)
}
if parts[0] != "" {
host = parts[0]
}
if len(parts) == 2 {
parsed, err := strconv.Atoi(parts[1])
if err != nil || parsed < 1 || parsed > 65535 {
return serverAddress{}, fmt.Errorf("invalid Speech Dispatcher port in %q", address)
}
port = parsed
}
}
return serverAddress{network: "tcp4", address: net.JoinHostPort(host, strconv.Itoa(port))}, nil
default:
return serverAddress{}, fmt.Errorf("unsupported Speech Dispatcher address %q", address)
}
}