class Socket::AncillaryData

要約

BasicSocket#sendmsgBasicSocket#recvmsg で用いる ancillary data (補助データ、制御情報) を表すクラスです。

Socket::AncillaryData#family(socket family), Socket::AncillaryData#level(cmsg level), Socket::AncillaryData#type(cmsg type), Socket::AncillaryData#data(cmsg data), といった要素を持ちます。

目次

特異メソッド
インスタンスメソッド

特異メソッド

int(family, cmsg_level, cmsg_type, integer) -> Socket::AncillaryData[permalink][rdoc]

データとして整数を保持する Socket::AncillaryData オブジェクトを生成します。

整数データのサイズおよびエンディアンは実行するホストによって異なります。

require 'socket'

p Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, STDERR.fileno)
#=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 2>
[PARAM] family:
ソケットファミリー
[PARAM] cmsg_level:
プロトコル
[PARAM] cmsg_type:
補助データの種類
[PARAM] integer:
データ内容

[SEE_ALSO] Socket::AncillaryData.new

ip_pktinfo(addr, ifindex, spec_dst=addr) -> Socket::AncillaryData[permalink][rdoc]

type が IP_PKTINFO である AncillaryData を生成します。

IP_PKTINFO は非標準的拡張であり、システムによっては使えない場合があります。

require 'socket'

addr = Addrinfo.ip("127.0.0.1")
ifindex = 0
spec_dst = Addrinfo.ip("127.0.0.1")
p Socket::AncillaryData.ip_pktinfo(addr, ifindex, spec_dst)
#=> #<Socket::AncillaryData: INET IP PKTINFO 127.0.0.1 ifindex:0 spec_dst:127.0.0.1>
[PARAM] addr:
アドレス(文字列もしくは Addrinfo)
[PARAM] ifindex:
インターフェースのインデックス(整数)
[PARAM] spec_dst:
パケットのローカルアドレス(文字列もしくは Addrinfo)

[SEE_ALSO] Socket::AncillaryData#ip_pktinfo, Socket::Constants::IP_PKTINFO

ipv6_pktinfo(addr, ifindex) -> Socket::AncillaryData[permalink][rdoc]

type が IPV6_PKTINFO である AncillaryData を生成します。

IPV6_PKTINFO は [RFC3542] で定義されています。

require 'socket'

addr = Addrinfo.ip("::1")
ifindex = 0
p Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
#=> #<Socket::AncillaryData: INET6 IPV6 PKTINFO ::1 ifindex:0>
[PARAM] addr:
アドレス(文字列もしくは Addrinfo)
[PARAM] ifindex:
インターフェースのインデックス(整数)

[SEE_ALSO] Socket::AncillaryData#ipv6_pktinfo, Socket::Constants::IPV6_PKTINFO

new(family, cmsg_level, cmsg_type, cmsg_data) -> Socket::AncillaryData[permalink][rdoc]

新たな Socket::AncillaryData オブジェクトを生成します。

family はソケットファミリーを指定します。整数、文字列、シンボルを渡します。

  • Socket::AF_INET, "AF_INET", "INET", :AF_INET, :INET
  • Socket::AF_UNIX, "AF_UNIX", "UNIX", :AF_UNIX, :UNIX
  • など

cmsg_level にはメッセージの元となるプロトコルを指定します。整数、文字列、シンボルを渡します。

  • Socket::SOL_SOCKET, "SOL_SOCKET", "SOCKET", :SOL_SOCKET and :SOCKET
  • Socket::IPPROTO_IP, "IP" and :IP
  • Socket::IPPROTO_IPV6, "IPV6" and :IPV6
  • Socket::IPPROTO_TCP, "TCP" and :TCP
  • など

cmsg_type は補助データの種類を指定します。 cmsg_level で指定したプロトコルによってこの部分の解釈は異なります。整数、文字列、シンボルを渡します。

  • Socket::SCM_RIGHTS, "SCM_RIGHTS", "RIGHTS", :SCM_RIGHTS, :RIGHTS for SOL_SOCKET
  • Socket::IP_RECVTTL, "RECVTTL" and :RECVTTL for IPPROTO_IP
  • Socket::IPV6_PKTINFO, "PKTINFO" and :PKTINFO for IPPROTO_IPV6
  • など

cmsg_data には補助データの内容となる文字列を渡します

require 'socket'

p Socket::AncillaryData.new(:INET, :TCP, :NODELAY, "")
#=> #<Socket::AncillaryData: INET TCP NODELAY "">

p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "")
#=> #<Socket::AncillaryData: INET6 IPV6 PKTINFO "">
[PARAM] family:
ソケットファミリー
[PARAM] cmsg_level:
プロトコル
[PARAM] cmsg_type:
補助データの種類
[PARAM] cmsg_data:
データ内容
unix_rights(*ios) -> Socket::AncillaryData[permalink][rdoc]

ios で指定したファイルのファイルデスクリプタをデータとして持つ family=AF_UNIX, level=SOL_SOCKET, type=SCM_RIGHTS という Socket::AncillaryData オブジェクトを生成して返します。

require 'socket'

p Socket::AncillaryData.unix_rights(STDERR)
#=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 2>
[PARAM] ios:
IO オブジェクトの配列

[SEE_ALSO] Socket::AncillaryData#unix_rights, Socket::Constants::SCM_RIGHTS

インスタンスメソッド

cmsg_is?(level, type) -> bool[permalink][rdoc]

自身の level と type が引数のものと一致している場合に真を返します。

require 'socket'

ancdata = Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "")
ancdata.cmsg_is?(Socket::IPPROTO_IPV6, Socket::IPV6_PKTINFO) #=> true
ancdata.cmsg_is?(:IPV6, :PKTINFO)       #=> true
ancdata.cmsg_is?(:IP, :PKTINFO)         #=> false
ancdata.cmsg_is?(:SOCKET, :RIGHTS)      #=> false
[PARAM] level:
一致を確認する cmsg_level (文字列、シンボル、整数)
[PARAM] type:
一致を確認する cmsg_type (文字列、シンボル、整数)

[SEE_ALSO] Socket::AncillaryData#level, Socket::AncillaryData#type

data -> String[permalink][rdoc]

自身が保持している cmsg data (データ) を返します。

require 'socket'

p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").type
#=> ""

[SEE_ALSO] Socket::AncillaryData.new

family -> Integer[permalink][rdoc]

自身が保持している socket family を返します。

require 'socket'

p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").family
#=> 10

[SEE_ALSO] Socket::AncillaryData.new

int -> Integer[permalink][rdoc]

自身が保持している cmsg data (データ) を整数の形で返します。

整数データのサイズおよびエンディアンは実行するホストによって異なります。

require 'socket'

ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, STDERR.fileno)
p ancdata.int #=> 2
[EXCEPTION] TypeError:
cmgs data のサイズが int のバイト数と異なる場合に発生します

[SEE_ALSO] Socket::AncillaryData.new Socket::AncillaryData.int

ip_pktinfo -> [Addrinfo, Integer, Addrinfo][permalink][rdoc]

自身の type が IP_PKTINFO である場合、保持しているデータ (アドレス、インターフェースのインデックス、ローカルアドレス) を3要素の配列で返します。

IP_PKTINFO は非標準的拡張であり、システムによっては使えない場合があります。

require 'socket'

addr = Addrinfo.ip("127.0.0.1")
ifindex = 0
spec_dest = Addrinfo.ip("127.0.0.1")
ancdata = Socket::AncillaryData.ip_pktinfo(addr, ifindex, spec_dest)
p ancdata.ip_pktinfo
#=> [#<Addrinfo: 127.0.0.1>, 0, #<Addrinfo: 127.0.0.1>]
[EXCEPTION] TypeError:
level, type が IPPROTO_IP, IP_PKTINFO でない場合に発生します。

[SEE_ALSO] Socket::AncillaryData.ip_pktinfo, Socket::Constants::IP_PKTINFO

ipv6_pktinfo -> [Addrinfo, Integer][permalink][rdoc]

自身の type が IPV6_PKTINFO である場合、保持しているデータ (アドレス、インターフェースのインデックス) を2要素の配列で返します。

IPV6_PKTINFO については [RFC3542] を参照してください。

require 'socket'

addr = Addrinfo.ip("::1")
ifindex = 0
ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
p ancdata.ipv6_pktinfo #=> [#<Addrinfo: ::1>, 0]

[SEE_ALSO] Socket::AncillaryData.ipv6_pktinfo, Socket::AncillaryData#ipv6_pktinfo_addr, Socket::AncillaryData#ipv6_pktinfo_ifindex, Socket::Constants::IPV6_PKTINFO

ipv6_pktinfo_addr -> Addrinfo[permalink][rdoc]

自身の type が IPV6_PKTINFO である場合、保持しているデータ (アドレス、インターフェースのインデックス) のアドレスを返します。

require 'socket'

addr = Addrinfo.ip("::1")
ifindex = 0
ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
p ancdata.ipv6_pktinfo_addr #=> #<Addrinfo: ::1>

[SEE_ALSO] Socket::AncillaryData.ipv6_pktinfo, Socket::AncillaryData#ipv6_pktinfo, Socket::AncillaryData#ipv6_pktinfo_ifindex, Socket::Constants::IPV6_PKTINFO

ipv6_pktinfo_ifindex -> Integer[permalink][rdoc]

自身の type が IPV6_PKTINFO である場合、保持しているデータ (アドレス、インターフェースのインデックス) のインデックスを返します。

require 'socket'

addr = Addrinfo.ip("::1")
ifindex = 0
ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
p ancdata.ipv6_pktinfo_ifindex #=> 0

[SEE_ALSO] Socket::AncillaryData.ipv6_pktinfo, Socket::AncillaryData#ipv6_pktinfo, Socket::AncillaryData#ipv6_pktinfo_addr, Socket::Constants::IPV6_PKTINFO

level -> Integer[permalink][rdoc]

自身が保持している cmsg level (元プロトコル) を返します。

require 'socket'

p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").level
#=> 41

[SEE_ALSO] Socket::AncillaryData.new

timestamp -> Time[permalink][rdoc]

タイムスタンプ制御メッセージに含まれる時刻を Time オブジェクトで返します。

"タイムスタンプ制御メッセージ" は以下のいずれかです。

  • SOL_SOCKET/SCM_TIMESTAMP (micro second) GNU/Linux, FreeBSD, NetBSD, OpenBSD, Solaris, MacOS X
  • SOL_SOCKET/SCM_TIMESTAMPNS (nano second) GNU/Linux
  • SOL_SOCKET/SCM_BINTIME (2**(-64) second) FreeBSD
require 'socket'

Addrinfo.udp("127.0.0.1", 0).bind {|s1|
  Addrinfo.udp("127.0.0.1", 0).bind {|s2|
    s1.setsockopt(:SOCKET, :TIMESTAMP, true)
    s2.send "a", 0, s1.local_address
    ctl = s1.recvmsg.last
    p ctl
    #=> #<Socket::AncillaryData: INET SOCKET TIMESTAMP 2009-02-24 17:35:46.775581>
    t = ctl.timestamp
    p t      #=> 2009-02-24 17:35:46 +0900
    p t.usec #=> 775581
    p t.nsec #=> 775581000
  }
}

[SEE_ALSO] Socket::Constants::SCM_TIMESTAMP, Socket::Constants::SCM_TIMESTAMPNS, Socket::Constants::SCM_BINTIME, Socket::Constants::SO_TIMESTAMP, Socket::Constants::SO_TIMESTAMPNS, Socket::Constants::SO_BINTIME

type -> Integer[permalink][rdoc]

自身が保持している cmsg type (種類) を返します。

require 'socket'

p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").type
#=> 2

[SEE_ALSO] Socket::AncillaryData.new

unix_rights -> [IO] | nil[permalink][rdoc]

Unix domain socket の SCM_RIGHTS 制御メッセージに含まれるファイルディスクリプタを IO オブジェクトの配列として返します。

得られる IO オブジェクトか IOSocket です。

この配列は Socket::AncillaryData が初期化されたときに作られます。例えば BasicSocket#recvmsg を :scm_rights => true

オプションを付けて呼びだし、

SCM_RIGHTS な 制御メッセージを受け取ったときに配列が作られます。適切なオプションを指定しなかった場合は配列は生成されず、このメソッドは nil を返します。

require 'socket'

# recvmsg needs :scm_rights=>true for unix_rights
s1, s2 = UNIXSocket.pair
p s1                                         #=> #<UNIXSocket:fd 3>
s1.sendmsg "stdin and a socket", 0, nil, Socket::AncillaryData.unix_rights(STDIN, s1)
_, _, _, ctl = s2.recvmsg(:scm_rights=>true)
p ctl
#=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 6 7>
p ctl.unix_rights                            #=> [#<IO:fd 6>, #<Socket:fd 7>]
p File.identical?(STDIN, ctl.unix_rights[0]) #=> true
p File.identical?(s1, ctl.unix_rights[1])    #=> true

# If :scm_rights=>true is not given, unix_rights returns nil
s1, s2 = UNIXSocket.pair
s1.sendmsg "stdin and a socket", 0, nil, Socket::AncillaryData.unix_rights(STDIN, s1)
_, _, _, ctl = s2.recvmsg
p ctl #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 6 7>
p ctl.unix_rights #=> nil
[EXCEPTION] TypeError:
family/level/type が AF_UNIX/SOL_SOCKET/SCM_RIGHTS でない場合に発生します。

[SEE_ALSO] Socket::Constants::SCM_RIGHTS