102 lines
4.3 KiB
Swift
102 lines
4.3 KiB
Swift
import Foundation
|
|
import UltraMeshCore
|
|
|
|
let args = Array(CommandLine.arguments.dropFirst())
|
|
|
|
func usage() -> Never {
|
|
print("""
|
|
Ultra Mesh Network
|
|
umn status | address | peers | routes | interface status | ping <target>
|
|
umn alias set <name> <address> | remove <name> | list
|
|
umn firewall allow|revoke <overlay|tcp|udp> <port> --from <address|any> | list
|
|
umn text send <target> <port> <message> | listen <port>
|
|
umn expose <mesh-port> --to <host:port>
|
|
umn proxy [--listen 127.0.0.1:<port>]
|
|
""")
|
|
exit(2)
|
|
}
|
|
|
|
func parsePort(_ value: String) -> UInt16 {
|
|
guard let port = UInt16(value), port > 0 else { usage() }
|
|
return port
|
|
}
|
|
|
|
do {
|
|
guard let command = args.first else { usage() }
|
|
if command == "expose" {
|
|
guard args.count == 4, args[2] == "--to", let split = args[3].lastIndex(of: ":") else { usage() }
|
|
let host = String(args[3][..<split])
|
|
let localPort = parsePort(String(args[3][args[3].index(after: split)...]))
|
|
try runExpose(meshPort: parsePort(args[1]), host: host, localPort: localPort)
|
|
}
|
|
if command == "proxy" {
|
|
var listenPort: UInt16 = 1080
|
|
if args.count == 3, args[1] == "--listen", let split = args[2].lastIndex(of: ":") {
|
|
listenPort = parsePort(String(args[2][args[2].index(after: split)...]))
|
|
} else if args.count != 1 { usage() }
|
|
try runSOCKS(port: listenPort)
|
|
}
|
|
|
|
let daemon = try DaemonConnection()
|
|
var request: IPCMessage
|
|
switch command {
|
|
case "status": request = IPCMessage(operation: .status)
|
|
case "address": request = IPCMessage(operation: .address)
|
|
case "peers": request = IPCMessage(operation: .peers)
|
|
case "routes": request = IPCMessage(operation: .routes)
|
|
case "interface":
|
|
guard args.count == 2, args[1] == "status" else { usage() }
|
|
request = IPCMessage(operation: .interfaceStatus)
|
|
case "ping":
|
|
guard args.count == 2 else { usage() }
|
|
request = IPCMessage(operation: .ping); request.target = args[1]
|
|
case "alias":
|
|
guard args.count >= 2 else { usage() }
|
|
switch args[1] {
|
|
case "list": request = IPCMessage(operation: .aliasList)
|
|
case "set":
|
|
guard args.count == 4 else { usage() }
|
|
request = IPCMessage(operation: .aliasSet); request.name = args[2]; request.target = args[3]
|
|
case "remove":
|
|
guard args.count == 3 else { usage() }
|
|
request = IPCMessage(operation: .aliasRemove); request.name = args[2]
|
|
default: usage()
|
|
}
|
|
case "firewall":
|
|
guard args.count >= 2 else { usage() }
|
|
if args[1] == "list" { request = IPCMessage(operation: .firewallList) }
|
|
else {
|
|
guard args.count == 6, args[4] == "--from", ["allow", "revoke"].contains(args[1]),
|
|
let protocolKind = FirewallProtocol(rawValue: args[2]) else { usage() }
|
|
request = IPCMessage(operation: args[1] == "allow" ? .firewallAllow : .firewallRevoke)
|
|
request.firewallProtocol = protocolKind; request.port = parsePort(args[3]); request.source = args[5]
|
|
}
|
|
case "text":
|
|
guard args.count >= 3 else { usage() }
|
|
if args[1] == "listen" {
|
|
request = IPCMessage(operation: .bindText); request.port = parsePort(args[2])
|
|
guard printResponse(try daemon.request(request)) else { exit(1) }
|
|
while let event = try daemon.receive() {
|
|
if event.operation == .textSend, let data = event.data,
|
|
let text = String(data: data, encoding: .utf8) {
|
|
print("[\(event.source ?? "unknown")] \(text)")
|
|
}
|
|
}
|
|
throw UMNError.message("daemon disconnected")
|
|
} else if args[1] == "send" {
|
|
guard args.count >= 5 else { usage() }
|
|
request = IPCMessage(operation: .textSend); request.target = args[2]
|
|
request.port = parsePort(args[3]); request.data = Data(args.dropFirst(4).joined(separator: " ").utf8)
|
|
} else { usage() }
|
|
default: usage()
|
|
}
|
|
let result = try daemon.request(request)
|
|
exit(printResponse(result) ? 0 : 1)
|
|
} catch {
|
|
fputs("umn: \(error.localizedDescription)\n", stderr)
|
|
if (error as NSError).domain == NSPOSIXErrorDomain {
|
|
fputs("Is umnd running? Install it or start with `swift run umnd`.\n", stderr)
|
|
}
|
|
exit(1)
|
|
}
|