hermes/backend/commonbackend/unmarshal.go

665 lines
16 KiB
Go

package commonbackend
import (
"encoding/binary"
"fmt"
"io"
"net"
)
func unmarshalIndividualConnectionStruct(conn io.Reader) (*ProxyClientConnection, error) {
serverIPVersion := make([]byte, 1)
if _, err := conn.Read(serverIPVersion); err != nil {
return nil, fmt.Errorf("couldn't read server IP version")
}
var serverIPSize uint8
if serverIPVersion[0] == 4 {
serverIPSize = IPv4Size
} else if serverIPVersion[0] == 6 {
serverIPSize = IPv6Size
} else if serverIPVersion[0] == '\n' {
return nil, fmt.Errorf("no data found")
} else {
return nil, fmt.Errorf("invalid server IP version recieved")
}
serverIP := make(net.IP, serverIPSize)
if _, err := conn.Read(serverIP); err != nil {
return nil, fmt.Errorf("couldn't read server IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return nil, fmt.Errorf("couldn't read source port")
}
destinationPort := make([]byte, 2)
if _, err := conn.Read(destinationPort); err != nil {
return nil, fmt.Errorf("couldn't read source port")
}
clientIPVersion := make([]byte, 1)
if _, err := conn.Read(clientIPVersion); err != nil {
return nil, fmt.Errorf("couldn't read server IP version")
}
var clientIPSize uint8
if clientIPVersion[0] == 4 {
clientIPSize = IPv4Size
} else if clientIPVersion[0] == 6 {
clientIPSize = IPv6Size
} else {
return nil, fmt.Errorf("invalid server IP version recieved")
}
clientIP := make(net.IP, clientIPSize)
if _, err := conn.Read(clientIP); err != nil {
return nil, fmt.Errorf("couldn't read server IP")
}
clientPort := make([]byte, 2)
if _, err := conn.Read(clientPort); err != nil {
return nil, fmt.Errorf("couldn't read source port")
}
return &ProxyClientConnection{
SourceIP: serverIP.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destinationPort),
ClientIP: clientIP.String(),
ClientPort: binary.BigEndian.Uint16(clientPort),
}, nil
}
func unmarshalIndividualProxyStruct(conn io.Reader) (*ProxyInstance, error) {
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else if ipVersion[0] == '\n' {
return nil, fmt.Errorf("no data found")
} else {
return nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[0] == UDP {
protocol = "udp"
} else {
return nil, fmt.Errorf("invalid protocol")
}
return &ProxyInstance{
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
}, nil
}
func Unmarshal(conn io.Reader) (string, interface{}, error) {
commandType := make([]byte, 1)
if _, err := conn.Read(commandType); err != nil {
return "", nil, fmt.Errorf("couldn't read command")
}
switch commandType[0] {
case StartID:
argumentsLength := make([]byte, 2)
if _, err := conn.Read(argumentsLength); err != nil {
return "", nil, fmt.Errorf("couldn't read argument length")
}
arguments := make([]byte, binary.BigEndian.Uint16(argumentsLength))
if _, err := conn.Read(arguments); err != nil {
return "", nil, fmt.Errorf("couldn't read arguments")
}
return "start", &Start{
Type: "start",
Arguments: arguments,
}, nil
case StopID:
return "stop", &Stop{
Type: "stop",
}, nil
case AddProxyID:
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return "", nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else {
return "", nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return "", nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return "", nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return "", nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[1] == UDP {
protocol = "udp"
} else {
return "", nil, fmt.Errorf("invalid protocol")
}
return "addProxy", &AddProxy{
Type: "addProxy",
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
}, nil
case RemoveProxyID:
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return "", nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else {
return "", nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return "", nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return "", nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return "", nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[1] == UDP {
protocol = "udp"
} else {
return "", nil, fmt.Errorf("invalid protocol")
}
return "removeProxy", &RemoveProxy{
Type: "removeProxy",
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
}, nil
case ProxyConnectionsResponseID:
connections := []*ProxyClientConnection{}
delimiter := make([]byte, 1)
var errorReturn error
// Infinite loop because we don't know the length
for {
connection, err := unmarshalIndividualConnectionStruct(conn)
if err != nil {
if err.Error() == "no data found" {
break
}
return "", nil, err
}
connections = append(connections, connection)
if _, err := conn.Read(delimiter); err != nil {
return "", nil, fmt.Errorf("couldn't read delimiter")
}
if delimiter[0] == '\r' {
continue
} else if delimiter[0] == '\n' {
break
} else {
// WTF? This shouldn't happen. Break out and return, but give an error
errorReturn = fmt.Errorf("invalid delimiter recieved while processing stream")
break
}
}
return "proxyConnectionsResponse", &ProxyConnectionsResponse{
Type: "proxyConnectionsResponse",
Connections: connections,
}, errorReturn
case CheckClientParametersID:
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return "", nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else {
return "", nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return "", nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return "", nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return "", nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[1] == UDP {
protocol = "udp"
} else {
return "", nil, fmt.Errorf("invalid protocol")
}
return "checkClientParameters", &CheckClientParameters{
Type: "checkClientParameters",
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
}, nil
case CheckServerParametersID:
argumentsLength := make([]byte, 2)
if _, err := conn.Read(argumentsLength); err != nil {
return "", nil, fmt.Errorf("couldn't read argument length")
}
arguments := make([]byte, binary.BigEndian.Uint16(argumentsLength))
if _, err := conn.Read(arguments); err != nil {
return "", nil, fmt.Errorf("couldn't read arguments")
}
return "checkServerParameters", &CheckServerParameters{
Type: "checkServerParameters",
Arguments: arguments,
}, nil
case CheckParametersResponseID:
checkMethodByte := make([]byte, 1)
if _, err := conn.Read(checkMethodByte); err != nil {
return "", nil, fmt.Errorf("couldn't read check method byte")
}
var checkMethod string
if checkMethodByte[0] == CheckClientParametersID {
checkMethod = "checkClientParameters"
} else if checkMethodByte[0] == CheckServerParametersID {
checkMethod = "checkServerParameters"
} else {
return "", nil, fmt.Errorf("invalid check method recieved")
}
isValid := make([]byte, 1)
if _, err := conn.Read(isValid); err != nil {
return "", nil, fmt.Errorf("couldn't read isValid byte")
}
messageLengthBytes := make([]byte, 2)
if _, err := conn.Read(messageLengthBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read message length")
}
messageLength := binary.BigEndian.Uint16(messageLengthBytes)
var message string
if messageLength != 0 {
messageBytes := make([]byte, messageLength)
if _, err := conn.Read(messageBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read message")
}
message = string(messageBytes)
}
return "checkParametersResponse", &CheckParametersResponse{
Type: "checkParametersResponse",
InResponseTo: checkMethod,
IsValid: isValid[0] == 1,
Message: message,
}, nil
case BackendStatusResponseID:
isRunning := make([]byte, 1)
if _, err := conn.Read(isRunning); err != nil {
return "", nil, fmt.Errorf("couldn't read isRunning field")
}
statusCode := make([]byte, 1)
if _, err := conn.Read(statusCode); err != nil {
return "", nil, fmt.Errorf("couldn't read status code field")
}
messageLengthBytes := make([]byte, 2)
if _, err := conn.Read(messageLengthBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read message length")
}
messageLength := binary.BigEndian.Uint16(messageLengthBytes)
var message string
if messageLength != 0 {
messageBytes := make([]byte, messageLength)
if _, err := conn.Read(messageBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read message")
}
message = string(messageBytes)
}
return "backendStatusResponse", &BackendStatusResponse{
Type: "backendStatusResponse",
IsRunning: isRunning[0] == 1,
StatusCode: int(statusCode[0]),
Message: message,
}, nil
case BackendStatusRequestID:
return "backendStatusRequest", &BackendStatusRequest{
Type: "backendStatusRequest",
}, nil
case ProxyStatusRequestID:
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return "", nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else {
return "", nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return "", nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return "", nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return "", nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[1] == UDP {
protocol = "udp"
} else {
return "", nil, fmt.Errorf("invalid protocol")
}
return "proxyStatusRequest", &ProxyStatusRequest{
Type: "proxyStatusRequest",
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
}, nil
case ProxyStatusResponseID:
ipVersion := make([]byte, 1)
if _, err := conn.Read(ipVersion); err != nil {
return "", nil, fmt.Errorf("couldn't read ip version")
}
var ipSize uint8
if ipVersion[0] == 4 {
ipSize = IPv4Size
} else if ipVersion[0] == 6 {
ipSize = IPv6Size
} else {
return "", nil, fmt.Errorf("invalid IP version recieved")
}
ip := make(net.IP, ipSize)
if _, err := conn.Read(ip); err != nil {
return "", nil, fmt.Errorf("couldn't read source IP")
}
sourcePort := make([]byte, 2)
if _, err := conn.Read(sourcePort); err != nil {
return "", nil, fmt.Errorf("couldn't read source port")
}
destPort := make([]byte, 2)
if _, err := conn.Read(destPort); err != nil {
return "", nil, fmt.Errorf("couldn't read destination port")
}
protocolBytes := make([]byte, 1)
if _, err := conn.Read(protocolBytes); err != nil {
return "", nil, fmt.Errorf("couldn't read protocol")
}
var protocol string
if protocolBytes[0] == TCP {
protocol = "tcp"
} else if protocolBytes[1] == UDP {
protocol = "udp"
} else {
return "", nil, fmt.Errorf("invalid protocol")
}
isActive := make([]byte, 1)
if _, err := conn.Read(isActive); err != nil {
return "", nil, fmt.Errorf("couldn't read isActive field")
}
return "proxyStatusResponse", &ProxyStatusResponse{
Type: "proxyStatusResponse",
SourceIP: ip.String(),
SourcePort: binary.BigEndian.Uint16(sourcePort),
DestPort: binary.BigEndian.Uint16(destPort),
Protocol: protocol,
IsActive: isActive[0] == 1,
}, nil
case ProxyInstanceRequestID:
return "proxyInstanceRequest", &ProxyInstanceRequest{
Type: "proxyInstanceRequest",
}, nil
case ProxyInstanceResponseID:
proxies := []*ProxyInstance{}
delimiter := make([]byte, 1)
var errorReturn error
// Infinite loop because we don't know the length
for {
proxy, err := unmarshalIndividualProxyStruct(conn)
if err != nil {
if err.Error() == "no data found" {
break
}
return "", nil, err
}
proxies = append(proxies, proxy)
if _, err := conn.Read(delimiter); err != nil {
return "", nil, fmt.Errorf("couldn't read delimiter")
}
if delimiter[0] == '\r' {
continue
} else if delimiter[0] == '\n' {
break
} else {
// WTF? This shouldn't happen. Break out and return, but give an error
errorReturn = fmt.Errorf("invalid delimiter recieved while processing stream")
break
}
}
return "proxyInstanceResponse", &ProxyInstanceResponse{
Type: "proxyInstanceResponse",
Proxies: proxies,
}, errorReturn
case ProxyConnectionsRequestID:
return "proxyConnectionsRequest", &ProxyConnectionsRequest{
Type: "proxyConnectionsRequest",
}, nil
}
return "", nil, fmt.Errorf("couldn't match command ID")
}