// Package ristypes defines the data structures for RIS Live BGP messages and announcements. package ristypes import ( "encoding/json" "time" ) // ASPath represents a BGP AS path as a slice of AS numbers. // It handles JSON unmarshaling of both simple arrays and nested AS sets, // flattening any nested structures into a single sequence of AS numbers. type ASPath []int // UnmarshalJSON implements the json.Unmarshaler interface for ASPath. // It handles both simple integer arrays [1, 2, 3] and nested AS sets // like [1, [2, 3], 4], flattening them into a single slice of integers. func (p *ASPath) UnmarshalJSON(data []byte) error { // First try to unmarshal as a simple array of integers var simple []int if err := json.Unmarshal(data, &simple); err == nil { *p = ASPath(simple) return nil } // If that fails, unmarshal as array of interfaces and flatten var raw []interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } // Flatten the array result := make([]int, 0) for _, item := range raw { switch v := item.(type) { case float64: result = append(result, int(v)) case []interface{}: // Nested array - flatten it for _, nested := range v { if num, ok := nested.(float64); ok { result = append(result, int(num)) } } } } *p = ASPath(result) return nil } // RISLiveMessage represents the outer wrapper message from the RIPE RIS Live stream. // Each message contains a Type field indicating the message type and a Data field // containing the actual BGP message payload. type RISLiveMessage struct { Type string `json:"type"` Data RISMessage `json:"data"` } // RISMessage represents a BGP update message from the RIPE RIS Live stream. // It contains metadata about the BGP session (peer, ASN, host) along with // the actual BGP update data including AS path, communities, announcements, // and withdrawals. type RISMessage struct { Type string `json:"type"` Timestamp float64 `json:"timestamp"` ParsedTimestamp time.Time `json:"-"` // Parsed from Timestamp field Peer string `json:"peer"` PeerASN string `json:"peer_asn"` ID string `json:"id"` Host string `json:"host"` RRC string `json:"rrc,omitempty"` MrtTime float64 `json:"mrt_time,omitempty"` SocketTime float64 `json:"socket_time,omitempty"` Path ASPath `json:"path,omitempty"` Community [][]int `json:"community,omitempty"` Origin string `json:"origin,omitempty"` MED *int `json:"med,omitempty"` LocalPref *int `json:"local_pref,omitempty"` Announcements []RISAnnouncement `json:"announcements,omitempty"` Withdrawals []string `json:"withdrawals,omitempty"` Raw string `json:"raw,omitempty"` } // RISAnnouncement represents a BGP route announcement within a RIS message. // It contains the next hop IP address and the list of prefixes being announced // via that next hop. type RISAnnouncement struct { NextHop string `json:"next_hop"` Prefixes []string `json:"prefixes"` }