Skip to content

Commit dcd4058

Browse files
committed
FEAT: including WHOIS protocol
Usage example: ``` read whois://seznam.cz ;<- will do recursive lookup write whois://whois.nic.cz "seznam.cz" ;<- query a given whois server directly ```
1 parent 2433000 commit dcd4058

File tree

3 files changed

+183
-0
lines changed

3 files changed

+183
-0
lines changed

src/mezz/boot-files.r

+1
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ REBOL [
6363
[
6464
%prot-http.r
6565
%prot-tls.r
66+
%prot-whois.r
6667
]

src/mezz/prot-whois.r

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
Rebol [
2+
title: "WHOIS Protocol"
3+
author: "Oldes"
4+
version: 0.0.1
5+
file: %prot-whois.r
6+
date: 30-Apr-2019
7+
purpose: {
8+
Low level WHOIS protocol implementation, which may be used to write
9+
more advanced WHOIS command}
10+
links: [
11+
https://www.iana.org/domains/root/db
12+
https://github.com/rfc1036/whois
13+
https://simonecarletti.com/blog/2012/03/whois-protocol/
14+
]
15+
usage: [
16+
;- version 1:
17+
read whois://seznam.cz ;<- will do recursive lookup
18+
;- version 2:
19+
write whois://whois.nic.cz "seznam.cz"
20+
]
21+
]
22+
23+
append system/options/log [whois: 1]
24+
sys/make-scheme [
25+
name: 'whois
26+
title: "WHOIS Protocol"
27+
spec: make system/standard/port-spec-net [port-id: 43 timeout: 15 ]
28+
awake: func [event /local port parent] [
29+
sys/log/debug 'WHOIS ["Awake:^[[22m" event/type]
30+
port: event/port
31+
parent: port/locals
32+
switch event/type [
33+
lookup [ open port ]
34+
connect [
35+
parent/state/state: 'ready
36+
either parent/data [
37+
write port parent/data
38+
][ return true ]
39+
]
40+
read [ read port ]
41+
wrote [ parent/state/state: 'reading read port ]
42+
close [
43+
parent/state/state: none
44+
parent/data: none
45+
close port
46+
return true
47+
]
48+
error [
49+
parent/state/state: make error! [
50+
type: 'Access
51+
id: 'Protocol
52+
arg1: to integer! event/offset/x ;@@ needs revire once EVENT will be fixed
53+
]
54+
]
55+
]
56+
false
57+
]
58+
actor: [
59+
open: func [
60+
port [port!]
61+
/local conn
62+
] [
63+
if all [
64+
port/state
65+
conn: port/state/connection
66+
][
67+
case [
68+
none? port/state/state [ open conn ]
69+
all [port/state/state = 'ready port/data][
70+
write conn port/data
71+
]
72+
]
73+
return port
74+
]
75+
76+
if none? port/spec/host [ port/spec/host: "whois.iana.org" ]
77+
78+
port/state: context [
79+
state: 'inited
80+
connection:
81+
awake: :port/awake
82+
close?: false
83+
]
84+
port/state/connection: conn: make port! [
85+
scheme: 'tcp
86+
host: port/spec/host
87+
port-id: port/spec/port-id
88+
ref: rejoin [tcp:// host #":" port-id]
89+
]
90+
conn/locals: port
91+
conn/awake: :awake
92+
open conn
93+
port
94+
]
95+
96+
open?: func [port [port!]][
97+
not none? all [
98+
port/state
99+
open? port/state/connection
100+
]
101+
]
102+
103+
close: func [ port [port!]] [
104+
if open? port [
105+
close port/state/connection
106+
port/state: none
107+
]
108+
]
109+
110+
write: func [
111+
port [port!]
112+
target [string! tuple!]
113+
/local conn
114+
][
115+
port/spec/path: target
116+
if tuple? target [
117+
target: join
118+
any [
119+
select [
120+
"whois.ripe.net" "-V Md5.2 "
121+
"whois.iana.org" ""
122+
] port/spec/host
123+
"n + "
124+
]
125+
target
126+
]
127+
sys/log/info 'WHOIS ["Query:^[[22m" target "^[[1mfrom:^[[22m" port/spec/host]
128+
port/data: join target CRLF
129+
open port
130+
conn: port/state/connection
131+
either port? wait [conn port/spec/timeout][
132+
port/actor/on-result port
133+
][
134+
do make error! [type: 'Access id: 'Timeout arg1: port/spec/ref]
135+
]
136+
]
137+
138+
read: func [
139+
port [port!]
140+
/local target
141+
][
142+
target: port/spec/host
143+
try [target: to tuple! target]
144+
port/spec/host: "whois.iana.org"
145+
port/actor/write port target
146+
]
147+
148+
on-result: func[
149+
port [port!]
150+
/local result refer
151+
][
152+
result: port/state/connection/data
153+
if result [
154+
try [ result: to string! result ]
155+
sys/log/info 'WHOIS ajoin ["Result:^/^[[22m" result]
156+
if all [
157+
parse result [
158+
[
159+
thru "^/whois: " |
160+
thru "^/ Registrar WHOIS Server: "
161+
] copy refer to LF to end
162+
]
163+
find port/spec/path #"." ;- follow only if request is TLD
164+
port/spec/host <> refer: trim/all refer
165+
][
166+
close port/state/connection
167+
port/state: none
168+
port/spec/host: refer
169+
return port/actor/write port port/spec/path
170+
]
171+
]
172+
result
173+
]
174+
]
175+
]

src/tests/units/port-test.r3

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ Rebol [
5959

6060
===end-group===
6161

62+
===start-group=== "WHOIS scheme"
63+
--test-- "read WHOIS"
64+
--assert string? try [read whois://google.com]
65+
--test-- "write WHOIS"
66+
--assert string? try [write whois://whois.nic.cz "seznam.cz"]
67+
===end-group===
68+
6269
if "true" <> get-env "CONTINUOUS_INTEGRATION" [
6370
===start-group=== "console port"
6471
--test-- "query input port"

0 commit comments

Comments
 (0)