From 216b6a2f59cca9f475beb07653d2e919a9454ff8 Mon Sep 17 00:00:00 2001 From: LandaMm Date: Sun, 20 Apr 2025 13:53:07 +0200 Subject: [PATCH] feat: hspnet cli --- cmd/hspnet.go | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/main.go | 166 -------------------------------------------------- 2 files changed, 165 insertions(+), 166 deletions(-) create mode 100644 cmd/hspnet.go delete mode 100644 cmd/main.go diff --git a/cmd/hspnet.go b/cmd/hspnet.go new file mode 100644 index 0000000..1c11716 --- /dev/null +++ b/cmd/hspnet.go @@ -0,0 +1,165 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "net" + "os" + "os/signal" + "strings" + "syscall" + + "github.com/LandaMm/hsp-go/hsp" + "github.com/LandaMm/hsp-go/hsp/client" + "github.com/LandaMm/hsp-go/hsp/server" + "github.com/chzyer/readline" +) + +func Index(req *hsp.Request) *hsp.Response { + pkt := req.GetRawPacket() + + fmt.Printf("%s %s\n", strings.ToUpper(req.GetRequestKind()), req.GetRoute()) + fmt.Println("Headers:") + + for k, v := range pkt.Headers { + fmt.Printf("\t%s: %s\n", k, v) + } + + df, err := req.GetDataFormat() + if err != nil { + h, ok := req.GetHeader(hsp.H_DATA_FORMAT) + if !ok { + fmt.Println("ERR: Data-Format header is not present") + return hsp.NewErrorResponse(err) + } + fmt.Printf("Invalid Data Format: %s\n", h) + return hsp.NewErrorResponse(err) + } + + fmt.Printf("Payload (%s):\n", df.String()) + + switch df.Format { + case "text": + body, err := req.ExtractText() + if err != nil { + fmt.Println("ERR: Failed to extract text from payload:", err) + return hsp.NewErrorResponse(err) + } + + fmt.Println(body) + break + case "json": + var out map[string]any + err := req.ExtractJson(&out) + if err != nil { + fmt.Println("ERR: Failed to extract json from payload:", err) + return hsp.NewErrorResponse(err) + } + + fmt.Println(json.MarshalIndent(out, "", " ")) + break + case "bytes": + bts, err := req.ExtractBytes() + if err != nil { + fmt.Println("ERR: Failed to extract bytes from payload:", err) + return hsp.NewErrorResponse(err) + } + + fmt.Println(bts) + break; + default: + fmt.Printf("ERR: Unsupported data format: %s\n", df.String()) + } + + return hsp.NewStatusResponse(hsp.STATUS_SUCCESS) +} + +func StartServer(addr *hsp.Adddress) { + srv := server.NewServer(*addr) + fmt.Printf("Server created on address: %s\n", srv.Addr.String()) + + handler := make(chan net.Conn, 1) + + router := server.NewRouter() + + router.AddRoute("/", Index) + + srv.SetListener(handler) + + go func() { + for { + conn := <-handler + if err := router.Handle(conn); err != nil { + fmt.Println("ERR: Couldn't handle connection:", err.Error()) + } + } + }() + + sigs := make(chan os.Signal, 1) + + go func() { + s := <-sigs + if s == syscall.SIGINT || s == syscall.SIGTERM { + fmt.Println("Gracefully shutting down the server") + if err := srv.Stop(); err != nil { + fmt.Println("Failed to close the server:", err) + } + } + }() + + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + if err := srv.Start(); err != nil { + fmt.Println("ERR: Failed to start server:", err) + } +} + +func StartSession(addr *hsp.Adddress) { + fmt.Println("Starting session on", addr.String()) + + rl, err := readline.New("> ") + if err != nil { + fmt.Println("ERR: Failed to open readline session:", err) + } + + defer rl.Close() + + c := client.NewClient() + + for { + line, err := rl.Readline() + if err != nil { + break + } + + c.SendText(addr.String(), line) + } +} + +func main() { + var listening bool + flag.BoolVar(&listening, "server", false, "start a simple server") + + var host string + var service string + + flag.StringVar(&host, "host", "localhost", "specify target host (default: localhost)") + flag.StringVar(&service, "port", "998", "specify target port (default: 998)") + + flag.Parse() + + a := fmt.Sprintf("%s:%s", host, service) + addr, err := hsp.ParseAddress(a) + if err != nil { + fmt.Printf("ERR: Invalid address %s: %v\n", a, err) + return + } + + if listening { + StartServer(addr) + return + } + + StartSession(addr) +} diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index c159202..0000000 --- a/cmd/main.go +++ /dev/null @@ -1,166 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "log" - "net" - "os" - "os/signal" - "syscall" - "time" - - "github.com/LandaMm/hsp-go/hsp" - "github.com/LandaMm/hsp-go/hsp/client" - "github.com/LandaMm/hsp-go/hsp/server" -) - -func PingPongRoute(req *hsp.Request) *hsp.Response { - log.Println("Ping pong request:", req.GetRawPacket()) - df, err := req.GetDataFormat() - if err != nil { - return hsp.NewErrorResponse(err) - } - - log.Println("Data format of the request:", df) - - text, err := req.ExtractText() - if err != nil { - return hsp.NewErrorResponse(err) - } - - log.Println("Received text from req:", text) - - // return hsp.NewStatusResponse(hsp.STATUS_SUCCESS) - res, err := hsp.NewJsonResponse(map[string]any{ - "success": true, - "message": text, - }) - - if err != nil { - return hsp.NewErrorResponse(err) - } - - return res -} - -func FileUploadStreamer(req *hsp.Request, c chan []byte) { - log.Println("[MAIN] File Upload request:", req.GetRawPacket()) - - filename := "received.bin" - - file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - log.Fatalf("Failed to open file: %v", err) - } - - defer file.Close() - - for buf := range c { - if _, err := file.Write(buf); err != nil { - log.Printf("Write error: %v", err) - } - } -} - -func JsonMockRoute(req *hsp.Request) *hsp.Response { - log.Println("[JSON MOCK] New request:", req.GetRawPacket()) - - var test map[string]any - - if err := req.ExtractJson(&test); err != nil { - return hsp.NewErrorResponse(err) - } - - log.Println("Json data from request:", test) - - res, err := hsp.NewJsonResponse(test) - if err != nil { - return hsp.NewErrorResponse(err) - } - - return res -} - -func main() { - addr, err := hsp.ParseAddress("127.0.0.1") - if err != nil { - panic(err) - } - srv := server.NewServer(*addr) - fmt.Printf("Server created on address: %s\n", srv.Addr.String()) - - handler := make(chan net.Conn, 1) - - router := server.NewRouter() - - router.AddStreamer("/file-upload", FileUploadStreamer) - router.AddRoute("/ping-pong", PingPongRoute) - router.AddRoute("/mock-json", JsonMockRoute) - - srv.SetListener(handler) - - go func() { - for { - conn := <-handler - if err := router.Handle(conn); err != nil { - log.Println("[MAIN] Error handling connection:", err.Error()) - } - } - }() - - sigs := make(chan os.Signal, 1) - - go func() { - s := <-sigs - if s == syscall.SIGINT || s == syscall.SIGTERM { - log.Println("Gracefully shutting down the server") - if err := srv.Stop(); err != nil { - log.Fatalln("Failed to close the server:", err) - } - } - }() - - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - - go func() { - time.Sleep(3 * time.Second) - c := client.NewClient() - rsp, err := c.SendText("localhost/ping-pong", "Hello, guys!") - if err != nil { - log.Fatalf("[CLIENT] Failed to received response from ping-pong: %s\n", err) - } - log.Println("[CLIENT] received response from remote server:", rsp) - bts, err := json.Marshal(rsp) - if err != nil { - log.Fatalln("[CLIENT] Failed to serialize response from server") - } - - log.Println("[CLIENT] Serialized response from server:", string(bts)) - }() - - go func() { - time.Sleep(1 * time.Second) - c := client.NewClient() - rsp, err := c.SendJson("localhost/mock-json", map[string]any{ - "mock": true, - "message": "Hello, everyone!", - }) - - if err != nil { - log.Fatalf("[CLIENT] Failed to received response from ping-pong: %s\n", err) - } - - log.Println("[CLIENT] received response from remote server:", rsp) - bts, err := json.Marshal(rsp) - if err != nil { - log.Fatalln("[CLIENT] Failed to serialize response from server") - } - - log.Println("[CLIENT] Serialized response from server:", string(bts)) - }() - - if err := srv.Start(); err != nil { - log.Fatalln("Failed to start server:", err) - } -}