Fix: fuck udp
This commit is contained in:
1
cmd.go
1
cmd.go
@@ -26,5 +26,4 @@ func init() {
|
|||||||
|
|
||||||
RootCmd.AddCommand(authCmd)
|
RootCmd.AddCommand(authCmd)
|
||||||
RootCmd.AddCommand(playerCmd)
|
RootCmd.AddCommand(playerCmd)
|
||||||
RootCmd.AddCommand(testCmd)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package wordle
|
package wordle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ import (
|
|||||||
"gitea.konchin.com/ytshih/inp2025/utils"
|
"gitea.konchin.com/ytshih/inp2025/utils"
|
||||||
"github.com/uptrace/bunrouter"
|
"github.com/uptrace/bunrouter"
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PostGuessInput struct {
|
type PostGuessInput struct {
|
||||||
@@ -18,7 +20,7 @@ func (self *Handlers) PostGuess(
|
|||||||
w http.ResponseWriter,
|
w http.ResponseWriter,
|
||||||
req bunrouter.Request,
|
req bunrouter.Request,
|
||||||
) error {
|
) error {
|
||||||
// fmt.Fprintf(os.Stderr, "POST /api/guess\n")
|
zap.L().Info("POST /api/guess")
|
||||||
b, err := io.ReadAll(req.Body)
|
b, err := io.ReadAll(req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return middlewares.HTTPError{
|
return middlewares.HTTPError{
|
||||||
@@ -37,6 +39,9 @@ func (self *Handlers) PostGuess(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zap.L().Info("input",
|
||||||
|
zap.String("input", fmt.Sprintf("%+v", input)))
|
||||||
|
|
||||||
username, _, ok := req.BasicAuth()
|
username, _, ok := req.BasicAuth()
|
||||||
if !ok {
|
if !ok {
|
||||||
return middlewares.HTTPError{
|
return middlewares.HTTPError{
|
||||||
|
|||||||
13
player.go
13
player.go
@@ -6,11 +6,22 @@ import (
|
|||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var playerCmd = &cobra.Command{
|
var playerCmd = &cobra.Command{
|
||||||
Use: "player",
|
Use: "player",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
logger, _ := zap.Config{
|
||||||
|
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
Encoding: "json",
|
||||||
|
OutputPaths: []string{"logs/player-stdout.log"},
|
||||||
|
ErrorOutputPaths: []string{"logs/player-stderr.log"},
|
||||||
|
EncoderConfig: zap.NewProductionEncoderConfig(),
|
||||||
|
}.Build()
|
||||||
|
undo := zap.ReplaceGlobals(logger)
|
||||||
|
defer undo()
|
||||||
|
|
||||||
base := stages.NewBaseModel(viper.GetString("auth-endpoint"))
|
base := stages.NewBaseModel(viper.GetString("auth-endpoint"))
|
||||||
p := tea.NewProgram(stages.NewLandingModel(base))
|
p := tea.NewProgram(stages.NewLandingModel(base))
|
||||||
base.Push(types.Program{
|
base.Push(types.Program{
|
||||||
@@ -28,6 +39,8 @@ var playerCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
playerCmd.Flags().
|
||||||
|
String("host", "127.0.0.1", "")
|
||||||
playerCmd.Flags().
|
playerCmd.Flags().
|
||||||
Int("udp-listen-port", 18787, "")
|
Int("udp-listen-port", 18787, "")
|
||||||
playerCmd.Flags().
|
playerCmd.Flags().
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func (m *LobbyModel) serverSendReply(response bool) tea.Cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local := fmt.Sprintf("%s:%d",
|
local := fmt.Sprintf("%s:%d",
|
||||||
m.listener.Addr().(*net.TCPAddr).IP.String(),
|
viper.GetString("host"),
|
||||||
m.listener.Addr().(*net.TCPAddr).Port)
|
m.listener.Addr().(*net.TCPAddr).Port)
|
||||||
m.err = utils.SendPayload(local, m.remote,
|
m.err = utils.SendPayload(local, m.remote,
|
||||||
types.JoinResponse{Endpoint: local})
|
types.JoinResponse{Endpoint: local})
|
||||||
@@ -116,12 +116,7 @@ type clientScanMsg time.Time
|
|||||||
|
|
||||||
func (m *LobbyModel) clientScan() tea.Cmd {
|
func (m *LobbyModel) clientScan() tea.Cmd {
|
||||||
return tea.Tick(REFRESH_TIME, func(t time.Time) tea.Msg {
|
return tea.Tick(REFRESH_TIME, func(t time.Time) tea.Msg {
|
||||||
m.endpoints = []string{}
|
m.endpoints, m.err = utils.Ping(viper.GetStringSlice("udp-endpoints"))
|
||||||
for _, endpoint := range viper.GetStringSlice("udp-endpoints") {
|
|
||||||
if err := utils.Ping(endpoint); err == nil {
|
|
||||||
m.endpoints = append(m.endpoints, endpoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clientScanMsg(t)
|
return clientScanMsg(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,9 +86,8 @@ func (m *WordleClientModel) getState() tea.Cmd {
|
|||||||
|
|
||||||
func (m *WordleClientModel) postGuess(guess string) tea.Cmd {
|
func (m *WordleClientModel) postGuess(guess string) tea.Cmd {
|
||||||
return func() tea.Msg {
|
return func() tea.Msg {
|
||||||
b, err := msgpack.Marshal(wordle.OperationGuess{
|
b, err := msgpack.Marshal(wordle.PostGuessInput{
|
||||||
Username: m.client.UserInfo.Username,
|
Guess: guess,
|
||||||
Guess: guess,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.err = fmt.Errorf("failed to post guess, %w", err)
|
m.err = fmt.Errorf("failed to post guess, %w", err)
|
||||||
|
|||||||
38
test.go
38
test.go
@@ -1,38 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gitea.konchin.com/ytshih/inp2025/utils"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var testCmd = &cobra.Command{
|
|
||||||
Use: "test",
|
|
||||||
}
|
|
||||||
|
|
||||||
var testServerCmd = &cobra.Command{
|
|
||||||
Use: "server",
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
dataCh := make(chan string)
|
|
||||||
_, shutdown, err := utils.ListenUDPData(18787, dataCh)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer shutdown()
|
|
||||||
<-dataCh
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var testClientCmd = &cobra.Command{
|
|
||||||
Use: "client",
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
err := utils.Ping("localhost:18787")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
testCmd.AddCommand(testServerCmd)
|
|
||||||
testCmd.AddCommand(testClientCmd)
|
|
||||||
}
|
|
||||||
52
utils/udp.go
52
utils/udp.go
@@ -1,16 +1,22 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.konchin.com/ytshih/inp2025/types"
|
"gitea.konchin.com/ytshih/inp2025/types"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BUFFER_SIZE int = 1024
|
BUFFER_SIZE int = 1024
|
||||||
MAGIC_NUMBER int = 114514
|
MAGIC_NUMBER int = 114514
|
||||||
|
|
||||||
|
LISTEN_TIMEOUT = 200 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
type UDPReqType int
|
type UDPReqType int
|
||||||
@@ -36,24 +42,36 @@ func ListenUDPData(
|
|||||||
return ListenUDP(port, dataCh, nil)
|
return ListenUDP(port, dataCh, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ping(endpoint string) error {
|
func Ping(endpoints []string) ([]string, error) {
|
||||||
pingCh := make(chan string)
|
pingCh := make(chan string)
|
||||||
local, shutdown, err := ListenUDP(0, nil, pingCh)
|
local, shutdown, err := ListenUDP(0, nil, pingCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
err = SendRawPayload(endpoint, UDPPayload{
|
for _, endpoint := range endpoints {
|
||||||
MagicNumber: MAGIC_NUMBER,
|
SendRawPayload(endpoint, UDPPayload{
|
||||||
Endpoint: local,
|
MagicNumber: MAGIC_NUMBER,
|
||||||
Type: UDPReqTypePingRequest,
|
Endpoint: local,
|
||||||
})
|
Type: UDPReqTypePingRequest,
|
||||||
if err != nil {
|
})
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
time.Sleep(LISTEN_TIMEOUT)
|
||||||
|
doneCh <- struct{}{}
|
||||||
|
}()
|
||||||
|
ret := []string{}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-doneCh:
|
||||||
|
return ret, nil
|
||||||
|
case endpoint := <-pingCh:
|
||||||
|
ret = append(ret, endpoint)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
<-pingCh
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenUDP(
|
func ListenUDP(
|
||||||
@@ -61,11 +79,12 @@ func ListenUDP(
|
|||||||
dataCh chan string,
|
dataCh chan string,
|
||||||
pingCh chan string,
|
pingCh chan string,
|
||||||
) (string, types.ShutdownFunc, error) {
|
) (string, types.ShutdownFunc, error) {
|
||||||
conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: port})
|
conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: port})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, fmt.Errorf("failed to listen udp, %w", err)
|
return "", nil, fmt.Errorf("failed to listen udp, %w", err)
|
||||||
}
|
}
|
||||||
local := conn.LocalAddr().String()
|
addr, _ := net.ResolveUDPAddr("udp4", conn.LocalAddr().String())
|
||||||
|
local := fmt.Sprintf("%s:%d", viper.GetString("host"), addr.Port)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@@ -73,6 +92,11 @@ func ListenUDP(
|
|||||||
|
|
||||||
n, _, err := conn.ReadFromUDP(buffer)
|
n, _, err := conn.ReadFromUDP(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
zap.L().Error("fuck udp",
|
||||||
|
zap.Error(err))
|
||||||
|
if errors.Is(err, net.ErrClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +147,7 @@ func SendRawPayload(
|
|||||||
endpoint string,
|
endpoint string,
|
||||||
payload UDPPayload,
|
payload UDPPayload,
|
||||||
) error {
|
) error {
|
||||||
conn, err := net.Dial("udp", endpoint)
|
conn, err := net.Dial("udp4", endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to dial endpoint, %w", err)
|
return fmt.Errorf("failed to dial endpoint, %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user