func NewTransaction() { if betternode.CountNodes() == 0 { fmt.Println("Unable to initiate transaction: No nodes connected.") return } from := betternode.RandomNode() to := betternode.RandomNode() for i := 1; i < 1000; i++ { if to != from { break } to = betternode.RandomNode() } log.Message("NewTransmission()") t := betternode.NewTransaction( <-idgen, mapping[to], hops, "Lorem ipsum", fine, ceil, RoundId, ) // Send transaction log.Message("NewTransmission() 1") betternode.SendTransaction(t, from) log.Message("NewTransmission() 2") database.Insert(t) log.Message("NewTransmission() 3") transaction.Add <- t log.Message("NewTransmission() 4") }
func RandomNode() string { log.Message("RandomNode()") nutex.RLock() defer nutex.RUnlock() n := nodes[random.Intn(len(nodes))].Conn.RemoteAddr().String() log.Message(n) s := strings.SplitN(n, ":", 2)[0] log.Message(s) return s }
// Sends data to the node func (n *Node) sender() { defer RemoveNode(n) enc := json.NewEncoder(n.Conn) for { log.Message("SenderLoop") select { case b, ok := <-n.Updates: // There is an balance update upcoming if !ok { n.Conn.Close() return } enc.Encode(NewCheckUpdate(b)) // Send as json case t, ok := <-n.Transactions: // We want to send a transaction if !ok { n.Conn.Close() return } enc.Encode(t) // Send the transaction } } }
func CountNodes() int { log.Message("CountNodes()") nutex.RLock() defer nutex.RUnlock() return len(nodes) }
func SendBalances(balances map[string]*Balance) { log.Message("SendBalances()") nutex.RLock() for _, n := range nodes { n.Updates <- balances } nutex.RUnlock() }
func SendTransaction(transaction *Transaction, to string) { log.Message("SendTransaction()") nutex.RLock() defer nutex.RUnlock() for _, n := range nodes { s := strings.SplitN(n.Conn.RemoteAddr().String(), ":", 2)[0] if s == to { n.Transactions <- transaction break } } }
func GetDevices() []string { log.Message("GetDevices()") result := make([]string, 0, 0) nutex.RLock() for _, n := range nodes { result = append(result, n.Clients...) } nutex.RUnlock() return result }
// Gets the data from a node and saves into the database func (n *Node) receiver() { dec := json.NewDecoder(n.Conn) for { var obj interface{} err := dec.Decode(&obj) if err != nil { log.Error(err) if err.Error() == "EOF" { close(n.Transactions) return } // Hack: recover dec = json.NewDecoder(n.Conn) } log.Message("Received message from " + n.Conn.RemoteAddr().String() + ".") // n.updateDevices(obj) database.Insert(obj) } }
func main() { defer func() { log.Close() // Close log server.Close() // Close server betternode.Close() // Close nodes profile.StopProfile() // Close profile time.Sleep(time.Second) // Wait for everything to close }() // Make Go run parallel runtime.GOMAXPROCS(runtime.NumCPU()) log.Message("ManiacMaster starting.") // Initialize database log.Message("Connecting to database.") err := database.Connect("localhost:27018", "maniac", "", "") if err != nil { log.Error(err) fmt.Println("Error:", err.Error()) } // Create TCP server log.Message("Starting TCP server.") err = server.Start(":6789", betternode.NewNode) if err != nil { log.Error(err) fmt.Println("Error:", err.Error()) } // Take commands log.Message("Ready for command line input.") fmt.Println("MANIAC Master ready.") var command string s := bufio.NewScanner(os.Stdin) quit: for { // Get next command fmt.Print("M> ") if !s.Scan() { fmt.Println("Input ended!") break } command = s.Text() // to trimmed lower case command = strings.ToLower(strings.TrimSpace(command)) switch command { case "help": // show helpful text printHelp() case "quit", "exit": // quits the master break quit case "next": // starts new round rounds.NewRound() case "send": // sends new message rounds.NewTransaction() case "info": // show info about the master printInfo() case "load": fmt.Print("Profile file: ") fmt.Scanln(&command) profile.OpenProfile(command) case "run": fmt.Print("Profile name: ") fmt.Scanln(&command) go profile.RunProfile(command) case "kill": profile.StopProfile() case "list": profile.ListProfiles() case "close": fmt.Print("Profile name: ") fmt.Scanln(&command) profile.CloseProfile(command) default: fmt.Println("Invalid command: Type \"help\" to get help.") } } }