internal static void ProcessData(DevicesSeen observationReport)
        {
            // which AP is sending the report
            string queryString = "SELECT * FROM ReportingAPs WHERE apMac = '" + observationReport.Data.ApMac + "'";

            if (!DBConnection.DoesRecordExist(queryString))
            {
                // new reporting AP
                queryString = "INSERT INTO ReportingAPs (apMac) Values ('" +
                              observationReport.Data.ApMac + "')";

                DBConnection.UpdateDB(queryString);
            }

            // hacking temporal proximity...
            long reportReceived = DateTimeOffset.Now.ToUnixTimeSeconds();

            // Carve up the observationReport and push it into db
            int x;

            for (x = 0; x < observationReport.Data.Observations.Count; x++)
            {
                if (observationReport.Data.Observations[x].Location != null)
                {
                    queryString = "INSERT INTO ObservationReports " +
                                  "(ipv4, locationlat, locationlng, locationunc, x, y, seenTime, ssid, os, " +
                                  "clientMac, name, seenEpoch, rssi, ipv6, manufacturer, seenByApMac, " +
                                  "reportReceived) " +
                                  "Values (";

                    // a crude hack.  the reports dont contain the hostname preceding the / so just del the /
                    // v3 of the api drops the hostname entirely anyway
                    if (observationReport.Data.Observations[x].Ipv4 != null)
                    {
                        queryString += "'" + (observationReport.Data.Observations[x].Ipv4).Substring(1) + "', ";
                    }
                    else
                    {
                        queryString += "'" + observationReport.Data.Observations[x].Ipv4 + "', ";
                    }

                    queryString +=
                        "'" + observationReport.Data.Observations[x].Location.Lat + "', " +
                        "'" + observationReport.Data.Observations[x].Location.Lng + "', " +
                        "'" + observationReport.Data.Observations[x].Location.Unc + "', " +
                        // x and y are actually lists as the values can be returned as offsets
                        // on multiple floorplans.  just grabbing the first value for simplicity
                        "'" + observationReport.Data.Observations[x].Location.X[0] + "', " +
                        "'" + observationReport.Data.Observations[x].Location.Y[0] + "', " +
                        "'" + observationReport.Data.Observations[x].SeenTime + "', " +
                        "'" + observationReport.Data.Observations[x].Ssid + "', " +
                        "'" + observationReport.Data.Observations[x].Os + "', " +
                        "'" + observationReport.Data.Observations[x].ClientMac + "', " +
                        "'" + observationReport.Data.Observations[x].Name + "', " +
                        "'" + observationReport.Data.Observations[x].SeenEpoch + "', " +
                        "'" + observationReport.Data.Observations[x].Rssi + "', " +
                        "'" + observationReport.Data.Observations[x].Ipv6 + "', " +
                        "'" + observationReport.Data.Observations[x].Manufacturer + "', " +
                        "'" + observationReport.Data.ApMac + "', " +
                        "'" + reportReceived + "'" +
                        ")";

                    DBConnection.UpdateDB(queryString);
                }
            }

            Console.WriteLine("{0} reports received in this POST", x);
        }
Exemple #2
0
        private void ProcessRequestHandler(Task <HttpListenerContext> result)
        {
            var context = result.Result;
            HttpListenerRequest  typeoHTTPRrequest = context.Request;
            HttpListenerResponse serverResponse    = context.Response;

            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //
            // INSERT YOUR KEY AND SECRET BELOW
            //
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            string validationResponse = "the.string.you.copied.from.the.meraki.portal";
            string MySharedSecret     = "the.secret.you.configured.in.the.meraki.portal";

            if (!listener.IsListening)
            {
                return;
            }

            // Start new listener which replace this
            listener.GetContextAsync().ContinueWith(ProcessRequestHandler);

            // Read request
            string request = new StreamReader(context.Request.InputStream).ReadToEnd();

            // the only GET we care about is the Meraki backend verifying this server as
            // a POST target, so we send the expected response below.  Firewall yourself
            // appropriately...
            if (typeoHTTPRrequest.HttpMethod == "GET")
            {
                Console.WriteLine("SUCCESSFUL GET");
                var responseBytes = System.Text.Encoding.UTF8.GetBytes(validationResponse);
                serverResponse.ContentLength64 = responseBytes.Length;
                var output = serverResponse.OutputStream;
                output.WriteAsync(responseBytes, 0, responseBytes.Length);
                output.Close();
            }
            else if (typeoHTTPRrequest.HttpMethod == "POST")
            {
                Console.WriteLine("SUCCESSFUL POST");

                // the v2 API will return a non-rfc "NaN" string where you've been
                // told to expect a float/double.  The following prevents that from
                // nuking everything.  Pre-req is .NET 5.0

                var jsonOptions = new JsonSerializerOptions
                {
                    NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals
                                     // | JsonNumberHandling.WriteAsString
                };

                DevicesSeen observationReport = new DevicesSeen();
                observationReport = JsonSerializer.Deserialize <DevicesSeen>(request, jsonOptions);

                // is the shared secret a match
                if (observationReport.Secret != MySharedSecret)
                {
                    Console.WriteLine("Shared Secret does not match.  Discarding received data.");
                    return;
                }

                // for debug
                //DumpAsYaml(observationReport);

                // Deal with the POSTed data
                DataParser.ProcessData(observationReport);
            }
        }