public static async Task <WebSocketConnection> Connect(Uri peer, Action <string> log) { ClientWebSocket clientWebSocket = new ClientWebSocket(); await clientWebSocket.ConnectAsync(peer, CancellationToken.None); switch (clientWebSocket.State) { case WebSocketState.Open: // Connection log invoke log?.Invoke($"Opened connection to remote server: {peer}"); // ===== Creating socket connection object ===== WebSocketConnection socketConnection = new ClientWebSocketConnection(clientWebSocket, peer, log) { // ===== Attaching data parser to on message event ===== OnMessage = DataContext.Instance.ReceiveData }; // Setting the current connection for singleton connection implementation CurrentConnection = socketConnection; return(socketConnection); default: string errMsg = $"Cannot connect to remote server {peer} with status {clientWebSocket.State}"; log?.Invoke(errMsg); throw new WebSocketException(errMsg); } }
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); DiffContainer.Init(byte.Parse(ConfigurationSettings.AppSettings["quality"])); _connectionManager = new ConnectionManager { ServerIp = "localhost" }; _connectForm = new ConnectForm { ServerIp = _connectionManager.ServerIp }; _mainForm = new MainForm { ScreenshotScale = float.Parse(ConfigurationSettings.AppSettings["scale"]), ScreenshotTimeout = int.Parse(ConfigurationSettings.AppSettings["timeout"]), JpegQuality = byte.Parse(ConfigurationSettings.AppSettings["quality"]) }; _connectForm.VisibleChanged += (sender, eventArgs) => { if (!_connectForm.Visible) { _connectionManager.ServerIp = _connectForm.ServerIp; var clientWebSocketConnection = new ClientWebSocketConnection(_connectionManager.GetConnection()); _mainForm.ClientWebSocketConnection = clientWebSocketConnection; _mainForm.ConferenceId = _connectForm.ConferenceId; _mainForm.ClientName = _connectForm.ClientName; _connectionManager.Connect(); _mainForm.Show(); } else { _connectionManager.Disconnect(); } }; _mainForm.VisibleChanged += (sender, eventArgs) => { if (!_mainForm.Visible) { _connectForm.Show(); } }; Application.Run(_connectForm); }
private void ClientWebSocketConnectionOnConnectionStateChanged(object sender, SimpleEventArgs <bool> webSocketEventArgs) { Invoke(new Action(() => { if (webSocketEventArgs.Value) { connectionStateValueLabel.Text = "Connected"; ClientWebSocketConnection.QueryState(ConferenceId, (int)(Screen.PrimaryScreen.Bounds.Width * ScreenshotScale), (int)(Screen.PrimaryScreen.Bounds.Height * ScreenshotScale), ClientName); } else { connectionStateValueLabel.Text = "Connecting..."; _runDiffDetectThread = false; _runProcessCommandsThread = false; } })); }
private void InitPaintControl() { _paintControl = new PainterControl(); tableLayoutPanel.Controls.Add(_paintControl, 1, 1); _paintControl.Dock = DockStyle.Fill; _paintControl.FigureAdded += (s, e) => ClientWebSocketConnection.PaintAddFigureCommand(ConferenceId, e.Value.Id, e.Value.Points, e.Value.Color); _paintControl.FigureRemoved += (s, e) => ClientWebSocketConnection.PaintDeleteFigureCommand(ConferenceId, e.Value); _paintControl.MouseInputed += (sender, args) => ClientWebSocketConnection.SendInput(ConferenceId, args.Value); _paintControl.FullScreenCanceled += (s, e) => { silentRadioButton.Checked = true; }; }
/// <summary> /// Attempts to extract SIP messages from the data that has been received on the client web socket SIP stream connection. /// </summary> /// <param name="recvChannel">The receiving SIP channel.</param> /// <param name="clientConn">The web socket client connection properties including pending receive buffer</param> /// <param name="buffer">The buffer holding the current data from the stream. Note that the buffer can /// stretch over multiple receives.</param> /// <param name="bytesRead">The bytes that were read by the latest receive operation (the new bytes available).</param> private void ExtractSIPMessages(SIPChannel recvChannel, ClientWebSocketConnection clientConn, ArraySegment <byte> buffer, int bytesRead) { if (bytesRead + clientConn.RecvEndPosn > clientConn.PendingReceiveBuffer.Length) { // Don't have enough space for the read. Throw away the pending buffer and hope the SIP transaction is re-attempted. clientConn.RecvStartPosn = clientConn.RecvEndPosn = 0; } Buffer.BlockCopy(buffer.ToArray(), 0, clientConn.PendingReceiveBuffer, clientConn.RecvEndPosn, bytesRead); clientConn.RecvEndPosn += bytesRead; int bytesSkipped = 0; byte[] sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(clientConn.PendingReceiveBuffer, clientConn.RecvStartPosn, clientConn.RecvEndPosn, out bytesSkipped); while (sipMsgBuffer != null) { // A SIP message is available. if (SIPMessageReceived != null) { clientConn.LastTransmission = DateTime.Now; SIPMessageReceived(recvChannel, clientConn.LocalEndPoint, clientConn.RemoteEndPoint, sipMsgBuffer) .Wait(); } clientConn.RecvStartPosn += (sipMsgBuffer.Length + bytesSkipped); if (clientConn.RecvStartPosn == clientConn.RecvEndPosn) { // All data has been successfully extracted from the receive buffer. clientConn.RecvStartPosn = clientConn.RecvEndPosn = 0; break; } else { // Try and extract another SIP message from the receive buffer. sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(clientConn.PendingReceiveBuffer, clientConn.RecvStartPosn, clientConn.RecvEndPosn, out bytesSkipped); } } }
public static async Task <WebSocketConnection> Connect(Uri peer, Action <string> log) { ClientWebSocket clientWebSocket = new ClientWebSocket(); await clientWebSocket.ConnectAsync(peer, CancellationToken.None); switch (clientWebSocket.State) { case WebSocketState.Open: log?.Invoke($"Opened connection to remote server: {peer}"); WebSocketConnection socketConnection = new ClientWebSocketConnection(clientWebSocket, peer, log); socketConnection.onMessage = DataContext.Instance.ReceiveData; CurrentConnection = socketConnection; return(socketConnection); default: string errorMessage = $"Cannot connect to remote server {peer} with status {clientWebSocket.State}"; log?.Invoke(errorMessage); throw new WebSocketException(errorMessage); } }
private void RadioButtonOnCheckedChanged(object sender, EventArgs eventArgs) { if (sender == inputRadioButton) { if (inputRadioButton.Checked) { if (_isPresenter) { return; } ClientWebSocketConnection.RequestControlCommand(ConferenceId, _id, true); } else { ClientWebSocketConnection.RequestControlCommand(ConferenceId, _id, false); ClientWebSocketConnection.ControlAccessCommand(ConferenceId, "0", _id, false); //Хак (передаем ноль, так как в данной реализации может быть только один презентер и этот ноль переопределиться на сервере в нормальный id presenter'а) } } if (silentRadioButton.Checked) { _paintControl.Mode = PaintControlModes.Silent; } if (drawRadioButton.Checked) { if (_isPresenter) { _topMostForm.SetClickThrough(false); } _paintControl.Mode = PaintControlModes.Draw; } if (inputRadioButton.Checked) { _paintControl.Mode = PaintControlModes.Input; } }
/// <summary> /// Attempts a send to a remote web socket server. If there is an existing connection it will be used /// otherwise an attempt will made to establish a new one. /// </summary> /// <param name="serverEndPoint">The remote web socket server URI to send to.</param> /// <param name="buffer">The data buffer to send.</param> /// <returns>A success value or an error for failure.</returns> private async Task <SocketError> SendAsync(SIPEndPoint serverEndPoint, byte[] buffer) { try { string uriPrefix = (serverEndPoint.Protocol == SIPProtocolsEnum.wss) ? WEB_SOCKET_SECURE_URI_PREFIX : WEB_SOCKET_URI_PREFIX; var serverUri = new Uri($"{uriPrefix}{serverEndPoint.GetIPEndPoint()}"); string connectionID = GetConnectionID(serverUri); serverEndPoint.ChannelID = this.ID; serverEndPoint.ConnectionID = connectionID; if (m_egressConnections.TryGetValue(connectionID, out var conn)) { Logger.Logger.Debug( $"Sending {buffer.Length} bytes on client web socket connection to {conn.ServerUri}."); ArraySegment <byte> segmentBuffer = new ArraySegment <byte>(buffer); await conn.Client.SendAsync(segmentBuffer, WebSocketMessageType.Text, true, m_cts.Token) .ConfigureAwait(false); return(SocketError.Success); } else { // Attempt a new connection. ClientWebSocket clientWebSocket = new ClientWebSocket(); await clientWebSocket.ConnectAsync(serverUri, m_cts.Token).ConfigureAwait(false); Logger.Logger.Debug($"Successfully connected web socket client to {serverUri}."); ArraySegment <byte> segmentBuffer = new ArraySegment <byte>(buffer); await clientWebSocket.SendAsync(segmentBuffer, WebSocketMessageType.Text, true, m_cts.Token) .ConfigureAwait(false); var recvBuffer = new ArraySegment <byte>(new byte[2 * SIPStreamConnection.MaxSIPTCPMessageSize]); Task <WebSocketReceiveResult> receiveTask = clientWebSocket.ReceiveAsync(recvBuffer, m_cts.Token); // There's currently no way to get the socket IP end point used by the client web socket to establish // the connection. Instead provide a dummy local end point that has as much of the information as we can. IPEndPoint localEndPoint = new IPEndPoint( (serverEndPoint.Address.AddressFamily == AddressFamily.InterNetwork) ? IPAddress.Any : IPAddress.IPv6Any, 0); SIPEndPoint localSIPEndPoint = new SIPEndPoint(serverEndPoint.Protocol, localEndPoint, this.ID, connectionID); ClientWebSocketConnection newConn = new ClientWebSocketConnection { LocalEndPoint = localSIPEndPoint, ServerUri = serverUri, RemoteEndPoint = serverEndPoint, ConnectionID = connectionID, ReceiveBuffer = recvBuffer, ReceiveTask = receiveTask, Client = clientWebSocket }; if (!m_egressConnections.TryAdd(connectionID, newConn)) { Logger.Logger.Error( $"Could not add web socket client connected to {serverUri} to channel collection, closing."); await Close(connectionID, clientWebSocket).ConfigureAwait(false); } else { if (!m_isReceiveTaskRunning) { m_isReceiveTaskRunning = true; _ = Task.Factory.StartNew(MonitorReceiveTasks, TaskCreationOptions.LongRunning); } } return(SocketError.Success); } } catch (SocketException sockExcp) { return(sockExcp.SocketErrorCode); } }
public MainForm() { InitializeComponent(); InitPaintControl(); _topMostForm = new TopMostForm(); _topMostForm.Done += (sender, ea) => { Focus(); silentRadioButton.Checked = true; }; dataGridView.AutoGenerateColumns = false; dataGridView.SelectionChanged += (sender, ea) => dataGridView.ClearSelection(); dataGridView.CellDoubleClick += (sender, args) => { if (!_isPresenter) { return; } var clickedParticipantRowIndex = args.RowIndex; var participants = (IList <Participant>)dataGridView.DataSource; if (participants == null || clickedParticipantRowIndex < 0 || clickedParticipantRowIndex >= participants.Count) { return; } var clickedParticipant = participants[clickedParticipantRowIndex]; ClientWebSocketConnection.ControlAccessCommand(ConferenceId, _id, clickedParticipant.Id, true); }; dataGridView.CellPainting += (sender, args) => { if (dataGridView.Columns["ColorColumn"] != null && dataGridView.Columns["ColorColumn"].Index == args.ColumnIndex && args.RowIndex >= 0) { using ( Brush gridBrush = new SolidBrush(dataGridView.GridColor), backColorBrush = new SolidBrush(args.CellStyle.BackColor)) { using (var gridLinePen = new Pen(gridBrush)) { args.Graphics.FillRectangle(backColorBrush, args.CellBounds); args.Graphics.DrawLine(gridLinePen, args.CellBounds.Left, args.CellBounds.Bottom - 1, args.CellBounds.Right - 1, args.CellBounds.Bottom - 1); args.Graphics.DrawLine(gridLinePen, args.CellBounds.Right - 1, args.CellBounds.Top, args.CellBounds.Right - 1, args.CellBounds.Bottom); args.Graphics.FillEllipse(new SolidBrush(Color.FromArgb((int)args.Value)), args.CellBounds.Location.X + args.CellBounds.Width / 2 - 5, args.CellBounds.Location.Y + args.CellBounds.Height / 2 - 5, 10, 10); args.Handled = true; } } } }; conferenceIdValueLabel.DoubleClick += (sender, args) => Clipboard.SetText(conferenceIdValueLabel.Text); VisibleChanged += (sender, ea) => { if (!Visible) { _topMostForm.Hide(); _runProcessCommandsThread = false; _runDiffDetectThread = false; _isPresenter = false; _presenterWidth = 0; _presenterHeight = 0; _id = string.Empty; conferenceIdValueLabel.Text = string.Empty; _paintControl.Image = null; roleValueLabel.Text = string.Empty; _paintControl.Mode = PaintControlModes.Silent; silentRadioButton.Checked = true; //modeGroupBox.Enabled = false; dataGridView.DataSource = null; } }; FormClosing += (sender, ea) => { Hide(); ea.Cancel = true; if (_clientWebSocketConnection != null) { _clientWebSocketConnection.ConnectionStateChangedEvent -= ClientWebSocketConnectionOnConnectionStateChanged; } }; silentRadioButton.CheckedChanged += RadioButtonOnCheckedChanged; drawRadioButton.CheckedChanged += RadioButtonOnCheckedChanged; inputRadioButton.CheckedChanged += RadioButtonOnCheckedChanged; }
public void StartDiffDetectThread() { _runDiffDetectThread = false; if (_diffDetectThread != null) { while (_diffDetectThread.IsAlive) { Thread.Sleep(100); } } _runDiffDetectThread = true; _diffDetectThread = new Thread(() => { IDiffDetector diffDetector = new CustomDiffDetector(JpegQuality); //IDiffDetector _diffDetector = new DiffDetector(); //IDiffDetector _diffDetector = new DiffDetectorOpenCvSharp(); while (_runDiffDetectThread) { try { var screenShot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); using (Graphics screenShotGraphics = Graphics.FromImage(screenShot)) { screenShotGraphics.CopyFromScreen(0, 0, 0, 0, new Size( Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)); if (Math.Abs(ScreenshotScale - 1) > 0.01) { screenShot = new Bitmap(screenShot, (int) (Screen.PrimaryScreen.Bounds.Width * ScreenshotScale), (int) (Screen.PrimaryScreen.Bounds.Height * ScreenshotScale)); } } DiffContainer diffContainer = diffDetector.GetDiffs(screenShot); var quality = DiffContainer.Quality; diffContainer.Data = DiffContainer.Split(diffContainer.Data, 64000, quality); foreach (var s in diffContainer.Data) { ClientWebSocketConnection.SendDiff(ConferenceId, new DiffItem(s, quality)); } } catch (Exception ex) { Console.WriteLine("_diffDetectThread : " + ex.Message); } Thread.Sleep(_delay); } }); _diffDetectThread.Start(); }