From 2c4a18434700f670fede8dc8228fa50b994bce32 Mon Sep 17 00:00:00 2001 From: LandaMm Date: Wed, 16 Apr 2025 13:14:16 +0200 Subject: [PATCH] chore: move files --- server/constants.go | 40 ---------- server/packet.go | 188 -------------------------------------------- server/request.go | 89 --------------------- server/response.go | 90 --------------------- server/router.go | 52 ------------ server/server.go | 86 -------------------- 6 files changed, 545 deletions(-) delete mode 100644 server/constants.go delete mode 100644 server/packet.go delete mode 100644 server/request.go delete mode 100644 server/response.go delete mode 100644 server/router.go delete mode 100644 server/server.go diff --git a/server/constants.go b/server/constants.go deleted file mode 100644 index 89c4853..0000000 --- a/server/constants.go +++ /dev/null @@ -1,40 +0,0 @@ - -package server - -const ( - H_STATUS = "status" - H_DATA_FORMAT = "data-format" - H_ROUTE = "route" -) - -const ( - DF_BYTES = "bytes" - DF_TEXT = "text" - DF_JSON = "json" -) - -const ( - E_UTF8 = "utf-8" -) - -const ( - STATUS_SUCCESS = 0 - STATUS_NOTFOUND = 69 - STATUS_INTERNALERR = 129 -) - -var DATA_FORMATS map[string]string = map[string]string{ - "bytes": DF_BYTES, - "text": DF_TEXT, - "json": DF_JSON, -} - -var ENCODINGS map[string]string = map[string]string{ - "utf-8": E_UTF8, -} - -type DataFormat struct { - Format string - Encoding string -} - diff --git a/server/packet.go b/server/packet.go deleted file mode 100644 index 50ecd1e..0000000 --- a/server/packet.go +++ /dev/null @@ -1,188 +0,0 @@ -package server - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "net" -) - -const ( - Magic uint32 = 0xDEADBEEF -) - -const ( - PacketVersion int = 1 -) - -type RawPacket struct { - Magic uint32 - Version uint8 - Flags uint8 - HeaderSize uint16 - PayloadSize uint32 - Header []byte - Payload []byte -} - -type Packet struct { - Version int - Flags int - Headers map[string]string - Payload []byte -} - -type PacketDuplex struct { - conn net.Conn -} - -func BuildPacket(headers map[string]string, payload []byte) *Packet { - return &Packet{ - Version: PacketVersion, - Flags: 0, // TODO: - Headers: headers, - Payload: payload, - } -} - -func ParseHeaders(rawHeaders []byte, headers *map[string]string) error { - i := 0 - for i < len(rawHeaders) { - if rawHeaders[i] == '\n' { - break - } - var key string - for rawHeaders[i] != ':' { - if rawHeaders[i] != ' ' { - key += string(rawHeaders[i]) - } - i++ - } - i++ - var value string - for rawHeaders[i] != '\n' { - if rawHeaders[i] != ' ' { - value += string(rawHeaders[i]) - } - i++ - } - i++ - (*headers)[key] = value - } - return nil -} - -func SerializeHeaders(headers *map[string]string) []byte { - buf := new(bytes.Buffer) - for k, v := range(*headers) { - fmt.Fprintf(buf, "%s:%s\n", k, v) - } - fmt.Fprintf(buf, "\n") - return buf.Bytes() -} - -func NewPacketDuplex(conn net.Conn) *PacketDuplex { - return &PacketDuplex{ - conn, - } -} - -func (r *PacketDuplex) ReadPacket() (*Packet, error) { - rpkt := &RawPacket{} - - err := binary.Read(r.conn, binary.BigEndian, &rpkt.Magic) - if err != nil { - return nil, err - } - - if rpkt.Magic != Magic { - return nil, errors.New("Magic bytes are invalid") - } - - err = binary.Read(r.conn, binary.BigEndian, &rpkt.Version) - if err != nil { - return nil, err - } - - err = binary.Read(r.conn, binary.BigEndian, &rpkt.Flags) - if err != nil { - return nil, err - } - - err = binary.Read(r.conn, binary.BigEndian, &rpkt.HeaderSize) - if err != nil { - return nil, err - } - - err = binary.Read(r.conn, binary.BigEndian, &rpkt.PayloadSize) - if err != nil { - return nil, err - } - - rpkt.Header = make([]byte, rpkt.HeaderSize) - if _, err := io.ReadFull(r.conn, rpkt.Header); err != nil { - return nil, err - } - - rpkt.Payload = make([]byte, rpkt.PayloadSize) - if _, err := io.ReadFull(r.conn, rpkt.Payload); err != nil { - return nil, err - } - - pkt := &Packet{ - Version: int(rpkt.Version), - Flags: int(rpkt.Flags), - Headers: make(map[string]string), - Payload: rpkt.Payload, - } - - ParseHeaders(rpkt.Header, &pkt.Headers) - - return pkt, nil -} - -func (r *PacketDuplex) WritePacket(packet *Packet) (int, error) { - buf := new(bytes.Buffer) - - if err := binary.Write(buf, binary.BigEndian, Magic); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write magic into packet: %s", err.Error())) - } - - if err := binary.Write(buf, binary.BigEndian, uint8(packet.Version)); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write version into packet: %s", err.Error())) - } - - if err := binary.Write(buf, binary.BigEndian, uint8(packet.Flags)); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write flags into packet: %s", err.Error())) - } - - rawHeaders := SerializeHeaders(&packet.Headers) - headerSize := len(rawHeaders) - payloadSize := len(packet.Payload) - - if err := binary.Write(buf, binary.BigEndian, uint16(headerSize)); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write header size into packet: %s", err.Error())) - } - - if err := binary.Write(buf, binary.BigEndian, uint32(payloadSize)); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write payload size into packet: %s", err.Error())) - } - - if _, err := buf.Write(rawHeaders[:headerSize]); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write raw headers: %s", err.Error())) - } - - if _, err := buf.Write(packet.Payload[:payloadSize]); err != nil { - return 0, errors.New(fmt.Sprintf("Failed to write payload: %s", err.Error())) - } - - n, err := r.conn.Write(buf.Bytes()) - if err != nil { - return 0, errors.New(fmt.Sprintf("Failed to send packet over connection: %s", err.Error())) - } - - return n, nil -} - diff --git a/server/request.go b/server/request.go deleted file mode 100644 index 9858443..0000000 --- a/server/request.go +++ /dev/null @@ -1,89 +0,0 @@ -package server - -import ( - "errors" - "fmt" - "net" - "slices" - "strings" -) - -type Request struct { - conn net.Conn - packet *Packet -} - -func NewRequest(conn net.Conn, packet *Packet) *Request { - return &Request{ - conn, packet, - } -} - -func (req *Request) Conn() net.Conn { - return req.conn -} - -func (req *Request) GetHeader(key string) (string, bool) { - value, ok := req.packet.Headers[key] - return value, ok -} - -func (req *Request) GetDataFormat() (*DataFormat, error) { - // TODO: use predefined header names - format, ok := req.packet.Headers["data-format"] - if !ok { - return nil, errors.New("Data format header is not provided in request") - } - - parts := strings.Split(format, ":") - if len(parts) != 2 { - if format == "bytes" { - return &DataFormat{ - Format: DF_BYTES, - }, nil - } - return nil, errors.New("Invalid data format header") - } - - f, ok := DATA_FORMATS[parts[0]] - if !ok { - return nil, errors.New(fmt.Sprintf("Unknown data format: %s", parts[0])) - } - - encoding, ok := ENCODINGS[parts[1]] - if !ok { - return nil, errors.New(fmt.Sprintf("Unknown payload encoding: %s", parts[1])) - } - - return &DataFormat{ - Format: f, - Encoding: encoding, - }, nil -} - -func (req *Request) ExtractText() (string, error) { - df, err := req.GetDataFormat() - if err != nil { - return "", err - } - - if !slices.Contains([]string{DF_TEXT, DF_JSON}, df.Format) { - return "", errors.New(fmt.Sprintf("Data format '%s' cannot be extracted as text", df.Format)) - } - - return string(req.packet.Payload), nil -} - -func (req *Request) ExtractBytes() ([]byte, error) { - df, err := req.GetDataFormat() - if err != nil { - return nil, err - } - - if df.Format != "bytes" { - return nil, errors.New(fmt.Sprintf("Data format '%s' is invalid for extracting bytes", df.Format)) - } - - return req.packet.Payload, nil -} - diff --git a/server/response.go b/server/response.go deleted file mode 100644 index d40ce10..0000000 --- a/server/response.go +++ /dev/null @@ -1,90 +0,0 @@ -package server - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "maps" - "strconv" -) - -type Response struct { - StatusCode int - Format DataFormat - Headers map[string]string - Payload []byte -} - -func NewStatusResponse(status int) *Response { - return &Response{ - StatusCode: status, - Headers: make(map[string]string), - Format: DataFormat{ - Format: DF_BYTES, - Encoding: "", - }, - Payload: make([]byte, 0), - } -} - -func NewTextResponse(text string) *Response { - return &Response{ - StatusCode: STATUS_SUCCESS, - Headers: make(map[string]string), - Format: DataFormat{ - Format: DF_TEXT, - Encoding: E_UTF8, - }, - Payload: []byte(text), - } -} - -func NewJsonResponse(data map[string]string) (*Response, error) { - jsonBytes, err := json.Marshal(data) - if err != nil { - return nil, err - } - - return &Response{ - StatusCode: STATUS_SUCCESS, - Headers: make(map[string]string), - Format: DataFormat{ - Format: DF_JSON, - Encoding: E_UTF8, - }, - Payload: jsonBytes, - }, nil -} - -func (res *Response) ToPacket() *Packet { - headers := make(map[string]string) - - maps.Copy(headers, res.Headers) - - headers[H_DATA_FORMAT] = fmt.Sprintf("%s:%s", res.Format.Format, res.Format.Encoding) - headers[H_STATUS] = strconv.Itoa(res.StatusCode) - - return BuildPacket(headers, res.Payload) -} - -func (res *Response) AddHeader(key, value string) { - if _, ok := res.Headers[key]; ok { - log.Printf("WARN: Rewriting already existing header: '%s'\n", key) - } - res.Headers[key] = value -} - -func (res *Response) Write(p []byte) (int, error) { - buf := new(bytes.Buffer) - - n, err := buf.Write(p) - if err != nil { - return n, err - } - - res.Payload = buf.Bytes() - - return n, err -} - diff --git a/server/router.go b/server/router.go deleted file mode 100644 index 1ba68fc..0000000 --- a/server/router.go +++ /dev/null @@ -1,52 +0,0 @@ -package server - -import ( - "errors" - "log" - "net" -) - -type RouteHandler func(req *Request) *Response - -type Router struct { - Routes map[string]RouteHandler -} - -func NewRouter() *Router { - return &Router{ - Routes: make(map[string]RouteHandler), - } -} - -func (r *Router) AddRoute(pathname string, handler RouteHandler) { - if _, ok := r.Routes[pathname]; ok { - log.Printf("WARN: Rewriting existing route '%s'\n", pathname) - } - r.Routes[pathname] = handler -} - -func (r *Router) Handle(conn net.Conn) error { - defer conn.Close() - - log.Printf("Got new connection from %s\n", conn.RemoteAddr().String()) - - dupl := NewPacketDuplex(conn) - - // TODO: Ability to keep connection alive - packet, err := dupl.ReadPacket() - if err != nil { - return err - } - - if route, ok := packet.Headers["route"]; ok { - log.Printf("[ROUTER] New connection to '%s'", route) - if handler, ok := r.Routes[route]; ok { - req := NewRequest(conn, packet) - res := handler(req) - _, err := dupl.WritePacket(res.ToPacket()) - return err - } - } - return errors.New("Not Found") -} - diff --git a/server/server.go b/server/server.go deleted file mode 100644 index fffe599..0000000 --- a/server/server.go +++ /dev/null @@ -1,86 +0,0 @@ -package server - -import ( - "log" - "net" - "sync" -) - -type Server struct { - Addr string - Running bool - ConnChan chan net.Conn - listener net.Listener - mu sync.Mutex -} - -func NewServer(addr string) *Server { - return &Server{ - Addr: addr, - Running: false, - } -} - -func (s *Server) SetListener(ln chan net.Conn) { - s.ConnChan = ln -} - -func (s *Server) Start() error { - ln, err := net.Listen("tcp", ":3000") - if err != nil { - return err - } - - s.mu.Lock() - s.listener = ln - s.Running = true - s.mu.Unlock() - - for s.IsRunning() { - log.Println("DEBUG:", "Waiting for new connection to accept") - conn, err := ln.Accept() - if err != nil { - if !s.IsRunning() { - break; - } - return err - } - - if s.ConnChan != nil { - s.ConnChan <- conn - } - } - - log.Println("DEBUG:", "Finished listening for connections") - - s.mu.Lock() - s.Running = false - s.listener = nil - s.mu.Unlock() - - return nil -} - - -func (s *Server) Stop() error { - s.mu.Lock() - defer s.mu.Unlock() - - s.Running = false - if s.listener != nil { - return s.listener.Close() - } - if s.ConnChan != nil { - close(s.ConnChan) - } - - return nil -} - -func (s *Server) IsRunning() bool { - s.mu.Lock() - defer s.mu.Unlock() - return s.Running -} - -