/*          *** WSPRLocate ***
 *
 * This program attempts to find the IP address of a Raspberry Pi (rPi)
 * computer on a Class C network. The rPi expects to acquire an IP address
 * through DHCP. The rPi waits of an incoming request on port 25197 (I
 * figured that was an odd enough port than there were unlikely to be
 * any collisions) and returns the result of an ifconfig command.
 *
 * What's actually happening is the program gets the IP address of the
 * computer it's running on and searches all ports on that particular
 * subnet. If a match is found the results are printed to the screen.
 *
 * Author: Bruce Raymond  (c) 2016
 *
 * Version 0.1    10 Oct 2016
 *
 * License:
 *
 * WSPRLocate is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * WSPRLocate is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details:
 *    www.gnu.org/licenses
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace WSPR_Locate
{
   public partial class WSPRLocate : Form
   {
      private List<string> ipvalid = new List<string>();

      public WSPRLocate()
      {
         InitializeComponent();
         labelStatus.Text = "Idle";
         labelStatus.ForeColor = default( Color );
         this.Text = "WSPR Data Locate             Bruce Raymond/ND8I (c) 2016        version "
            + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
      }

      private void button1_Click( object sender, EventArgs e )
      {
         richTextBoxWSPR.Text = "";
         labelStatus.Text = "Busy";
         labelStatus.ForeColor = Color.Red;
         progressBarWSPR.Value = 0;
         int ipMin = 2;
         int ipMax = 254;

         try
         {
            string[] host = GetIPAddress().Split( '.' );
            string ipAddr = host[ 0 ] + '.' + host[ 1 ] + '.' + host[ 2 ] + '.';

            for( int n = ipMin; n <= ipMax; n++ )
            {
               int progressBarIncrement = ( 100 * ( n - ipMin + 1 ) / ( ipMax - ipMin + 1 ) );
               progressBarWSPR.Value = progressBarIncrement;

               string ip = ipAddr + n.ToString();
               const int port = 25197;

               try
               {
                  using( TcpClient client = new TcpClient() )
                  {
                     var result = client.BeginConnect( ip, port, null, null );
                     {
                        result.AsyncWaitHandle.WaitOne( TimeSpan.FromSeconds( 1 ) );
                        if( client.Connected )
                        {
                           // we have connected
                           client.EndConnect( result );

                           NetworkStream serverStream = client.GetStream();

                           int m = 0;
                           byte[] inp = new byte[ 30000 ];
                           int b = 0;
                           for( int k = 0; b != -1; k++ )
                           {
                              b = serverStream.ReadByte();
                              inp[ k ] = (byte)b;
                              m = k;
                           }

                           byte[] x = new byte[ m ];
                           Array.Copy( inp, x, m );
                           string str = Encoding.Default.GetString( x );

                           string[] words = str.Split( '\n' );
                           foreach( string s in words )
                              richTextBoxWSPR.AppendText( s + '\r' );

                           serverStream.Close();
                           client.Close();
                        }
                     }
                  }
               }
               catch
               {
               }
               Application.DoEvents();
            }
         }
         catch( Exception ex )
         {
            MessageBox.Show( ex.Message );
         }
         labelStatus.Text = "Finished";
         labelStatus.ForeColor = Color.Green;
      }

      public static string GetIPAddress()
      {
         string addr = "";
         // Get a list of all network interfaces (usually one per network card, dialup, and VPN connection)
         NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

         foreach( NetworkInterface network in networkInterfaces )
         {
            // Read the IP configuration for each network
            IPInterfaceProperties properties = network.GetIPProperties();

            // Each network interface may have multiple IP addresses
            foreach( IPAddressInformation address in properties.UnicastAddresses )
            {
               // We're only interested in IPv4 addresses for now
               if( address.Address.AddressFamily != AddressFamily.InterNetwork )
                  continue;

               if( address.Address.ToString().Contains( "192.168." ) )
                  addr = address.Address.ToString();
            }
         }

         return addr;
      }

      private void buttonExit_Click( object sender, EventArgs e )
      {
         Application.Exit();
      }
   }
}