Skip to content

Commit

Permalink
Base containerized application workflow (#17)
Browse files Browse the repository at this point in the history
* feat: sample TCP server + broken pipe

* fix: local package path for benchmark utility

* refactor: MQTT republisher example to stream

* refactor: client-server model to new file

* fix: test config. & final directory structure

* feat: internal Docker host config (MQTT)

* feat: SHA256 hash & file contents test case

* docs: example failed test case

* Revert "docs: example failed test case"

This reverts commit d5283b1.

* docs: bump directory structure tree
  • Loading branch information
TechSolomon authored Feb 19, 2024
1 parent ec2d157 commit 60739bf
Show file tree
Hide file tree
Showing 14 changed files with 333 additions and 250 deletions.
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# syntax=docker/dockerfile:1
# Data Diode CLI in Go via container image.
# https://docs.docker.com/language/golang/build-images/

FROM golang:alpine
WORKDIR /cli
COPY . /cli
RUN CGO_ENABLED=0 GOOS=linux go build -o diode
CMD [ "./diode", "mqtt" ]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
build:
go build -o diode -ldflags="-X main.SemVer=0.0.5" diode.go
go build -o diode -ldflags="-X main.SemVer=0.0.6" diode.go

test:
go test -v
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@ Scripts for verifying TCP passthrough functionality.

```zsh
.
├── benchmark
├── config
├── config.yaml
├── data
├── diode.go
├── diode_test.go
├── docker-compose.yaml
├── Dockerfile
├── go.mod
├── go.sum
├── Makefile
├── mqtt
├── Pipfile
├── Pipfile.lock
├── README.md
└── sample
├── sample
└── utility

4 directories, 11 files

4 directories, 9 files
```

## User Stories
Expand Down
36 changes: 0 additions & 36 deletions benchmark/utility.go

This file was deleted.

7 changes: 7 additions & 0 deletions config/mosquitto.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
listener 1883
allow_anonymous true
persistence false

# https://hub.docker.com/_/eclipse-mosquitto
# persistence_location /mosquitto/data/
# log_dest file /mosquitto/log/mosquitto.log
50 changes: 0 additions & 50 deletions data/logbook.ipynb

This file was deleted.

164 changes: 19 additions & 145 deletions diode.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ package main
import (
"fmt"
"log"
"net"
"os"
"time"

mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/acep-uaf/data-diode/utility"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v2"
)
Expand All @@ -40,147 +39,11 @@ type Configuration struct {
}
}

func newClient(ip string, port int) {
// Create a socket

client, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), time.Second)

if err != nil {
fmt.Println(">> Error establishing connection to the diode input side: ", err.Error())
log.Fatal(err)
}
defer client.Close()

numberOfSends := 1

for {
sendMessage := fmt.Sprintf("This is TCP passthrough test message number: %d", numberOfSends)
_, err := client.Write([]byte(sendMessage))
if err != nil {
fmt.Println(">> Error sending message to the diode input side: ", err.Error())
log.Fatal(err)
break
}

// if string(response) == "OK\r\n" {
// fmt.Println(">> Message sent successfully!")
// }

numberOfSends++

time.Sleep(1 * time.Second)
}
}

func newServer(ip string, port int) {
// Begin listening for incoming connections

server, err := net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))

if err != nil {
fmt.Println(">> Error listening for incoming connections: ", err.Error())
return
}
defer server.Close()

fmt.Printf(">> Server listening on %s:%d\n", ip, port)

for {
// Wait for connection
connection, err := server.Accept()

if err != nil {
fmt.Println(">> Error accepting connection: ", err.Error())
return
}

fmt.Println("Connected to client IP:", connection.RemoteAddr().String())

go communicationHandler(connection)

}

}

func communicationHandler(connection net.Conn) {

defer connection.Close()

// Buffer for incoming data (holding recieved data)
buffer := make([]byte, 10240)

for {
// Read incoming data into buffer
bytesRead, err := connection.Read(buffer)
if err != nil {
fmt.Println(">> Error reading: ", err.Error())
break
}

if bytesRead > 0 {
fmt.Println(">> Message recieved: ", string(buffer[:bytesRead]))
}

if bytesRead < 10240 {
break
}
}

}

func sampleMetrics() {
func sampleMetrics(server string, port int) {
fmt.Println(">> Local time: ", time.Now())
fmt.Println(">> UTC time: ", time.Now().UTC())
}

func demoRepublisher(server string, port int, topic string, message string) {
fmt.Println(">> MQTT")
fmt.Println(">> Broker: ", server)
fmt.Println(">> Port: ", port)

// Source: https://github.com/eclipse/paho.mqtt.golang/blob/master/cmd/simple/main.go
var example mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
fmt.Printf(">> Topic: %s\n", msg.Topic())
fmt.Printf(">> Message: %s\n", msg.Payload())
}

mqtt.DEBUG = log.New(os.Stdout, "", 0)
mqtt.ERROR = log.New(os.Stdout, "", 0)

// Initial Connection
opts := mqtt.NewClientOptions().AddBroker(fmt.Sprintf("tcp://%s:%d", server, port))
opts.SetKeepAlive(2 * time.Second)
opts.SetDefaultPublishHandler(example)
opts.SetPingTimeout(1 * time.Second)

// Create and start a client using the above ClientOptions
client := mqtt.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
}

// Subscribe to a topic
if token := client.Subscribe(topic, 0, nil); token.Wait() && token.Error() != nil {
fmt.Println(token.Error())
os.Exit(1)
}

// Publish to a topic
token := client.Publish(topic, 0, false, message)
token.Wait()

time.Sleep(6 * time.Second)

// Disconnect from the broker
if token := client.Unsubscribe(topic); token.Wait() && token.Error() != nil {
fmt.Println(token.Error())
os.Exit(1)
}

client.Disconnect(250)

time.Sleep(1 * time.Second)

fmt.Println(">> Value: ", utility.Value())
// utility.Client(server, port)
}

func main() {
Expand Down Expand Up @@ -222,7 +85,7 @@ func main() {
Usage: "Input side of the data diode",
Action: func(cCtx *cli.Context) error {
fmt.Println("----- INPUT -----")
newClient(diodeInputSideIP, diodeTCPPassthroughPort)
utility.Client(diodeInputSideIP, diodeTCPPassthroughPort)
return nil
},
},
Expand All @@ -232,7 +95,18 @@ func main() {
Usage: "Output side of the data diode",
Action: func(sCtx *cli.Context) error {
fmt.Println("----- OUTPUT -----")
newServer(targetTCPServerIP, targetTCPServerPort)
utility.Server(targetTCPServerIP, targetTCPServerPort)
return nil
},
},
{
Name: "test",
Aliases: []string{"t"},
Usage: "Testing state synchronization via diode I/O",
Action: func(tCtx *cli.Context) error {
fmt.Println("----- TEST -----")
example := utility.Checksum()
fmt.Printf(">> Checksum: %x\n", example)
return nil
},
},
Expand All @@ -252,7 +126,7 @@ func main() {
Usage: "System benchmark analysis + report performance metrics",
Action: func(bCtx *cli.Context) error {
fmt.Println("----- BENCHMARKS -----")
sampleMetrics()
sampleMetrics(utility.CONN_HOST, 3333)
return nil
},
},
Expand All @@ -262,7 +136,7 @@ func main() {
Usage: "MQTT (TCP stream) demo",
Action: func(mCtx *cli.Context) error {
fmt.Println("----- MQTT -----")
demoRepublisher(mqttBrokerIP, mqttBrokerPort, mqttBrokerTopic, mqttBrokerMessage)
utility.Republisher(mqttBrokerIP, mqttBrokerPort, mqttBrokerTopic, mqttBrokerMessage)
return nil
},
},
Expand Down
40 changes: 29 additions & 11 deletions diode_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
package main

import "testing"
import (
"fmt"
"testing"

func TestNewClient(t *testing.T) {
name := "Input"
t.Run(name, func(t *testing.T) {
t.Parallel()
})
"github.com/acep-uaf/data-diode/utility"
)

func TestCLI(t *testing.T) {
got := "diode"
want := "diode"

if got != want {
t.Errorf("got %q, want %q", got, want)
}
}

func TestConfiguration(t *testing.T) {
got := Configuration{}
want := Configuration{}

if got != want {
t.Errorf("got %q, want %q", got, want)
}
}

func TestNewServer(t *testing.T) {
name := "Output"
t.Run(name, func(t *testing.T) {
t.Parallel()
})
func TestFileContents(t *testing.T) {
got := fmt.Sprintf("%x", utility.Checksum())
want := "ed03bb5d7385010c645c2c72ceabea3b15806db757005071309745c59933586f"

if got != want {
t.Errorf("got %q, want %q", got, want)
}
}
Loading

0 comments on commit 60739bf

Please sign in to comment.