mirror of
https://github.com/MeowLynxSea/pocketmine-rcon.git
synced 2025-07-09 10:54:39 +00:00
Initial commit.
This commit is contained in:
commit
396c9d5b16
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Michael Bang
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
This is a very simple minecraft (and source engine?) RCON client. See [cli/main.go](cli/main.go) for an example on how to use it.
|
||||||
|
|
||||||
|
# Shortcomings
|
||||||
|
- Long (split) responses aren't handled correctly.
|
||||||
|
- Probably a lot more.
|
||||||
|
|
||||||
|
|
||||||
|
# License
|
||||||
|
See the [LICENSE](LICENSE) file.
|
||||||
|
|
51
cli/main.go
Normal file
51
cli/main.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/katnegermis/pocketmine-rcon"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Printf("Usage: ./rcon address password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := os.Args[1]
|
||||||
|
pass := os.Args[2]
|
||||||
|
|
||||||
|
conn, err := rcon.NewConnection(addr, pass)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Successfully logged in at %s!\n", addr)
|
||||||
|
|
||||||
|
prompt()
|
||||||
|
stdin := bufio.NewReader(os.Stdin)
|
||||||
|
input := ""
|
||||||
|
for {
|
||||||
|
if input, err = stdin.ReadString('\n'); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
input = strings.Trim(input[:len(input)-1], " ")
|
||||||
|
if input == ".exit" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if len(input) == 0 {
|
||||||
|
prompt()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r := conn.SendCommand(input)
|
||||||
|
fmt.Printf("Server:\n%s\n", r)
|
||||||
|
prompt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prompt() {
|
||||||
|
fmt.Print("Enter command:\n>")
|
||||||
|
}
|
118
connection.go
Normal file
118
connection.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package rcon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
conn net.Conn
|
||||||
|
pass string
|
||||||
|
addr string
|
||||||
|
}
|
||||||
|
|
||||||
|
var uniqueId int32 = 0
|
||||||
|
|
||||||
|
func NewConnection(addr, pass string) (*Connection, error) {
|
||||||
|
conn, err := net.Dial("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
c := &Connection{conn: conn, pass: pass, addr: addr}
|
||||||
|
if err := c.auth(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) SendCommand(cmd string) string {
|
||||||
|
c.sendCommand(2, []byte(cmd))
|
||||||
|
pkg := c.readPkg()
|
||||||
|
return string(pkg.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) auth() error {
|
||||||
|
c.sendCommand(3, []byte(c.pass))
|
||||||
|
pkg := c.readPkg()
|
||||||
|
if pkg.Type != 2 || pkg.Id != uniqueId {
|
||||||
|
return errors.New("Incorrect password.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) sendCommand(typ int32, body []byte) {
|
||||||
|
size := int32(4 + 4 + len(body) + 2)
|
||||||
|
uniqueId += 1
|
||||||
|
id := uniqueId
|
||||||
|
|
||||||
|
wtr := binaryReadWriter{ByteOrder: binary.LittleEndian}
|
||||||
|
wtr.Write(size)
|
||||||
|
wtr.Write(id)
|
||||||
|
wtr.Write(typ)
|
||||||
|
wtr.Write(body)
|
||||||
|
wtr.Write([]byte{0x0, 0x0})
|
||||||
|
if wtr.err != nil {
|
||||||
|
log.Fatal(wtr.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.conn.Write(wtr.buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) readPkg() Pkg {
|
||||||
|
const bufSize = 4096
|
||||||
|
b := make([]byte, bufSize)
|
||||||
|
|
||||||
|
// Doesn't handle split messages correctly.
|
||||||
|
read, err := c.conn.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := Pkg{}
|
||||||
|
rdr := binaryReadWriter{ByteOrder: binary.LittleEndian,
|
||||||
|
buf: bytes.NewBuffer(b)}
|
||||||
|
rdr.Read(&p.Size)
|
||||||
|
rdr.Read(&p.Id)
|
||||||
|
rdr.Read(&p.Type)
|
||||||
|
body := [bufSize - 12]byte{}
|
||||||
|
rdr.Read(&body)
|
||||||
|
if rdr.err != nil {
|
||||||
|
log.Fatal(rdr.err)
|
||||||
|
}
|
||||||
|
p.Body = body[:read-12]
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pkg struct {
|
||||||
|
Size int32
|
||||||
|
Id int32
|
||||||
|
Type int32
|
||||||
|
Body []byte
|
||||||
|
_null int16
|
||||||
|
}
|
||||||
|
|
||||||
|
type binaryReadWriter struct {
|
||||||
|
ByteOrder binary.ByteOrder
|
||||||
|
err error
|
||||||
|
buf *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *binaryReadWriter) Write(v interface{}) {
|
||||||
|
if b.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.buf == nil {
|
||||||
|
b.buf = new(bytes.Buffer)
|
||||||
|
}
|
||||||
|
b.err = binary.Write(b.buf, b.ByteOrder, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *binaryReadWriter) Read(v interface{}) {
|
||||||
|
if b.err != nil || b.buf == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binary.Read(b.buf, b.ByteOrder, v)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user