proxy using support. close #231
This commit is contained in:
23
bot/mcbot.go
23
bot/mcbot.go
@ -10,12 +10,13 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
mcnet "github.com/Tnze/go-mc/net"
|
mcnet "github.com/Tnze/go-mc/net"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
"github.com/Tnze/go-mc/yggdrasil/user"
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolVersion is the protocol version number of minecraft net protocol
|
// ProtocolVersion is the protocol version number of minecraft net protocol
|
||||||
@ -25,7 +26,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type JoinOptions struct {
|
type JoinOptions struct {
|
||||||
Dialer *net.Dialer
|
MCDialer mcnet.MCDialer
|
||||||
Context context.Context
|
Context context.Context
|
||||||
|
|
||||||
// Indicate not to fetch and sending player's PubKey
|
// Indicate not to fetch and sending player's PubKey
|
||||||
@ -41,21 +42,21 @@ type JoinOptions struct {
|
|||||||
func (c *Client) JoinServer(addr string) (err error) {
|
func (c *Client) JoinServer(addr string) (err error) {
|
||||||
return c.join(addr, JoinOptions{
|
return c.join(addr, JoinOptions{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
Dialer: (*net.Dialer)(&mcnet.DefaultDialer),
|
MCDialer: &mcnet.DefaultDialer,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinServerWithDialer is similar to JoinServer but using a Dialer.
|
// JoinServerWithDialer is similar to JoinServer but using a net.Dialer.
|
||||||
func (c *Client) JoinServerWithDialer(dialer *net.Dialer, addr string) (err error) {
|
func (c *Client) JoinServerWithDialer(dialer *net.Dialer, addr string) (err error) {
|
||||||
return c.join(addr, JoinOptions{
|
return c.join(addr, JoinOptions{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
Dialer: dialer,
|
MCDialer: (*mcnet.Dialer)(dialer),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) JoinServerWithOptions(addr string, options JoinOptions) (err error) {
|
func (c *Client) JoinServerWithOptions(addr string, options JoinOptions) (err error) {
|
||||||
if options.Dialer == nil {
|
if options.MCDialer == nil {
|
||||||
options.Dialer = (*net.Dialer)(&mcnet.DefaultDialer)
|
options.MCDialer = &mcnet.DefaultDialer
|
||||||
}
|
}
|
||||||
if options.Context == nil {
|
if options.Context == nil {
|
||||||
options.Context = context.Background()
|
options.Context = context.Background()
|
||||||
@ -65,7 +66,9 @@ func (c *Client) JoinServerWithOptions(addr string, options JoinOptions) (err er
|
|||||||
|
|
||||||
func (c *Client) join(addr string, options JoinOptions) error {
|
func (c *Client) join(addr string, options JoinOptions) error {
|
||||||
const Handshake = 0x00
|
const Handshake = 0x00
|
||||||
// Split Host and Port
|
|
||||||
|
// Split Host and Port. The DialMCContext will do this once,
|
||||||
|
// but we need the result for sending handshake packet here.
|
||||||
host, portStr, err := net.SplitHostPort(addr)
|
host, portStr, err := net.SplitHostPort(addr)
|
||||||
var port uint64
|
var port uint64
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -85,9 +88,7 @@ func (c *Client) join(addr string, options JoinOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial connection
|
// Dial connection
|
||||||
d := (*mcnet.Dialer)(options.Dialer)
|
c.Conn, err = options.MCDialer.DialMCContext(options.Context, addr)
|
||||||
ctx := options.Context
|
|
||||||
c.Conn, err = d.DialMCContext(ctx, addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return LoginErr{"connect server", err}
|
return LoginErr{"connect server", err}
|
||||||
}
|
}
|
||||||
|
27
net/conn.go
27
net/conn.go
@ -62,6 +62,23 @@ func DialMCTimeout(addr string, timeout time.Duration) (*Conn, error) {
|
|||||||
return DefaultDialer.DialMCContext(ctx, addr)
|
return DefaultDialer.DialMCContext(ctx, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MCDialer provide DialMCContext method, can be used to dial a minecraft server.
|
||||||
|
// [Dialer] is its default implementation, and support SRV lookup.
|
||||||
|
//
|
||||||
|
// Typically, if you want to use built-in proxies or custom dialer,
|
||||||
|
// you can hook go-mc/bot package by implement this interface.
|
||||||
|
// When implementing a custom MCDialer, SRV lookup is optional.
|
||||||
|
type MCDialer interface {
|
||||||
|
// The DialMCContext dial TCP connection to a minecraft server, and warp the net.Conn by calling [WrapConn].
|
||||||
|
DialMCContext(ctx context.Context, addr string) (*Conn, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dialer implements MCDialer interface.
|
||||||
|
//
|
||||||
|
// It can be easily convert from net.Dialer.
|
||||||
|
//
|
||||||
|
// dialer := net.Dialer{}
|
||||||
|
// mcDialer := (*Dialer)(&dialer)
|
||||||
type Dialer net.Dialer
|
type Dialer net.Dialer
|
||||||
|
|
||||||
func (d *Dialer) resolver() *net.Resolver {
|
func (d *Dialer) resolver() *net.Resolver {
|
||||||
@ -82,23 +99,23 @@ func (d *Dialer) DialMCContext(ctx context.Context, addr string) (*Conn, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var ras []string
|
var addresses []string
|
||||||
if port == "" {
|
if port == "" {
|
||||||
// We look up SRV only if the port is not specified
|
// We look up SRV only if the port is not specified
|
||||||
_, srvRecords, err := d.resolver().LookupSRV(ctx, "minecraft", "tcp", host)
|
_, srvRecords, err := d.resolver().LookupSRV(ctx, "minecraft", "tcp", host)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, record := range srvRecords {
|
for _, record := range srvRecords {
|
||||||
addr := net.JoinHostPort(record.Target, strconv.Itoa(int(record.Port)))
|
addr := net.JoinHostPort(record.Target, strconv.Itoa(int(record.Port)))
|
||||||
ras = append(ras, addr)
|
addresses = append(addresses, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Whatever the SRV records is found,
|
// Whatever the SRV records is found,
|
||||||
addr = net.JoinHostPort(addr, strconv.Itoa(DefaultPort))
|
addr = net.JoinHostPort(addr, strconv.Itoa(DefaultPort))
|
||||||
}
|
}
|
||||||
ras = append(ras, addr)
|
addresses = append(addresses, addr)
|
||||||
|
|
||||||
var firstErr error
|
var firstErr error
|
||||||
for i, addr := range ras {
|
for i, addr := range addresses {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, context.Canceled
|
return nil, context.Canceled
|
||||||
@ -106,7 +123,7 @@ func (d *Dialer) DialMCContext(ctx context.Context, addr string) (*Conn, error)
|
|||||||
}
|
}
|
||||||
dialCtx := ctx
|
dialCtx := ctx
|
||||||
if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
|
if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
|
||||||
partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i)
|
partialDeadline, err := partialDeadline(time.Now(), deadline, len(addresses)-i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ran out of time.
|
// Ran out of time.
|
||||||
if firstErr == nil {
|
if firstErr == nil {
|
||||||
|
Reference in New Issue
Block a user