Skip to content

Commit fcab3ef

Browse files
committed
ipn,rpn: Kids, Main fns return RpnServer
1 parent 88f158e commit fcab3ef

6 files changed

Lines changed: 119 additions & 39 deletions

File tree

intra/backend/ipn_proxies.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,10 @@ type RpnProxy interface {
257257
Purge(cc string) bool
258258
// Get returns proxy for country code, cc.
259259
Get(cc string) (Proxy, error)
260-
// Kids returns csv of forked proxy PIDs, excluding this one.
261-
Kids() (csvpids string)
260+
// Kids returns RpnServers describing all forked kids, excluding the main proxy.
261+
Kids() RpnServers
262+
// Main returns RpnServer describing the main proxy, if present.
263+
Main() *RpnServer
262264
}
263265

264266
// RpnAcc represents an account with RPN provider.

intra/ipn/proxies.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ type Rpn interface {
194194
x.Rpn
195195
rpnProxyProvider
196196
// addRpnProxy adds an RPN proxy to this multi-transport.
197-
addRpnProxy(acc RpnAcc, cc string) (Proxy, error)
197+
addRpnProxy(acc RpnAcc, cc string) (Proxy, *x.RpnServer, error)
198198
// removeRpnProxy removes an RPN proxy from this multi-transport.
199199
removeRpnProxy(acc RpnAcc, cc string) bool
200200
}
@@ -1322,7 +1322,7 @@ func (px *proxifier) RegisterWin(entitlementOrState []byte, did string, ops *x.R
13221322

13231323
// TODO: create a new proxy type for win, so Refresh() could be sent to /connect
13241324
// TODO: best location: github.com/Windscribe/browser-extension/blob/ed83749ad1/modules/ext/src/utils/getBestLocation.js
1325-
rp, err := px.addRpnProxy(win, anycc(win))
1325+
rp, _, err := px.addRpnProxy(win, anycc(win))
13261326
if err != nil || rp == nil {
13271327
log.E("proxy: ws: add wg for %s failed: %v", win.Who(), err)
13281328
return nil, core.JoinErr(err, errNotRpnProxy)

intra/ipn/proxy.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ func (pxr *proxifier) removeRpnProxy(acc RpnAcc, cc string) bool {
8787
}
8888

8989
// cc may be a fully qualified ID in case when re-adding the main proxy.
90-
func (pxr *proxifier) addRpnProxy(acc RpnAcc, cc string) (Proxy, error) {
90+
func (pxr *proxifier) addRpnProxy(acc RpnAcc, cc string) (Proxy, *x.RpnServer, error) {
9191
if acc == nil || core.IsNil(acc) {
92-
return nil, errNotRpnAcc
92+
return nil, nil, errNotRpnAcc
9393
}
9494

9595
typ := acc.ProviderID()
9696
if !isRPN(typ) {
97-
return nil, errNotRpnID
97+
return nil, nil, errNotRpnID
9898
}
9999

100100
if !acc.MultiCountry() && cc != noCountryForOldMen {
@@ -108,9 +108,9 @@ func (pxr *proxifier) addRpnProxy(acc RpnAcc, cc string) (Proxy, error) {
108108
// but we need cc to be "city;cc" (ref struct RpnServer.Key)
109109
cc, _ = strings.CutPrefix(cc, typ)
110110

111-
txt, err := acc.Conf(cc)
111+
txt, srv, err := acc.Conf(cc)
112112
if err != nil {
113-
return nil, err
113+
return nil, nil, err
114114
}
115115

116116
rpnid := typ + cc
@@ -119,10 +119,11 @@ func (pxr *proxifier) addRpnProxy(acc RpnAcc, cc string) (Proxy, error) {
119119
p, err := pxr.forceAddProxy(rpnid, txt)
120120
if p == nil {
121121
pxr.postAddRpnProxyError(acc) // remove from pxr.rp if exists
122-
return nil, core.JoinErr(err, errAddProxy)
122+
return nil, srv, core.JoinErr(err, errAddProxy)
123123
}
124124

125-
return pxr.postAddRpnProxy(p, acc)
125+
proxy, err := pxr.postAddRpnProxy(p, srv, acc)
126+
return proxy, srv, err
126127
}
127128

128129
// TODO: on add / update a via proxy; refresh all dependent origins
@@ -143,10 +144,10 @@ func (pxr *proxifier) addRpnProxy2(p Proxy, acc RpnAcc) (Proxy, error) {
143144
// TODO: setup hop from mainCountryCode to forked rpn proxies
144145
core.Gx(who, func() { pxr.refreshHopOriginsIfAny(p, who) })
145146

146-
return pxr.postAddRpnProxy(p, acc)
147+
return pxr.postAddRpnProxy(p, nil, acc)
147148
}
148149

149-
func (pxr *proxifier) postAddRpnProxy(p Proxy, acc RpnAcc) (_ Proxy, err error) {
150+
func (pxr *proxifier) postAddRpnProxy(p Proxy, srv *x.RpnServer, acc RpnAcc) (_ Proxy, err error) {
150151
proxyid := idstr(p)
151152
provider := acc.ProviderID()
152153

@@ -160,7 +161,7 @@ func (pxr *proxifier) postAddRpnProxy(p Proxy, acc RpnAcc) (_ Proxy, err error)
160161
// as forked children countries only need be added as plain-old proxies
161162
// which is done before calling this function (ie, a no-op)
162163
if rp == nil {
163-
rp, err = asRpnProxy(p, acc, pxr)
164+
rp, err = asRpnProxy(p, srv, acc, pxr)
164165
if rp == nil { // should not happen; unexpected!
165166
defer pxr.removeProxy(proxyid, true /*force*/)
166167
return nil, core.JoinErr(err, errAddProxyAsRpn)

intra/ipn/rpn.go

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package ipn
88

99
import (
10+
"encoding/json"
1011
"errors"
1112
"fmt"
1213
"strings"
@@ -32,7 +33,7 @@ type RpnAcc = rpn.RpnAcc
3233

3334
// and kick-off an update if the acc is expired?
3435
type rpnp struct {
35-
mu sync.RWMutex // protects Proxy & kids
36+
mu sync.RWMutex // protects p, s, kids, & skids
3637

3738
// parent proxy
3839
p Proxy
@@ -45,6 +46,10 @@ type rpnp struct {
4546

4647
// forked child proxy IDs, may be empty (returned proxy IDs may have stopped)
4748
kids map[string]struct{}
49+
// server metadata for each forked kid (keyed by CC)
50+
skids map[string]*x.RpnServer
51+
// server metadata for the main proxy
52+
s *x.RpnServer
4853
}
4954

5055
var _ RpnProxy = (*rpnp)(nil)
@@ -63,7 +68,7 @@ var (
6368
)
6469

6570
// nb: client code isn't really expecting error from asRpnProxy.
66-
func asRpnProxy(e Proxy, acc RpnAcc, pxr Rpn) (RpnProxy, error) {
71+
func asRpnProxy(e Proxy, srv *x.RpnServer, acc RpnAcc, pxr Rpn) (RpnProxy, error) {
6772
if e == nil || acc == nil || pxr == nil {
6873
return nil, errRpnBadArgs
6974
}
@@ -75,7 +80,7 @@ func asRpnProxy(e Proxy, acc RpnAcc, pxr Rpn) (RpnProxy, error) {
7580
return nil, errRpnIDsMismatch
7681
}
7782
log.D("proxy: rpn: make: %s[%s]", providerid, proxyid)
78-
return &rpnp{sync.RWMutex{}, e, acc, pxr, make(map[string]struct{}, 0)}, nil
83+
return &rpnp{sync.RWMutex{}, e, acc, pxr, make(map[string]struct{}, 0), make(map[string]*x.RpnServer, 0), srv}, nil
7984
}
8085

8186
func (r *rpnp) ensureProxy() Proxy {
@@ -324,7 +329,13 @@ func (r *rpnp) fork(cc string) (x.Proxy, error) {
324329
// re-forking main proxy (which may not be multi-country acc) via Update() => forkAll()
325330
log.I("proxy: rpn: fork: %s main cc %s; re-adding...", provider, cc)
326331
// expect Emplace to be called
327-
return r.pxr.addRpnProxy(acc, cc) // re-generates conf and re-adds
332+
kid, srv, err := r.pxr.addRpnProxy(acc, cc) // re-generates conf and re-adds
333+
if kid != nil && core.IsNotNil(kid) {
334+
r.mu.Lock()
335+
r.s = srv
336+
r.mu.Unlock()
337+
}
338+
return kid, err
328339
}
329340

330341
// check main's status if not forking main
@@ -344,11 +355,14 @@ func (r *rpnp) fork(cc string) (x.Proxy, error) {
344355
log.I("proxy: rpn: fork: %s[%s]", provider, cc)
345356

346357
// re-adds + updates if the proxy already exists
347-
kid, err := r.pxr.addRpnProxy(acc, cc)
358+
kid, srv, err := r.pxr.addRpnProxy(acc, cc)
348359

349360
if kid != nil && core.IsNotNil(kid) {
350361
r.mu.Lock()
351362
r.kids[cc] = struct{}{}
363+
if srv != nil {
364+
r.skids[cc] = srv
365+
}
352366
r.mu.Unlock()
353367
}
354368

@@ -476,6 +490,9 @@ func (r *rpnp) purgeMain() bool {
476490
if err != nil {
477491
return false
478492
}
493+
r.mu.Lock()
494+
r.s = nil
495+
r.mu.Unlock()
479496
return r.pxr.removeRpnProxy(r.RpnAcc, mainpid)
480497
}
481498

@@ -511,6 +528,7 @@ func (r *rpnp) purge(cc string) bool {
511528

512529
r.mu.Lock()
513530
delete(r.kids, cc)
531+
delete(r.skids, cc)
514532
r.mu.Unlock()
515533

516534
log.D("proxy: rpn: purge: %s[%s]? %t", provider, cc, rmv)
@@ -569,12 +587,16 @@ func (r *rpnp) get(cc string) (Proxy, error) {
569587
}
570588

571589
// Kids implements x.RpnProxy.
572-
func (r *rpnp) Kids() (csvpids string) {
573-
return r.kidsCsv()
574-
}
575-
576-
func (r *rpnp) kidsCsv() string {
577-
return strings.Join(r.flattenKids(), ",")
590+
func (r *rpnp) Kids() x.RpnServers {
591+
r.mu.RLock()
592+
all := make([]x.RpnServer, 0, len(r.skids))
593+
for _, s := range r.skids {
594+
if s != nil {
595+
all = append(all, *s)
596+
}
597+
}
598+
r.mu.RUnlock()
599+
return &liveServers{all: all}
578600
}
579601

580602
func (r *rpnp) flattenKids() (ccs []string) {
@@ -588,6 +610,46 @@ func (r *rpnp) flattenKids() (ccs []string) {
588610
return
589611
}
590612

613+
// liveServers implements x.RpnServers.
614+
type liveServers struct {
615+
all []x.RpnServer
616+
}
617+
618+
var _ x.RpnServers = (*liveServers)(nil)
619+
620+
func (s *liveServers) Get(i int) (*x.RpnServer, error) {
621+
if i < 0 || i >= len(s.all) {
622+
return nil, fmt.Errorf("rpn: live: %d out of range [0, %d)", i, len(s.all))
623+
}
624+
return &s.all[i], nil
625+
}
626+
627+
func (s *liveServers) Len() int {
628+
return len(s.all)
629+
}
630+
631+
func (s *liveServers) Json() ([]byte, error) {
632+
if s == nil || len(s.all) <= 0 {
633+
return nil, fmt.Errorf("rpn: live: no servers")
634+
}
635+
b, err := json.Marshal(s.all)
636+
if err != nil {
637+
return nil, fmt.Errorf("rpn: live: json: %w", err)
638+
}
639+
return b, nil
640+
}
641+
642+
// Main implements x.RpnProxy.
643+
func (r *rpnp) Main() (m *x.RpnServer) {
644+
r.mu.RLock()
645+
if s := r.s; s != nil {
646+
m = new(x.RpnServer)
647+
*m = *s
648+
}
649+
r.mu.RUnlock()
650+
return
651+
}
652+
591653
// Update implements RpnAcc.
592654
func (r *rpnp) Update(ops *x.RpnOps) (newState []byte, err error) {
593655
newState, err = r.RpnAcc.Update(ops)

intra/ipn/rpn/cfg.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type RpnAcc interface {
5555
x.RpnAcc
5656
ProviderID() string // x.RpnWg, x.RpnPro, x.RpnAmz, x.RpnWin
5757
MultiCountry() bool
58-
Conf(key string) (string, error)
58+
Conf(key string) (string, *x.RpnServer, error)
5959
}
6060

6161
var _ RpnAcc = (*WsClient)(nil)
@@ -88,7 +88,7 @@ type RpnStateless struct {
8888

8989
func (RpnStateless) Updated() int64 { return neverEver.UnixMilli() }
9090
func (RpnStateless) State() ([]byte, error) { return nil, errRpnStateless }
91-
func (RpnStateless) Conf(cc string) (string, error) { return "", errRpnStateless }
91+
func (RpnStateless) Conf(cc string) (string, *x.RpnServer, error) { return "", nil, errRpnStateless }
9292

9393
type RpnUpdateless struct{}
9494

intra/ipn/rpn/yegor.go

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,10 +1150,10 @@ func (a *WsClient) shallowCopyConfig(b *WsClient) (copied bool, err error) {
11501150
}
11511151

11521152
// Conf implements RpnAcc.
1153-
func (a *WsClient) Conf(cc string) (string, error) {
1153+
func (a *WsClient) Conf(cc string) (string, *x.RpnServer, error) {
11541154
cfg := a.config()
11551155
if cfg == nil {
1156-
return "", errWsNoConfig
1156+
return "", nil, errWsNoConfig
11571157
}
11581158
usePerma := !disablePermaCreds && a.Ops().Perma()
11591159
if usePerma && cfg.PermaCreds == nil {
@@ -1179,7 +1179,7 @@ func (a *WsClient) Conf(cc string) (string, error) {
11791179
if !chooseAny && len(excl) > 0 {
11801180
if _, excluded := excl[cc]; excluded {
11811181
log.W("ws: conf: cc %s is excluded...", cc)
1182-
return "", errWsCCExcluded
1182+
return "", nil, errWsCCExcluded
11831183
}
11841184
}
11851185

@@ -1188,11 +1188,11 @@ reconf:
11881188
tot := 0 // total seen
11891189
c := 0 // good cc conf
11901190
badc := 0 // bad cc conf
1191-
x := 0 // total excluded
1191+
xl := 0 // total excluded
11921192
v := 0 // total visited
11931193
visited := make(map[string]struct{}, len(cfg.Configs))
11941194
out := make([]string, 0, maxPerRegionWgConfs)
1195-
ids := make([]string, 0, maxPerRegionWgConfs)
1195+
srvs := make([]x.RpnServer, 0, maxPerRegionWgConfs)
11961196
for _, rc := range cfg.Configs {
11971197
// TODO: strings.HasSuffix(rc.Cc, cc) replaced with ==?
11981198
if (chooseAny || strings.HasSuffix(rc.CC, cc)) && (!hasCity || rc.City == city) {
@@ -1204,7 +1204,7 @@ reconf:
12041204
v++
12051205
// skip CCs the user has excluded
12061206
if _, excluded := excl[rc.CC]; excluded {
1207-
x++
1207+
xl++
12081208
continue
12091209
}
12101210
if c > 2 {
@@ -1240,8 +1240,22 @@ reconf:
12401240
confstr, confok = rc.MakeUapiConfig(cfg.Creds, portstr)
12411241
}
12421242
if confok {
1243+
// _, isExcluded := excl[rc.CC] assert false!
12431244
out = append(out, confstr)
1244-
ids = append(ids, strings.Join([]string{rc.CC, rc.City, rc.Name}, "/"))
1245+
srvs = append(srvs, x.RpnServer{
1246+
CC: rc.CC,
1247+
City: rc.City,
1248+
Name: rc.Name,
1249+
Load: rc.Load,
1250+
Link: rc.Link,
1251+
Count: rc.Count,
1252+
Premium: rc.Premium,
1253+
Excluded: false,
1254+
PubPub: trunc8(rc.ServerPubKey) + "&" + trunc8(rc.ClientPubKey),
1255+
Allowed: strings.Join(rc.AllowedIPs, ","),
1256+
Key: strings.Join([]string{rc.City, rc.CC}, confKeySep),
1257+
Addrs: strings.Join([]string{rc.ServerDomainPort, rc.addrCsv()}, ","),
1258+
})
12451259
c++
12461260
} else {
12471261
badc++
@@ -1251,12 +1265,13 @@ reconf:
12511265
}
12521266
if len(out) > 0 {
12531267
r := rand.IntN(len(out))
1254-
log.I("ws: conf: cc %s(%s): %d/%d => chosen (any? %t): %d[%s] (port: %s)", cc, city, c, len(out), chooseAny, r, ids[r], portstr)
1255-
return out[r], nil
1268+
log.I("ws: conf: cc %s(%s): %d/%d => chosen (any? %t): %d[%s/%s] (port: %s)",
1269+
cc, city, c, len(out), chooseAny, r, srvs[r].City, srvs[r].CC, portstr)
1270+
return out[r], &srvs[r], nil
12561271
}
1257-
if x > 0 && (tot == 0 || v <= x) { // fail open if all CCs excluded
1272+
if xl > 0 && (tot == 0 || v <= xl) { // fail open if all CCs excluded
12581273
logew(retried)("ws: conf: cc %s(%s): all visited(%d) / excluded(%d) / bad(%d); tot: %d / excl: %d; retry?",
1259-
cc, city, v, x, badc, tot, len(excl), !retried)
1274+
cc, city, v, xl, badc, tot, len(excl), !retried)
12601275
if !retried {
12611276
clear(excl) // fail open; excluded none
12621277
clear(visited)
@@ -1265,7 +1280,7 @@ reconf:
12651280
}
12661281
}
12671282
log.E("ws: conf: cc %s(%s) not found (tot: %d)", cc, city, tot)
1268-
return "", errWsNoCcConfig
1283+
return "", nil, errWsNoCcConfig
12691284
}
12701285

12711286
// unused on the control plane, so use a fixed but valid hostname

0 commit comments

Comments
 (0)