/* to use
         * ulong installedMemory;
         *  MEMORYSTATUSEX memStatus = new MEMORYSTATUSEX();
         *  if( GlobalMemoryStatusEx( memStatus))
         *  {
         *     installedMemory = memStatus.ullTotalPhys;
         *  }
         */
        //============ borrowed END
        //==================================================
        //                Update report
        //==================================================
        static void UpdateReport()
        {
            msgStatic.msgtype = MessageTypes.MSG_UPDATEPUSH;

            msgStatic.msg_number = MessageCount();
            msgStatic.time_stamp = DateTime.Now;
#if !NDEBUG
            Console.WriteLine("#" + msgStatic.msg_number + "  " + msgStatic.time_stamp);
#endif
            //--ping
            Ping      pingSender = new Ping();
            PingReply pingReply  = pingSender.Send(srv_address);
            if (pingReply.Status == IPStatus.Success)
            {
                msgStatic.ping = pingReply.RoundtripTime;
            }
            else
            {
                msgStatic.ping = -1;
            }
            //---cpus
#if !NDEBUG
            Console.WriteLine("Getting Cpus...");
#endif
            //http://stackoverflow.com/questions/9777661/returning-cpu-usage-in-wmi-using-c-sharp
            ManagementObjectSearcher   searcher        = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor");
            ManagementObjectCollection cpus_collection = searcher.Get();
            ManagementObject[]         cpus            = new ManagementObject[cpus_collection.Count];
            cpus_collection.CopyTo(cpus, 0);
            msgStatic.cpus = new ushort[cpus.Count() - 1]; //-1 for "_total"
            for (int i = 0; i < msgStatic.cpus.Length; ++i)
            {
                msgStatic.cpus[i] = (ushort)(ulong)(cpus[i]["PercentProcessorTime"]); //raw is Int64
            }
            //---ram
#if !NDEBUG
            Console.WriteLine("Getting Memory...");
#endif
            MEMORYSTATUSEX memStatus = new MEMORYSTATUSEX();
            if (GlobalMemoryStatusEx(memStatus))
            {
                msgStatic.ram_used  = memStatus.ullAvailPhys;
                msgStatic.swap_used = memStatus.ullAvailPageFile;
            }
            //---get hdds
#if !NDEBUG
            Console.WriteLine("Getting Drives...");
#endif
            DriveInfo[] drives = DriveInfo.GetDrives();
            msgStatic.drives = new DriveInfoSlim[drives.Length];
            for (int i = 0; i < drives.Length; ++i)
            {
                msgStatic.drives[i].name = drives[i].Name;
                msgStatic.drives[i].type = drives[i].DriveType;
                if (drives[i].IsReady)
                {
                    msgStatic.drives[i].free  = drives[i].TotalFreeSpace;
                    msgStatic.drives[i].total = drives[i].TotalSize;
                }
            }
            //---processes
#if !NDEBUG
            Console.WriteLine("Getting Processes...");
#endif
            msgStatic.processes_total = Process.GetProcesses().Length;

            //======get network info
#if !NDEBUG
            Console.WriteLine("Getting NICs...");
#endif
            //http://stackoverflow.com/questions/850650/reliable-method-to-get-machines-mac-address-in-c-sharp#7661829
            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
            msgStatic.nics = new NetworkInterfaceSlim[nics.Length];
            for (int i = 0; i < nics.Length; ++i)
            {
                msgStatic.nics[i].name        = nics[i].Name;
                msgStatic.nics[i].status      = nics[i].OperationalStatus;
                msgStatic.nics[i].speed       = nics[i].Speed;
                msgStatic.nics[i].mac_address = nics[i].GetPhysicalAddress().ToString(); //PhysicalAddress type wont serialize T_T
                                                                                         //ip complciated because multiple addresses possible
                foreach (var x in nics[i].GetIPProperties().UnicastAddresses)
                {
                    if (x.Address.AddressFamily == AddressFamily.InterNetwork && x.IsDnsEligible)
                    {
                        msgStatic.nics[i].ip = x.Address.ToString();
                    }
                }
                //msg.nics[i].type = nics[i].GetType();
            }
        }