Exemple #1
0
        /// <summary>
        /// Stop the network capture
        /// </summary>
        public static void Stop()
        {
            TraceLog.TraceInfo("Stopping collector");

            if (devices != null)
            {
                try
                {
                    foreach (var device in devices)
                    {
                        // Stop the capturing process
                        TraceLog.TraceInfo(string.Format("Stopping {0} {1}", device.Name, device.Description));
                        device.OnPacketArrival -= new PacketArrivalEventHandler(device_OnPacketArrival);
                        device.StopCapture();
                        device.Close();

                        // Print out the device statistics
                        TraceLog.TraceInfo(device.Statistics.ToString());
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("Stop caught exception", ex);
                }
            }

            TraceLog.TraceInfo("Stopped collector");
        }
Exemple #2
0
        /// <summary>
        /// stop the upload client
        /// </summary>
        public static void Stop()
        {
            lock (startLock)
            {
                TraceLog.TraceInfo("Stopping updater");

                // terminate the loop
                loopFlag = false;

                TraceLog.TraceInfo("Stopped updater");
            }
        }
Exemple #3
0
 /// <summary>
 /// Start the upload client
 /// </summary>
 public static void Start()
 {
     lock (startLock)
     {
         if (!started)
         {
             TraceLog.TraceInfo("Starting updater");
             ThreadStart ts     = new ThreadStart(GetVersionLoop);
             Thread      thread = new Thread(ts);
             loopFlag = true;
             thread.Start();
             started = true;
         }
     }
 }
Exemple #4
0
        /// <summary>
        /// stop the upload client
        /// </summary>
        public static void Stop()
        {
            lock (startLock)
            {
                TraceLog.TraceInfo("Stopping uploader");

                // terminate the loop
                uploadFlag = false;

                // one last send
                TraceLog.TraceInfo("Stop processing: sending last buffer");
                Send();

                TraceLog.TraceInfo("Stopped uploader");
            }
        }
Exemple #5
0
        /// <summary>
        /// Start the upload client
        /// </summary>
        public static void Start()
        {
            lock (startLock)
            {
                if (!started)
                {
                    TraceLog.TraceInfo("Starting uploader");

                    // retrieve creds and device ID
                    credentials = ConfigClient.Read(ConfigClient.Credentials);
                    deviceId    = ConfigClient.Read(ConfigClient.DeviceId);
                    deviceName  = ConfigClient.Read(ConfigClient.DeviceName);

                    // start the uploader loop on a new thread
                    ThreadStart ts     = new ThreadStart(SendLoop);
                    Thread      thread = new Thread(ts);
                    uploadFlag = true;
                    thread.Start();
                    started = true;
                }
            }
        }
Exemple #6
0
        private static void Install(string filename)
        {
            // spawn a new process process - we must do this outside of the service because the
            // installer will shut down the current running service as part of the uninstall
            using (var process = new Process())
            {
                process.StartInfo.FileName  = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "msiexec.exe");
                process.StartInfo.Arguments = string.Format(
                    "/i {0} /qn /quiet /L*vx \"{1}\" REBOOT=ReallySuppress",
                    filename,
                    LogFilename);
                process.StartInfo.CreateNoWindow  = true;
                process.StartInfo.UseShellExecute = false;

                TraceLog.TraceInfo(string.Format("Starting msiexec {0}", process.StartInfo.Arguments));
                process.Start();
            }

            // note - if the update does not succeed, the updater service will continue running and updateFlag will still be true.
            // this is a FEATURE since the update failed.  The next time the update will be downloaded will be when the service restarts,
            // not in the next update interval.  this in turn will reduce the likelihood that a bad update will create lots of junk 1MB images
            // on the user's HDD.
        }
Exemple #7
0
        private static void GetVersionLoop()
        {
            while (loopFlag)
            {
                // sleep for timeout
                Thread.Sleep(timeout);

                // don't want two concurrent updates
                if (checkingFlag || updatingFlag)
                {
                    continue;
                }

                try
                {
                    // locking is overkill here because only one thread that wakes up every <timeout>
                    checkingFlag = true;

                    WebServiceHelper.GetCurrentSoftwareVersion(
                        VersionUrl,
                        new WebServiceHelper.AccountDelegate((version) =>
                    {
                        if (string.IsNullOrEmpty(version))
                        {
                            TraceLog.TraceError("Could not download version file");
                            checkingFlag = false;
                            return;
                        }
                        try
                        {
                            // compare versions
                            var newVersion = new Version(version);
                            if (newVersion > CurrentVersion)
                            {
                                TraceLog.TraceInfo(string.Format(
                                                       "New version {0} more recent than current version {1}; downloading new version",
                                                       newVersion, CurrentVersion));
                                updatingFlag = true;

                                // download and install new software
                                WebServiceHelper.DownloadCurrentSoftware(
                                    DownloadUrl,
                                    new WebServiceHelper.AccountDelegate((filename) =>
                                {
                                    // install the new software
                                    TraceLog.TraceInfo(string.Format("Download successful; installing {0}", filename));
                                    Install(filename);
                                }),
                                    new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                                {
                                    // cleanup the checking flag based on network operation status (typically failures)
                                    if (inProgress == false)
                                    {
                                        updatingFlag = false;
                                    }
                                }));
                            }
                            checkingFlag = false;
                        }
                        catch (Exception ex)
                        {
                            TraceLog.TraceException("Version check failed", ex);
                            checkingFlag = false;
                            updatingFlag = false;
                        }
                    }),
                        new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                    {
                        // cleanup the checking flag based on network operation status (typically failures)
                        if (inProgress == false)
                        {
                            checkingFlag = false;
                        }
                    }));
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("GetVersionLoop failed", ex);
                    checkingFlag = false;
                    updatingFlag = false;
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Start a network capture
        /// </summary>
        public static void Start()
        {
            lock (startingLock)
            {
                try
                {
                    // Retrieve the device list
                    devices = CaptureDeviceList.Instance;

                    // If no devices were found print an error
                    if (devices.Count < 1)
                    {
                        var error = "No devices were found on this machine";
                        TraceLog.TraceFatal(error);
                        throw new Exception(error);
                    }

                    // if capture is started on all devices, nothing to do
                    var started = true;
                    foreach (var dev in devices)
                    {
                        if (!dev.Started || !string.IsNullOrEmpty(dev.LastError))
                        {
                            started = false;
                            break;
                        }
                    }
                    if (started)
                    {
                        return;
                    }

                    // Print SharpPcap version
                    string ver = SharpPcap.Version.VersionString;
                    TraceLog.TraceInfo(string.Format("Starting collector with version {0}", ver));

                    foreach (var device in devices)
                    {
                        // reset device if already started
                        if (device.Started)
                        {
                            TraceLog.TraceInfo(string.Format("Stopping {0} {1}", device.Name, device.Description));
                            device.OnPacketArrival -= new PacketArrivalEventHandler(device_OnPacketArrival);
                            device.StopCapture();
                            device.Close();
                        }

                        // Register our handler function to the 'packet arrival' event
                        device.OnPacketArrival +=
                            new PacketArrivalEventHandler(device_OnPacketArrival);

                        // Open the device for capturing
                        int readTimeoutMilliseconds = 1000;
                        device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

                        TraceLog.TraceInfo(string.Format("Listening on {0} {1}",
                                                         device.Name, device.Description));

                        // DNS only
                        string filter = "udp dst port 53";
                        device.Filter = filter;

                        // Start the capturing process
                        device.StartCapture();
                    }

                    // get the device ID, and store it if it's not in the config file already
                    deviceId = ConfigClient.Read(ConfigClient.DeviceId);
                    if (deviceId == null)
                    {
                        deviceId = devices[0].MacAddress.ToString();
                        ConfigClient.Write(ConfigClient.DeviceId, deviceId);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("FATAL: Start caught exception", ex);
                    throw ex;
                }
            }
        }
Exemple #9
0
        private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            try
            {
                var packet = PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
                if (packet is PacketDotNet.EthernetPacket)
                {
                    var eth = packet as EthernetPacket;

                    // this syntax is from PacketDotNet 0.13.0 which isn't supported in the nuget package (0.12.0)
                    //var udp = packet.Extract(typeof(UdpPacket)) as UdpPacket;
                    var udp = Extract(packet, typeof(UdpPacket)) as UdpPacket;
                    if (udp != null)
                    {
                        string websiteName = null;

                        if (udp.DestinationPort == 53) // DNS
                        {
                            // extract hostname.  it is encoded in segments: one-byte length followed by the segment in ASCII
                            // the first segment starts at 0x0c

                            const int START = 0x0c;

                            int  start = START;
                            byte len   = udp.PayloadData[start];
                            var  sb    = new StringBuilder();
                            while (len > 0)
                            {
                                sb.Append(Encoding.ASCII.GetString(udp.PayloadData, start + 1, len));
                                start += len + 1;
                                len    = udp.PayloadData[start];
                                if (len > 0)
                                {
                                    sb.Append('.');
                                }
                            }
                            websiteName = sb.ToString();
                        }

                        var hostMacAddress = eth.SourceHwAddress.ToString();

#if DEBUG
                        // only log this level of detail if we're logging to the console
                        if (TraceLog.TraceDestination == TraceLog.Destination.Console)
                        {
                            // get the IP packet info
                            var ip = packet.PayloadPacket as IPv4Packet;
                            if (ip != null)
                            {
                                var hostIpAddress = ip.SourceAddress.ToString();
                                var destIpAddress = ip.DestinationAddress.ToString();
                                var sourcePort    = udp.SourcePort;
                                var destPort      = udp.DestinationPort;
                                var hostName      = hostIpAddress;

                                try
                                {
                                    IPHostEntry entry = null;
                                    if (Environment.Version.CompareTo(new System.Version(4, 0)) < 0)
                                    {
                                        entry = Dns.GetHostByAddress(ip.SourceAddress);
                                    }
                                    else
                                    {
                                        entry = Dns.GetHostEntry(ip.SourceAddress);
                                    }
                                    if (entry != null)
                                    {
                                        hostName = entry.HostName;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    TraceLog.TraceException(String.Format("GetHostByAddress failed for {0}", hostIpAddress), ex);
                                }

                                var destMacAddress = eth.DestinationHwAddress.ToString();

                                TraceLog.TraceInfo(String.Format("Source: [{0}; {1}:{2}; {3}]; Dest: [{4}; {5}:{6}; Website: {7}",
                                                                 hostMacAddress, hostIpAddress, sourcePort, hostName,
                                                                 destMacAddress, destIpAddress, destPort,
                                                                 websiteName));
                            }
                        }
#endif

                        lock (records)
                        {
                            records.Add(new Record()
                            {
                                HostMacAddress = hostMacAddress,
                                WebsiteName    = websiteName,
                                Timestamp      = DateTime.Now.ToString("s")
                            });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("OnPacketArrival caught exception", ex);
            }
        }
Exemple #10
0
        // Common code to process the response from any web service call.  This is invoked from the callback
        // method for the web service, and passed a Type for deserializing the response body.
        // This method will also invoke the delegate with the result of the Web Service call
        private static void ProcessResponse <T>(IAsyncResult result)
        {
            WebServiceState state = result.AsyncState as WebServiceState;

            if (state == null)
            {
                TraceLog.TraceError("Web Service State not found");
                return;
            }

            // get the network operation status delegate
            Delegate netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate;

            // get the web response and make sure it's not null (failed)
            //HttpWebResponseWrapper<T> resp = GetWebResponse<T>(result);
            HttpWebResponse resp = GetWebResponse(result);

            if (resp == null)
            {
                TraceLog.TraceError("GetWebResponse failed");

                // signal that the network operation completed unsuccessfully
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
                return;
            }
            else
            {
                OperationStatus status = AsOperationStatus(resp.StatusCode);
                if (resp.StatusCode == HttpStatusCode.Unauthorized)
                {     // using this status code to indicate cookie has expired or is invalid
                    if (authCookie != null)
                    { // remove cookie and retry with credentials
                        status     = OperationStatus.Retry;
                        authCookie = null;
                    }
                }
                if (resp.StatusCode == HttpStatusCode.Forbidden)
                {   // remove cookie and force authentication on next request
                    authCookie = null;
                }

                if (netOpInProgressDel != null)
                {   // signal the network operation completed and whether it completed successfully
                    netOpInProgressDel.DynamicInvoke(false, status);
                    if (status == OperationStatus.Retry)
                    {   // delegate will retry, exit now
                        TraceLog.TraceInfo("Received a Retry response from Service");
                        return;
                    }
                }
            }

            // get the method-specific delegate
            Delegate del = state.Delegate as Delegate;

            //if (del == null)
            //    return;  // if no delegate was passed, the results can't be processed

            // invoke the delegate with the response body
            try
            {
                T resultObject = (T) new DataContractJsonSerializer(typeof(T)).ReadObject(resp.GetResponseStream());
                //T resultObject = resp.GetBody();
                if (del == null)
                {
                    return;  // if no delegate was passed, the results can't be processed
                }
                del.DynamicInvoke(resultObject);
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("ProcessResponse: exception from GetBody or DynamicInvoke", ex);
                // signal the operation is done and unsuccessful
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
                if (del == null)
                {
                    return;  // if no delegate was passed, the results can't be processed
                }
                del.DynamicInvoke(null);
            }
        }
Exemple #11
0
        // This method is the callback for an HTTP request that returns a file.  It will save the
        // file to a temporary location and invoke the delegate with the location.
        private static void ProcessFile(IAsyncResult result)
        {
            const string updateDir = @"updates";
            const string msiname   = @"WebTimer.msi";

            WebServiceState state = result.AsyncState as WebServiceState;

            if (state == null)
            {
                TraceLog.TraceError("Web Service State not found");
                return;
            }

            // get the network operation status delegate
            Delegate netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate;

            // get the web response and make sure it's not null (failed)
            HttpWebResponse resp = GetWebResponse(result);

            if (resp == null)
            {
                TraceLog.TraceError("GetWebResponse failed");

                // signal that the network operation completed unsuccessfully
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
                return;
            }

            // get the method-specific delegate
            Delegate del = state.Delegate as Delegate;

            if (del == null)
            {
                return;  // if no delegate was passed, the results can't be processed
            }
            try
            {
                // create directory if it doesn't exist
                if (!Directory.Exists(updateDir))
                {
                    Directory.CreateDirectory(updateDir);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Could not create updates directory", ex);
                // signal the operation is done and unsuccessful
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
                // can't process further
                return;
            }

            // write the result of the GET to a temp file
            //string updatepath = Path.GetRandomFileName();
            var    now        = DateTime.Now;
            string updatepath = Path.Combine(updateDir, string.Format("update-{0}", now.ToString("yyyy-MM-dd-HH-mm-ss")));
            string updatefile = Path.Combine(updatepath, msiname);

            try
            {
                TraceLog.TraceInfo(string.Format("Creating update directory {0}", updatepath));
                Directory.CreateDirectory(updatepath);

                TraceLog.TraceInfo(string.Format("Saving MSI in {0}", updatefile));
                using (var inputStream = resp.GetResponseStream())
                    using (var fileStream = File.OpenWrite(updatefile))
                    {
                        byte[] buffer = new byte[8 * 1024];
                        int    len;
                        while ((len = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            fileStream.Write(buffer, 0, len);
                        }
                    }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException(string.Format("Could not create temporary file {0}", updatefile), ex);
                // signal the operation is done and unsuccessful
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
                return;
            }

            // invoke the delegate with the temp file name
            try
            {
                del.DynamicInvoke(updatefile);
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("ProcessFile: exception from DynamicInvoke", ex);
                // signal the operation is done and unsuccessful
                if (netOpInProgressDel != null)
                {
                    netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed);
                }
            }
        }
Exemple #12
0
        private static void Send()
        {
            try
            {
                // snap the record list
                var recordList = CollectorClient.GetRecords();

                // if no records, may need to recover capture service
                if (recordList.Count == 0)
                {
                    if (recovering)
                    {
                        // this is the second timeout period that we didn't see records.
                        // attempt to restart the collector
                        CollectorClient.Start();
                        recovering = false;
                    }
                    else
                    {
                        // this will trigger recovery if the next run through also has zero records
                        recovering = true;
                    }

                    // nothing to do this time (no records to process)
                    return;
                }
                else
                {
                    // reset recovery mode
                    recovering = false;
                }

                // compact the record list
                var uniqueHosts = recordList.Select(r => r.HostMacAddress).Distinct();
                foreach (var host in uniqueHosts)
                {
                    var uniqueDests = recordList.Where(r => r.HostMacAddress == host).Select(r => r.WebsiteName).Distinct();
                    foreach (var dest in uniqueDests)
                    {
                        var records = recordList.Where(r => r.HostMacAddress == host && r.WebsiteName == dest).OrderBy(r => r.Timestamp);

                        // only keep the first and last record so that the duration calculated on the server will be > 0
                        var firstRecord = records.FirstOrDefault();
                        var lastRecord  = records.LastOrDefault();

                        // if the last record is a second or more later, add the duration to the first record
                        TimeSpan duration;
                        if (lastRecord != null && lastRecord != firstRecord &&
                            (duration = Convert.ToDateTime(lastRecord.Timestamp) - Convert.ToDateTime(firstRecord.Timestamp))
                            >= TimeSpan.FromSeconds(1.0))
                        {
                            firstRecord.Duration = (int)duration.TotalSeconds;
                        }

                        lock (sendQueue)
                        {
                            var existingRecord = sendQueue.FirstOrDefault(r => r.HostMacAddress == host && r.WebsiteName == dest);
                            if (existingRecord == null ||
                                Convert.ToDateTime(firstRecord.Timestamp) - (Convert.ToDateTime(existingRecord.Timestamp) + TimeSpan.FromSeconds(existingRecord.Duration)) >= TimeSpan.FromSeconds(300.0)) // more than 5 minutes between records
                            {
                                // add the record to the send queue
                                sendQueue.Add(firstRecord);
                            }
                            else
                            {
                                // augment existing record with new duration
                                duration = Convert.ToDateTime(firstRecord.Timestamp) - Convert.ToDateTime(existingRecord.Timestamp) + TimeSpan.FromSeconds(firstRecord.Duration);
                                existingRecord.Duration = (int)duration.TotalSeconds;
                            }
                        }
                    }
                }

                if (sendQueue.Count > 0)
                {
                    // snap the send queue
                    var recordBuffer = new List <Record>();
                    lock (sendQueue)
                    {
                        // clear this buffer if collection is suspended
                        if (collectionStatus == ControlMessage.SuspendCollection)
                        {
                            sendQueue.Clear();
                            TraceLog.TraceInfo("Probing for new collection status");
                        }
                        else
                        {
                            recordBuffer.AddRange(sendQueue);
                            TraceLog.TraceInfo(String.Format("Sending records: {0}", JsonConvert.SerializeObject(sendQueue)));
                        }
                    }

                    var sendList = new RecordList()
                    {
                        DeviceId        = deviceId,
                        DeviceName      = deviceName,
                        SoftwareVersion = UpdateClient.CurrentVersion.ToString(),
                        Records         = recordBuffer
                    };

                    // send the queue to the web service
                    WebServiceHelper.PostRecords(
                        credentials,
                        sendList,
                        new WebServiceHelper.PostRecordsDelegate((response) =>
                    {
                        // a callback means the service processed the records successfully; we can free them now.
                        // note a slight race condition - if the callback takes longer than the sleep interval, we
                        // could lose a buffer.  since the sleep interval is 60sec, this isn't an important issue
                        // to address.
                        lock (sendQueue)
                        {
                            sendQueue.Clear();
                        }
                        var msg = (ControlMessage)response.controlMessage;
                        if (collectionStatus == msg)
                        {
                            return;
                        }

                        // process the control message
                        lock (configLock)
                        {
                            switch (msg)
                            {
                            case ControlMessage.Normal:
                                TraceLog.TraceInfo("Changing collection status to Normal");
                                collectionStatus = msg;
                                ConfigClient.Write(ConfigClient.Disabled, Convert.ToString(false));
                                break;

                            case ControlMessage.SuspendCollection:
                                TraceLog.TraceInfo("Changing collection status to Suspended");
                                collectionStatus = msg;
                                ConfigClient.Write(ConfigClient.Disabled, Convert.ToString(true));
                                break;

                            case ControlMessage.DisableDevice:
                                TraceLog.TraceInfo("Disabling the device by wiping the config");
                                collectionStatus = msg;
                                deviceId         = null;
                                deviceName       = null;
                                // wipe the config
                                ConfigClient.Clear();
                                break;

                            default:
                                // new message we don't understand yet
                                TraceLog.TraceInfo(string.Format("Received unknown control message {0}", msg));
                                break;
                            }
                        }
                    }),
                        new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                    {
                        if (status == OperationStatus.Retry)
                        {
                            // no need to do anything: next iteration will send original credentials
                        }
                        // no failure state to clean up
                    }));
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Upload processing failed", ex);
            }
        }