// Listen for any host trying to contact him. // Will launch in a goroutine the srv function once a connection is established func (t *TcpHost) Listen(addr string, fn func(Conn)) { global, _ := cliutils.GlobalBind(addr) ln, err := net.Listen("tcp", global) if err != nil { dbg.Fatal("error listening (host", t.Name(), ")") } dbg.Lvl3(t.Name(), "Waiting for connections on addr", addr, "..\n") for { conn, err := ln.Accept() if err != nil { dbg.Lvl2(t.Name(), "error accepting connection:", err) continue } c := TcpConn{ Peer: conn.RemoteAddr().String(), Conn: conn, enc: gob.NewEncoder(conn), dec: gob.NewDecoder(conn), host: t, } t.peers[conn.RemoteAddr().String()] = &c go fn(&c) } }
// Listen listens for incoming TCP connections. // It is a non-blocking call that runs in the background. // It accepts incoming connections and establishes Peers. // When a peer attempts to connect it must send over its name (as a StringMarshaler), // as well as its public key. // Only after that point can be communicated with. func (h *TCPHost) Listen() error { var err error dbg.Lvl3("Starting to listen on", h.name) address, err := cliutils.GlobalBind(h.name) if err != nil { dbg.Fatal("Didn't get global binding for", address, err) } ln, err := net.Listen("tcp4", address) if err != nil { dbg.Lvl2("failed to listen on", address, ":", err) return err } h.listener = ln go func() { for { var err error dbg.Lvl3(h.Name(), "Accepting incoming") conn, err := ln.Accept() dbg.Lvl3(h.Name(), "Connection request - handling") if err != nil { dbg.Lvl3("failed to accept connection:", err) // if the host has been closed then stop listening if atomic.LoadInt64(&h.closed) == 1 { return } continue } // Read in name of client tp := NewTCPConnFromNet(conn) var mname StringMarshaler err = tp.GetData(&mname) if err != nil { log.Errorln("failed to establish connection: getting name:", err) tp.Close() continue } name := string(mname) // create connection tp.SetName(name) // get and set public key suite := h.suite pubkey := suite.Point() err = tp.GetData(pubkey) if err != nil { log.Errorln("failed to establish connection: getting pubkey:", err) tp.Close() continue } tp.SetPubKey(pubkey) // give child the public key err = tp.PutData(h.Pubkey) if err != nil { log.Errorln("failed to send public key:", err) continue } // the connection is now Ready to use h.PeerLock.Lock() h.Ready[name] = true h.peers[name] = tp dbg.Lvl3("Connected to child:", tp.Name()) h.PeerLock.Unlock() go func() { for { data := h.pool.Get().(BinaryUnmarshaler) err := tp.GetData(data) h.msgchan <- NetworkMessg{Data: data, From: tp.Name(), Err: err} } }() } }() return nil }
// listen for clients connections func (s *StampListener) ListenRequests() error { dbg.Lvl3("Setup StampListener on", s.NameL) global, _ := cliutils.GlobalBind(s.NameL) var err error s.Port, err = net.Listen("tcp4", global) if err != nil { panic(err) } go func() { for { dbg.Lvlf2("Listening to sign-requests: %p", s) conn, err := s.Port.Accept() if err != nil { // handle error dbg.Lvl3("failed to accept connection") select { case w := <-s.waitClose: dbg.Lvl3("Closing stamplistener:", w) return default: continue } } dbg.Lvl3("Waiting for connection") c := coconet.NewTCPConnFromNet(conn) if _, ok := s.Clients[c.Name()]; !ok { s.Clients[c.Name()] = c go func(co coconet.Conn) { for { tsm := TimeStampMessage{} err := co.GetData(&tsm) dbg.Lvlf2("Got data to sign %+v - %+v", tsm, tsm.Sreq) if err != nil { dbg.Lvlf1("%p Failed to get from child: %s", s.NameL, err) co.Close() return } switch tsm.Type { default: dbg.Lvlf1("Message of unknown type: %v\n", tsm.Type) case StampRequestType: s.Mux.Lock() s.Queue[READING] = append(s.Queue[READING], MustReplyMessage{Tsm: tsm, To: co.Name()}) s.Mux.Unlock() case StampClose: dbg.Lvl2("Closing connection") co.Close() return case StampExit: dbg.Lvl2("Exiting server upon request") os.Exit(-1) } } }(c) } } }() return nil }
// Main entry point of the validation mode func Validation(keyFile string) { // First, retrieve our public / private key pair + address for which it has // been created kp, addr := readKeyFile(keyFile) // Then wait for the connection // Accept incoming connections global, _ := cliutils.GlobalBind(addr) ln, err := net.Listen("tcp", global) if err != nil { dbg.Fatal("Could not listen for validation:", err) } var conn net.Conn for ; ; conn.Close() { dbg.Lvl1("Waiting for verifier connection ...") // Accept the one conn, err = ln.Accept() if err != nil { dbg.Fatal("Could not accept an input connection:", err) } dbg.Lvl1("Verifier connected! Validation in progress...") // Craft the message about our system,signs it, and then send the whole msg := createSystemPacket() signature := signSystemPacket(msg, kp) // We also send the size of the signature for the receiver to know how much // byte he is expecting if err := suite.Write(conn, msg, len(signature), signature); err != nil { dbg.Lvl1("Error when writing the system packet to the connection:", err) continue } // Receive the response var ack Ack if err := suite.Read(conn, &ack); err != nil { dbg.Lvl1("Error when reading the response:", err) } var er string = "Validation is NOT correct, something is wrong about your " // All went fine dbg.Lvl2("Received code", ack) switch ack.Code { default: dbg.Lvl1("Validation received unknown ACK: type =", ack.Type, "Code =", ack.Code) continue case SYS_OK: dbg.Lvl1("Validation finished successfully! You should receive an email from development team soon.") case SYS_WRONG_HOST: dbg.Lvl1(er + "HOSTNAME") case SYS_WRONG_SOFT: dbg.Lvl1(er + "SOFT limits") case SYS_WRONG_SIG: dbg.Lvl1(er + "signature!") case SYS_EXIT: dbg.Lvl1("Exiting - need to update to get config.toml") os.Exit(1) } } }