/// <summary> /// /// </summary> /// <returns></returns> /// <exception cref="IOException"></exception> public async Task <AttachmentV3UploadAttributes> GetAttachmentV3UploadAttributesAsync() { WebSocketRequestMessage requestMessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.GetSecretBytes(sizeof(long)), 0), Verb = "GET", Path = "/v3/attachments/form/upload" }; var sendTask = (await websocket.SendRequest(requestMessage)).Task; var timerCancelSource = new CancellationTokenSource(); if (await Task.WhenAny(sendTask, Task.Delay(TimeSpan.FromSeconds(10), timerCancelSource.Token)) == sendTask) { timerCancelSource.Cancel(); var(status, body) = sendTask.Result; if (status < 200 || status >= 300) { throw new IOException($"Non-successful response: {status}"); } return(JsonUtil.FromJson <AttachmentV3UploadAttributes>(body)); } else { throw new IOException("Timeout reached while waiting for attachment upload attributes."); } }
public void ReadBlocking(MessagePipeCallback callback) { LinkedList <WebSocketRequestMessage> requests = Websocket.readRequests(); int amount = requests.Count; SignalServiceEnvelope[] envelopes = new SignalServiceEnvelope[amount]; WebSocketResponseMessage[] responses = new WebSocketResponseMessage[amount]; for (int i = 0; i < amount; i++) { WebSocketRequestMessage msg = requests.First.Value; requests.RemoveFirst(); if (isSignalServiceEnvelope(msg)) { envelopes[i] = new SignalServiceEnvelope(msg.Body.ToByteArray(), CredentialsProvider.GetSignalingKey()); } responses[i] = createWebSocketResponse(msg); } try { callback.onMessages(envelopes); } finally { foreach (WebSocketResponseMessage response in responses) { Websocket.SendResponse(response); } } }
/// <summary> /// Sends a message through the pipe. Blocks until delivery is confirmed or throws an IOException if a timeout occurs. /// </summary> /// <param name="list"></param> /// <returns></returns> public async Task <SendMessageResponse> Send(OutgoingPushMessageList list) { Logger.LogTrace("Send()"); WebSocketRequestMessage requestmessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.GetSecretBytes(sizeof(long)), 0), Verb = "PUT", Path = $"/v1/messages/{list.Destination}", Body = ByteString.CopyFrom(Encoding.UTF8.GetBytes(JsonUtil.ToJson(list))) }; requestmessage.Headers.Add("content-type:application/json"); var sendTask = (await Websocket.SendRequest(requestmessage)).Task; var timerCancelSource = new CancellationTokenSource(); if (await Task.WhenAny(sendTask, Task.Delay(10 * 1000, timerCancelSource.Token)) == sendTask) { timerCancelSource.Cancel(); var(Status, Body) = sendTask.Result; if (Status < 200 || Status >= 300) { throw new IOException("non-successfull response: " + Status); } if (Util.IsEmpty(Body)) { return(new SendMessageResponse(false)); } return(JsonUtil.FromJson <SendMessageResponse>(Body)); } else { Logger.LogError("Sending message {0} failed: timeout", requestmessage.Id); throw new IOException("timeout reached while waiting for confirmation"); } }
public SendMessageResponse Send(OutgoingPushMessageList list) { WebSocketRequestMessage requestmessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.getSecretBytes(sizeof(long)), 0), Verb = "PUT", Path = $"/v1/messages/{list.getDestination()}", Body = ByteString.CopyFrom(Encoding.UTF8.GetBytes(JsonUtil.toJson(list))) }; requestmessage.Headers.Add("content-type:application/json"); var t = Websocket.SendRequest(requestmessage); t.Wait(); if (t.IsCompleted) { var response = t.Result; if (response.Item1 < 200 || response.Item1 >= 300) { throw new IOException("non-successfull response: " + response.Item1 + " " + response.Item2); } return(JsonUtil.fromJson <SendMessageResponse>(response.Item2)); } else { throw new IOException("timeout reached while waiting for confirmation"); } }
/// <summary> /// Fetches a profile from the server. Blocks until the response arrives or a timeout occurs. /// </summary> /// <param name="address"></param> /// <returns></returns> public async Task <SignalServiceProfile> GetProfile(SignalServiceAddress address) { Logger.LogTrace("GetProfile()"); WebSocketRequestMessage requestMessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.GetSecretBytes(sizeof(long)), 0), Verb = "GET", Path = $"/v1/profile/{address.E164number}" }; var sendTask = (await Websocket.SendRequest(requestMessage)).Task; var timerCancelSource = new CancellationTokenSource(); if (await Task.WhenAny(sendTask, Task.Delay(10 * 1000, timerCancelSource.Token)) == sendTask) { timerCancelSource.Cancel(); var(Status, Body) = sendTask.Result; if (Status < 200 || Status >= 300) { throw new IOException("non-successfull response: " + Status); } return(JsonUtil.FromJson <SignalServiceProfile>(Body)); } else { throw new IOException("timeout reached while waiting for profile"); } }
/// <summary> /// Blocks until a message was received, calls the IMessagePipeCallback and confirms the message to the server, unless the pipe's token is cancelled. /// </summary> /// <param name="callback"></param> public async Task ReadBlocking(IMessagePipeCallback callback) { Logger.LogTrace("ReadBlocking()"); WebSocketRequestMessage request = Websocket.ReadRequestBlocking(); if (IsSignalServiceEnvelope(request)) { SignalServiceMessagePipeMessage message = new SignalServiceEnvelope(request.Body.ToByteArray(), CredentialsProvider.SignalingKey); WebSocketResponseMessage response = CreateWebSocketResponse(request); try { Logger.LogDebug("Calling callback with message {0}", request.Id); await callback.OnMessage(message); } finally { if (!Token.IsCancellationRequested) { Logger.LogDebug("Confirming message {0}", request.Id); Websocket.SendResponse(response); } } } else if (IsPipeEmptyMessage(request)) { Logger.LogInformation("Calling callback with SignalServiceMessagePipeEmptyMessage"); await callback.OnMessage(new SignalServiceMessagePipeEmptyMessage()); } else { Logger.LogWarning("Unknown request: {0} {1}", request.Verb, request.Path); } }
public SignalServiceProfile GetProfile(SignalServiceAddress address) { WebSocketRequestMessage requestMessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.getSecretBytes(sizeof(long)), 0), Verb = "GET", Path = $"/v1/profile/{address.getNumber()}" }; var t = Websocket.SendRequest(requestMessage); t.Wait(); if (t.IsCompleted) { var response = t.Result; if (response.Item1 < 200 || response.Item1 >= 300) { throw new IOException("non-successfull response: " + response.Item1 + " " + response.Item2); } return(JsonUtil.fromJson <SignalServiceProfile>(response.Item2)); } else { throw new IOException("timeout reached while waiting for profile"); } }
private void sendKeepAlive(object state) { Debug.WriteLine("keepAlive"); sendMessage(WebSocketMessage.CreateBuilder() .SetType(WebSocketMessage.Types.Type.REQUEST) .SetRequest(WebSocketRequestMessage.CreateBuilder() .SetId(KeyHelper.getTime()) .SetPath("/v1/keepalive") .SetVerb("GET") .Build()).Build()); }
/*internal async Task sendMessage(WebSocketMessage message) * { * if (socket == null) * { * throw new Exception("Connection closed!"); * } * * messageWriter.WriteBytes(message.ToByteArray()); * await messageWriter.StoreAsync(); * } * * internal async Task sendResponse(WebSocketResponseMessage response) * { * if (socket == null) * { * throw new Exception("Connection closed!"); * } * * WebSocketMessage message = WebSocketMessage.CreateBuilder() * .SetType(WebSocketMessage.Types.Type.RESPONSE) * .SetResponse(response) * .Build(); * * messageWriter.WriteBytes(message.ToByteArray()); * await messageWriter.StoreAsync(); * }*/ private void sendKeepAlive(object state) { if (socket != null) { Debug.WriteLine("keepAlive"); byte[] message = WebSocketMessage.CreateBuilder() .SetType(WebSocketMessage.Types.Type.REQUEST) .SetRequest(WebSocketRequestMessage.CreateBuilder() .SetId(KeyHelper.getTime()) .SetPath("/v1/keepalive") .SetVerb("GET") .Build()).Build() .ToByteArray(); messageWriter.WriteBytes(message); messageWriter.StoreAsync(); } }
private WebSocketResponseMessage createWebSocketResponse(WebSocketRequestMessage request) { if (isSignalServiceEnvelope(request)) { return(WebSocketResponseMessage.CreateBuilder() .SetId(request.Id) .SetStatus(200) .SetMessage("OK") .Build()); } else { return(WebSocketResponseMessage.CreateBuilder() .SetId(request.Id) .SetStatus(400) .SetMessage("Unknown") .Build()); } }
private WebSocketResponseMessage createWebSocketResponse(WebSocketRequestMessage request) { if (isSignalServiceEnvelope(request)) { return(new WebSocketResponseMessage { Id = request.Id, Status = 200, Message = "OK" }); } else { return(new WebSocketResponseMessage { Id = request.Id, Status = 400, Message = "Unknown" }); } }
/*public WebSocketRequestMessage readRequest(ulong timeoutMillis) * { * if (client == null) * { * throw new Exception("Connection closed!"); * } * * ulong startTime = KeyHelper.getTime(); * * while (client != null && incomingRequests.Count == 0 && elapsedTime(startTime) < timeoutMillis) * { * //Util.wait(this, Math.Max(1, timeoutMillis - elapsedTime(startTime))); * } * * if (incomingRequests.Count == 0 && client == null) throw new Exception("Connection closed!"); * else if (incomingRequests.Count == 0) throw new TimeoutException("Timeout exceeded"); * else * { * WebSocketRequestMessage message = incomingRequests.First(); * incomingRequests.RemoveFirst(); * return message; * } * }*/ internal async Task <Tuple <int, string> > sendRequest(WebSocketRequestMessage request) { if (socket == null || !connected) { throw new IOException("No connection!"); } WebSocketMessage message = WebSocketMessage.CreateBuilder() .SetType(WebSocketMessage.Types.Type.REQUEST) .SetRequest(request) .Build(); Tuple <int, string> empty = new Tuple <int, string>(0, string.Empty); outgoingRequests.Add((long)request.Id, empty); messageWriter.WriteBytes(message.ToByteArray()); await messageWriter.StoreAsync(); return(empty); }
private void OnMessageReceived(WebSocketConnection sender, WebSocketRequestMessage request) { WebSocketResponseMessage response = createWebSocketResponse(request); Debug.WriteLine($"Verb: {request.Verb}, Path {request.Path}, Body({request.Body.Length}): {request.Body}, Id: {request.Id}"); try { if (isTextSecureEnvelope(request)) { TextSecureEnvelope envelope = new TextSecureEnvelope(request.Body.ToByteArray(), credentialsProvider.GetSignalingKey()); MessageReceived(this, envelope); } } //catch (Exception e) { } // ignore for now finally { websocket.sendResponse(response); } }
private void OnMessageReceived(WebSocketConnection sender, WebSocketRequestMessage request) { WebSocketResponseMessage response = createWebSocketResponse(request); Debug.WriteLine($"Verb: {request.Verb}, Path {request.Path}, Body({request.Body.Length}): {request.Body}, Id: {request.Id}"); try { if (isSignalServiceEnvelope(request)) { SignalServiceEnvelope envelope = new SignalServiceEnvelope(request.Body.ToByteArray(), credentialsProvider.GetSignalingKey()); MessageReceived(this, envelope); } } //catch (Exception e) { } // ignore for now finally { websocket.sendResponse(response); } }
/// <summary> /// Fetches a profile from the server. Blocks until the response arrives or a timeout occurs. /// </summary> /// <param name="address"></param> /// <param name="unidentifiedAccess"></param> /// <returns></returns> public async Task <SignalServiceProfile> GetProfileAsync(SignalServiceAddress address, UnidentifiedAccess?unidentifiedAccess) { logger.LogTrace("GetProfile()"); var headers = new List <string>() { "content-type:application/json" }; if (unidentifiedAccess != null) { headers.Add("Unidentified-Access-Key:" + Base64.EncodeBytes(unidentifiedAccess.UnidentifiedAccessKey)); } WebSocketRequestMessage requestMessage = new WebSocketRequestMessage() { Id = BitConverter.ToUInt64(Util.GetSecretBytes(sizeof(long)), 0), Verb = "GET", Path = $"/v1/profile/{address.GetIdentifier()}" }; var sendTask = (await websocket.SendRequest(requestMessage)).Task; var timerCancelSource = new CancellationTokenSource(); if (await Task.WhenAny(sendTask, Task.Delay(TimeSpan.FromSeconds(10), timerCancelSource.Token)) == sendTask) { timerCancelSource.Cancel(); var(Status, Body) = sendTask.Result; if (Status < 200 || Status >= 300) { throw new IOException("non-successful response: " + Status); } return(JsonUtil.FromJson <SignalServiceProfile>(Body)); } else { throw new IOException("timeout reached while waiting for profile"); } }
/// <summary> /// Blocks until a message was received, calls the IMessagePipeCallback and confirms the message to the server, unless the pipe's token is canceled. /// </summary> /// <param name="callback"></param> public async Task ReadBlockingAsync(IMessagePipeCallback callback) { logger.LogTrace("ReadBlocking()"); if (credentialsProvider == null) { throw new ArgumentException("You can't read messages if you haven't specified credentials"); } WebSocketRequestMessage request = websocket.ReadRequestBlocking(); if (IsSignalServiceEnvelope(request)) { SignalServiceMessagePipeMessage message = new SignalServiceEnvelope(request.Body.ToByteArray()); WebSocketResponseMessage response = CreateWebSocketResponse(request); try { logger.LogDebug("Calling callback with message {0}", request.Id); await callback.OnMessageAsync(message); } finally { if (!token.IsCancellationRequested) { logger.LogDebug("Confirming message {0}", request.Id); websocket.SendResponse(response); } } } else if (IsPipeEmptyMessage(request)) { logger.LogInformation("Calling callback with SignalServiceMessagePipeEmptyMessage"); await callback.OnMessageAsync(new SignalServiceMessagePipeEmptyMessage()); } else { logger.LogWarning("Unknown request: {0} {1}", request.Verb, request.Path); } }
private bool IsPipeEmptyMessage(WebSocketRequestMessage message) { return(message.Verb == "PUT" && message.Path == "/api/v1/queue/empty"); }
private bool isTextSecureEnvelope(WebSocketRequestMessage message) { return "PUT".Equals(message.Verb) && "/api/v1/message".Equals(message.Path); }
private bool isSignalServiceEnvelope(WebSocketRequestMessage message) { return("PUT".Equals(message.Verb) && "/api/v1/message".Equals(message.Path)); }
private bool isTextSecureEnvelope(WebSocketRequestMessage message) { return("PUT".Equals(message.Verb) && "/api/v1/message".Equals(message.Path)); }
private WebSocketResponseMessage createWebSocketResponse(WebSocketRequestMessage request) { if (isTextSecureEnvelope(request)) { return WebSocketResponseMessage.CreateBuilder() .SetId(request.Id) .SetStatus(200) .SetMessage("OK") .Build(); } else { return WebSocketResponseMessage.CreateBuilder() .SetId(request.Id) .SetStatus(400) .SetMessage("Unknown") .Build(); } }
private bool IsSignalServiceEnvelope(WebSocketRequestMessage message) { return(message.Verb == "PUT" && message.Path == "/api/v1/message"); }