/// <summary> /// Alg 4. /// </summary> /// <param name="client">Instance clienta</param> /// <param name="version">Domluvena verze</param> private async void HandleMessages( TcpClient client, int version ) { var networkStream = client.GetStream(); var cancelClient = new CancellationTokenSource(); try { while( true ) { //Vytvoreni tasku pro odpojeni clienta, pokud 180sec neposle ping if( version > 0 ) #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run( () => Task.Delay( 180000, cancelClient.Token ). ContinueWith( ( x ) => DisconnectClient( client ), cancelClient.Token ) ); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed //Task pro prijmuti zpravy od clienta byte[] buffer = new byte[ 4096 ]; int bufferSize = await networkStream.ReadAsync( buffer, 0, buffer.Length ); Message msg = Message.ParseMsgFromBytes( buffer, bufferSize ); //Prisla zprava typu Msg, tak ji preposlu vsem clientum if( msg.MsgType == Msg.MSG ) { byte[] toBroadcast = msg.ToByteArray(); foreach( var other in Clients ) { if(other.Connected) await other.GetStream().WriteAsync( toBroadcast, 0, toBroadcast.Length ); } } //Prisla zprava typu Ping, takze zrusim predchozi task na pingovani a vytvorim novy pro dalsich 180sec //a jeste odeslu clientovi pong if(version > 0 && msg.MsgType == Msg.PING ) { cancelClient.Cancel(); cancelClient = new CancellationTokenSource(); var pong = new Message( Msg.PONG, DateTime.Now, 1 ).ToByteArray(); await networkStream.WriteAsync( pong, 0, pong.Length ); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run( () => Task.Delay( 180000, cancelClient.Token ). ContinueWith( ( x ) => DisconnectClient( client ), cancelClient.Token ) ); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } } } catch( ObjectDisposedException ) { window.AddTextLine( "Error Server: HandleMessages() ObjectDisposedException" ); this.Stop(); return; } catch( System.IO.IOException ) { window.AddTextLine( "Error Server: HandleMessages() IOException" ); this.Stop(); return; } catch( Exception e ) { System.Windows.MessageBox.Show( "Unknown Server error: " + e.Message ); this.Stop(); return; } }
/// <summary> /// Alg 3. /// </summary> /// <param name="client">Instance clienta</param> /// <returns></returns> private async Task<int> SendHandshake( TcpClient client ) { var networkStream = client.GetStream(); byte[] buffer = new byte[ 4096 ]; //WAITING FOR HELLO int bufferSize = await networkStream.ReadAsync( buffer, 0, buffer.Length ); var helloMsg = Message.ParseMsgFromBytes( buffer, bufferSize ); if(helloMsg.MsgType != Msg.HELLO ) //Pokud prislo neco jinyho nez hello, tak odpojim clienta (zpatny pro DDOS) DisconnectClient( client ); string[] bodySplits = helloMsg.Body.Split( ' ' ); string latestVersion = bodySplits[ bodySplits.Length - 1 ]; int intVersion = latestVersion == "1.1" ? 1 : 0; //ACCEPTED HELLO, SENDING OLLEH var ollehBytes = new Message( Msg.OLLEH, DateTime.Now, intVersion ).ToByteArray(); await networkStream.WriteAsync( ollehBytes, 0, ollehBytes.Length ); //OLLEH SENT, WAITING FOR ACK bufferSize = await networkStream.ReadAsync( buffer, 0, buffer.Length ); var ackMsg = Message.ParseMsgFromBytes( buffer, bufferSize ); if( ackMsg.MsgType != Msg.ACK ) //Pokud prislo neco jinyho nez ack, tak odpojim clienta (zpatny protokol) DisconnectClient( client ); //ACCEPTED ACK return intVersion; }
/// <summary> /// Alg 4. /// </summary> /// <param name="username"></param> /// <returns></returns> private async Task InitializeConnection( string username ) { byte[] buffer = new byte[ 4096 ]; //SENDING HELLO var hello = new Message( Msg.HELLO, DateTime.Now, 1 ); var helloBytes = hello.ToByteArray(); await stream.WriteAsync( helloBytes, 0, helloBytes.Length ); //WAITING FOR OLLEH int bufferSize = await stream.ReadAsync( buffer, 0, buffer.Length ); var olleh = Message.ParseMsgFromBytes( buffer, bufferSize ); if( olleh.MsgType != Msg.OLLEH ) throw new Exception( "Got something else than OLLEH packet" ); //ACCEPTED OLLEH, SENDING ACK var ackBytes = new Message( Msg.ACK, DateTime.Now, 1 ).ToByteArray(); await stream.WriteAsync( ackBytes, 0, ackBytes.Length ); //CONNECTED }
/// <summary> /// Metoda pro odesilani zprav typu "MSG" na server /// </summary> /// <param name="message"></param> public async void SendMessage( string message ) { if( !client.Connected ) { System.Windows.MessageBox.Show( "Cannot send messages (not connected)" ); return; } var msgBytes = new Message( Msg.MSG, DateTime.Now, 1, message, username ).ToByteArray(); await stream.WriteAsync( msgBytes, 0, msgBytes.Length ); }
/// <summary> /// Nekonecny task pro posilani pingu po 60sec. /// Vytvari se s pingCancelation tokenem pro jeho zruseni pri Disconnectu /// </summary> private async void SendPing() { var ping = new Message( Msg.PING, DateTime.Now, 1 ).ToByteArray(); await stream.WriteAsync( ping, 0, ping.Length ); try { await Task.Delay( 60000 ).ContinueWith( ( x ) => SendPing(), pingCancelation.Token ); } catch( TaskCanceledException ) { } }