<commit_before>;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Indent-tabs-mode: NIL -*-
;;;
;;; address.lisp --- IP address classes.
;;;
;;; Copyright (C) 2006-2007, <NAME>  <<EMAIL>>
;;;
;;; This code is free software; you can redistribute it and/or
;;; modify it under the terms of the version 2.1 of
;;; the GNU Lesser General Public License as published by
;;; the Free Software Foundation, as clarified by the
;;; preamble found here:
;;;     http://opensource.franz.com/preamble.html
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General
;;; Public License along with this library; if not, write to the
;;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
;;; Boston, MA 02110-1301, USA

(in-package :net.sockets)

;;;; Class Definitions

(defclass address ()
  ((name :initarg :name :reader address-name :type vector))
  (:documentation "Base class for all socket address classes."))

(defclass inet-address (address) ()
  (:documentation "Base class for IPv4 and IPv6 addresses."))

(defclass ipv4-address (inet-address) ()
  (:documentation "IPv4 address.  Its low-level representation
can be accessed as vector of type IPV4-ARRAY through the
ADDRESS-NAME reader."))

(defclass ipv6-address (inet-address) ()
  (:documentation "IPv6 address.  Its low-level representation
can be accessed as vector of type IPV6-ARRAY through the
ADDRESS-NAME reader."))

(defclass local-address (address)
  ((abstract :initform nil :initarg :abstract
             :reader abstract-address-p :type boolean))
  (:documentation "UNIX socket address."))

;;;; Conversion functions

(defun integer-to-dotted (integer)
  "Convert a 32-bit unsigned integer to a dotted string."
  (check-type integer ub32)
  (format nil "~A.~A.~A.~A"
          (ldb (byte 8 24) integer)
          (ldb (byte 8 16) integer)
          (ldb (byte 8 8) integer)
          (ldb (byte 8 0) integer)))

(defun dotted-to-vector (address)
  "Convert a dotted IPv4 address to a (simple-array (unsigned-byte 8) 4)."
  (check-type address string)
  (let ((addr (make-array 4 :element-type 'ub8 :initial-element 0))
        (split (split-sequence #\. address :count 5)))
    (flet ((set-array-value (index str)
             (setf (aref addr index)
                   (or (parse-number-or-nil str :ub8)
                       (error 'parse-error)))))
      (let ((len (length split)))
        (unless (<= 1 len 4)
          (error 'parse-error))
        (set-array-value 3 (nth (1- len) split))
        (loop :for n :in split
              :for index :below (1- len)
              :do (set-array-value index n))))
    (values addr)))

(defun dotted-to-integer (address)
  "Convert a dotted IPv4 address to a 32-bit unsigned integer."
  (vector-to-integer (dotted-to-vector address)))

(defun vector-to-dotted (vector)
  "Convert an 4-element vector to a dotted string."
  (coercef vector 'ipv4-array)
  (let ((*print-pretty* nil))
    (with-output-to-string (s)
      (princ (aref vector 0) s) (princ #\. s)
      (princ (aref vector 1) s) (princ #\. s)
      (princ (aref vector 2) s) (princ #\. s)
      (princ (aref vector 3) s))))

#+windows
(defun %ipv6-string-to-vector (string)
  (with-foreign-object (in6-sockaddr 'sockaddr-in6)
    (bzero in6-sockaddr size-of-sockaddr-in6)
    (with-foreign-object (length :int)
      (setf (mem-ref length :int) size-of-sockaddr-in6)
      (handler-case
          (wsa-string-to-address string af-inet6 (null-pointer) in6-sockaddr
                                 length)
        (socket-error () (error 'parse-error)))
      (in6-addr-to-ipv6-array
       (foreign-slot-value in6-sockaddr 'sockaddr-in6 'addr)))))

#+windows
(handler-case (%ipv6-string-to-vector "::")
  (parse-error () (pushnew 'ipv6-disabled *features*)))

#-windows
(defun %ipv6-string-to-vector (string)
  (with-foreign-object (in6-addr :uint16 8)
    (bzero in6-addr 16)
    (handler-case (inet-pton af-inet6 string-pointer in6-addr)
      (posix-error () (error 'parse-error)))
    (in6-addr-to-ipv6-array in6-addr)))

(defun colon-separated-to-vector (string)
  "Convert a colon-separated IPv6 address to
a (simple-array (unsigned-byte 16) 8)."
  (check-type string string)
  (%ipv6-string-to-vector string))

(defun ipv4-on-ipv6-mapped-vector-p (vector)
  (and (dotimes (i 5 t)
         (when (plusp (aref vector i))
           (return nil)))<commit_msg>Fix minor breakage on non-windows.<commit_after>;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Indent-tabs-mode: NIL -*-
;;;
;;; address.lisp --- IP address classes.
;;;
;;; Copyright (C) 2006-2007, <NAME>  <<EMAIL>>
;;;
;;; This code is free software; you can redistribute it and/or
;;; modify it under the terms of the version 2.1 of
;;; the GNU Lesser General Public License as published by
;;; the Free Software Foundation, as clarified by the
;;; preamble found here:
;;;     http://opensource.franz.com/preamble.html
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General
;;; Public License along with this library; if not, write to the
;;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
;;; Boston, MA 02110-1301, USA

(in-package :net.sockets)

;;;; Class Definitions

(defclass address ()
  ((name :initarg :name :reader address-name :type vector))
  (:documentation "Base class for all socket address classes."))

(defclass inet-address (address) ()
  (:documentation "Base class for IPv4 and IPv6 addresses."))

(defclass ipv4-address (inet-address) ()
  (:documentation "IPv4 address.  Its low-level representation
can be accessed as vector of type IPV4-ARRAY through the
ADDRESS-NAME reader."))

(defclass ipv6-address (inet-address) ()
  (:documentation "IPv6 address.  Its low-level representation
can be accessed as vector of type IPV6-ARRAY through the
ADDRESS-NAME reader."))

(defclass local-address (address)
  ((abstract :initform nil :initarg :abstract
             :reader abstract-address-p :type boolean))
  (:documentation "UNIX socket address."))

;;;; Conversion functions

(defun integer-to-dotted (integer)
  "Convert a 32-bit unsigned integer to a dotted string."
  (check-type integer ub32)
  (format nil "~A.~A.~A.~A"
          (ldb (byte 8 24) integer)
          (ldb (byte 8 16) integer)
          (ldb (byte 8 8) integer)
          (ldb (byte 8 0) integer)))

(defun dotted-to-vector (address)
  "Convert a dotted IPv4 address to a (simple-array (unsigned-byte 8) 4)."
  (check-type address string)
  (let ((addr (make-array 4 :element-type 'ub8 :initial-element 0))
        (split (split-sequence #\. address :count 5)))
    (flet ((set-array-value (index str)
             (setf (aref addr index)
                   (or (parse-number-or-nil str :ub8)
                       (error 'parse-error)))))
      (let ((len (length split)))
        (unless (<= 1 len 4)
          (error 'parse-error))
        (set-array-value 3 (nth (1- len) split))
        (loop :for n :in split
              :for index :below (1- len)
              :do (set-array-value index n))))
    (values addr)))

(defun dotted-to-integer (address)
  "Convert a dotted IPv4 address to a 32-bit unsigned integer."
  (vector-to-integer (dotted-to-vector address)))

(defun vector-to-dotted (vector)
  "Convert an 4-element vector to a dotted string."
  (coercef vector 'ipv4-array)
  (let ((*print-pretty* nil))
    (with-output-to-string (s)
      (princ (aref vector 0) s) (princ #\. s)
      (princ (aref vector 1) s) (princ #\. s)
      (princ (aref vector 2) s) (princ #\. s)
      (princ (aref vector 3) s))))

#+windows
(defun %ipv6-string-to-vector (string)
  (with-foreign-object (in6-sockaddr 'sockaddr-in6)
    (bzero in6-sockaddr size-of-sockaddr-in6)
    (with-foreign-object (length :int)
      (setf (mem-ref length :int) size-of-sockaddr-in6)
      (handler-case
          (wsa-string-to-address string af-inet6 (null-pointer) in6-sockaddr
                                 length)
        (socket-error () (error 'parse-error)))
      (in6-addr-to-ipv6-array
       (foreign-slot-value in6-sockaddr 'sockaddr-in6 'addr)))))

#+windows
(handler-case (%ipv6-string-to-vector "::")
  (parse-error () (pushnew 'ipv6-disabled *features*)))

#-windows
(defun %ipv6-string-to-vector (string)
  (with-foreign-object (in6-addr :uint16 8)
    (bzero in6-addr 16)
    (handler-case (inet-pton af-inet6 string in6-addr)
      (posix-error () (error 'parse-error)))
    (in6-addr-to-ipv6-array in6-addr)))

(defun colon-separated-to-vector (string)
  "Convert a colon-separated IPv6 address to
a (simple-array (unsigned-byte 16) 8)."
  (check-type string string)
  (%ipv6-string-to-vector string))

(defun ipv4-on-ipv6-mapped-vector-p (vector)
  (and (dotimes (i 5 t)
         (when (plusp (aref vector i))
           (return nil)))
{'fraction_non_alphanumeric': 0.1418970189701897, 'fraction_numerical': 0.02168021680216802, 'mean_word_length': 3.075088339222615, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7619048', 'n_tokens_mistral': 3178, 'n_tokens_neox': 2985, 'n_words': 987}