-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathris-client.go
144 lines (126 loc) · 3.41 KB
/
ris-client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// RIS Client for https://ris-live.ripe.net/manual/
// based on:
// https://github.com/gorilla/websocket/blob/master/examples/echo/client.go
// +build ignore
package main
import (
"flag"
"log"
"net/url"
"os"
"os/signal"
"time"
"github.com/gorilla/websocket"
"encoding/json"
"github.com/davecgh/go-spew/spew"
"fmt"
)
type ris_message struct {
Type string `json:"type"`
Data struct {
Timestamp float64 `json:"timestamp"`
Peer string `json:"peer"`
PeerAsn string `json:"peer_asn"`
ID string `json:"id"`
Host string `json:"host"`
Type string `json:"type"`
Path []int `json:"path"`
Community [][]int `json:"community"`
Origin string `json:"origin"`
Announcements []struct {
NextHop string `json:"next_hop"`
Prefixes []string `json:"prefixes"`
} `json:"announcements"`
} `json:"data"`
}
var addr = flag.String("addr", "ris-live.ripe.net", "http service address")
func main() {
flag.Parse()
log.SetFlags(0)
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
u := url.URL{Scheme: "wss", Host: *addr, Path: "/v1/ws/"}
log.Printf("connecting to %s", u.String())
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
// Tell the server what we want
// See list of hosts at:
// https://www.ripe.net/analyse/internet-measurements/routing-information-service-ris/ris-raw-data
// c.WriteMessage(1, []byte(`{"type": "ris_subscribe", "data": {"host": "rrc00"}}`) )
c.WriteMessage(1, []byte(`{"type": "ris_subscribe", "data": {"host": "rrc00", "type": "UPDATE"}}`) )
done := make(chan struct{})
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
// log.Printf("recv: %s", message)
process_message(message)
}
}()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
return
case t := <-ticker.C:
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
if err != nil {
log.Println("write:", err)
return
}
case <-interrupt:
log.Println("interrupt")
// Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection.
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("write close:", err)
return
}
select {
case <-done:
case <-time.After(time.Second):
}
return
}
}
}
func process_message (message []byte) (bool) {
// log.Printf("recv: %s", message)
var rismessage ris_message
if err := json.Unmarshal(message, &rismessage); err != nil {
return false
}
if rismessage.Type != `ris_message` {
// fmt.Println(rismessage.Type)
return false
}
// log.Printf("recv: %s", message)
// spew.Dump(rismessage)
fmt.Printf("Host: %s\n", rismessage.Data.Host)
var asn int
if len(rismessage.Data.Path) > 0 {
asn = rismessage.Data.Path[len(rismessage.Data.Path)-1]
} else {
asn = -1
spew.Dump(rismessage)
}
fmt.Printf("ASN: %d\n", asn)
for _, announcement := range rismessage.Data.Announcements {
// fmt.Printf("Prefix: %s\n", prefix)
// spew.Dump(announcement)
for _, prefix := range announcement.Prefixes {
fmt.Printf("Prefix: %s\n", prefix)
}
}
fmt.Println("---")
return true
}