func epmdC(n *Node, resp chan uint16) { conn, err := net.Dial("tcp", ":4369") if err != nil { resp <- 100 return } defer conn.Close() epmdFROM := make(chan []byte) go epmdREADER(conn, epmdFROM) epmdTO := make(chan []byte) go epmdWRITER(conn, epmdFROM, epmdTO) epmdTO <- epmd.Compose_ALIVE2_REQ(&n.NodeInfo) for { select { case reply := <-epmdFROM: nLog("From EPMD: %v", reply) switch epmd.MessageId(reply[0]) { case epmd.ALIVE2_RESP: if creation, ok := epmd.Read_ALIVE2_RESP(reply); ok { resp <- creation } else { resp <- 99 } } } } }
func epmReg(in <-chan regReq) { var nReg = make(map[string]*nodeRec) for { select { case req := <-in: buf := req.buf if len(buf) == 0 { rs := len(nReg) log.Printf("REG %d records", rs) now := time.Now() for node, rec := range nReg { if rec.conn == req.conn { log.Printf("Connection for %s dropped", node) nReg[node].Active = false nReg[node].Time = now nReg[node].conn = nil } else if rs > regLimit && !rec.Active && now.Sub(rec.Time).Minutes() > float64(unregTTL) { log.Printf("REG prune %s:%+v", node, rec) delete(nReg, node) } } continue } replyTo := req.replyTo log.Printf("IN: %v", buf) switch epmd.MessageId(buf[0]) { case epmd.ALIVE2_REQ: nConn := req.conn nInfo := epmd.Read_ALIVE2_REQ(buf) log.Printf("NodeInfo: %+v", nInfo) var reply []byte if rec, ok := nReg[nInfo.Name]; ok { log.Printf("Node %s found", nInfo.Name) if rec.Active { log.Printf("Node %s is running", nInfo.Name) reply = epmd.Compose_ALIVE2_RESP(false) } else { log.Printf("Node %s is not running", nInfo.Name) rec.conn = nConn nInfo.Creation = (rec.Creation % 3) + 1 rec.NodeInfo = nInfo rec.Active = true reply = epmd.Compose_ALIVE2_RESP(true, rec.NodeInfo) } } else { log.Printf("New node %s", nInfo.Name) nInfo.Creation = 1 rec := &nodeRec{ NodeInfo: nInfo, conn: nConn, Time: time.Now(), Active: true, } nReg[nInfo.Name] = rec reply = epmd.Compose_ALIVE2_RESP(true, rec.NodeInfo) } replyTo <- regAns{reply: reply, isClose: false} case epmd.PORT_PLEASE2_REQ: nName := epmd.Read_PORT_PLEASE2_REQ(buf) var reply []byte if rec, ok := nReg[nName]; ok && rec.Active { reply = epmd.Compose_PORT2_RESP(rec.NodeInfo) } else { reply = epmd.Compose_PORT2_RESP(nil) } replyTo <- regAns{reply: reply, isClose: true} case epmd.STOP_REQ: nName := epmd.Read_STOP_REQ(buf) var reply []byte if rec, ok := nReg[nName]; ok && rec.Active { // TODO: stop node reply = epmd.Compose_STOP_RESP(true) } else { reply = epmd.Compose_STOP_RESP(false) } replyTo <- regAns{reply: reply, isClose: true} case epmd.NAMES_REQ, epmd.DUMP_REQ: lp, err := strconv.Atoi(listenPort) if err != nil { log.Printf("Cannot convert %s to integer", listenPort) replyTo <- regAns{reply: nil, isClose: true} } else { replyB := new(bytes.Buffer) epmd.Compose_START_NAMES_RESP(replyB, lp) for _, rec := range nReg { if epmd.MessageId(buf[0]) == epmd.NAMES_REQ { if rec.Active { epmd.Append_NAMES_RESP(replyB, rec.NodeInfo) } else { if rec.Active { epmd.Append_DUMP_RESP_ACTIVE(replyB, rec.NodeInfo) } else { epmd.Append_DUMP_RESP_UNUSED(replyB, rec.NodeInfo) } } } } replyTo <- regAns{reply: replyB.Bytes(), isClose: true} } case epmd.KILL_REQ: reply := epmd.Compose_KILL_RESP() replyTo <- regAns{reply: reply, isClose: true} default: switch cliMessageId(buf[0]) { case REQ_NAMES: reply := ansNames(nReg) replyTo <- regAns{reply: reply, isClose: true} default: replyTo <- regAns{reply: nil, isClose: true} } } } } }