Beispiel #1
0
// Load and connect to all nodes from the NodeFile found in the ApiConfig.
func ReadNodes(config *ApiConfig) {
	file, err := os.Open(config.NodeFile)
	defer file.Close()
	if err != nil {
		fmt.Println("Could not open node file: ", err)
	}

	var count int

	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		str := scanner.Text()
		if len(str) < 0 || str == "<nil>" {
			continue
		}

		p := new(quibit.Peer)
		n := new(objects.Node)
		err = n.FromString(str)
		if err != nil {
			fmt.Println("Error Decoding Peer ", str, ": ", err)
			continue
		}

		p.IP = n.IP
		p.Port = n.Port
		config.PeerQueue <- *p
		config.NodeList.Nodes[n.String()] = *n
		count++
	}
	fmt.Println(count, "nodes pulled from node file.")
}
Beispiel #2
0
// Starts a new TCP Server wth configuration specified in ApiConfig.
// Server will terminate cleanly only when data is sent to the Quit channel.
//
// See (struct ApiConfig) for details.
func Start(config *ApiConfig) {
	var err error
	var frame quibit.Frame

	defer quit(config)

	config.Log <- "Starting api..."

	// Start Database Services
	err = db.Initialize(config.Log, config.DbFile)
	defer db.Cleanup()
	if err != nil {
		config.Log <- fmt.Sprintf("Error initializing database: %s", err)
		config.Log <- "Quit"
		return
	}
	config.LocalVersion.Timestamp = time.Now().Round(time.Second)

	locVersion := objects.MakeFrame(objects.VERSION, objects.REQUEST, &config.LocalVersion)
	for str, _ := range config.NodeList.Nodes {
		locVersion.Peer = str
		config.SendQueue <- *locVersion
	}

	// Set Up Clocks
	second := time.Tick(2 * time.Second)
	minute := time.Tick(time.Minute)

	for {
		select {
		case frame = <-config.RecvQueue:
			config.Log <- fmt.Sprintf("Received %s frame...", CmdString(frame.Header.Command))
			switch frame.Header.Command {
			case objects.VERSION:
				version := new(objects.Version)
				err = version.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing version: %s", err)
				} else {
					fVERSION(config, frame, version)
				}
			case objects.PEER:
				nodeList := new(objects.NodeList)
				err = nodeList.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing peer list: %s", err)
				} else {
					fPEER(config, frame, nodeList)
				}
			case objects.OBJ:
				obj := new(objects.Obj)
				err = obj.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing obj list: %s", err)
				} else {
					fOBJ(config, frame, obj)
				}
			case objects.GETOBJ:
				getObj := new(objects.Hash)
				if len(frame.Payload) == 0 {
					break
				}
				err = getObj.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing getobj hash: %s", err)
				} else {
					fGETOBJ(config, frame, getObj)
				}
			case objects.PUBKEY_REQUEST:
				pubReq := new(objects.Hash)
				err = pubReq.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing pubkey request hash: %s", err)
				} else {
					fPUBKEY_REQUEST(config, frame, pubReq)
				}
			case objects.PUBKEY:
				pub := new(objects.EncryptedPubkey)
				err = pub.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing pubkey: %s", err)
				} else {
					fPUBKEY(config, frame, pub)
				}
			case objects.MSG:
				msg := new(objects.Message)
				err = msg.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing message: %s", err)
				} else {
					fMSG(config, frame, msg)
				}
			case objects.PUB:
				msg := new(objects.Message)
				err = msg.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing publication: %s", err)
				} else {
					fPUB(config, frame, msg)
				}
			case objects.PURGE:
				purge := new(objects.Purge)
				err = purge.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing purge: %s", err)
				} else {
					fPURGE(config, frame, purge)
				}
			case objects.CHECKTXID:
				chkTxid := new(objects.Hash)
				if len(frame.Payload) == 0 {
					break
				}
				err = chkTxid.FromBytes(frame.Payload)
				if err != nil {
					config.Log <- fmt.Sprintf("Error parsing checktxid hash: %s", err)
				} else {
					fCHECKTXID(config, frame, chkTxid)
				}
			default:
				config.Log <- fmt.Sprintf("Received invalid frame for command: %d", frame.Header.Command)
			}
		case <-config.Quit:
			fmt.Println()
			// Dump Nodes to File
			DumpNodes(config)
			return
		case <-second:
			// Reconnection Logic
			for key, node := range config.NodeList.Nodes {
				peer := quibit.GetPeer(key)
				if peer == nil || !peer.IsConnected() {
					quibit.KillPeer(key)
					if node.Attempts >= 3 {
						config.Log <- fmt.Sprintf("Max connection attempts reached for %s, disconnecting...", key)
						// Max Attempts Reached, disconnect
						delete(config.NodeList.Nodes, key)
					} else {
						config.Log <- fmt.Sprintf("Disconnected from peer %s, trying to reconnect...", key)
						peer = new(quibit.Peer)
						peer.IP = node.IP
						peer.Port = node.Port
						config.PeerQueue <- *peer
						runtime.Gosched()
						peer = nil
						node.Attempts++
						config.NodeList.Nodes[key] = node
						locVersion.Peer = key
						config.SendQueue <- *locVersion
					}
				}
			}

			if len(config.NodeList.Nodes) < 1 {
				config.Log <- "All connections lost, re-bootstrapping..."

				for i, str := range config.Bootstrap {
					if i >= bufLen {
						break
					}

					p := new(quibit.Peer)
					n := new(objects.Node)
					err := n.FromString(str)
					if err != nil {
						fmt.Println("Error Decoding Peer ", str, ": ", err)
						continue
					}

					p.IP = n.IP
					p.Port = n.Port
					config.PeerQueue <- *p
					runtime.Gosched()
					config.NodeList.Nodes[n.String()] = *n
				}

				for str, _ := range config.NodeList.Nodes {
					locVersion.Peer = str
					config.SendQueue <- *locVersion
				}
			}
		case <-minute:
			// Dump old messages
			err = db.SweepMessages(30 * 24 * time.Hour)
			if err != nil {
				config.Log <- fmt.Sprintf("Error Sweeping Messages: %s", err)
			}
		}
	}

	// Should NEVER get here!
	panic("Must've been a cosmic ray!")
}
Beispiel #3
0
// Generate new config from configuration file. File provided as an Absolute Path.
func GetConfig(confFile string) *ApiConfig {

	var tomlConf tomlConfig

	if _, err := toml.DecodeFile(confFile, &tomlConf); err != nil {
		fmt.Println("Config Error: ", err)
		return nil
	}

	config := new(ApiConfig)

	// Network Channels
	config.RecvQueue = make(chan quibit.Frame, bufLen)
	config.SendQueue = make(chan quibit.Frame, bufLen)
	config.PeerQueue = make(chan quibit.Peer, bufLen)

	// Local Logic
	config.DbFile = GetConfDir() + tomlConf.Inventory
	config.LocalDB = GetConfDir() + tomlConf.Local
	if len(config.DbFile) == 0 || len(config.LocalDB) == 0 {
		fmt.Println("Database file not found in config!")
		return nil
	}
	config.NodeFile = GetConfDir() + tomlConf.Nodes

	config.LocalVersion.Port = tomlConf.Port
	if tomlConf.IP != "0.0.0.0" {
		config.LocalVersion.IpAddress = net.ParseIP(tomlConf.IP)
	}
	config.LocalVersion.Timestamp = time.Now().Round(time.Second)
	config.LocalVersion.Version = objects.LOCAL_VERSION
	config.LocalVersion.UserAgent = objects.LOCAL_USER

	// RPC
	config.RPCPort = tomlConf.RPCConf.Port
	config.RPCUser = tomlConf.RPCConf.User
	config.RPCPass = tomlConf.RPCConf.Pass
	config.LocalOnly = tomlConf.RPCConf.LocalOnly
	config.HttpRoot = GetConfDir() + tomlConf.RPCConf.Local

	// Local Registers
	config.PubkeyRegister = make(chan objects.Hash, bufLen)
	config.MessageRegister = make(chan objects.Message, bufLen)
	config.PubRegister = make(chan objects.Message, bufLen)
	config.PurgeRegister = make(chan [16]byte, bufLen)

	// Administration
	config.Log = make(chan string, bufLen)
	config.Quit = make(chan os.Signal, 1)

	// Initialize Map
	config.NodeList.Nodes = make(map[string]objects.Node)

	// Bootstrap Nodes
	config.Bootstrap = make([]string, len(tomlConf.Peers), cap(tomlConf.Peers))
	copy(config.Bootstrap, tomlConf.Peers)
	for i, str := range tomlConf.Peers {
		if i >= bufLen {
			break
		}

		p := new(quibit.Peer)
		n := new(objects.Node)
		err := n.FromString(str)
		if err != nil {
			fmt.Println("Error Decoding Peer ", str, ": ", err)
			continue
		}

		p.IP = n.IP
		p.Port = n.Port
		config.PeerQueue <- *p
		config.NodeList.Nodes[n.String()] = *n
	}

	// Pull Nodes from node file
	if len(config.NodeFile) > 0 {
		ReadNodes(config)
	}

	return config
}