Пример #1
0
func (rpcs *rpcRex) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	nLog("REX: HandleCall: %#v, From: %#v", *message, *from)
	var replyTerm etf.Term
	valid := false
	switch req := (*message).(type) {
	case etf.Tuple:
		if len(req) > 0 {
			switch act := req[0].(type) {
			case etf.Atom:
				if string(act) == "call" {
					valid = true
					if fun, ok := rpcs.callMap[modFun{string(req[1].(etf.Atom)), string(req[2].(etf.Atom))}]; ok {
						replyTerm = fun(req[3].(etf.List))
					} else {
						replyTerm = etf.Term(etf.Tuple{etf.Atom("badrpc"), etf.Tuple{etf.Atom("EXIT"), etf.Tuple{etf.Atom("undef"), etf.List{etf.Tuple{req[1], req[2], req[3], etf.List{}}}}}})
					}
				}
			}
		}
	}
	if !valid {
		replyTerm = etf.Term(etf.Tuple{etf.Atom("badrpc"), etf.Atom("unknown")})
	}
	reply = &replyTerm
	return
}
Пример #2
0
// shutdown request
// takes no arguments
func (r *Relay) rpcShutdown(terms etf.List) etf.Term {
	if len(terms) != 0 {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarith")})
	}
	r.shutdown()
	r.shutdownChan <- struct{}{}
	return etf.Term(etf.Atom("ok"))
}
Пример #3
0
// HandleCall handles incoming messages from `gen_server:call/2`, if returns non-nil term,
// then calling process have reply
// Call `gen_server:call({go_srv, gonode@localhost}, Message)` at Erlang node
func (gs *gonodeSrv) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	log.Printf("GO_SRV: HandleCall: %#v, From: %#v", *message, *from)

	// Just create new term tuple where first element is atom 'ok', second 'go_reply' and third is original message
	replyTerm := etf.Term(etf.Tuple{etf.Atom("ok"), etf.Atom("go_reply"), *message})
	reply = &replyTerm
	return
}
Пример #4
0
func main() {
	// Parse CLI flags
	flag.Parse()

	setup_logging()
	write_pid()

	log.Println("node started")

	// Initialize new node with given name and cookie
	enode := node.NewNode(NodeName, Cookie)

	// Allow node be available on EpmdPort port
	err = enode.Publish(EpmdPort)
	if err != nil {
		log.Fatalf("Cannot publish: %s", err)
	}

	// Create channel to receive message when main process should be stopped
	completeChan := make(chan bool)

	// Initialize new instance of srv structure which implements Process behaviour
	eSrv := new(srv)

	// Spawn process with one arguments
	enode.Spawn(eSrv, completeChan)

	// RPC
	if EnableRPC {
		// Create closure
		eClos := func(terms etf.List) (r etf.Term) {
			r = etf.Term(etf.Tuple{etf.Atom("gonode"), etf.Atom("reply"), len(terms)})
			return
		}

		// Provide it to call via RPC with `rpc:call(gonode@localhost, go_rpc, call, [as, qwe])`
		err = enode.RpcProvide("go_rpc", "call", eClos)
		if err != nil {
			log.Printf("Cannot provide function to RPC: %s", err)
		}
	}

	// Wait to stop
	<-completeChan

	log.Println("node finished")

	return
}
Пример #5
0
func (r *Relay) createDevice(fsName, deviceName string,
	isSensor, isAffector bool) (etf.Atom, error) {
	fs, ok := r.fss[fsName]
	if !ok {
		return etf.Atom(""), errors.New("no such fs")
	}
	device, err := fs.CreateDevice(deviceName, isSensor, isAffector)
	if err != nil {
		return etf.Atom(""), err
	}
	dp := newDeviceProc(device)
	fullName := deviceName + "@" + fsName
	r.node.Spawn(dp, fullName)
	return etf.Atom(fullName), nil
}
Пример #6
0
func (n *Node) registrator() {
	for {
		select {
		case req := <-n.registry.storeChan:
			// FIXME: make proper allocation, now it just stub
			var id uint32 = 0
			for k, _ := range n.channels {
				if k.Id >= id {
					id = k.Id + 1
				}
			}
			var pid etf.Pid
			pid.Node = etf.Atom(n.FullName)
			pid.Id = id
			pid.Serial = 0 // FIXME
			pid.Creation = byte(n.Creation)

			n.channels[pid] = req.channels
			req.replyTo <- pid
		case req := <-n.registry.regNameChan:
			n.registered[req.name] = req.pid
		case req := <-n.registry.unregNameChan:
			delete(n.registered, req.name)
		}
	}
}
Пример #7
0
func (currNode *Node) handleTerms(c net.Conn, wchan chan []etf.Term, terms []etf.Term) {
	nLog("Node terms: %#v", terms)

	if len(terms) == 0 {
		return
	}
	switch t := terms[0].(type) {
	case etf.Tuple:
		if len(t) > 0 {
			switch act := t.Element(1).(type) {
			case int:
				switch act {
				case REG_SEND:
					if len(terms) == 2 {
						currNode.RegSend(t.Element(2), t.Element(4), terms[1])
					} else {
						nLog("*** ERROR: bad REG_SEND: %#v", terms)
					}
				default:
					nLog("Unhandled node message (act %d): %#v", act, t)
				}
			case etf.Atom:
				switch act {
				case etf.Atom("$go_set_node"):
					nLog("SET NODE %#v", t)
					currNode.neighbors[t[1].(etf.Atom)] = nodeConn{conn: c, wchan: wchan}
				}
			default:
				nLog("UNHANDLED ACT: %#v", t.Element(1))
			}
		}
	}
}
Пример #8
0
// Init initializes process state using arbitrary arguments
func (gs *gonodeSrv) Init(args ...interface{}) {
	log.Printf("GO_SRV: Init: %#v", args)

	// Self-registration with name go_srv
	gs.Node.Register(etf.Atom("go_srv"), gs.Self)

	// Store first argument as channel
	gs.completeChan = args[0].(chan bool)
}
Пример #9
0
func (rpcs *rpcRex) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	nLog("REX: HandleCall: %#v, From: %#v", *message, *from)
	switch req := (*message).(type) {
	case etf.Tuple:
		if len(req) > 0 {
			switch act := req[0].(type) {
			case etf.Atom:
				if string(act) == "call" {
					nLog("RPC CALL: Module: %#v, Function: %#v, Args: %#v, GroupLeader: %#v", req[1], req[2], req[3], req[4])
					replyTerm := etf.Term(etf.Tuple{req[1], req[2]})
					reply = &replyTerm
				}
			}
		}
	}
	if reply == nil {
		replyTerm := etf.Term(etf.Tuple{etf.Atom("badrpc"), etf.Atom("unknown")})
		reply = &replyTerm
	}
	return
}
Пример #10
0
// Send sends message to destination process withoud source
func (currNode *Node) Send(to etf.Pid, message etf.Term) {
	nLog("Send: %#v, %#v", to, message)
	if string(to.Node) == currNode.FullName {
		nLog("Send to local node")
		pcs := currNode.channels[to]
		pcs.in <- message
	} else {
		nLog("Send to remote node: %#v, %#v", to, currNode.neighbors[to.Node])

		msg := []etf.Term{etf.Tuple{SEND, etf.Atom(""), to}, message}
		currNode.neighbors[to.Node].wchan <- msg
	}
}
Пример #11
0
func main() {
	// Initialize new node with given name and cookie
	enode := node.NewNode("gonode@localhost", "123")

	// Allow node be available on 5588 port
	err := enode.Publish(5588)
	if err != nil {
		log.Fatalf("Cannot publish: %s", err)
	}

	// Create channel to receive message when main process should be stopped
	completeChan := make(chan bool)

	// Initialize new instance of gonodeSrv structure which implements Process behaviour
	eSrv := new(gonodeSrv)

	// Spawn process with one arguments
	enode.Spawn(eSrv, completeChan)

	// RPC
	// Create closure
	eClos := func(terms etf.List) (r etf.Term) {
		r = etf.Term(etf.Tuple{etf.Atom("gonode"), etf.Atom("reply"), len(terms)})
		return
	}

	// Provide it to call via RPC with `rpc:call(gonode@localhost, go_rpc, call, [as, qwe])`
	err = enode.RpcProvide("go_rpc", "call", eClos)
	if err != nil {
		log.Printf("Cannot provide function to RPC: %s", err)
	}

	// Wait to stop
	<-completeChan

	return
}
Пример #12
0
func (nk *netKernel) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	nLog("NET_KERNEL: HandleCall: %#v, From: %#v", *message, *from)
	switch t := (*message).(type) {
	case etf.Tuple:
		if len(t) == 2 {
			switch tag := t[0].(type) {
			case etf.Atom:
				if string(tag) == "is_auth" {
					nLog("NET_KERNEL: is_auth: %#v", t[1])
					replyTerm := etf.Term(etf.Atom("yes"))
					reply = &replyTerm
				}
			}
		}
	}
	return
}
Пример #13
0
// rpc funcs for erlang nodes
// args must be in form `[Name:string]`
// returns either `ok` or `{error, Reason}`
func (r *Relay) rpcCreateFS(terms etf.List) etf.Term {
	if len(terms) != 1 {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarith")})
	}
	t := terms[0]
	if _, ok := t.(string); !ok {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
	}
	name := t.(string)
	err := r.createFS(name)
	if err != nil {
		println("cannot create fs: ", err)
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("failed-to-create-fs")})
	}
	return etf.Term(etf.Atom("ok"))
}
Пример #14
0
func runNode() (enode *node.Node) {
	enode = node.NewNode(nodeName, nodeCookie)
	err := enode.Publish(nodePort)
	if err != nil {
		log.Printf("Cannot publish: %s", err)
		enode = nil
	}
	eSrv := new(eclusSrv)
	enode.Spawn(eSrv)

	eClos := func(terms etf.List) (r etf.Term) {
		r = etf.Term(etf.Tuple{etf.Atom("enode"), len(terms)})
		return
	}

	err = enode.RpcProvide("enode", "lambda", eClos)
	if err != nil {
		log.Printf("Cannot provide function to RPC: %s", err)
	}

	return
}
Пример #15
0
// affecter data request
// msg must be atom `req`
func (d *deviceProc) HandleCall(msg *etf.Term, from *etf.Tuple) *etf.Term {
	println("handling call")
	if atom, ok := (*msg).(etf.Atom); !ok {
		t := etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
		return &t
	} else {
		if string(atom) != "req" {
			t := etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
			return &t
		}
		buf := d.device.Affect()
		if buf == nil {
			t := etf.Term(etf.Tuple{etf.Atom("ok"), etf.Atom("nil")})
			return &t
		} else {
			t := etf.Term(etf.Tuple{etf.Atom("ok"), buf})
			return &t
		}
	}
}
Пример #16
0
// HandleCast
// Call `gen_server:cast({go_srv, gonode@localhost}, stop)` at Erlang node to stop this Go-node
func (gs *srv) HandleCast(message *etf.Term) {
	log.Printf("HandleCast: %#v", *message)

	// Check type of message
	switch req := (*message).(type) {
	case etf.Tuple:
		if len(req) > 0 {
			switch act := req[0].(type) {
			case etf.Atom:
				if string(act) == "ping" {
					var self_pid etf.Pid = gs.Self
					gs.Node.Send(req[1].(etf.Pid), etf.Tuple{etf.Atom("pong"), etf.Pid(self_pid)})
				}
			}
		}
	case etf.Atom:
		// If message is atom 'stop', we should say it to main process
		if string(req) == "stop" {
			gs.completeChan <- true
		}
	}
}
Пример #17
0
func (currNd *NodeDesc) ReadMessage(c net.Conn) (ts []etf.Term, err error) {

	sendData := func(headerLen int, data []byte) (int, error) {
		reply := make([]byte, len(data)+headerLen)
		if headerLen == 2 {
			binary.BigEndian.PutUint16(reply[0:headerLen], uint16(len(data)))
		} else {
			binary.BigEndian.PutUint32(reply[0:headerLen], uint32(len(data)))
		}
		copy(reply[headerLen:], data)
		dLog("Write to enode: %v", reply)
		return c.Write(reply)
	}

	switch currNd.state {
	case HANDSHAKE:
		var length uint16
		if err = binary.Read(c, binary.BigEndian, &length); err != nil {
			return
		}
		msg := make([]byte, length)
		if _, err = io.ReadFull(c, msg); err != nil {
			return
		}
		dLog("Read from enode %d: %v", length, msg)

		switch msg[0] {
		case 'n':
			sn := currNd.read_SEND_NAME(msg)
			// Statuses: ok, nok, ok_simultaneous, alive, not_allowed
			sok := currNd.compose_SEND_STATUS(sn, true)
			_, err = sendData(2, sok)
			if err != nil {
				return
			}

			rand.Seed(time.Now().UTC().UnixNano())
			currNd.challenge = rand.Uint32()

			// Now send challenge
			challenge := currNd.compose_SEND_CHALLENGE(sn)
			sendData(2, challenge)
			if err != nil {
				return
			}

		case 'r':
			sn := currNd.remote
			ok := currNd.read_SEND_CHALLENGE_REPLY(sn, msg)
			if ok {
				challengeAck := currNd.compose_SEND_CHALLENGE_ACK(sn)
				sendData(2, challengeAck)
				if err != nil {
					return
				}
				dLog("Remote: %#v", sn)
				ts = []etf.Term{etf.Term(etf.Tuple{etf.Atom("$go_set_node"), etf.Atom(sn.Name)})}
			} else {
				err = errors.New("bad handshake")
				return
			}
		}

	case CONNECTED:
		var length uint32
		if err = binary.Read(c, binary.BigEndian, &length); err != nil {
			return
		}
		if length == 0 {
			dLog("Keepalive")
			sendData(4, []byte{})
			return
		}
		r := &io.LimitedReader{c, int64(length)}

		if currNd.flag.isSet(DIST_HDR_ATOM_CACHE) {
			var ctl, message etf.Term
			if err = currNd.readDist(r); err != nil {
				break
			}
			if ctl, err = currNd.readCtl(r); err != nil {
				break
			}
			dLog("READ CTL: %#v", ctl)

			if message, err = currNd.readMessage(r); err != nil {
				break
			}
			dLog("READ MESSAGE: %#v", message)
			ts = append(ts, ctl, message)

		} else {
			msg := make([]byte, 1)
			if _, err = io.ReadFull(r, msg); err != nil {
				return
			}
			dLog("Read from enode %d: %#v", length, msg)

			switch msg[0] {
			case 'p':
				ts = make([]etf.Term, 0)
				for {
					var res etf.Term
					if res, err = currNd.readTerm(r); err != nil {
						break
					}
					ts = append(ts, res)
					dLog("READ TERM: %#v", res)
				}
				if err == io.EOF {
					err = nil
				}

			default:
				_, err = ioutil.ReadAll(r)
			}
		}

	}

	return
}
Пример #18
0
func (gns *globalNameServer) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	nLog("GLOBAL_NAME_SERVER: HandleCall: %#v, From: %#v", *message, *from)
	replyTerm := etf.Term(etf.Atom("reply"))
	reply = &replyTerm
	return
}
Пример #19
0
// ProcessLoop executes during whole time of process life.
// It receives incoming messages from channels and handle it using methods of behaviour implementation
func (gs *GenServerImpl) ProcessLoop(pcs procChannels, pd Process, args ...interface{}) {
	pd.(GenServer).Init(args...)
	//pcs.ctl <- etf.Tuple{etf.Atom("$go_ctl"), etf.Tuple{etf.Atom("control-message"), etf.Atom("example")}}
	defer func() {
		if r := recover(); r != nil {
			// TODO: send message to parent process
			log.Printf("GenServer recovered: %#v", r)
		}
	}()
	for {
		var message etf.Term
		var fromPid etf.Pid
		select {
		case msg := <-pcs.in:
			message = msg
		case msgFrom := <-pcs.inFrom:
			message = msgFrom[1]
			fromPid = msgFrom[0].(etf.Pid)
		case ctlMsg := <-pcs.ctl:
			switch m := ctlMsg.(type) {
			case etf.Tuple:
				switch mtag := m[0].(type) {
				case etf.Atom:
					switch mtag {
					case etf.Atom("$go_ctl"):
						nLog("Control message: %#v", m)
					default:
						nLog("Unknown message: %#v", m)
					}
				default:
					nLog("Unknown message: %#v", m)
				}
			default:
				nLog("Unknown message: %#v", m)
			}
			continue
		}
		nLog("Message from %#v", fromPid)
		switch m := message.(type) {
		case etf.Tuple:
			switch mtag := m[0].(type) {
			case etf.Atom:
				switch mtag {
				case etf.Atom("$go_ctl"):
					nLog("Control message: %#v", message)
				case etf.Atom("$gen_call"):
					fromTuple := m[1].(etf.Tuple)
					reply := pd.(GenServer).HandleCall(&m[2], &fromTuple)
					if reply != nil {
						gs.Reply(&fromTuple, reply)
					}
				case etf.Atom("$gen_cast"):
					pd.(GenServer).HandleCast(&m[1])
				default:
					pd.(GenServer).HandleInfo(&message)
				}
			default:
				nLog("mtag: %#v", mtag)
				pd.(GenServer).HandleInfo(&message)
			}
		default:
			nLog("m: %#v", m)
			pd.(GenServer).HandleInfo(&message)
		}
	}
}
Пример #20
0
func (es *eclusSrv) Init(args ...interface{}) {
	log.Printf("ECLUS_SRV: Init: %#v", args)
	es.Node.Register(etf.Atom("eclus"), es.Self)
}
Пример #21
0
func (rpcs *rpcRex) Init(args ...interface{}) {
	nLog("REX: Init: %#v", args)
	rpcs.Node.Register(etf.Atom("rex"), rpcs.Self)
}
Пример #22
0
func (es *eclusSrv) HandleCall(message *etf.Term, from *etf.Tuple) (reply *etf.Term) {
	log.Printf("ECLUS_SRV: HandleCall: %#v, From: %#v", *message, *from)
	replyTerm := etf.Term(etf.Tuple{etf.Atom("ok"), etf.Atom("eclus_reply"), *message})
	reply = &replyTerm
	return
}
Пример #23
0
// gen_server behavior
func (d *deviceProc) Init(args ...interface{}) {
	println("handling init")
	d.Node.Register(etf.Atom(args[0].(string)), d.Self)
	// initialization done before spawn
}
Пример #24
0
func (nk *netKernel) Init(args ...interface{}) {
	nLog("NET_KERNEL: Init: %#v", args)
	nk.Node.Register(etf.Atom("net_kernel"), nk.Self)
}
Пример #25
0
func (rpcs *rpcRex) Init(args ...interface{}) {
	nLog("REX: Init: %#v", args)
	rpcs.Node.Register(etf.Atom("rex"), rpcs.Self)
	rpcs.callMap = make(map[modFun]rpcFunction, 0)
}
Пример #26
0
func (gns *globalNameServer) Init(args ...interface{}) {
	nLog("GLOBAL_NAME_SERVER: Init: %#v", args)
	gns.Node.Register(etf.Atom("global_name_server"), gns.Self)
}
Пример #27
0
// args must be in form `[FSName:string, DevName:string, isSensor/optional,
//    isAffector/optional]
// return `{ok, Pid}` or `{error, Reason}`
func (r *Relay) rpcCreateDevice(terms etf.List) etf.Term {
	if len(terms) != 3 {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarith")})
	}
	tFSName := terms[0]
	if _, ok := tFSName.(string); !ok {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
	}
	fsName := tFSName.(string)
	tDeviceName := terms[1]
	if _, ok := tDeviceName.(string); !ok {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
	}
	deviceName := tDeviceName.(string)
	if _, ok := terms[2].(etf.List); !ok {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
	}
	isSensor, isAffector, err := parseCreateFlags(terms[2].(etf.List))
	if err != nil {
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("badarg")})
	}
	fullName, err := r.createDevice(fsName, deviceName, isSensor, isAffector)
	if err != nil {
		println("failed to create device: ", err)
		return etf.Term(etf.Tuple{etf.Atom("error"), etf.Atom("failed-to-create-device")})
	}
	return etf.Term(etf.Tuple{etf.Atom("ok"), fullName})
}