xmr-remote-nodes/internal/handler/response.go
Christian Ditaputratama 518d4b4335
feat: Added IPv6 nodes support (alpha) #84
This commit accept IPv6 nodes submission.

When user submit new public node, the server will check IP addresses
from given hostname. If host IP addresses doesn't have IPv4, it will
be recorded as "IPv6 only" node.

Probers that support IPv6 may add `IPV6_CAPABLE=true` to the `.env`
file.

Please note that this feature still experimental and may not being
merged to the main branch.
2024-09-06 00:08:59 +07:00

222 lines
5 KiB
Go

package handler
import (
"strconv"
"github.com/ditatompel/xmr-remote-nodes/internal/monero"
"github.com/gofiber/fiber/v2"
)
// Returns a single node information based on `id` query param
func Node(c *fiber.Ctx) error {
nodeId, err := c.ParamsInt("id", 0)
if err != nil {
return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
if nodeId == 0 {
return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
"status": "error",
"message": "Invalid node id",
"data": nil,
})
}
moneroRepo := monero.New()
node, err := moneroRepo.Node(nodeId)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": node,
})
}
// Returns a list of nodes
func Nodes(c *fiber.Ctx) error {
moneroRepo := monero.New()
query := monero.QueryNodes{
RowsPerPage: c.QueryInt("limit", 10),
Page: c.QueryInt("page", 1),
SortBy: c.Query("sort_by", "id"),
SortDirection: c.Query("sort_direction", "desc"),
Host: c.Query("host"),
Nettype: c.Query("nettype", "any"),
Protocol: c.Query("protocol", "any"),
CC: c.Query("cc", "any"),
Status: c.QueryInt("status", -1),
CORS: c.QueryInt("cors", -1),
}
nodes, err := moneroRepo.Nodes(query)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": nodes,
})
}
// Returns probe logs reported by nodes
//
// The embadded web UI use `node_id` query param to filter logs
func ProbeLogs(c *fiber.Ctx) error {
moneroRepo := monero.New()
query := monero.QueryLogs{
RowsPerPage: c.QueryInt("limit", 10),
Page: c.QueryInt("page", 1),
SortBy: c.Query("sort_by", "id"),
SortDirection: c.Query("sort_direction", "desc"),
NodeID: c.QueryInt("node_id", 0),
Status: c.QueryInt("status", -1),
FailedReason: c.Query("failed_reason"),
}
logs, err := moneroRepo.Logs(query)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": logs,
})
}
// Handles `POST /nodes` request to add a new node
func AddNode(c *fiber.Ctx) error {
formPort := c.FormValue("port")
port, err := strconv.Atoi(formPort)
if err != nil {
return c.JSON(fiber.Map{
"status": "error",
"message": "Invalid port number",
"data": nil,
})
}
protocol := c.FormValue("protocol")
hostname := c.FormValue("hostname")
moneroRepo := monero.New()
if err := moneroRepo.Add(protocol, hostname, uint(port)); err != nil {
return c.JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Query Ok",
"data": nil,
})
}
// Returns majority network fees
func NetFees(c *fiber.Ctx) error {
moneroRepo := monero.New()
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": moneroRepo.NetFees(),
})
}
// Returns list of countries (count by nodes)
func Countries(c *fiber.Ctx) error {
moneroRepo := monero.New()
countries, err := moneroRepo.Countries()
if err != nil {
return c.JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": countries,
})
}
// Returns node to be probed by the client (prober)
//
// This handler should protected by `CheckProber` middleware.
func GiveJob(c *fiber.Ctx) error {
acceptTor := c.QueryInt("accept_tor", 0)
acceptIPv6 := c.QueryInt("accept_ipv6", 0)
moneroRepo := monero.New()
node, err := moneroRepo.GiveJob(acceptTor, acceptIPv6)
if err != nil {
return c.JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": node,
})
}
// Handles probe report submission by the prober
//
// This handler should protected by `CheckProber` middleware.
func ProcessJob(c *fiber.Ctx) error {
var report monero.ProbeReport
if err := c.BodyParser(&report); err != nil {
return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
moneroRepo := monero.New()
if err := moneroRepo.ProcessJob(report, c.Locals("prober_id").(int64)); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": "error",
"message": err.Error(),
"data": nil,
})
}
return c.JSON(fiber.Map{
"status": "ok",
"message": "Success",
"data": nil,
})
}