Skip to content

Commit

Permalink
First implementation of server command
Browse files Browse the repository at this point in the history
Just received the message and returns a hard-coded response
  • Loading branch information
szaffarano committed Sep 19, 2021
1 parent d9a815b commit 8e7c875
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 1 deletion.
74 changes: 73 additions & 1 deletion cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,89 @@
package cmd

import (
"encoding/binary"

"github.com/apex/log"
"github.com/spf13/cobra"
"github.com/szaffarano/gotas/pkg/config"
"github.com/szaffarano/gotas/pkg/task"
)

func serverCmd() *cobra.Command {
daemon := false
var serverCmd = cobra.Command{
Use: "server",
Short: "Runs the server",
Run: func(_ *cobra.Command, _ []string) {
log.Info("not implemented")
server, err := task.NewServer()
if err != nil {
log.Fatalf("Error initializing server: %s", err.Error())
}
defer server.Close()

for {
client, err := server.NextClient()
if err != nil {
log.Errorf("Error receiving client: %s", err.Error())
}

go process(client)
}
},
}

serverCmd.Flags().BoolVarP(&daemon, "daemon", "d", false, "Runs server as a daemon")

return &serverCmd
}

func process(client *task.Client) {
log.Info("Processing new client")

defer client.Close()
c := config.Get()

buffer := make([]byte, c.Request.Limit)

// first 4 bytes are the message size
if num, err := client.Read(buffer[:4]); err != nil {
log.Errorf("Error reading size: %s", err.Error())
return
} else if num != 4 {
log.Errorf("Error reading size, expected 4 bytes, but got %d", num)
return
}
messageSize := int(binary.BigEndian.Uint32(buffer[:4]))

if messageSize > len(buffer) {
log.Errorf("Message limit exceeded: %d", messageSize)
client.Write([]byte("error"))
return
}

// messageSize includes the first 4 bytes
messageSize, err := client.Read(buffer[:messageSize-4])
if err != nil {
log.Errorf("Error reading: %s", err.Error())
return
}

if msg, err := task.NewMessage(string(buffer[:messageSize])); err != nil {
log.Errorf("Error parsing message", err)
} else {
log.Info("Message received")
log.Debug(msg.String())
response := task.Message{
Header: map[string]string{
"type": "response",
"code": "201",
"status": "Ok",
},
}

client.Write([]byte(response.Serialize()[:4]))
client.Write([]byte(response.Serialize()[4:]))
}

log.Info("Finishing")
}
89 changes: 89 additions & 0 deletions pkg/task/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright © 2021 Sebastián Zaffarano <sebas@zaffarano.com.ar>.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package task

import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net"

"github.com/apex/log"
"github.com/szaffarano/gotas/pkg/config"
)

type Client struct {
conn net.Conn
}

func (c *Client) Read(buf []byte) (int, error) {
return c.conn.Read(buf)
}

func (c *Client) Write(buf []byte) (int, error) {
return c.conn.Write(buf)
}

func (c *Client) Close() error {
return c.conn.Close()
}

type Server struct {
listener net.Listener
}

func (s *Server) NextClient() (*Client, error) {
if conn, err := s.listener.Accept(); err != nil {
return nil, err
} else {
return &Client{conn}, nil
}
}

func (s *Server) Close() {
s.listener.Close()
}

func NewServer() (*Server, error) {
var ca []byte
var cert tls.Certificate
var err error
conf := config.Get()

if ca, err = ioutil.ReadFile(conf.Ca.Cert); err != nil {
log.Fatalf("Failed to read root CA file", err)
}

roots := x509.NewCertPool()
if ok := roots.AppendCertsFromPEM(ca); !ok {
log.Fatal("failed to parse root certificate")
}

if cert, err = tls.LoadX509KeyPair(conf.Server.Cert, conf.Server.Key); err != nil {
log.Fatalf("Error reading certificate file", err)
}

cfg := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: roots,
}

listener, err := tls.Listen("tcp", conf.Server.BindAddress, cfg)
if err != nil {
return nil, err
}

log.Infof("Listening on %s...", conf.Server.BindAddress)
return &Server{listener}, nil
}

0 comments on commit 8e7c875

Please sign in to comment.