// 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 *erl.Term, from *erl.Tuple) (reply *erl.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 := erl.Term(erl.Tuple{erl.Atom("ok"), erl.Atom("go_reply"), *message}) reply = &replyTerm return }
func (currNode *Node) handleTerms(c net.Conn, wchan chan []erl.Term, terms []erl.Term) { nLog("Node terms: %#v", terms) if len(terms) == 0 { return } switch t := terms[0].(type) { case erl.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 erl.Atom: switch act { case erl.Atom("$go_set_node"): nLog("SET NODE %#v", t) currNode.neighbors[t[1].(erl.Atom)] = nodeConn{conn: c, wchan: wchan} } default: nLog("UNHANDLED ACT: %#v", t.Element(1)) } } } }
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 erl.Pid pid.Node = erl.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) } } }
// 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(erl.Atom("go_srv"), gs.Self) // Store first argument as channel gs.completeChan = args[0].(chan bool) }
func (rpcs *rpcRex) HandleCall(message *erl.Term, from *erl.Tuple) (reply *erl.Term) { nLog("REX: HandleCall: %#v, From: %#v", *message, *from) switch req := (*message).(type) { case erl.Tuple: if len(req) > 0 { switch act := req[0].(type) { case erl.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 := erl.Term(erl.Tuple{req[1], req[2]}) reply = &replyTerm } } } } if reply == nil { replyTerm := erl.Term(erl.Tuple{erl.Atom("badrpc"), erl.Atom("unknown")}) reply = &replyTerm } return }
// Send sends message to destination process withoud source func (currNode *Node) Send(to erl.Pid, message erl.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 := []erl.Term{erl.Tuple{SEND, erl.Atom(""), to}, message} currNode.neighbors[to.Node].wchan <- msg } }
func TestDecodeStruct3(t *testing.T) { type testStruct struct { types.Atom X uint8 i *big.Int S string } type testStruct3 struct { T testStruct i [2]byte Y int } var ts testStruct3 nilBig := (*big.Int)(nil) nilArr := [2]byte{0, 0} in := bytes.NewBuffer([]byte{ 131, 104, 2, 104, 3, 100, 0, 4, 98, 108, 97, 104, 97, 4, 108, 0, 0, 0, 4, 98, 0, 0, 4, 68, 98, 0, 0, 4, 75, 98, 0, 0, 4, 50, 98, 0, 0, 4, 48, 106, 98, 0, 0, 2, 154, }) exp := testStruct3{ testStruct{ types.Atom("blah"), 4, nilBig, "фыва", }, nilArr, 666, } if err := Decode(in, &ts); err != nil { t.Fatal(err) } else if l := in.Len(); l != 0 { t.Errorf("buffer len %d", l) } else if ts != exp { t.Errorf("expected %v, got %v", exp, ts) } }
func (nk *netKernel) HandleCall(message *erl.Term, from *erl.Tuple) (reply *erl.Term) { nLog("NET_KERNEL: HandleCall: %#v, From: %#v", *message, *from) switch t := (*message).(type) { case erl.Tuple: if len(t) == 2 { switch tag := t[0].(type) { case erl.Atom: if string(tag) == "is_auth" { nLog("NET_KERNEL: is_auth: %#v", t[1]) replyTerm := erl.Term(erl.Atom("yes")) reply = &replyTerm } } } } return }
func TestDecodeStruct(t *testing.T) { type testStruct struct { types.Atom X uint8 S string } var ts testStruct in := bytes.NewBuffer([]byte{ 131, 104, 3, 100, 0, 4, 98, 108, 97, 104, 97, 4, 108, 0, 0, 0, 4, 98, 0, 0, 4, 68, 98, 0, 0, 4, 75, 98, 0, 0, 4, 50, 98, 0, 0, 4, 48, 106, }) if err := Decode(in, &ts); err != nil { t.Fatal(err) } else if l := in.Len(); l != 0 { t.Errorf("buffer len %d", l) } else if exp := (testStruct{types.Atom("blah"), 4, "фыва"}); ts != exp { t.Errorf("expected %v, got %v", exp, ts) } }
func (gns *globalNameServer) HandleCall(message *erl.Term, from *erl.Tuple) (reply *erl.Term) { nLog("GLOBAL_NAME_SERVER: HandleCall: %#v, From: %#v", *message, *from) replyTerm := erl.Term(erl.Atom("reply")) reply = &replyTerm return }
func (gns *globalNameServer) Init(args ...interface{}) { nLog("GLOBAL_NAME_SERVER: Init: %#v", args) gns.Node.Register(erl.Atom("global_name_server"), gns.Self) }
// data structures and vice versa. package etf import ( "encoding/binary" "errors" "fmt" read "github.com/goerlang/etf/read" t "github.com/goerlang/etf/types" "io" "math/big" "reflect" ) var ( atomType = reflect.ValueOf(t.Atom("")).Type() ErrBadFormat = errors.New("etf: bad format") ) // Decode unmarshals a value and stores it to a variable pointed by ptr. func Decode(r io.Reader, ptr interface{}) (err error) { b := make([]byte, 1) _, err = io.ReadFull(r, b) if err == nil { if b[0] != t.EtVersion { err = fmt.Errorf("version %d not supported", b[0]) return } p := reflect.ValueOf(ptr) err = decode(r, p)
func (nk *netKernel) Init(args ...interface{}) { nLog("NET_KERNEL: Init: %#v", args) nk.Node.Register(erl.Atom("net_kernel"), nk.Self) }
// 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 <- erl.Tuple{erl.Atom("$go_ctl"), erl.Tuple{erl.Atom("control-message"), erl.Atom("example")}} defer func() { if r := recover(); r != nil { // TODO: send message to parent process log.Printf("GenServer recovered: %#v", r) } }() for { var message erl.Term var fromPid erl.Pid select { case msg := <-pcs.in: message = msg case msgFrom := <-pcs.inFrom: message = msgFrom[1] fromPid = msgFrom[0].(erl.Pid) case ctlMsg := <-pcs.ctl: switch m := ctlMsg.(type) { case erl.Tuple: switch mtag := m[0].(type) { case erl.Atom: switch mtag { case erl.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 erl.Tuple: switch mtag := m[0].(type) { case erl.Atom: switch mtag { case erl.Atom("$go_ctl"): nLog("Control message: %#v", message) case erl.Atom("$gen_call"): fromTuple := m[1].(erl.Tuple) reply := pd.(GenServer).HandleCall(&m[2], &fromTuple) if reply != nil { gs.Reply(&fromTuple, reply) } case erl.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) } } }
func (rpcs *rpcRex) Init(args ...interface{}) { nLog("REX: Init: %#v", args) rpcs.Node.Register(erl.Atom("rex"), rpcs.Self) }