blob: 2fe133feb3c0c1816aa9ecf65f61be1e9e6e9dd2 [file] [log] [blame]
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +02001package model
2
3import (
4 "context"
5 "fmt"
6 "net"
7 "strconv"
8)
9
10func (m *sqlModel) GetCheckablePeers(ctx context.Context) ([]*Peer, error) {
11
12 data := []struct {
13 sqlPeer `db:"peers"`
14 sqlPeerRouter `db:"peer_routers"`
15 }{}
16 q := `
17 SELECT
18 peers.id "peers.id",
19 peers.asn "peers.asn",
20 peers.name "peers.name",
21
22 peer_routers.peer_id "peer_routers.peer_id",
23 peer_routers.v6 "peer_routers.v6",
24 peer_routers.v4 "peer_routers.v4"
25 FROM peers
26 LEFT JOIN peer_routers
27 ON peer_routers.peer_id = peers.id
28 `
29 if err := m.db.SelectContext(ctx, &data, q); err != nil {
30 return nil, fmt.Errorf("SELECT peers/peerRouters: %v", err)
31 }
32
33 // Collapse peers into map
34 // ID -> Peer
35 peers := make(map[string]*Peer)
36
37 for _, row := range data {
38 peer, ok := peers[row.sqlPeer.ID]
39 if !ok {
40 asn, err := strconv.ParseInt(row.sqlPeer.ASN, 10, 64)
41 if err != nil {
42 return nil, fmt.Errorf("data corruption: invalid ASN %q", row.sqlPeer.ASN)
43 }
44 peer = &Peer{
45 ASN: asn,
46 Name: row.sqlPeer.Name,
47 Routers: []*Router{},
48 }
49 peers[row.sqlPeer.ID] = peer
50 }
51
52 var v6 net.IP
53 var v4 net.IP
54
55 if row.sqlPeerRouter.V6.Valid {
56 v6 = net.ParseIP(row.sqlPeerRouter.V6.String)
57 }
58 if row.sqlPeerRouter.V4.Valid {
59 v4 = net.ParseIP(row.sqlPeerRouter.V4.String)
60 }
61
62 peer.Routers = append(peer.Routers, &Router{
63 V6: v6,
64 V4: v4,
65 })
66 }
67
68 res := make([]*Peer, len(peers))
69 i := 0
70 for _, peer := range peers {
71 res[i] = peer
72 i += 1
73 }
74
75 return res, nil
76}