public bool FindService(ActionName wanted, string envelope, string ident, out ServiceInfo si, out ActionInfo ai) { lock (stateLock) { TimeCheck (DateTime.UtcNow); var cand = new List<ServiceInfo> (); foreach (var ssi in services.Values) { if (ident != null && ident != ssi.Identity) continue; ActionInfo sai = ssi.LookupAction (wanted); if (sai == null) continue; if (!auth.IsAuthorized (ssi, wanted)) continue; if (!ssi.IsSignatureValid) continue; if (!ssi.Envelopes.Contains (envelope)) continue; cand.Add (ssi); } si = null; ai = null; if (cand.Count == 0) return false; si = cand [new Random ().Next (cand.Count)]; ai = si.LookupAction (wanted); return true; } }
// the JS requestor uses a "forwardRequest" concept which is almost certainly a premature optimization and not duplicated here public static void MakeRequest(RequestLocalOptions opts, ActionName act, string envelope, Message req, Action<Message> on_rpy) { ServiceInfo si; ActionInfo ai; if (!discovery.FindService (act, envelope, opts.TargetIdent, out si, out ai)) { req.Discard (); Message.StreamToCallback (on_rpy, new RPCException ("transport", "Action {0} not found", act).AsHeader ()); return; } // important: aliases are processed here req.Header ["action"] = ai.Name.Namespace + '.' + ai.Name.Name; req.Header ["version"] = (double)ai.Name.Version; SOAClient client; try { client = GetConnection (si); } catch (Exception ex) { RPCException rpcex = RPCException.Wrap (ex); req.Discard (); Message.StreamToCallback (on_rpy, new RPCException ("transport", "Cannot establish connection", rpcex, RPCException.DispatchFailure ()).AsHeader ()); return; } if (opts.Timeout == 0) opts.Timeout = ai.Timeout; client.Request (opts, req, on_rpy); }
public static bool TryParse(string inp, out ActionName ret) { ret = null; int colon = inp.IndexOf (':'); int tilde = inp.LastIndexOf ('~', inp.Length - 1, inp.Length - (colon + 1)); if (tilde < 0) return false; int ldot = inp.LastIndexOf ('.', tilde - 1, tilde - (colon + 1)); if (ldot < 0) return false; uint ver; if (!uint.TryParse (inp.Substring (tilde + 1), out ver)) return false; if (ver == 0) return false; try { ret = new ActionName (colon >= 0 ? inp.Substring (0, colon) : "main", inp.Substring (colon + 1, ldot - (colon + 1)), inp.Substring (ldot + 1, tilde - (ldot + 1)), ver); } catch (Exception) { return false; } return true; }
public bool IsAuthorized(ServiceInfo inf, ActionName act) { var cert = inf.Certificate; if (cert == null) return false; Regex checker; if (!compiledAuth.TryGetValue (CryptoUtils.Fingerprint (cert), out checker)) return false; return checker.IsMatch (act.Sector + ':' + act.Namespace + '.' + act.Name); }
public ActionInfo(ActionName name, string flagstr, object handler = null) { if (name == null) throw new ArgumentNullException ("name"); if (flagstr == null) flagstr = ""; Name = name; Handler = handler; FlagString = flagstr; ParseFlags (FlagString, out Flags, out Timeout); }
public static void MakeJsonRequest(ActionName act, JObject header, JObject payload, Action<RPCException, JObject> cb) { header = header ?? new JObject (); byte[] body; try { body = Encoding.UTF8.GetBytes (JSON.Stringify (payload)); } catch (Exception ex) { cb (new RPCException ("transport", "cannot encode payload: {0}", ex), null); return; } Message m = new Message (header); MakeRequest (new RequestLocalOptions (), act, header ["envelope"].AsString ("json"), m, (resp) => { resp.Consume (10485760, (rpyheader, data, dlen, error) => { if (error != null) { cb (new RPCException ("transport", error), null); return; } if (rpyheader ["error_code"].AsString(null) != null) { cb (new RPCException (rpyheader), null); return; } JObject res = null; try { res = JSON.Parse (Encoding.UTF8.GetString (data, 0, dlen)).AsObject (); } catch (Exception) { } if (res == null) { cb (new RPCException ("transport", "failed to parse JSON response"), null); return; } cb (null, res); }); }); m.StreamData (body); }
public ActionInfo LookupAction(ActionName name) { ActionInfo ai; return(actionLookup.TryGetValue(name, out ai) ? ai : null); }
public ActionInfo(ActionName name, RPCActionFlags flags, int timeout, object handler) : this(name, UnparseFlags (flags, timeout), handler) { }
protected virtual void ScanType(List<ActionInfo> ail, Type type, List<Attribute> typePriv, string sector, string nspace, uint version) { foreach (var m in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { var action_meta = (RPCAttribute)Attribute.GetCustomAttribute (m, typeof(RPCAttribute)); if (action_meta == null) continue; var action_priv = new List<Attribute> (Attribute.GetCustomAttributes (m, typeof(RPCPrivilegeRequiredAttribute))); action_priv.AddRange (typePriv); List<string> privs = new List<string> (); foreach (var pra in action_priv) privs.Add ((pra as RPCPrivilegeRequiredAttribute).Privilege); uint ver = action_meta.Version != 0 ? action_meta.Version : version; ActionName an = new ActionName (sector, nspace, action_meta.Name ?? m.Name, ver); ActionInvokeDetails d = new ActionInvokeDetails { PermissionDemand = privs.Count == 0 ? null : privs.ToArray (), }; var dg = (Func<RPCRequestInfo, JObject, JObject>) Delegate.CreateDelegate (typeof(Func<RPCRequestInfo, JObject, JObject>), m, false); if (dg != null) { d.Handler = dg; } else { throw new Exception (string.Format ("Method {0}.{1} is marked as an RPC but does not have the correct signature", type, m)); } ail.Add (new ActionInfo (an, action_meta.Flags, action_meta.Timeout != 0 ? action_meta.Timeout : ActionInfo.DEFAULT_TIMEOUT, d)); } }
public ActionInfo LookupAction(ActionName name) { ActionInfo ai; return actionLookup.TryGetValue (name, out ai) ? ai : null; }