mirror of
https://github.com/Kyren223/eko.git
synced 2026-07-21 11:01:05 +00:00
feat: add ui for client
This commit is contained in:
3
cmd/client/client.log
Normal file
3
cmd/client/client.log
Normal file
@@ -0,0 +1,3 @@
|
||||
2024/10/17 16:45:33 client started, waiting for user input...
|
||||
2024/10/17 16:45:33 established connection with server: 127.0.0.1:7223
|
||||
2024/10/17 16:45:33 sent request to server
|
||||
26
go.mod
26
go.mod
@@ -4,4 +4,28 @@ go 1.23.2
|
||||
|
||||
require github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||
|
||||
require github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
require (
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.13.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.1.1
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
)
|
||||
|
||||
43
go.sum
43
go.sum
@@ -1,12 +1,55 @@
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY=
|
||||
github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
|
||||
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
|
||||
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -1,79 +1,94 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kyren223/eko/internal/packet"
|
||||
"github.com/kyren223/eko/pkg/assert"
|
||||
)
|
||||
|
||||
//go:embed server.crt
|
||||
var certPEM []byte
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
|
||||
func Run() {
|
||||
logFile, err := os.OpenFile("client.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer logFile.Close()
|
||||
log.SetOutput(logFile)
|
||||
|
||||
certPool := x509.NewCertPool()
|
||||
if !certPool.AppendCertsFromPEM(certPEM) {
|
||||
log.Fatalln("failed to append server certificate")
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
tlsConfig = &tls.Config{
|
||||
RootCAs: certPool,
|
||||
ServerName: "localhost",
|
||||
}
|
||||
|
||||
log.Println("client started, waiting for user input...")
|
||||
for {
|
||||
fmt.Print("> ")
|
||||
input, _ := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
input = strings.TrimSpace(input)
|
||||
if input == ":q" || input == "exit" || input == "quit" {
|
||||
break
|
||||
}
|
||||
err := processRequest(input, tlsConfig)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
startUI()
|
||||
|
||||
// for {
|
||||
// fmt.Print("> ")
|
||||
// input, _ := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
// input = strings.TrimSpace(input)
|
||||
// if input == ":q" || input == "exit" || input == "quit" {
|
||||
// break
|
||||
// }
|
||||
// if input == "" {
|
||||
// continue
|
||||
// }
|
||||
// err := processRequest(input)
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
func processRequest(input string, tlsConfig *tls.Config) error {
|
||||
func sendMessage(message string) error {
|
||||
request := packet.SendMessageMessage{Content: message}
|
||||
var response packet.EkoMessage
|
||||
if err := SendAndReceive(&request, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
assert.Assert(response.Message == "Eko OK", "server should return an OK status")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMessages() ([]string, error) {
|
||||
request := packet.GetMessagesMessage{}
|
||||
var response packet.MessagesMessage
|
||||
if err := SendAndReceive(&request, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var messages []string
|
||||
for _, message := range response.Messages {
|
||||
messages = append(messages, message.Contents)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func SendAndReceive(request packet.TypedMessage, response packet.TypedMessage) error {
|
||||
conn, err := tls.Dial("tcp4", ":7223", tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error establishing connection with server: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
log.Println("established connection with server:", conn.RemoteAddr().String())
|
||||
|
||||
if input == "SHOW" {
|
||||
request := packet.GetMessagesMessage{}
|
||||
var response packet.MessagesMessage
|
||||
if err := SendAndReceive(conn, &request, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println("server response:", response.Messages)
|
||||
} else {
|
||||
request := packet.SendMessageMessage{Content: input}
|
||||
var response packet.EkoMessage
|
||||
if err := SendAndReceive(conn, &request, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println("server response:", response.Message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendAndReceive(conn net.Conn, request packet.TypedMessage, response packet.TypedMessage) error {
|
||||
encoder, err := packet.NewMsgPackEncoder(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error encoding request: %v", err)
|
||||
@@ -92,7 +107,14 @@ func SendAndReceive(conn net.Conn, request packet.TypedMessage, response packet.
|
||||
select {
|
||||
case responsePacket := <-out:
|
||||
if err := responsePacket.DecodePayload(response); err != nil {
|
||||
return fmt.Errorf("error decoding response: %v", err)
|
||||
if responsePacket.Type() != packet.TypeError {
|
||||
return fmt.Errorf("error decoding response: %v", err)
|
||||
}
|
||||
var errorResponse packet.ErrorMessage
|
||||
if err := responsePacket.DecodePayload(&errorResponse); err != nil {
|
||||
return fmt.Errorf("error decoding error packet: %w", err)
|
||||
}
|
||||
return fmt.Errorf("server error: %v", errorResponse.Error)
|
||||
}
|
||||
|
||||
case err := <-outErr:
|
||||
|
||||
124
internal/client/ui.go
Normal file
124
internal/client/ui.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/cursor"
|
||||
"github.com/charmbracelet/bubbles/textarea"
|
||||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
|
||||
"github.com/kyren223/eko/pkg/assert"
|
||||
)
|
||||
|
||||
func startUI() {
|
||||
p := tea.NewProgram(initialModel(), tea.WithAltScreen())
|
||||
if _, err := p.Run(); err != nil {
|
||||
log.Println("charm ui error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
type model struct {
|
||||
viewport viewport.Model
|
||||
messages []string
|
||||
textarea textarea.Model
|
||||
senderStyle lipgloss.Style
|
||||
err error
|
||||
}
|
||||
|
||||
func initialModel() model {
|
||||
ta := textarea.New()
|
||||
ta.Placeholder = "Send a message..."
|
||||
ta.Focus()
|
||||
|
||||
ta.Prompt = "┃ "
|
||||
ta.CharLimit = 280
|
||||
|
||||
ta.SetWidth(30)
|
||||
ta.SetHeight(3)
|
||||
|
||||
// Remove cursor line styling
|
||||
ta.FocusedStyle.CursorLine = lipgloss.NewStyle()
|
||||
|
||||
ta.ShowLineNumbers = false
|
||||
|
||||
vp := viewport.New(30, 20)
|
||||
vp.SetContent("Welcome to Eko!\n Type a message and press Enter to send.")
|
||||
|
||||
ta.KeyMap.InsertNewline.SetEnabled(false)
|
||||
|
||||
messages, err := getMessages()
|
||||
assert.NoError(err, "TODO HANDLE ERROR")
|
||||
vp.SetContent(strings.Join(messages, "\n"))
|
||||
|
||||
return model{
|
||||
textarea: ta,
|
||||
messages: messages,
|
||||
viewport: vp,
|
||||
senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")),
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return textarea.Blink
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.viewport.Width = msg.Width
|
||||
m.textarea.SetWidth(msg.Width)
|
||||
return m, tea.Printf("%dx%d", msg.Width, msg.Height)
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyEsc, tea.KeyCtrlC:
|
||||
// Quit.
|
||||
fmt.Println(m.textarea.Value())
|
||||
return m, tea.Quit
|
||||
case tea.KeyEnter:
|
||||
value := m.textarea.Value()
|
||||
|
||||
content := strings.TrimSpace(value)
|
||||
if content == "" {
|
||||
// Don't send empty messages.
|
||||
return m, nil
|
||||
}
|
||||
assert.NoError(sendMessage(content), "TODO HANDLE ERROR")
|
||||
messages, err := getMessages()
|
||||
assert.NoError(err, "TODO HANDLE ERROR")
|
||||
|
||||
// m.messages = append(m.messages, m.senderStyle.Render("You: ")+content)
|
||||
m.messages = messages
|
||||
m.viewport.SetContent(strings.Join(m.messages, "\n"))
|
||||
m.textarea.Reset()
|
||||
m.viewport.GotoBottom()
|
||||
return m, nil
|
||||
default:
|
||||
// Send all other keypresses to the textarea.
|
||||
var cmd tea.Cmd
|
||||
m.textarea, cmd = m.textarea.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
case cursor.BlinkMsg:
|
||||
// Textarea should also process cursor blinks.
|
||||
var cmd tea.Cmd
|
||||
m.textarea, cmd = m.textarea.Update(msg)
|
||||
return m, cmd
|
||||
|
||||
default:
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
return fmt.Sprintf(
|
||||
"%s\n\n%s",
|
||||
m.viewport.View(),
|
||||
m.textarea.View(),
|
||||
) + "\n\n"
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (p Packet) PayloadLength() uint16 {
|
||||
}
|
||||
|
||||
func (p Packet) String() string {
|
||||
return fmt.Sprintf("{v%v %v %v %v: %v}", p.data[0], p.Encoding().String(), p.Type().String(), p.PayloadLength(), p.Payload())
|
||||
return fmt.Sprintf("{v%v %v %v [%v bytes...]}", p.Version(), p.Encoding().String(), p.Type().String(), p.PayloadLength())
|
||||
}
|
||||
|
||||
// The payload data, caller must not modify the returned slice, even temporarily
|
||||
|
||||
@@ -6,11 +6,13 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kyren223/eko/internal/data"
|
||||
"github.com/kyren223/eko/internal/packet"
|
||||
"github.com/kyren223/eko/pkg/assert"
|
||||
"github.com/kyren223/eko/pkg/snowflake"
|
||||
)
|
||||
|
||||
@@ -23,12 +25,14 @@ func handleConnection(conn net.Conn, wg *sync.WaitGroup) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
out, outErr := packet.RunFramer(ctx, conn)
|
||||
log.Printf("client %v: running framer\n", conn.RemoteAddr().String())
|
||||
|
||||
outer:
|
||||
for {
|
||||
select {
|
||||
case packet := <-out:
|
||||
case packet, ok := <-out:
|
||||
if !ok {
|
||||
break outer
|
||||
}
|
||||
log.Printf("client %v: request packet: %v\n", conn.RemoteAddr().String(), packet)
|
||||
responsePacket, err := handlePacket(packet)
|
||||
log.Printf("client %v: response packet: %v\n", conn.RemoteAddr().String(), responsePacket)
|
||||
@@ -43,16 +47,13 @@ outer:
|
||||
}
|
||||
|
||||
case err := <-outErr:
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
if err == packet.PacketUnsupportedEncoding {
|
||||
err := unsupportedEncodingErrorPacket.Into(conn)
|
||||
log.Printf("client %v: error writing unsupported encoding packet: %v\n", conn.RemoteAddr().String(), err)
|
||||
} else if err == packet.PacketUnsupportedType {
|
||||
err := unsupportedTypeErrorPacket.Into(conn)
|
||||
log.Printf("client %v: error writing unsupported type packet: %v\n", conn.RemoteAddr().String(), err)
|
||||
} else {
|
||||
} else if err != nil {
|
||||
log.Printf("client %v: internal error: %v\n", conn.RemoteAddr().String(), err)
|
||||
}
|
||||
break outer
|
||||
@@ -65,6 +66,7 @@ outer:
|
||||
}
|
||||
|
||||
func handlePacket(pkt packet.Packet) (packet.Packet, error) {
|
||||
var response packet.TypedMessage
|
||||
switch pkt.Type() {
|
||||
case packet.TypeEko:
|
||||
var request packet.EkoMessage
|
||||
@@ -72,51 +74,49 @@ func handlePacket(pkt packet.Packet) (packet.Packet, error) {
|
||||
return packet.Packet{}, fmt.Errorf("decode error: %v", err)
|
||||
}
|
||||
|
||||
response := packet.EkoMessage{Message: "Eko \"" + request.Message + "\""}
|
||||
encoder, err := packet.NewMsgPackEncoder(&response)
|
||||
if err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("encode error: %v", err)
|
||||
}
|
||||
return packet.NewPacket(encoder), nil
|
||||
response = &packet.EkoMessage{Message: "Eko \"" + request.Message + "\""}
|
||||
case packet.TypeSendMessage:
|
||||
var request packet.SendMessageMessage
|
||||
if err := pkt.DecodePayload(&request); err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("decode error: %v", err)
|
||||
}
|
||||
|
||||
content := strings.TrimSpace(request.Content)
|
||||
if content == "" {
|
||||
response = &packet.ErrorMessage{Error: "content must not be blank"}
|
||||
break
|
||||
}
|
||||
|
||||
message := data.Message{
|
||||
Id: node.Generate(),
|
||||
SenderId: node.Generate(),
|
||||
FrequencyId: node.Generate(),
|
||||
NetworkId: node.Generate(),
|
||||
Contents: request.Content,
|
||||
Contents: content,
|
||||
}
|
||||
messages = append(messages, message)
|
||||
|
||||
response := packet.EkoMessage{Message: "Eko OK"}
|
||||
encoder, err := packet.NewMsgPackEncoder(&response)
|
||||
if err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("encode error: %v", err)
|
||||
}
|
||||
return packet.NewPacket(encoder), nil
|
||||
response = &packet.EkoMessage{Message: "Eko OK"}
|
||||
case packet.TypeGetMessages:
|
||||
var request packet.GetMessagesMessage
|
||||
if err := pkt.DecodePayload(&request); err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("decode error: %v", err)
|
||||
}
|
||||
|
||||
response := packet.MessagesMessage{Messages: messages}
|
||||
encoder, err := packet.NewMsgPackEncoder(&response)
|
||||
if err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("encode error: %v", err)
|
||||
}
|
||||
return packet.NewPacket(encoder), nil
|
||||
response = &packet.MessagesMessage{Messages: messages}
|
||||
default:
|
||||
return packet.Packet{}, errors.New("TODO: not implemented yet")
|
||||
}
|
||||
|
||||
assert.NotNil(response, "response must always be set")
|
||||
encoder, err := packet.NewMsgPackEncoder(response)
|
||||
if err != nil {
|
||||
return packet.Packet{}, fmt.Errorf("encode error: %v", err)
|
||||
}
|
||||
return packet.NewPacket(encoder), nil
|
||||
}
|
||||
|
||||
var (
|
||||
node = snowflake.NewNode(1)
|
||||
messages []data.Message = make([]data.Message, 10)
|
||||
node = snowflake.NewNode(1)
|
||||
messages []data.Message
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user