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