func RunServer(flags *app.Flags, conf *app.ConfigColl) { hostname := flags.Hostname if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") app.RunFlags.StartedUp(len(conf.Hosts)) peer := conode.NewPeer(hostname, conf.ConfigConode) if app.RunFlags.AmRoot { for { setupRound := sign.NewRoundSetup(peer.Node) peer.StartAnnouncementWithWait(setupRound, 5*time.Second) counted := <-setupRound.Counted dbg.Lvl1("Number of peers counted:", counted) if counted == len(conf.Hosts) { dbg.Lvl1("All hosts replied") break } time.Sleep(time.Second) } } RegisterRoundMeasure(peer.Node.LastRound()) peer.LoopRounds(RoundMeasureType, conf.Rounds) dbg.Lvlf3("Done - flags are %+v", app.RunFlags) monitor.End() }
func createPeers() (p1, p2 *conode.Peer) { conf1 := readConfig() peer1 := createPeer(conf1, 1) dbg.Lvlf3("Peer 1 is %+v", peer1) // conf will hold part of the configuration for each server, // so we have to create a second one for the second server conf2 := readConfig() peer2 := createPeer(conf2, 2) dbg.Lvlf3("Peer 2 is %+v", peer2) return peer1, peer2 }
func NewRoundMeasure(node *sign.Node, firstRound int) *RoundMeasure { dbg.Lvlf3("Making new roundmeasure %+v", node) round := &RoundMeasure{} round.RoundStamperListener = conode.NewRoundStamperListener(node) round.Type = RoundMeasureType round.firstRound = firstRound return round }
func NewRoundMeasure(node *sign.Node, firstRound int) *RoundMeasure { dbg.Lvlf3("Making new roundmeasure %+v", node) round := &RoundMeasure{} round.RoundCosi = sign.NewRoundCosi(node) round.Type = RoundMeasureType round.firstRound = firstRound return round }
// Can we build the Peer without a valid key? func TestEmptyKeys(t *testing.T) { dbg.TestOutput(testing.Verbose(), 4) conf1 := readConfig() emptyKeys(conf1.Tree) peer1 := createPeer(conf1, 1) dbg.Lvlf3("Peer 1 is %+v", peer1) conf2 := readConfig() emptyKeys(conf2.Tree) peer2 := createPeer(conf2, 1) dbg.Lvlf3("Peer 1 is %+v", peer2) go peer1.LoopRounds(sign.RoundCosiType, 2) go peer2.LoopRounds(sign.RoundCosiType, 2) time.Sleep(time.Second * 2) peer1.Close() peer2.Close() }
func main() { conf := &app.ConfigColl{} app.ReadConfig(conf) // we must know who we are if app.RunFlags.Hostname == "" { dbg.Fatal("Hostname empty: Abort") } // Do some common setup if app.RunFlags.Mode == "client" { app.RunFlags.Hostname = app.RunFlags.Name } hostname := app.RunFlags.Hostname if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") app.RunFlags.StartedUp(len(conf.Hosts)) peer := conode.NewPeer(hostname, conf.ConfigConode) if app.RunFlags.AmRoot { for { time.Sleep(time.Second) setupRound := sign.NewRoundSetup(peer.Node) peer.StartAnnouncementWithWait(setupRound, 5*time.Second) counted := <-setupRound.Counted dbg.Lvl1("Number of peers counted:", counted) if counted == len(conf.Hosts) { dbg.Lvl1("All hosts replied") break } } } RegisterRoundMeasure(peer.Node.LastRound()) peer.LoopRounds(RoundMeasureType, conf.Rounds) dbg.Lvlf3("Done - flags are %+v", app.RunFlags) monitor.End() }
// Closes the channel func (peer *Peer) Close() { if peer.Closed { dbg.Lvl1("Peer", peer.Name(), "Already closed!") return } else { peer.Closed = true } peer.CloseChan <- true peer.Node.Close() StampListenersClose() dbg.Lvlf3("Closing of peer: %s finished", peer.Name()) }
/* Reads in a configuration-file for a run. The configuration-file has the * following syntax: * Name1 = value1 * Name2 = value2 * [empty line] * n1, n2, n3, n4 * v11, v12, v13, v14 * v21, v22, v23, v24 * * The Name1...Namen are global configuration-options. * n1..nn are configuration-options for one run * Both the global and the run-configuration are copied to both * the platform and the app-configuration. */ func ReadRunFile(p Platform, filename string) []RunConfig { var runconfigs []RunConfig masterConfig := NewRunConfig() dbg.Lvl3("Reading file", filename) file, err := os.Open(filename) defer file.Close() if err != nil { dbg.Fatal("Couldn't open file", file, err) } // Decoding of the first part of the run config file // where the config wont change for the whole set of the simulation's tests scanner := bufio.NewScanner(file) for scanner.Scan() { text := scanner.Text() dbg.Lvl3("Decoding", text) // end of the first part if text == "" { break } // checking if format is good vals := strings.Split(text, "=") if len(vals) != 2 { dbg.Fatal("Simulation file:", filename, " is not properly formatted ( key = value )") } // fill in the general config masterConfig.Put(strings.TrimSpace(vals[0]), strings.TrimSpace(vals[1])) // also put it in platform toml.Decode(text, p) dbg.Lvlf3("Platform is now %+v", p) } scanner.Scan() args := strings.Split(scanner.Text(), ", ") for scanner.Scan() { rc := masterConfig.Clone() // put each individual test configs for i, value := range strings.Split(scanner.Text(), ", ") { rc.Put(strings.TrimSpace(args[i]), strings.TrimSpace(value)) } runconfigs = append(runconfigs, *rc) } return runconfigs }
// Returns how many peers are ready func GetReady(addr string) (*Stats, error) { if encoder == nil { err := ConnectSink(addr) if err != nil { return nil, err } } dbg.Lvl3("Getting ready_count") send(Measure{Name: "ready_count"}) decoder := json.NewDecoder(connection) var s Stats err := decoder.Decode(&s) if err != nil { return nil, err } dbg.Lvlf3("Received stats with %+v", s) return &s, nil }
// verifyChallenge will reconstruct the challenge in order to see if any of the // components of the challenge has been spoofed or not. It may be a different // timestamp . func VerifyChallenge(suite abstract.Suite, reply *StampSignature) error { dbg.Lvlf3("Reply is %+v", reply) // marshal the V pbuf, err := reply.AggCommit.MarshalBinary() if err != nil { return err } c := suite.Cipher(pbuf) // concat timestamp and merkle root var b bytes.Buffer if err := binary.Write(&b, binary.LittleEndian, reply.Timestamp); err != nil { return err } cbuf := append(b.Bytes(), reply.MerkleRoot...) c.Message(nil, nil, cbuf) challenge := suite.Secret().Pick(c) if challenge.Equal(reply.Challenge) { return nil } return errors.New("Challenge reconstructed is not equal to the one given") }
// handleConnection will decode the data received and aggregates it into its // stats func (m *Monitor) handleConnection(conn net.Conn) { dec := json.NewDecoder(conn) enc := json.NewEncoder(conn) nerr := 0 for { measure := Measure{} if err := dec.Decode(&measure); err != nil { // if end of connection if err == io.EOF { break } // otherwise log it dbg.Lvl2("Error monitor decoding from", conn.RemoteAddr().String(), ":", err) nerr += 1 if nerr > 1 { dbg.Lvl2("Monitor: too many errors from", conn.RemoteAddr().String(), ": Abort.") break } } dbg.Lvlf3("Monitor: received a Measure from %s: %+v", conn.RemoteAddr().String(), measure) // Special case where the measurement is indicating a FINISHED step switch strings.ToLower(measure.Name) { case "end": dbg.Lvl3("Finishing monitor") m.done <- conn.RemoteAddr().String() case "ready": m.stats.Ready++ dbg.Lvl3("Increasing counter to", m.stats.Ready) case "ready_count": dbg.Lvl3("Sending stats") m_send := measure m_send.Ready = m.stats.Ready enc.Encode(m_send) default: m.measures <- measure } } }
/* * Reads in the config for the application - * also parses the init-flags and connects to * the monitor. */ func ReadConfig(conf interface{}, dir ...string) { var err error err = ReadTomlConfig(conf, "app.toml", dir...) if err != nil { log.Fatal("Couldn't load app-config-file in exec") } debug := reflect.ValueOf(conf).Elem().FieldByName("Debug") if debug.IsValid() { dbg.DebugVisible = debug.Interface().(int) } FlagInit() flag.Parse() dbg.Lvlf3("Flags are %+v", RunFlags) if RunFlags.AmRoot { if err := monitor.ConnectSink(RunFlags.Logger); err != nil { dbg.Fatal("Couldn't connect to monitor", err) } } dbg.Lvl3("Running", RunFlags.Hostname, "with logger at", RunFlags.Logger) }
func main() { conf := &app.ConfigColl{} app.ReadConfig(conf) // we must know who we are if app.RunFlags.Hostname == "" { dbg.Fatal("Hostname empty: Abort") } // Do some common setup if app.RunFlags.Mode == "client" { app.RunFlags.Hostname = app.RunFlags.Name } hostname := app.RunFlags.Hostname if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") app.RunFlags.StartedUp(len(conf.Hosts)) peer := conode.NewPeer(hostname, conf.ConfigConode) Releases = make(map[string]CommitEntry) //ReleaseInformation() ReadRelease(PolicyFile, SignaturesFile, CommitIdFile) if app.RunFlags.AmRoot { err := peer.WaitRoundSetup(len(conf.Hosts), 5, 2) if err != nil { dbg.Fatal(err) } dbg.Lvl1("Starting the rounds") } if app.RunFlags.AmRoot { for round := 0; round < conf.Rounds; round++ { dbg.Lvl1("Doing round", round, "of", conf.Rounds) wallTime := monitor.NewMeasure("round") hashToSign, _ := CommitScanner(CommitIdFile) // retrieve commitid/hash that the root is willing to get signed entry := Releases[hashToSign] if entry.policy != "" && entry.signatures != "" { rootpgpTime := monitor.NewMeasure("rootpgp") decision, err := ApprovalCheck(entry.policy, entry.signatures, hashToSign) rootpgpTime.Measure() if decision && err == nil { round := NewRoundSwsign(peer.Node) round.Hash = []byte(hashToSign) // passing hash of the file that we want to produce a signature for peer.StartAnnouncement(round) wallTime.Measure() Signature := <-round.Signature dbg.Lvlf1("Received signature %+v", Signature) } else { dbg.Fatal("Developers related to the root haven't approved the release so the root didn't start signing process") } } else { dbg.Error("There is no input with such commitid", hashToSign) } } peer.SendCloseAll() } else { peer.LoopRounds(RoundSwsignType, conf.Rounds) } dbg.Lvlf3("Done - flags are %+v", app.RunFlags) monitor.End() }
func NewRoundCosi(node *Node) *RoundCosi { dbg.Lvlf3("Making new RoundCosi", node.Name()) round := &RoundCosi{} round.RoundStruct = NewRoundStruct(node, RoundCosiType) return round }
func main() { // First, let's read our config // You should create your own config in lib/app. // TOML is a pretty simple and readable format // Whatever information needed, supply it in the simulation/.toml file that // will be parsed into your ConfigSkeleton struct. conf := &app.ConfigSkeleton{} app.ReadConfig(conf) // we must know who we are if app.RunFlags.Hostname == "" { dbg.Fatal("Hostname empty: Abort") } // Do some common setup if app.RunFlags.Mode == "client" { app.RunFlags.Hostname = app.RunFlags.Name } hostname := app.RunFlags.Hostname // i.e. we are root if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") // Connect to the monitor process. This monitor process is run on your // machine and accepts connections from any node, usually you only connect // with the root for readability and performance reasons (don't connect to // your machine from 8000 nodes .. !) if app.RunFlags.Logger != "" { monitor.ConnectSink(app.RunFlags.Logger) } else { dbg.Fatal("No logger specified") } // Here you create a "Peer",that's the struct that will create a new round // each seconds and handle other subtleties for you peer := conode.NewPeer(hostname, conf.ConfigConode) // The root waits everyone's to be up if app.RunFlags.AmRoot { for { time.Sleep(time.Second) setupRound := sign.NewRoundSetup(peer.Node) peer.StartAnnouncementWithWait(setupRound, 5*time.Second) counted := <-setupRound.Counted dbg.Lvl1("Number of peers counted:", counted) if counted == len(conf.Hosts) { dbg.Lvl1("All hosts replied") break } } } // You register by giving the type, and a function that takes a sign.Node in // input (basically the underlying protocol) and returns a Round. sign.RegisterRoundFactory(RoundSkeletonType, func(node *sign.Node) sign.Round { return NewRoundSkeleton(node) }) // Here it will create a new round each seconds automatically. // If you need more fined grained control, you must implement yourself the // conode.Peer struct (it's quite easy). peer.LoopRounds(RoundSkeletonType, conf.Rounds) // Notify the monitor that we finished so that the simulation can be stopped monitor.End() }
func (sn *Node) Commit(sm *SigningMessage) error { view := sm.ViewNbr roundNbr := sm.RoundNbr // update max seen round sn.roundmu.Lock() sn.LastSeenRound = max(sn.LastSeenRound, roundNbr) sn.roundmu.Unlock() commitList, ok := sn.RoundCommits[roundNbr] if !ok { // first time we see a commit message for this round commitList = make([]*SigningMessage, 0) sn.RoundCommits[roundNbr] = commitList } // signingmessage nil <=> we are a leaf if sm.Com != nil { commitList = append(commitList, sm) sn.RoundCommits[roundNbr] = commitList } dbg.Lvl3("Got", len(sn.RoundCommits[roundNbr]), "of", len(sn.Children(view)), "commits") // not enough commits yet (not all children replied) if len(sn.RoundCommits[roundNbr]) != len(sn.Children(view)) { dbg.Lvl3(sn.Name(), "Not enough commits received to call the Commit of the round") return nil } ri := sn.Rounds[roundNbr] if ri == nil { dbg.Lvl3(sn.Name(), "No round interface for commit round number", roundNbr) return fmt.Errorf("No Round Interface defined for this round number (commitment)") } out := &SigningMessage{ Suite: sn.Suite().String(), ViewNbr: view, Type: Commitment, //LastSeenVote: int(atomic.LoadInt64(&sn.LastSeenVote)), RoundNbr: roundNbr, Com: &CommitmentMessage{ Message: make([]byte, 0), }, } err := ri.Commitment(sn.RoundCommits[roundNbr], out) // now we can delete the commits for this round delete(sn.RoundCommits, roundNbr) if err != nil { return nil } if sn.IsRoot(view) { sn.commitsDone <- roundNbr err = sn.Challenge(&SigningMessage{ Suite: sn.Suite().String(), RoundNbr: roundNbr, Type: Challenge, ViewNbr: view, Chm: &ChallengeMessage{}, }) } else { // create and putup own commit message // ctx, _ := context.WithTimeout(context.Background(), 2000*time.Millisecond) dbg.Lvl4(sn.Name(), "puts up commit") ctx := context.TODO() dbg.Lvlf3("Out is %+v", out) err = sn.PutUp(ctx, view, out) } return err }
// Proxy will launch a routine that waits for input connections // It takes a redirection address soas to where redirect incoming packets // Proxy will listen on Sink:SinkPort variables so that the user do not // differentiate between connecting to a proxy or directly to the sink // It will panic if it can not contact the server or can not bind to the address func Proxy(redirection string) { // Connect to the sink if err := connectToSink(redirection); err != nil { panic(err) } dbg.Lvl2("Proxy connected to sink", redirection) // Here it listens the same way monitor.go would // usually 0.0.0.0:4000 ln, err := net.Listen("tcp", Sink+":"+SinkPort) if err != nil { dbg.Fatalf("Error while binding proxy to addr %s: %v", Sink+":"+SinkPort, err) } dbg.Lvl2("Proxy listening on", Sink+":"+SinkPort) var newConn = make(chan bool) var closeConn = make(chan bool) var finished = false proxyConns = make(map[string]*json.Encoder) readyCount = 0 // Listen for incoming connections go func() { for finished == false { conn, err := ln.Accept() if err != nil { operr, ok := err.(*net.OpError) // the listener is closed if ok && operr.Op == "accept" { break } dbg.Lvl1("Error proxy accepting connection:", err) continue } dbg.Lvl3("Proxy accepting incoming connection from:", conn.RemoteAddr().String()) newConn <- true proxyConns[conn.RemoteAddr().String()] = json.NewEncoder(conn) go proxyConnection(conn, closeConn) } }() // Listen for replies and give them further go func() { for finished == false { m := Measure{} err := serverDec.Decode(&m) if err != nil { return } dbg.Lvlf3("Proxy received %+v", m) c, ok := proxyConns[m.Sender] if !ok { return } dbg.Lvl3("Found connection") c.Encode(m) } }() // notify every new connection and every end of connection. When all // connections are closed, send an "end" measure to the sink. var nconn int for finished == false { select { case <-newConn: nconn += 1 case <-closeConn: nconn -= 1 if nconn == 0 { // everything is finished serverEnc.Encode(Measure{Name: "end"}) serverConn.Close() ln.Close() finished = true break } } } }