/// <summary> /// Break links of all pids linked to pids on the fromNode node /// </summary> internal void BreakLinks(ErlAtom fromNode, IErlObject reason) { foreach (var m in m_Mailboxes) { m.Value.BreakLinks(fromNode, reason); } }
internal ErlTuple ToCtrlTuple(ErlAtom cookie) { switch (Type) { case Tag.Link: return(new ErlTuple((int)Type, m_From, m_To)); case Tag.Send: return(new ErlTuple((int)Type, cookie, m_To)); case Tag.Exit: return(new ErlTuple((int)Type, m_From, m_To, Reason)); case Tag.Unlink: return(new ErlTuple((int)Type, m_From, m_To)); case Tag.NodeLink: return(new ErlTuple((int)Type)); case Tag.RegSend: return(new ErlTuple((int)Type, m_From, cookie, m_To)); case Tag.GroupLeader: return(new ErlTuple((int)Type, m_From, m_To)); case Tag.Exit2: return(new ErlTuple((int)Type, m_From, m_To, Reason)); case Tag.SendTT: return(new ErlTuple((int)Type, cookie, m_To, TraceToken)); case Tag.Exit2TT: case Tag.ExitTT: return(new ErlTuple((int)Type, m_From, m_To, TraceToken, Reason)); case Tag.RegSendTT: return(new ErlTuple((int)Type, m_From, cookie, m_To, TraceToken)); case Tag.MonitorP: case Tag.DemonitorP: return(new ErlTuple((int)Type, m_From, Recipient, Ref)); case Tag.MonitorPexit: return(new ErlTuple((int)Type, Sender, m_To, Ref, Reason)); default: throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(Type)); } }
protected internal virtual void OnNodeStatusChange(ErlAtom node, bool up, object info) { if (NodeStatusChange != null) { NodeStatusChange(this, node, up, info); } }
/// <summary> /// Create a node with the given name, cookie, and short name indicator /// </summary> public ErlLocalNode(string node, ErlAtom cookie, bool shortName = true, bool acceptConns = true) : base(node, cookie, shortName) { m_AcceptConnections = acceptConns; TraceLevel = ErlApp.DefaultTraceLevel; }
protected internal virtual void OnIoOutput(ErlAtom encoding, IErlObject output) { if (IoOutput != null) { IoOutput(this, encoding, output); } }
internal void IoOutput(ErlAtom encoding, IErlObject output) { if (m_OnIoOutput != null) { m_OnIoOutput(encoding, output); } }
public ErlConnection Connection(ErlAtom toNode, ErlAtom?cookie = null) { ErlConnection c; if (m_Connections.TryGetValue(toNode, out c)) { return(c); } var peer = new ErlRemoteNode(this, toNode, cookie); //try to append config to remote node TryAppendConfigToRemoteNode(peer); lock (m_Connections) { if (m_Connections.TryGetValue(toNode, out c)) { return(c); } try { c = new ErlConnection(this, peer, true); } catch { return(null); } m_Connections.TryAdd(toNode, c); return(c); } }
internal void NodeStatus(ErlAtom node, bool up, object info) { if (m_OnNodeStatus != null) { m_OnNodeStatus(node, up, info); } }
internal void ConnectAttempt(ErlAtom node, Direction dir, object info) { if (m_OnConnectAttempt != null) { m_OnConnectAttempt(node, dir, info); } }
/// <summary> /// Used to break all known links to this mbox /// </summary> internal void BreakLinks(ErlAtom reason) { foreach (var l in m_Links.Clear()) { m_Node.Deliver(ErlMsg.Exit(m_Self, l.Pid, reason)); } }
static ErlAbstractNode() { try { LocalHost = System.Net.Dns.GetHostName(); } catch { LocalHost = "localhost"; } s_DefaultCookie = tryReadDefaultCookieFromFile(); }
protected internal virtual void OnConnectAttempt(ErlAtom node, Direction dir, object info) { if (ConnectAttempt != null) { ConnectAttempt(this, node, dir, info); } }
protected internal void OnEpmdFailedConnectAttempt(ErlAtom node, object info) { if (EpmdFailedConnectAttempt != null) { EpmdFailedConnectAttempt(this, node, info); } }
/// <summary> /// Create a node with the given name and cookie /// </summary> /// <param name="name">Node name in the form "name" or "name@hostname"</param> /// <param name="cookie">Security cookie used to connect to this/other node(s)</param> /// <param name="shortName">Use short/long host names</param> protected ErlAbstractNode(string name, ErlAtom cookie, bool shortName) : base(null) { m_Cookie = new ErlAtom(cookie.Empty ? s_DefaultCookie : cookie); m_UseShortName = shortName; SetNodeName(name); }
/// <summary> /// Create an Erlang pid from the given values /// </summary> public ErlPid(ErlAtom node, int id, int serial, int creation) { // TODO: check compatibility with latest version of Erlang supporting 28bit pids Node = node; // m_Num is 15+13+2 bits m_Num = (((id & 0x7fff) << 15) | ((serial & 0x1fff) << 2) | (creation & 0x3)) & 0x3fffFFFF; }
internal ErlMbox(ErlLocalNode home, ErlPid self, ErlAtom name) { m_Self = self; m_Node = home; m_RegName = name; m_Queue = new ErlBlockingQueue <IQueable>(); m_Links = new ErlLinks(); m_Monitors = new ErlMonitors(this); }
private byte[] genDigest(int challenge, ErlAtom cookie) { long ch2 = challenge < 0 ? 1L << 31 | (long)(challenge & 0x7FFFFFFFL) : (long)challenge; return(new MD5CryptoServiceProvider().ComputeHash( Encoding.UTF8.GetBytes(cookie.Value + Convert.ToString(ch2)))); }
public IErlObject RPC(ErlAtom node, ErlAtom mod, ErlAtom fun, ErlList args, int timeout, ErlAtom?remoteCookie = null) { AsyncRPC(node, mod, fun, args, remoteCookie); var r = m_Monitors.Add(node); using (Scope.OnExit(() => m_Monitors.Remove(r))) { return(ReceiveRPC(timeout)); } }
public bool Register(ErlAtom name) { var res = m_Node.Mailboxes.Register(name, this); if (res) { m_RegName = name; } return(res); }
/// <summary> /// Close this mailbox /// </summary> /// <remarks> /// After this operation, the mailbox will no longer be able to /// receive messages. Any delivered but as yet unretrieved messages /// can still be retrieved however. /// /// If there are links from this mailbox to other <see cref="ErlPid"/> /// pids they will be broken when this method is /// called and exit signals will be sent. /// </remarks> internal void Close() { // Notify all registered monitors that this pid is closing foreach (var monitor in m_Monitors) { var msg = ErlMsg.MonitorPexit(m_Self, monitor.Value, monitor.Key, ErlAtom.Normal); m_Node.Deliver(monitor.Value.Node, msg); } m_Node.CloseMbox(this); m_RegName = ErlAtom.Null; }
public List <ErlLink> Remove(ErlAtom toNode) { var links = new List <ErlLink>(Math.Min(m_Links.Count, 32)); lock (m_Links) m_Links.RemoveWhere(l => { var r = l.Node == toNode; if (r) { links.Add(l); } return(r); }); return(links); }
public IErlObject RPC(ErlAtom node, ErlAtom mod, ErlAtom fun, ErlList args, int timeout) { var mbox = m_Mailboxes.Create(true); try { var res = mbox.RPC(node, mod, fun, args, timeout); return(res); } finally { m_Mailboxes.Unregister(mbox); } }
public void RPCcast(ErlAtom node, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject ioServer) { if (node.Equals(m_Node.NodeName)) { throw new ErlException(StringConsts.ERL_CONN_CANT_RPC_TO_LOCAL_NODE_ERROR); } else { var msg = Internal.ErlRpcServer.EncodeRPCcast(m_Self, mod, fun, args, ioServer); var conn = m_Node.Connection(node); if (conn == null) { throw new ErlConnectionException( node, StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(node)); } conn.Send(m_Self, ConstAtoms.Rex, msg); } }
internal bool Deliver(ErlAtom node, ErlMsg msg) { if (node == NodeName) { return(Deliver(msg)); } var conn = Connection(node); if (conn == null) { return(false); } try { conn.Send(msg); } catch { return(false); } return(true); }
private void sendChallenge(int dist, ErlAbstractNode.NodeCompatibility flags, int challenge) { ErlAtom str = m_Home.NodeName; var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 11 + str.Length); obuf.Write2BE((short)str.Length + 11); // 11 bytes + nodename obuf.Write1((byte)ErlAbstractNode.NodeType.Ntype_R6); obuf.Write2BE((short)dist); obuf.Write4BE((int)flags); obuf.Write4BE(challenge); obuf.Write(Encoding.ASCII.GetBytes(str.Value)); obuf.WriteTo(m_TcpClient.GetStream()); m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () => "sendChallenge(flags({0:X2})={1}, dist={2}, challenge={3}, local={4}".Args( (int)flags, flags, dist, challenge, m_Home.AliveName)); }
/// <summary> /// Send an auth error to peer because he sent a bad cookie /// The auth error uses his cookie (not revealing ours). /// This is just like send_reg otherwise /// </summary> private void cookieError(ErlLocalNode local, ErlAtom cookie) { var header = new ErlOutputStream(writeVersion: false, capacity: HEADER_LEN); // preamble: 4 byte length + "PASS_THROUGH" tag + version header.Write4BE(0); // reserve space for length header.Write1(PASS_THROUGH); header.Write1((byte)ErlExternalTag.Version); header.WriteTupleHead(4); header.WriteLong((long)ErlMsg.Tag.RegSend); header.WritePid(local.CreatePid()); // disposable pid header.WriteAtom(cookie); // important: his cookie, not mine... header.WriteAtom("auth"); // version for payload written later by the payload stream //header.Write1((byte)ErlExternalTag.Version); // the payload // the no_auth message (copied from Erlang) Don't change this (Erlang will crash) // {$gen_cast, {print, "~n** Unauthorized cookie ~w **~n", [foo@aule]}} var msg = ErlObject.Parse( "{'$gen_cast', {print, \"\n** Unauthorized cookie ~w **\n\", [" + local.NodeName.Value + "]}}"); var payload = new ErlOutputStream(msg, writeVersion: true); // fix up length in preamble header.Poke4BE(0, (int)(header.Length + payload.Length - 4)); try { DoSend(header, payload); } catch (Exception e) { Close(); throw new ErlException(StringConsts.ERL_CONN_UNAUTH_COOKIE_ERROR.Args(cookie.Value), e); } }
/// <summary> /// Create an Erlang reference from the given values /// </summary> public ErlRef(ErlAtom node, uint[] ids, int creation) { Node = node; Creation = creation & 0x3; if (ids.Length == 3) { Ids = ids; } else { Ids = new uint[3]; int i = 0; for (int n = Math.Min(ids.Length, 3); i < n; i++) { Ids[i] = ids[i]; } for (; i < 3; i++) { Ids[i] = 0; } } }
/// <summary> /// Used to break all known links to this mbox /// </summary> internal void BreakLinks(ErlAtom fromNode, IErlObject reason) { var links = m_Links.Remove(fromNode); foreach (var link in links) { if (link.HasPid) { m_Node.Deliver(ErlMsg.Exit(m_Self, link.Pid, reason)); } else { m_Node.Deliver(new ErlConnectionException(fromNode, reason)); } } foreach (var m in m_Monitors.Where(o => o.Value.Node == fromNode) .Where(m => m_Monitors.Remove(m.Key))) { Deliver(new ErlConnectionException(fromNode, reason)); } }
internal static void splitNodeName(string name, bool shortName, out string alive, out string host, out ErlAtom nodeName, out ErlAtom longName) { int i = name.IndexOf('@'); if (i < 0) { alive = name; host = LocalHost; } else { alive = name.Substring(0, i); host = name.Substring(i + 1); } if (alive.Length > AtomTable.MAX_ATOM_LEN) { alive = alive.Substring(0, AtomTable.MAX_ATOM_LEN); } longName = new ErlAtom(alive + "@" + host); nodeName = node(longName, shortName); }
public void Down(ErlRef eref, ErlPid pid, ErlAtom reason) { // TODO throw new NotImplementedException(); }