aboutsummaryrefslogtreecommitdiffstats
path: root/geoip
diff options
context:
space:
mode:
authorOscar Najera <hi@oscarnajera.com>2025-06-06 18:09:50 +0200
committerOscar Najera <hi@oscarnajera.com>2025-06-06 18:27:04 +0200
commitb18f18229a2e1294fd10f759c60b89fededae9c8 (patch)
treec16096673af2c7b222f651016c593afac9c1492b /geoip
parent0ce7a9320aab651218585d25738269692017b4ac (diff)
downloadscratch-b18f18229a2e1294fd10f759c60b89fededae9c8.tar.gz
scratch-b18f18229a2e1294fd10f759c60b89fededae9c8.tar.bz2
scratch-b18f18229a2e1294fd10f759c60b89fededae9c8.zip
create a system package
Diffstat (limited to 'geoip')
-rw-r--r--geoip/geoip.asd20
-rw-r--r--geoip/ip.lisp59
-rw-r--r--geoip/tests.lisp14
3 files changed, 44 insertions, 49 deletions
diff --git a/geoip/geoip.asd b/geoip/geoip.asd
new file mode 100644
index 0000000..53826dd
--- /dev/null
+++ b/geoip/geoip.asd
@@ -0,0 +1,20 @@
+
+(defsystem "geoip"
+ :version "0.1.0"
+ :author "Oscar"
+ :license "GPL-3"
+ :depends-on ("cffi"
+ "mmap"
+ "split-sequence")
+ :components ((:file "ip"))
+ :description "Query maxminddb for ip information"
+ :in-order-to ((test-op (test-op "geoip/tests"))))
+
+(defsystem "geoip/tests"
+ :author "Oscar"
+ :license "GPL-3"
+ :depends-on ("geoip"
+ "fiveam")
+ :components ((:file "tests"))
+ :description "Test system for geoip"
+ :perform (test-op (op c) (symbol-call :fiveam :run!)))
diff --git a/geoip/ip.lisp b/geoip/ip.lisp
index a61989d..aae0702 100644
--- a/geoip/ip.lisp
+++ b/geoip/ip.lisp
@@ -1,21 +1,8 @@
;;;; -*- mode: lisp -*-
-
-(ql:quickload '(cffi cffi-libffi split-sequence mmap ironclad babel nibbles fiveam local-time))
-
(defpackage :geoip
(:use :common-lisp :cffi :split-sequence))
-(in-package :geoip)
-
-(defun octet-to-int (seq &key (big-endian t))
- (reduce (lambda (acc n)
- (+ (ash acc 8) n))
- (if big-endian
- seq (reverse seq))
- :initial-value 0))
-(5am:test t-ints
- (5am:is (= (octet-to-int '(1 5) :big-endian t) #x105))
- (5am:is (= (octet-to-int '(1 5) :big-endian nil) #x501)))
+(in-package :geoip)
(defun parse-ipv4 (ip-address)
(reduce (lambda (acc n)
@@ -38,15 +25,11 @@
(cons 4 (parse-ipv4 ip-address))
(cons 6 (parse-ipv6 ip-address))))
-(5am:test ipv4
- (5am:is (= (parse-ipv4 "8.8.8.8") 134744072))
- (5am:is (= (parse-ipv6 "::1") 1)))
-
(alexandria:define-constant
+metadata-marker+
- (concatenate 'vector
- #(#xab #xcd #xef)
- (map 'vector #'char-code "MaxMind.com"))
+ (make-array 14 :element-type '(unsigned-byte 8)
+ :initial-contents
+ (list* #xab #xcd #xef (map 'list #'char-code "MaxMind.com")))
:test #'equalp)
(defstruct maxmind-database
@@ -93,15 +76,15 @@
:record-size (get-val data :record-size)))
(defun metadata-marker-p (ptr offset)
- (loop for i below #.(length *metadata-marker*)
+ (loop for i below #.(length +metadata-marker+)
always (eql (mem-ref ptr :uchar (+ i offset))
- (svref *metadata-marker* i))))
+ (aref +metadata-marker+ i))))
(defun find-metadata-start (ptr size)
- (loop for offset from (- size 1 #.(length *metadata-marker*))
+ (loop for offset from (- size 1 #.(length +metadata-marker+))
downto (- size 1 (* 128 1024))
when (metadata-marker-p ptr offset)
- return (+ offset #.(length *metadata-marker*))))
+ return (+ offset #.(length +metadata-marker+))))
(defun read-db-char (reader)
(with-slots (db-ptr) reader
@@ -139,15 +122,6 @@
(- uval #.(expt 2 32))
uval)))
-(5am:test reader
- (with-foreign-array (a #(0 0 1 23 126 195 159 195 156) '(:array :uint8 9))
- (let ((r (make-db-reader :db-ptr a)))
- (5am:is (= 279 (mread-unsigned r 4)))
- (5am:is (equal "~ßÜ" (mread-uft8 r 5))))))
-
-(5am:run-all-tests)
-
-
(defun mread-datafield-metadata (db-ptr)
(let* ((control-byte (read-db-char db-ptr))
(type (ldb (byte 3 5) control-byte))
@@ -226,10 +200,9 @@
(defun record-value (mmdb ip-bits)
(with-slots (node-count) mmdb
- (loop with node = 0
+ (loop for start = 0 then node
for bit in ip-bits
- for next-node = (read-node-record mmdb node bit)
- do (setf node next-node)
+ for node = (read-node-record mmdb start bit)
when (= node node-count)
return nil
when (> node node-count)
@@ -272,15 +245,3 @@
(with-slots (ptr fd size) mmdb
(mmap:munmap ptr fd size)))
-(defvar *mmdb* (make-mmdb "GeoLite2-Country.mmdb"))
-
-(with-slots (metadata) *mmdb*
- (with-slots (build-epoch) metadata
- (local-time:unix-to-timestamp
- build-epoch)))
-
-(lookup-ip *mmdb* (integer-to-bits (parse-ipv4 "28.8.8.8") 128))
-(lookup-ip *mmdb* (integer-to-bits (parse-ipv4 "89.244.127.3") 128))
-(lookup-ip *mmdb* (integer-to-bits (parse-ipv6 "2001:9e8:3d0f:2600:f081:c212:46c9:7cef") 128))
-
-
diff --git a/geoip/tests.lisp b/geoip/tests.lisp
new file mode 100644
index 0000000..3aeebf7
--- /dev/null
+++ b/geoip/tests.lisp
@@ -0,0 +1,14 @@
+(defpackage geoip/tests
+ (:use :cl :cffi :fiveam :alexandria :geoip))
+(in-package :geoip/tests)
+
+(test ipv4
+ (is (= (geoip::parse-ipv4 "8.8.8.8") 134744072))
+ (is (= (geoip::parse-ipv6 "::1") 1)))
+
+(test reader
+ (with-foreign-array (a #(0 0 1 23 126 195 159 195 156) '(:array :uint8 9))
+ (let ((r (geoip::make-db-reader :db-ptr a)))
+ (is (= 279 (geoip::mread-unsigned r 4)))
+ (is (equal "~ßÜ" (geoip::mread-uft8 r 5))))))
+