From 8dc438658b773d74f692c4fd656ab9c7cd5253d3 Mon Sep 17 00:00:00 2001
From: Xavier Perret <xa.perret@outlook.com>
Date: Fri, 28 Oct 2022 15:49:20 +0200
Subject: [PATCH] divided methods into multiple packages

---
 app/command-line/userinput.go                | 150 +++++++++++++++++
 app/manage-connection/manage-connection.go   |   1 +
 app/process-connection/process-connection.go | 162 +++++++++++++++++++
 app/sender/sender.go                         | 119 ++++++++++++++
 4 files changed, 432 insertions(+)
 create mode 100644 app/command-line/userinput.go
 create mode 100644 app/manage-connection/manage-connection.go
 create mode 100644 app/process-connection/process-connection.go
 create mode 100644 app/sender/sender.go

diff --git a/app/command-line/userinput.go b/app/command-line/userinput.go
new file mode 100644
index 0000000..537c93e
--- /dev/null
+++ b/app/command-line/userinput.go
@@ -0,0 +1,150 @@
+package command_line
+
+import (
+	"fmt"
+	. "node/types"
+	"os"
+	"strconv"
+)
+
+func UserInputLoop(config Config, isAlsoServer bool) {
+	for true {
+		var operation string
+		if !ServerReady {
+			continue
+		}
+		fmt.Println()
+		fmt.Println()
+		fmt.Println("Please enter the operation you want to do")
+		fmt.Println("1. Create a transaction")
+		fmt.Println("2. Rate a transaction (from the client)")
+		fmt.Println("3. Fabricate a fake transaction")
+		fmt.Println("4. Print all transactions")
+		fmt.Println("8. Exit")
+		fmt.Print("Your choice: ")
+		_, err := fmt.Scanln(&operation)
+		if err != nil {
+			fmt.Println("error :", err.Error())
+			os.Exit(1)
+		}
+		switch operation {
+		case "1":
+			fmt.Println("You chose to create a transaction")
+			if isAlsoServer {
+				fmt.Println("Not yet implemented!")
+				//newTrans := userCreatedTransaction(config)
+				//createTransaction(newTrans)
+			} else {
+				newTrans := userCreatedTransaction(config)
+				addTransactionToDb(newTrans)
+				printAllNeighbours(config)
+				fmt.Println("TRANSACTION READY TO BE SENT")
+				fmt.Println("Please enter the ID of the neighbour you want to send the transaction to")
+				var neighbourID string
+				_, err := fmt.Scanln(&neighbourID)
+				if err != nil {
+					fmt.Println("error :", err.Error())
+					os.Exit(1)
+				}
+				neighbourIDInt, err := strconv.ParseInt(neighbourID, 10, 64)
+				if err != nil {
+					fmt.Println("error :", err.Error())
+					os.Exit(1)
+				}
+				sendTransactionToNeighbour(config, newTrans, config.Neighbours[neighbourIDInt].Address, strconv.Itoa(config.Neighbours[neighbourIDInt].Port))
+			}
+			break
+		case "2":
+			fmt.Println("You chose to rate a transaction")
+			listAllTransactions()
+			fmt.Print("\nPlease enter the index of the transaction you want to rate:")
+			var transID string
+			_, err := fmt.Scanln(&transID)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			transIDInt, err := strconv.ParseInt(transID, 10, 64)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			printAllNeighbours(config)
+			fmt.Println("Please enter the ID of the neighbour you want to send the transaction to")
+			var neighbourID string
+			_, err = fmt.Scanln(&neighbourID)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			neighbourIDInt, err := strconv.ParseInt(neighbourID, 10, 64)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			address := config.Neighbours[neighbourIDInt].Address + ":" + strconv.Itoa(config.Neighbours[neighbourIDInt].Port)
+			fmt.Println("Sending rate demand to ", address)
+			sendVoteToNeighbour(config, DB[transIDInt], address)
+			break
+		case "3":
+			fmt.Println("You chose to fabricate a fake transaction")
+			fmt.Println("You chose to fake a transaction")
+			listAllTransactions()
+			fmt.Print("\nPlease enter the index of the transaction you want to overwrite by faking:")
+			var transID string
+			_, err := fmt.Scanln(&transID)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			transIDInt, err := strconv.ParseInt(transID, 10, 64)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			printAllNeighbours(config)
+			fmt.Println("Please enter the ID of the neighbour you to ask to fake the given transaction")
+			var neighbourID string
+			_, err = fmt.Scanln(&neighbourID)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			neighbourIDInt, err := strconv.ParseInt(neighbourID, 10, 64)
+			if err != nil {
+				fmt.Println("error :", err.Error())
+				os.Exit(1)
+			}
+			tmpFakeTrans := userCreatedTransaction(config)
+			transToFake := DB[transIDInt]
+			fakeTrans := Transaction{
+				Id:       transToFake.Id,
+				Sender:   tmpFakeTrans.Sender,
+				Receiver: tmpFakeTrans.Receiver,
+				Amount:   tmpFakeTrans.Amount,
+			}
+			ip := config.Neighbours[neighbourIDInt].Address
+			port := strconv.Itoa(config.Neighbours[neighbourIDInt].Port)
+			address := ip + ":" + port
+			sendFakeTransactionToNeighbour(fakeTrans, address)
+			break
+		case "4":
+			fmt.Println("You chose to print all transactions")
+			listAllTransactions()
+			break
+		case "5":
+			fmt.Println("You chose to ask for all transactions of a given node")
+			break
+		case "6":
+			break
+		case "7":
+			break
+		case "8":
+			fmt.Println("You chose to exit")
+			os.Exit(0)
+		default:
+			fmt.Println("You chose an invalid option")
+			break
+		}
+	}
+}
diff --git a/app/manage-connection/manage-connection.go b/app/manage-connection/manage-connection.go
new file mode 100644
index 0000000..d461671
--- /dev/null
+++ b/app/manage-connection/manage-connection.go
@@ -0,0 +1 @@
+package manage_connection
diff --git a/app/process-connection/process-connection.go b/app/process-connection/process-connection.go
new file mode 100644
index 0000000..c09c12a
--- /dev/null
+++ b/app/process-connection/process-connection.go
@@ -0,0 +1,162 @@
+package ProcessConnection
+
+import (
+	"encoding/json"
+	"fmt"
+	"net"
+	ObjectStorageAPI "node/object-storage"
+	Sender "node/sender"
+	. "node/types"
+	"node/utilities"
+	"os"
+	"strings"
+	"sync"
+)
+
+func listAllTransactionsToClient(conn net.Conn) {
+	mess := Message{
+		MessageType: "list",
+		MessageBody: DB,
+	}
+
+	fmt.Println("Sending message to neighbour", mess)
+	encoder := json.NewEncoder(conn)
+	err := encoder.Encode(mess)
+	if err != nil {
+		fmt.Println("Error while encoding the transaction", err)
+		os.Exit(1)
+	}
+	conn.Close()
+}
+
+func processTransaction(serverListener net.Listener, serverConfig Config, objectStorage Blob, mess Message, amIRoot bool) {
+	var trans Transaction
+	var body map[string]interface{} = mess.MessageBody.(map[string]interface{})
+
+	// Convert mess to transaction
+	fmt.Println("Processing transaction")
+	trans.Id = body["id"].(string)
+	trans.Receiver = body["receiver"].(string)
+	trans.Sender = body["sender"].(string)
+	trans.Amount = body["amount"].(string)
+	utilities.PrintTransaction(trans)
+
+	database := ObjectStorageAPI.ReadDatabaseFromBlobStorage(objectStorage)
+	fmt.Println("The database before adding the transaction is ")
+	utilities.PrintingDatabaseToConsole(database)
+
+	reach := false
+	count := 0
+
+	limit := len(serverConfig.Neighbours)
+	if amIRoot {
+		reach = true
+		database = ObjectStorageAPI.AddTransactionToBlobStorage(trans, database, objectStorage)
+		fmt.Println("The database after adding the transaction is ")
+		utilities.PrintingDatabaseToConsole(database)
+		go Sender.SendTransactionToAllNeighbours(serverConfig, trans)
+	}
+
+	for count < limit {
+		if count != 0 || reach {
+			fmt.Println("Count is ", count, " to ", limit)
+
+			connection, err := serverListener.Accept()
+			if err != nil {
+				fmt.Println("Error accepting: ", err.Error())
+				err = nil
+				continue
+			}
+			fmt.Println("*****************************************")
+			fmt.Println("Processing client request number ", count)
+			fmt.Println("The process-manage-connection is ", connection)
+			fmt.Println("The remote address is ", connection.RemoteAddr())
+			fmt.Println("The local address is ", connection.LocalAddr())
+			fmt.Println("*****************************************")
+
+			err = json.NewDecoder(connection).Decode(&trans)
+			if err != nil {
+				fmt.Println("Error while decoding the transaction", err)
+				err = nil
+				continue
+			}
+			fmt.Println("Received back a transaction")
+			utilities.PrintTransaction(trans)
+		}
+
+		count++ // received message
+		if !reach {
+			reach = true
+			addTransactionToDb(trans)
+			go sendTransactionToAllNeighbours(serverConfig, trans)
+		}
+	}
+	fmt.Println("***********************************")
+	fmt.Println("All transactions have been received")
+	fmt.Println("***********************************")
+}
+
+func processRate(serverListener net.Listener, serverConfig Config, mess Message, amIRoot bool) {
+	var trans Transaction
+	var body map[string]interface{} = mess.MessageBody.(map[string]interface{})
+	trans.Id = body["id"].(string)
+	trans.Receiver = body["receiver"].(string)
+	trans.Sender = body["sender"].(string)
+	trans.Amount = body["amount"].(string)
+	utilities.PrintTransaction(trans)
+
+	// todo change this for cloud
+	address := strings.Split(conn.RemoteAddr().String(), ":")[0]
+	vote(server, trans, serverConfig, address, amIRoot)
+}
+
+func processFake(serverListener net.Listener, serverConfig Config, mess Message, amIRoot bool) {
+	var fakeTransaction Transaction
+	var body map[string]interface{} = mess.MessageBody.(map[string]interface{})
+	fakeTransaction.Id = body["id"].(string)
+	fakeTransaction.Receiver = body["receiver"].(string)
+	fakeTransaction.Sender = body["sender"].(string)
+	fakeTransaction.Amount = body["amount"].(string)
+	for transactionIndex := range DB {
+		if DB[transactionIndex].Id == fakeTransaction.Id {
+			DB[transactionIndex].Sender = fakeTransaction.Sender
+			DB[transactionIndex].Receiver = fakeTransaction.Receiver
+			DB[transactionIndex].Amount = fakeTransaction.Amount
+			fmt.Println("Successfully replaced the legitimate transaction with a fake one!")
+		}
+	}
+}
+
+func ProcessClient(conn net.Conn, server net.Listener, objectStorage Blob, serverConfig Config, amIRoot bool, mutex *sync.Mutex) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	fmt.Println("Processing client")
+	fmt.Println("The conn is ", conn)
+	fmt.Println("The remote address is ", conn.RemoteAddr())
+	fmt.Println("The local address is ", conn.LocalAddr())
+
+	var mess Message
+	jsonDecoder := json.NewDecoder(conn)
+	err := jsonDecoder.Decode(&mess)
+	if err != nil || mess.MessageType == "error" {
+		fmt.Println("Error while decoding the message", err)
+		return
+	}
+
+	fmt.Println("The message is ", mess)
+	if mess.MessageType == "transaction" {
+		fmt.Println("Received a transaction.. processing")
+		processTransaction(server, serverConfig, objectStorage, mess, amIRoot)
+	} else if mess.MessageType == "rate" {
+		fmt.Println("Received a rate")
+		processRate()
+	} else if mess.MessageType == "fake" {
+		fmt.Println("Received a fake transaction")
+		processFake()
+	} else if mess.MessageType == "list" {
+		fmt.Println("Received an order to list all transactions")
+		listAllTransactionsToClient(conn)
+	} else {
+		fmt.Println("Unknown message type")
+	}
+}
diff --git a/app/sender/sender.go b/app/sender/sender.go
new file mode 100644
index 0000000..59e4c83
--- /dev/null
+++ b/app/sender/sender.go
@@ -0,0 +1,119 @@
+package sender
+
+import (
+	"encoding/json"
+	"fmt"
+	"net"
+	. "node/types"
+	"os"
+	"strconv"
+)
+
+func SendVoteToNeighbour(config Config, trans Transaction, address string) {
+	fmt.Println()
+	fmt.Println("Trying to connect to ", address)
+
+	conn, err := net.Dial("tcp", address)
+	if err != nil {
+		fmt.Println("Error while connecting to the neighbour", err)
+		os.Exit(1)
+	}
+
+	mess := Message{
+		MessageType: "rate",
+		MessageBody: trans,
+	}
+	fmt.Println("Sending message to neighbour", mess)
+	encoder := json.NewEncoder(conn)
+	err = encoder.Encode(mess)
+	if err != nil {
+		fmt.Println("Error while encoding the transaction", err)
+		os.Exit(1)
+	}
+
+	err = conn.Close()
+	if err != nil {
+		fmt.Println("Error while closing the process-manage-connection", err)
+	}
+
+	fmt.Println("MessageBody successfully sent to neighbour")
+}
+
+func SendAckToNeighbour(config Config, ack AckTransaction, address string) {
+	fmt.Println("*******************STARTING TO SEND ACK*******************")
+	fmt.Println("Trying to connect to ", address)
+	var ackToSend AckTransaction
+	ackToSend.Id = ack.Id
+	ackToSend.AmountOfCorrectNode = ack.AmountOfCorrectNode
+	ackToSend.TotalNodes = ack.TotalNodes
+
+	conn, err := net.Dial("tcp", address)
+	if err != nil {
+		fmt.Println("Error while connecting to the neighbour", err)
+		os.Exit(1)
+	}
+
+	mess := Message{
+		MessageType: "AckResponse",
+		MessageBody: ackToSend,
+	}
+	fmt.Println("Sending message to neighbour", mess)
+	encoder := json.NewEncoder(conn)
+	err = encoder.Encode(mess)
+	if err != nil {
+		fmt.Println("Error while encoding the transaction", err)
+		os.Exit(1)
+	}
+	conn.Close()
+
+	fmt.Println("MessageBody successfully sent to neighbour")
+	fmt.Println("*******************FINISHED ACK*******************")
+}
+
+func SendVoteToAllNeighbours(config Config, trans Transaction, parentIp string) {
+	for neighbour := range config.Neighbours {
+		ip := config.Neighbours[neighbour].Address
+		port := strconv.Itoa(config.Neighbours[neighbour].Port)
+		address := ip + ":" + port
+		if parentIp != ip {
+			go SendVoteToNeighbour(config, trans, address)
+		}
+	}
+}
+
+// sendTransactionToNeighbour is a function to send a transaction to a neighbour
+func SendTransactionToNeighbour(config Config, trans Transaction, destinationIp string, destinationPort string) {
+	fmt.Println()
+	ipAddr := destinationIp + ":" + destinationPort
+	fmt.Println("Trying to connect to ", destinationIp, ":", destinationPort)
+
+	conn, err := net.Dial("tcp", ipAddr)
+	if err != nil {
+		fmt.Println("Error while connecting to the neighbour", err)
+		os.Exit(1)
+	}
+
+	mess := Message{
+		MessageType: "transaction",
+		MessageBody: trans,
+	}
+	fmt.Println("Sending message to neighbour", mess)
+	encoder := json.NewEncoder(conn)
+	err = encoder.Encode(mess)
+	if err != nil {
+		fmt.Println("Error while encoding the transaction", err)
+		os.Exit(1)
+	}
+	conn.Close()
+
+	fmt.Println("MessageBody successfully sent to neighbour")
+}
+
+func SendTransactionToAllNeighbours(config Config, trans Transaction) {
+	for neighbour := range config.Neighbours {
+		fmt.Println("Sending transaction to neighbour ", config.Neighbours[neighbour].ID)
+		ip := config.Neighbours[neighbour].Address
+		port := strconv.Itoa(config.Neighbours[neighbour].Port)
+		SendTransactionToNeighbour(config, trans, ip, port)
+	}
+}
-- 
GitLab