private Task SendAsync(bool isBinary, byte[] bytes, int offset, int length, CancellationToken cancellationToken) { var task = TaskAsyncHelper.Empty; var max = MaxFrameDataLength; var opcode = isBinary ? WebSocketOpcode.Binary : WebSocketOpcode.Text; while (length > 0) { var size = Math.Min(length, max); length -= size; var frame = new WebSocketClientFrame { Opcode = opcode, IsFin = length == 0, }; frame.Payload = new WebSocketPayload(frame, bytes, offset, size); offset += size; opcode = WebSocketOpcode.Continuation; task = task.Then(f => SendAsync(f, cancellationToken), frame); } return(task); }
private async void ReceiveLoop() { _cts = new CancellationTokenSource(); WebSocketMessage currentMessage = null; while (!_cts.IsCancellationRequested) { try { var frame = await _webSocket.ReceiveFrameAsync(_cts.Token); if (frame == null) { throw new Exception("null frame"); break; } OnFrameReceived(frame); if (frame.Opcode == WebSocketOpcode.Close) { if (Closed != null) { await CloseAsync(); } break; } if (frame.IsControlFrame) { // Handle ping frame if (frame.Opcode == WebSocketOpcode.Ping && this.AutoSendPongResponse) { var pongFrame = new WebSocketClientFrame { Opcode = WebSocketOpcode.Pong, Payload = frame.Payload }; await SendAsync(pongFrame, _cts.Token); } } else if (frame.IsDataFrame) { if (currentMessage != null) { throw new WebSocketException(WebSocketErrorCode.CloseInconstistentData); } currentMessage = new WebSocketMessage(); currentMessage.AddFrame(frame); } else if (frame.Opcode == WebSocketOpcode.Continuation) { if (currentMessage == null) { throw new WebSocketException(WebSocketErrorCode.CloseInconstistentData); } currentMessage.AddFrame(frame); } else { System.Diagnostics.Debug.WriteLine(String.Format("Other frame received: {0}", frame.Opcode)); this.LogDebug("Other frame received: {0}", frame.Opcode); } if (currentMessage != null && currentMessage.IsComplete) { OnMessageReceived(currentMessage); currentMessage = null; } } catch (WebSocketException wsex) { break; } catch (ObjectDisposedException ex) { //https://github.com/rdavisau/sockets-for-pcl/issues/34 break; } catch (TaskCanceledException ex) { break; } catch (Exception ex) { this.LogError("An unexpected error occurred.", ex); this.OnError(ex); break; } } }