public static AmiMessage FromBytes(Byte[] bytes) { var result = new AmiMessage(); for (var nrLine = 1;; nrLine++) { var crlfPos = bytes.Find(AmiMessage.TerminatorBytes, 0, bytes.Length); if (crlfPos == -1) { throw new ArgumentException($"unexpected end of message after {nrLine} line(s)", nameof(bytes)); } var line = Encoding.UTF8.GetString(bytes.Slice(0, crlfPos)); bytes = bytes.Slice(crlfPos + AmiMessage.TerminatorBytes.Length); if (line.Equals(String.Empty)) { break; // empty line terminates } var kvp = line.Split(new[] { ':' }, 2); if (kvp.Length != 2) { throw new ArgumentException($"malformed field on line {nrLine}", nameof(bytes)); } result.Add(kvp[0], kvp[1]); } return(result); }
public async Task <AmiMessage> Publish(AmiMessage action) { try { var tcs = new TaskCompletionSource <AmiMessage>(TaskCreationOptions.AttachedToParent); Debug.Assert(this.inFlight.TryAdd(action["ActionID"], tcs)); var buffer = action.ToBytes(); lock (this.writerLock) this.stream.Write(buffer, 0, buffer.Length); this.DataSent?.Invoke(this, new DataEventArgs(action.ToString())); var response = await tcs.Task; Debug.Assert(this.inFlight.TryRemove(response["ActionID"], out _)); return(response); } catch (Exception ex) { this.Dispatch(ex); Debug.Assert(this.inFlight.TryRemove(action["ActionID"], out _)); return(null); } }
public static AmiMessage FromBytes(Byte[] bytes) { var result = new AmiMessage(); var stream = new MemoryStream(bytes); var reader = new StreamReader(stream, new UTF8Encoding(false)); for (var nrLine = 1; ; nrLine++) { var line = reader.ReadLine(); if (line == null) { throw new ArgumentException("unterminated message", nameof(bytes)); } if (line.Equals(String.Empty)) { break; // empty line terminates } var kvp = line.Split(new[] { ':' }, 2); if (kvp.Length != 2) { throw new ArgumentException($"malformed field on line {nrLine}", nameof(bytes)); } result.Add(kvp[0], kvp[1]); } return(result); }
public async Task <Boolean> Logoff() { AmiMessage request, response; request = new AmiMessage { { "Action", "Logoff" }, }; response = await this.Publish(request); return((response["Response"] ?? String.Empty).Equals("Goodbye", StringComparison.OrdinalIgnoreCase)); }
public static AmiMessage FromString(String @string) { var bytes = Encoding.UTF8.GetBytes(@string); return(AmiMessage.FromBytes(bytes)); }
public async Task <Boolean> Login(String username, String secret, Boolean md5 = true) { if (username == null) { throw new ArgumentNullException(nameof(username)); } if (secret == null) { throw new ArgumentNullException(nameof(secret)); } AmiMessage request, response; if (md5) { request = new AmiMessage { { "Action", "Challenge" }, { "AuthType", "MD5" }, }; response = await this.Publish(request); if (!(response["Response"] ?? String.Empty).Equals("Success", StringComparison.OrdinalIgnoreCase)) { return(false); } var challengeResponse = MD5.Create() .ComputeHash(Encoding.ASCII.GetBytes(response["Challenge"] + secret)); var key = ""; for (var i = 0; i < challengeResponse.Length; i++) { key += challengeResponse[i].ToString("x2"); } request = new AmiMessage { { "Action", "Login" }, { "AuthType", "MD5" }, { "Username", username }, { "Key", key }, }; response = await this.Publish(request); } else { request = new AmiMessage { { "Action", "Login" }, { "Username", username }, { "Secret", secret }, }; response = await this.Publish(request); } return((response["Response"] ?? String.Empty).Equals("Success", StringComparison.OrdinalIgnoreCase)); }
private void WorkerMain() { try { this.processing = true; var reader = new StreamReader(this.stream, new UTF8Encoding(false)); if (this.processing && this.stream != null && this.stream.CanRead) { var line = reader.ReadLine(); this.DataReceived?.Invoke(this, new DataEventArgs(line + "\r\n")); if (!line.StartsWith("Asterisk Call Manager", StringComparison.OrdinalIgnoreCase)) { throw new Exception("this does not appear to be an Asterisk server"); } } var lines = new List <String>(); while (this.processing && this.stream != null && this.stream.CanRead) { lines.Add(reader.ReadLine()); if (lines.Last() != String.Empty) { continue; } this.DataReceived?.Invoke(this, new DataEventArgs(String.Join("\r\n", lines) + "\r\n")); var message = new AmiMessage(); foreach (var line in lines.Where(line => line != String.Empty)) { var kv = line.Split(new[] { ':' }, 2); Debug.Assert(kv.Length == 2); message.Add(kv[0], kv[1]); } if (message["Response"] != null && this.inFlight.TryGetValue(message["ActionID"], out var tcs)) { Debug.Assert(tcs.TrySetResult(message)); } else { this.Dispatch(message); } lines.Clear(); } } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception ex) { this.Dispatch(ex); } }