From d3ea37a5d493c6e3a086dd6ded3fd3e11689e302 Mon Sep 17 00:00:00 2001 From: Anton Maminov Date: Fri, 4 Oct 2024 12:48:59 +0300 Subject: [PATCH] Add Socket::Address.from without addrlen --- spec/std/socket/address_spec.cr | 3 +++ src/socket/address.cr | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/spec/std/socket/address_spec.cr b/spec/std/socket/address_spec.cr index d2e4768db987..08508940bc7d 100644 --- a/spec/std/socket/address_spec.cr +++ b/spec/std/socket/address_spec.cr @@ -51,6 +51,7 @@ describe Socket::IPAddress do addr2.port.should eq(addr1.port) typeof(addr2.address).should eq(String) addr2.address.should eq(addr1.address) + addr2.should eq(Socket::IPAddress.from(addr1_c)) end it "transforms an IPv6 address into a C struct and back" do @@ -64,6 +65,7 @@ describe Socket::IPAddress do addr2.port.should eq(addr1.port) typeof(addr2.address).should eq(String) addr2.address.should eq(addr1.address) + addr2.should eq(Socket::IPAddress.from(addr1_c)) end it "won't resolve domains" do @@ -431,6 +433,7 @@ end addr2.family.should eq(addr1.family) addr2.path.should eq(addr1.path) addr2.to_s.should eq(path) + addr2 = Socket::UNIXAddress.from(addr1.to_unsafe) end it "raises when path is too long" do diff --git a/src/socket/address.cr b/src/socket/address.cr index 20fca43544e6..bac36088152f 100644 --- a/src/socket/address.cr +++ b/src/socket/address.cr @@ -21,6 +21,26 @@ class Socket end end + # :ditto: + def self.from(sockaddr : LibC::Sockaddr*) : Address + case family = Family.new(sockaddr.value.sa_family) + when Family::INET6 + sockaddr = sockaddr.as(LibC::SockaddrIn6*) + + IPAddress.new(sockaddr, sizeof(typeof(sockaddr))) + when Family::INET + sockaddr = sockaddr.as(LibC::SockaddrIn*) + + IPAddress.new(sockaddr, sizeof(typeof(sockaddr))) + when Family::UNIX + sockaddr = sockaddr.as(LibC::SockaddrUn*) + + UNIXAddress.new(sockaddr, sizeof(typeof(sockaddr))) + else + raise "Unsupported family type: #{family} (#{family.value})" + end + end + # Parses a `Socket::Address` from an URI. # # Supported formats: @@ -113,6 +133,22 @@ class Socket end end + # :ditto: + def self.from(sockaddr : LibC::Sockaddr*) : IPAddress + case family = Family.new(sockaddr.value.sa_family) + when Family::INET6 + sockaddr = sockaddr.as(LibC::SockaddrIn6*) + + new(sockaddr, sizeof(typeof(sockaddr))) + when Family::INET + sockaddr = sockaddr.as(LibC::SockaddrIn*) + + new(sockaddr, sizeof(typeof(sockaddr))) + else + raise "Unsupported family type: #{family} (#{family.value})" + end + end + # Parses a `Socket::IPAddress` from an URI. # # It expects the URI to include `://:` where `scheme` as @@ -750,6 +786,17 @@ class Socket {% end %} end + # :ditto: + def self.from(sockaddr : LibC::Sockaddr*) : UNIXAddress + {% if flag?(:wasm32) %} + raise NotImplementedError.new "Socket::UNIXAddress.from" + {% else %} + sockaddr = sockaddr.as(LibC::SockaddrUn*) + + new(sockaddr, sizeof(typeof(sockaddr))) + {% end %} + end + # Parses a `Socket::UNIXAddress` from an URI. # # It expects the URI to include `://` where `scheme` as well