Skip to content

Commit

Permalink
offer hostname
Browse files Browse the repository at this point in the history
  • Loading branch information
pcarrier committed Feb 6, 2025
1 parent c614064 commit 28fe41a
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 44 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- run: |
cmake -A win32 .
cmake --build .
cmake --build . --config MinSizeRel
working-directory: cli
- uses: actions/upload-artifact@v4
with:
Expand All @@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v3
- run: |
cmake -A x64 .
cmake --build .
cmake --build . --config MinSizeRel
working-directory: cli
- uses: actions/upload-artifact@v4
with:
Expand All @@ -38,7 +38,7 @@ jobs:
- uses: actions/checkout@v3
- run: |
cmake -A ARM64 .
cmake --build .
cmake --build . --config MinSizeRel
working-directory: cli
- uses: actions/upload-artifact@v4
with:
Expand Down
10 changes: 10 additions & 0 deletions backend/http/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

type JSON struct {
IP string `json:"ip,omitempty"`
Hostname string `json:"hostname,omitempty"`
ASO string `json:"aso,omitempty"`
ASN uint `json:"asn,omitempty"`
Continent string `json:"continent,omitempty"`
Expand All @@ -32,9 +33,18 @@ type JSON struct {
TZ string `json:"tz,omitempty"`
}

func lookupAddr(ip string) string {
names, err := net.LookupAddr(ip)
if err != nil || len(names) == 0 {
return ""
}
return strings.TrimSuffix(names[0], ".")
}

func toJSON(ip string, city *geoip2.City, asn *geoip2.ASN) JSON {
return JSON{
IP: ip,
Hostname: lookupAddr(ip),
ASO: asn.AutonomousSystemOrganization,
ASN: asn.AutonomousSystemNumber,
Continent: city.Continent.Code,
Expand Down
1 change: 1 addition & 0 deletions cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ _deps/
build/
CMakeCache.txt
CMakeFiles/
identme
1 change: 1 addition & 0 deletions cli/Response.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

struct Response {
std::string ip;
std::optional<std::string> hostname;
std::optional<std::string> aso;
std::optional<int> asn;
std::optional<std::string> continent;
Expand Down
20 changes: 12 additions & 8 deletions cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

inline void print_ident_data(const std::string& label, const Response& data) {
std::cout << label << " address: " << data.ip << '\n';
if (data.hostname) {
std::cout << " Hostname: " << *data.hostname << '\n';
}
if (data.aso && data.asn) {
std::cout << " AS: " << *data.aso << " (" << *data.asn << ")\n";
}
Expand Down Expand Up @@ -53,16 +56,17 @@ Response parse_ident_json(const std::string& jsonStr) {
}
};

maybe_set_string("hostname", result.hostname);
maybe_set_string("aso", result.aso);
maybe_set_int("asn", result.asn);
maybe_set_int("asn", result.asn);
maybe_set_string("continent", result.continent);
maybe_set_string("cc", result.cc);
maybe_set_string("country", result.country);
maybe_set_string("city", result.city);
maybe_set_string("postal", result.postal);
maybe_set_float("latitude", result.latitude);
maybe_set_float("longitude", result.longitude);
maybe_set_string("tz", result.tz);
maybe_set_string("cc", result.cc);
maybe_set_string("country", result.country);
maybe_set_string("city", result.city);
maybe_set_string("postal", result.postal);
maybe_set_float("latitude", result.latitude);
maybe_set_float("longitude", result.longitude);
maybe_set_string("tz", result.tz);

return result;
} catch (const nlohmann::json::parse_error& e) {
Expand Down
23 changes: 23 additions & 0 deletions ios/ident.me/identMeApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func getInternalAddrs() -> ([InternalAddr], [InternalAddr])? {

struct Ident: Codable {
let ip: String
let hostname: String?
let aso: String?
let asn: Int?
let postal: String?
Expand Down Expand Up @@ -183,6 +184,28 @@ struct PublicView: View {
Text("Copy")
}
}
if let hostname = model.hostname {
GridRow {
VStack {
Text("Hostname")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
Text(hostname)
.frame(maxWidth: .infinity, alignment: .leading)
.monospaced()
}
Button {
#if os(OSX)
NSPasteboard.general.setString(hostname, forType: .string)
#else
UIPasteboard.general.string = hostname
#endif
} label: {
Image(systemName: "clipboard")
Text("Copy")
}
}
}
GridRow {
VStack {
Text("Location")
Expand Down
112 changes: 79 additions & 33 deletions www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@
display: grid;
}

#options, #outro, #docs {
#options,
#outro,
#docs {
text-align: center;
margin: var(--space-sm);
}
Expand Down Expand Up @@ -292,6 +294,7 @@ <h2>Browser data</h2>

const renderIPData = ({
ip,
hostname,
aso,
asn,
continent,
Expand All @@ -312,6 +315,11 @@ <h2>Browser data</h2>
</a>
</code>
</dd>
<dt>Hostname</dt><dd>${
hostname
? `<a href="#" class="copy" data-copy="${hostname}">${hostname}<span class="copy-icon" aria-hidden="true">📋</span></a>`
: "<i>unknown</i>"
}</dd>
<dt>Autonomous System (ISP)</dt>
<dd><a href="https://bgpview.io/asn/${asn}" target="_blank">${aso} (${asn})</a></dd>
<dt>Timezone</dt><dd>${tz}</dd>
Expand Down Expand Up @@ -482,11 +490,11 @@ <h2>Browser data</h2>

async function drawSparkline(canvasId, data1, data2, options = {}) {
const {
color1 = '#4CAF50',
color2 = '#2196F3',
label1 = 'reqs',
label2 = 'IPs',
stacked = false
color1 = "#4CAF50",
color2 = "#2196F3",
label1 = "reqs",
label2 = "IPs",
stacked = false,
} = options;

const canvas = document.getElementById(canvasId);
Expand All @@ -495,34 +503,48 @@ <h2>Browser data</h2>
const textPadding = 2;
const circleRadius = 4;
const graphPadding = circleRadius + 1;
const fontSize = '1em';
const fontSize = "1em";

ctx.font = `${fontSize} sans-serif`;
const metrics = ctx.measureText(`${label1}: ${data1[0].toLocaleString()}`);
const lineHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
const metrics = ctx.measureText(
`${label1}: ${data1[0].toLocaleString()}`
);
const lineHeight =
metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
const textBaseOffset = metrics.actualBoundingBoxAscent;
const textBoxHeight = (textPadding + lineHeight) * 2;

const points = [];
let hoveredPoint = null;

function drawLine(data, color, yKey, maxValue = Math.max(...data), minValue = Math.min(...data)) {
function drawLine(
data,
color,
yKey,
maxValue = Math.max(...data),
minValue = Math.min(...data)
) {
const valueRange = maxValue - minValue;

ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 2;

data.forEach((value, i) => {
const x = graphPadding + (i * (width - 2 * graphPadding)) / (data.length - 1);
const y = height - graphPadding - ((height - 2 * graphPadding) * (value - minValue)) / valueRange;
const x =
graphPadding +
(i * (width - 2 * graphPadding)) / (data.length - 1);
const y =
height -
graphPadding -
((height - 2 * graphPadding) * (value - minValue)) / valueRange;

if (!points[i]) points[i] = { x };
points[i][label1] = data1[i];
points[i][label2] = data2[i];
points[i][yKey] = y;

ctx[i === 0 ? 'moveTo' : 'lineTo'](x, y);
ctx[i === 0 ? "moveTo" : "lineTo"](x, y);
});
ctx.stroke();

Expand All @@ -540,28 +562,39 @@ <h2>Browser data</h2>

if (stacked) {
const maxValue = Math.max(...data1.map((v, i) => v + data2[i]));
drawLine(data2, color2, 'y2', maxValue, 0);
drawLine(data1.map((v, i) => v + data2[i]), color1, 'y', maxValue, 0);
drawLine(data2, color2, "y2", maxValue, 0);
drawLine(
data1.map((v, i) => v + data2[i]),
color1,
"y",
maxValue,
0
);
} else {
drawLine(data1, color1, 'y');
drawLine(data2, color2, 'y2');
drawLine(data1, color1, "y");
drawLine(data2, color2, "y2");
}

if (hoveredPoint) {
ctx.font = `${fontSize} sans-serif`;
ctx.textAlign = 'right';
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.textAlign = "right";
ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

const metrics = ctx.measureText(
`${label1}: ${hoveredPoint[label1].toLocaleString()}`
);
const boxWidth = metrics.width + textPadding * 2;

ctx.fillRect(width - boxWidth, textPadding, boxWidth, textBoxHeight);
ctx.fillRect(
width - boxWidth,
textPadding,
boxWidth,
textBoxHeight
);

[
{ label: label1, color: color1 },
{ label: label2, color: color2 }
{ label: label2, color: color2 },
].forEach(({ label, color }, i) => {
ctx.fillStyle = color;
ctx.fillText(
Expand All @@ -575,7 +608,7 @@ <h2>Browser data</h2>

draw();

canvas.addEventListener('mousemove', (e) => {
canvas.addEventListener("mousemove", (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;

Expand All @@ -588,7 +621,7 @@ <h2>Browser data</h2>

[
{ y: hoveredPoint.y, color: color1 },
{ y: hoveredPoint.y2, color: color2 }
{ y: hoveredPoint.y2, color: color2 },
].forEach(({ y, color }) => {
ctx.beginPath();
ctx.arc(hoveredPoint.x, y, circleRadius, 0, 2 * Math.PI);
Expand All @@ -597,7 +630,7 @@ <h2>Browser data</h2>
});
});

canvas.addEventListener('mouseleave', () => {
canvas.addEventListener("mouseleave", () => {
hoveredPoint = null;
draw();
});
Expand Down Expand Up @@ -673,15 +706,28 @@ <h3>${m} user agents (sampled)</h3>

await Promise.all(
mirrors.flatMap((m, i) => [
drawSparkline(`${m}-hourly`, statsData[i].hourly.reqs, statsData[i].hourly.ips),
drawSparkline(`${m}-daily`, statsData[i].daily.reqs, statsData[i].daily.ips),
drawSparkline(`${m}-daily-pertype`, statsData[i].daily.ipv4, statsData[i].daily.ipv6, {
color1: '#E91E63',
color2: '#9C27B0',
label1: 'IPv4',
label2: 'IPv6',
stacked: true
})
drawSparkline(
`${m}-hourly`,
statsData[i].hourly.reqs,
statsData[i].hourly.ips
),
drawSparkline(
`${m}-daily`,
statsData[i].daily.reqs,
statsData[i].daily.ips
),
drawSparkline(
`${m}-daily-pertype`,
statsData[i].daily.ipv4,
statsData[i].daily.ipv6,
{
color1: "#E91E63",
color2: "#9C27B0",
label1: "IPv4",
label2: "IPv6",
stacked: true,
}
),
])
);

Expand Down

0 comments on commit 28fe41a

Please sign in to comment.