mirror of
https://github.com/hamburghammer/grcon.git
synced 2024-05-11 05:45:25 +02:00
Compare commits
6 commits
290507617d
...
7b8e1bbe41
Author | SHA1 | Date | |
---|---|---|---|
Augusto Dwenger J. | 7b8e1bbe41 | ||
Augusto Dwenger J. | d0ed6d814c | ||
Augusto Dwenger J. | 24ed78a39e | ||
Augusto Dwenger J. | aaf3f727df | ||
Augusto Dwenger J. | ece0a5f4af | ||
Augusto Dwenger J. | a05d58813c |
|
@ -1,2 +1,10 @@
|
|||
// A package with client implementations to interact over RCON with different servers.
|
||||
package client
|
||||
|
||||
// Client is the interface that should be implemented by ever client type.
|
||||
type Client interface {
|
||||
// Auth authenticates the client against the server.
|
||||
Auth(password string) error
|
||||
// Exec executes a command on the remote console.
|
||||
Exec(cmd string) ([]byte, error)
|
||||
}
|
||||
|
|
|
@ -7,68 +7,68 @@ import (
|
|||
"github.com/hamburghammer/grcon"
|
||||
)
|
||||
|
||||
func newGrconUtilError(act grcon.Action, err error) GrconUtilError {
|
||||
return GrconUtilError{
|
||||
func newGrconClientError(act grcon.Action, err error) GrconClientError {
|
||||
return GrconClientError{
|
||||
Act: act,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// GrconUtilError is a generic error that provides default implementations for the GrconError interface in the util module.
|
||||
type GrconUtilError struct {
|
||||
// GrconClientError is a generic error that provides default implementations for the GrconError interface in the util module.
|
||||
type GrconClientError struct {
|
||||
Err error
|
||||
Act grcon.Action
|
||||
}
|
||||
|
||||
func (grue GrconUtilError) Error() string {
|
||||
func (grue GrconClientError) Error() string {
|
||||
return fmt.Sprintf("grcon-client: on %s: %s", grue.Action(), grue.Err.Error())
|
||||
}
|
||||
|
||||
func (grue GrconUtilError) Action() grcon.Action {
|
||||
func (grue GrconClientError) Action() grcon.Action {
|
||||
return grue.Act
|
||||
}
|
||||
|
||||
func newInvalidResponseTypeError(expected, actual grcon.PacketType) InvalidResponseTypeError {
|
||||
return InvalidResponseTypeError{
|
||||
GrconUtilError: newGrconUtilError(grcon.Read, fmt.Errorf("invalid response type: expected %d but got %d", expected, actual)),
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
GrconClientError: newGrconClientError(grcon.Read, fmt.Errorf("invalid response type: expected %d but got %d", expected, actual)),
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
}
|
||||
}
|
||||
|
||||
type InvalidResponseTypeError struct {
|
||||
GrconUtilError
|
||||
GrconClientError
|
||||
Expected grcon.PacketType
|
||||
Actual grcon.PacketType
|
||||
}
|
||||
|
||||
func newAuthFailedError() AuthFailedError {
|
||||
return AuthFailedError{
|
||||
newGrconUtilError(grcon.Read, errors.New("authentication failed")),
|
||||
newGrconClientError(grcon.Read, errors.New("authentication failed")),
|
||||
}
|
||||
}
|
||||
|
||||
type AuthFailedError struct {
|
||||
GrconUtilError
|
||||
GrconClientError
|
||||
}
|
||||
|
||||
func newResponseIdMismatchError(expected, actual grcon.PacketId) ResponseIdMismatchError {
|
||||
return ResponseIdMismatchError{
|
||||
GrconUtilError: newGrconUtilError(grcon.Read, errors.New("invalid response type")),
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
GrconClientError: newGrconClientError(grcon.Read, errors.New("invalid response type")),
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
}
|
||||
}
|
||||
|
||||
type ResponseIdMismatchError struct {
|
||||
GrconUtilError
|
||||
GrconClientError
|
||||
Expected grcon.PacketId
|
||||
Actual grcon.PacketId
|
||||
}
|
||||
|
||||
func newResponseBodyError(expected, actual string) ResponseBodyError {
|
||||
return ResponseBodyError{
|
||||
newGrconUtilError(
|
||||
newGrconClientError(
|
||||
grcon.Read,
|
||||
fmt.Errorf("response body error: expected '%s' got '%s'", expected, actual),
|
||||
),
|
||||
|
@ -76,5 +76,5 @@ func newResponseBodyError(expected, actual string) ResponseBodyError {
|
|||
}
|
||||
|
||||
type ResponseBodyError struct {
|
||||
GrconUtilError
|
||||
GrconClientError
|
||||
}
|
||||
|
|
84
client/minecraft_client.go
Normal file
84
client/minecraft_client.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"github.com/hamburghammer/grcon"
|
||||
"github.com/hamburghammer/grcon/util"
|
||||
)
|
||||
|
||||
// NewMinecraftClient is a constructor for the MinecraftClient struct.
|
||||
// The util.GenerateNewId can be used as idGenFunc.
|
||||
func NewMinecraftClient(r util.RemoteConsole, idGenFunc func() grcon.PacketId) MinecraftClient {
|
||||
return MinecraftClient{RemoteConsole: r, IdGenFunc: idGenFunc}
|
||||
}
|
||||
|
||||
// MinecraftClient is a wrapper for a RemoteConsole that provides some utility functions.
|
||||
// It simplifies the interaction with a remote console of a minecraft server.
|
||||
type MinecraftClient struct {
|
||||
// RemoteConsole is the console to use for the interactions.
|
||||
util.RemoteConsole
|
||||
// IdGenFunc is the function to use to generate ids.
|
||||
IdGenFunc func() grcon.PacketId
|
||||
}
|
||||
|
||||
// Auth should be used to authenticate the connection.
|
||||
//
|
||||
// It can return following errors:
|
||||
// - InvalidResponseTypeError
|
||||
// - ResponseIdMismatchError
|
||||
// - AuthFailedError
|
||||
func (sc MinecraftClient) Auth(password string) error {
|
||||
reqID := sc.IdGenFunc()
|
||||
err := sc.Write(grcon.Packet{Id: reqID, Type: grcon.SERVERDATA_AUTH, Body: []byte(password)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packet, err := sc.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if packet.Type != grcon.SERVERDATA_AUTH_RESPONSE {
|
||||
return newInvalidResponseTypeError(grcon.SERVERDATA_AUTH_RESPONSE, packet.Type)
|
||||
}
|
||||
if packet.Id == -1 {
|
||||
return newAuthFailedError()
|
||||
}
|
||||
if packet.Id != reqID {
|
||||
return newResponseIdMismatchError(reqID, packet.Id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exec executes the command on the given RemoteConsole implementation and
|
||||
// waits till the response is read returns it.
|
||||
//
|
||||
// Errors:
|
||||
// Returns all errors returned from the Write and Read methode from the RemoteConsole implementation.
|
||||
// Can also return an InvalidResponseTypeError if the response is not of the type
|
||||
// grcon.SERVERDATA_RESPONSE_VALUE.
|
||||
func (sc MinecraftClient) Exec(cmd string) ([]byte, error) {
|
||||
cmdPacket := grcon.Packet{
|
||||
Id: sc.IdGenFunc(),
|
||||
Type: grcon.SERVERDATA_EXECCOMMAND,
|
||||
Body: []byte(cmd),
|
||||
}
|
||||
err := sc.Write(cmdPacket)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
packet, err := sc.Read()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
if packet.Type != grcon.SERVERDATA_RESPONSE_VALUE {
|
||||
return []byte{}, newInvalidResponseTypeError(grcon.SERVERDATA_RESPONSE_VALUE, packet.Type)
|
||||
}
|
||||
|
||||
if packet.Id != cmdPacket.Id {
|
||||
return []byte{}, newResponseIdMismatchError(cmdPacket.Id, packet.Id)
|
||||
}
|
||||
|
||||
return packet.Body, nil
|
||||
}
|
|
@ -59,6 +59,7 @@ func newUnexpectedFormatError() UnexpectedFormatError {
|
|||
}
|
||||
|
||||
// UnexpectedFormatError occurres when the packet size is smaller than the minimum size.
|
||||
// This indicates a wrongly composed/formatted packet.
|
||||
type UnexpectedFormatError struct {
|
||||
GrconGenericError
|
||||
}
|
||||
|
@ -72,8 +73,8 @@ func newRequestTooLongError() RequestTooLongError {
|
|||
}
|
||||
}
|
||||
|
||||
// RequestTooLongError occurres when the body of a packet is to big.
|
||||
// Can also be an indicator that the package is malformed/corrupted.
|
||||
// RequestTooLongError occurres when the length of a packet is to big.
|
||||
// This indicates that the body is too long.
|
||||
type RequestTooLongError struct {
|
||||
GrconGenericError
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ func newResponseTooLongError() ResponseTooLongError {
|
|||
return ResponseTooLongError{
|
||||
newGrconGenericError(
|
||||
Read,
|
||||
errors.New("response body is too long"),
|
||||
errors.New("response packet is too long"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue