update selector

This commit is contained in:
ginuerzh 2022-09-02 21:55:25 +08:00
parent 5acccebe7b
commit ca0de58757
3 changed files with 51 additions and 50 deletions

View File

@ -9,8 +9,9 @@ import (
"strings" "strings"
"time" "time"
mdutil "github.com/go-gost/core/metadata/util"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
"github.com/go-gost/x/metadata" mdx "github.com/go-gost/x/metadata"
"github.com/go-gost/x/registry" "github.com/go-gost/x/registry"
) )
@ -88,7 +89,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
} }
mc := nodeConfig.Connector.Metadata mc := nodeConfig.Connector.Metadata
md := metadata.NewMetadata(mc) md := mdx.NewMetadata(mc)
hopConfig := &config.HopConfig{ hopConfig := &config.HopConfig{
Name: fmt.Sprintf("hop-%d", i), Name: fmt.Sprintf("hop-%d", i),
@ -96,7 +97,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
Nodes: nodes, Nodes: nodes,
} }
if v := metadata.GetString(md, "bypass"); v != "" { if v := mdutil.GetString(md, "bypass"); v != "" {
bypassCfg := &config.BypassConfig{ bypassCfg := &config.BypassConfig{
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)), Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
} }
@ -114,7 +115,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Bypasses = append(cfg.Bypasses, bypassCfg) cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
delete(mc, "bypass") delete(mc, "bypass")
} }
if v := metadata.GetString(md, "resolver"); v != "" { if v := mdutil.GetString(md, "resolver"); v != "" {
resolverCfg := &config.ResolverConfig{ resolverCfg := &config.ResolverConfig{
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)), Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
} }
@ -133,7 +134,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Resolvers = append(cfg.Resolvers, resolverCfg) cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
delete(mc, "resolver") delete(mc, "resolver")
} }
if v := metadata.GetString(md, "hosts"); v != "" { if v := mdutil.GetString(md, "hosts"); v != "" {
hostsCfg := &config.HostsConfig{ hostsCfg := &config.HostsConfig{
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)), Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
} }
@ -155,11 +156,11 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
delete(mc, "hosts") delete(mc, "hosts")
} }
if v := metadata.GetString(md, "interface"); v != "" { if v := mdutil.GetString(md, "interface"); v != "" {
hopConfig.Interface = v hopConfig.Interface = v
delete(mc, "interface") delete(mc, "interface")
} }
if v := metadata.GetInt(md, "so_mark"); v > 0 { if v := mdutil.GetInt(md, "so_mark"); v > 0 {
hopConfig.SockOpts = &config.SockOptsConfig{ hopConfig.SockOpts = &config.SockOptsConfig{
Mark: v, Mark: v,
} }
@ -190,12 +191,12 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Services = append(cfg.Services, service) cfg.Services = append(cfg.Services, service)
mh := service.Handler.Metadata mh := service.Handler.Metadata
md := metadata.NewMetadata(mh) md := mdx.NewMetadata(mh)
if v := metadata.GetInt(md, "retries"); v > 0 { if v := mdutil.GetInt(md, "retries"); v > 0 {
service.Handler.Retries = v service.Handler.Retries = v
delete(mh, "retries") delete(mh, "retries")
} }
if v := metadata.GetString(md, "admission"); v != "" { if v := mdutil.GetString(md, "admission"); v != "" {
admCfg := &config.AdmissionConfig{ admCfg := &config.AdmissionConfig{
Name: fmt.Sprintf("admission-%d", len(cfg.Admissions)), Name: fmt.Sprintf("admission-%d", len(cfg.Admissions)),
} }
@ -213,7 +214,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Admissions = append(cfg.Admissions, admCfg) cfg.Admissions = append(cfg.Admissions, admCfg)
delete(mh, "admission") delete(mh, "admission")
} }
if v := metadata.GetString(md, "bypass"); v != "" { if v := mdutil.GetString(md, "bypass"); v != "" {
bypassCfg := &config.BypassConfig{ bypassCfg := &config.BypassConfig{
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)), Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
} }
@ -231,7 +232,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Bypasses = append(cfg.Bypasses, bypassCfg) cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
delete(mh, "bypass") delete(mh, "bypass")
} }
if v := metadata.GetString(md, "resolver"); v != "" { if v := mdutil.GetString(md, "resolver"); v != "" {
resolverCfg := &config.ResolverConfig{ resolverCfg := &config.ResolverConfig{
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)), Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
} }
@ -243,7 +244,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
resolverCfg.Nameservers, resolverCfg.Nameservers,
&config.NameserverConfig{ &config.NameserverConfig{
Addr: rs, Addr: rs,
Prefer: metadata.GetString(md, "prefer"), Prefer: mdutil.GetString(md, "prefer"),
}, },
) )
} }
@ -251,7 +252,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg.Resolvers = append(cfg.Resolvers, resolverCfg) cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
delete(mh, "resolver") delete(mh, "resolver")
} }
if v := metadata.GetString(md, "hosts"); v != "" { if v := mdutil.GetString(md, "hosts"); v != "" {
hostsCfg := &config.HostsConfig{ hostsCfg := &config.HostsConfig{
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)), Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
} }
@ -341,9 +342,9 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
m[k] = v[0] m[k] = v[0]
} }
} }
md := metadata.NewMetadata(m) md := mdx.NewMetadata(m)
if sa := metadata.GetString(md, "auth"); sa != "" { if sa := mdutil.GetString(md, "auth"); sa != "" {
au, err := parseAuthFromCmd(sa) au, err := parseAuthFromCmd(sa)
if err != nil { if err != nil {
return nil, err return nil, err
@ -353,18 +354,18 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
delete(m, "auth") delete(m, "auth")
tlsConfig := &config.TLSConfig{ tlsConfig := &config.TLSConfig{
CertFile: metadata.GetString(md, "certFile"), CertFile: mdutil.GetString(md, "certFile"),
KeyFile: metadata.GetString(md, "keyFile"), KeyFile: mdutil.GetString(md, "keyFile"),
CAFile: metadata.GetString(md, "caFile"), CAFile: mdutil.GetString(md, "caFile"),
} }
if tlsConfig.CertFile == "" { if tlsConfig.CertFile == "" {
tlsConfig.CertFile = metadata.GetString(md, "cert") tlsConfig.CertFile = mdutil.GetString(md, "cert")
} }
if tlsConfig.KeyFile == "" { if tlsConfig.KeyFile == "" {
tlsConfig.KeyFile = metadata.GetString(md, "key") tlsConfig.KeyFile = mdutil.GetString(md, "key")
} }
if tlsConfig.CAFile == "" { if tlsConfig.CAFile == "" {
tlsConfig.CAFile = metadata.GetString(md, "ca") tlsConfig.CAFile = mdutil.GetString(md, "ca")
} }
delete(m, "certFile") delete(m, "certFile")
@ -378,14 +379,14 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
tlsConfig = nil tlsConfig = nil
} }
if v := metadata.GetString(md, "dns"); v != "" { if v := mdutil.GetString(md, "dns"); v != "" {
md.Set("dns", strings.Split(v, ",")) md.Set("dns", strings.Split(v, ","))
} }
if v := metadata.GetString(md, "interface"); v != "" { if v := mdutil.GetString(md, "interface"); v != "" {
svc.Interface = v svc.Interface = v
delete(m, "interface") delete(m, "interface")
} }
if v := metadata.GetInt(md, "so_mark"); v > 0 { if v := mdutil.GetInt(md, "so_mark"); v > 0 {
svc.SockOpts = &config.SockOptsConfig{ svc.SockOpts = &config.SockOptsConfig{
Mark: v, Mark: v,
} }
@ -455,9 +456,9 @@ func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
m[k] = v[0] m[k] = v[0]
} }
} }
md := metadata.NewMetadata(m) md := mdx.NewMetadata(m)
if sauth := metadata.GetString(md, "auth"); sauth != "" && auth == nil { if sauth := mdutil.GetString(md, "auth"); sauth != "" && auth == nil {
au, err := parseAuthFromCmd(sauth) au, err := parseAuthFromCmd(sauth)
if err != nil { if err != nil {
return nil, err return nil, err
@ -467,23 +468,23 @@ func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
delete(m, "auth") delete(m, "auth")
tlsConfig := &config.TLSConfig{ tlsConfig := &config.TLSConfig{
CertFile: metadata.GetString(md, "certFile"), CertFile: mdutil.GetString(md, "certFile"),
KeyFile: metadata.GetString(md, "keyFile"), KeyFile: mdutil.GetString(md, "keyFile"),
CAFile: metadata.GetString(md, "caFile"), CAFile: mdutil.GetString(md, "caFile"),
Secure: metadata.GetBool(md, "secure"), Secure: mdutil.GetBool(md, "secure"),
ServerName: metadata.GetString(md, "serverName"), ServerName: mdutil.GetString(md, "serverName"),
} }
if tlsConfig.ServerName == "" { if tlsConfig.ServerName == "" {
tlsConfig.ServerName = url.Hostname() tlsConfig.ServerName = url.Hostname()
} }
if tlsConfig.CertFile == "" { if tlsConfig.CertFile == "" {
tlsConfig.CertFile = metadata.GetString(md, "cert") tlsConfig.CertFile = mdutil.GetString(md, "cert")
} }
if tlsConfig.KeyFile == "" { if tlsConfig.KeyFile == "" {
tlsConfig.KeyFile = metadata.GetString(md, "key") tlsConfig.KeyFile = mdutil.GetString(md, "key")
} }
if tlsConfig.CAFile == "" { if tlsConfig.CAFile == "" {
tlsConfig.CAFile = metadata.GetString(md, "ca") tlsConfig.CAFile = mdutil.GetString(md, "ca")
} }
delete(m, "certFile") delete(m, "certFile")
@ -559,15 +560,15 @@ func parseAuthFromCmd(sa string) (*config.AuthConfig, error) {
} }
func parseSelector(m map[string]any) *config.SelectorConfig { func parseSelector(m map[string]any) *config.SelectorConfig {
md := metadata.NewMetadata(m) md := mdx.NewMetadata(m)
strategy := metadata.GetString(md, "strategy") strategy := mdutil.GetString(md, "strategy")
maxFails := metadata.GetInt(md, "maxFails") maxFails := mdutil.GetInt(md, "maxFails")
if maxFails == 0 { if maxFails == 0 {
maxFails = metadata.GetInt(md, "max_fails") maxFails = mdutil.GetInt(md, "max_fails")
} }
failTimeout := metadata.GetDuration(md, "failTimeout") failTimeout := mdutil.GetDuration(md, "failTimeout")
if failTimeout == 0 { if failTimeout == 0 {
failTimeout = metadata.GetDuration(md, "fail_timeout") failTimeout = mdutil.GetDuration(md, "fail_timeout")
} }
if strategy == "" && maxFails <= 0 && failTimeout <= 0 { if strategy == "" && maxFails <= 0 && failTimeout <= 0 {
return nil return nil

6
go.mod
View File

@ -5,8 +5,8 @@ go 1.18
replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a
require ( require (
github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63 github.com/go-gost/core v0.0.0-20220902092328-713671067369
github.com/go-gost/x v0.0.0-20220831121852-470d229c5821 github.com/go-gost/x v0.0.0-20220902135350-6546f4a9056a
) )
require ( require (
@ -83,7 +83,7 @@ require (
github.com/xtaci/tcpraw v1.2.25 // indirect github.com/xtaci/tcpraw v1.2.25 // indirect
github.com/yl2chen/cidranger v1.0.2 // indirect github.com/yl2chen/cidranger v1.0.2 // indirect
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect

12
go.sum
View File

@ -96,8 +96,8 @@ github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63 h1:3IjymE34G/oU0s/rc9KlSOUw+bIEkmNtEuw62INqV2Q= github.com/go-gost/core v0.0.0-20220902092328-713671067369 h1:qPZgaT7p3WP06X0uVGv5bVxD2DUP7x+RiMaYxJyQuwI=
github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= github.com/go-gost/core v0.0.0-20220902092328-713671067369/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ=
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04= github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04=
@ -106,8 +106,8 @@ github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 h1:itaaJhQJ19kUXEB
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8=
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I= github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I=
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
github.com/go-gost/x v0.0.0-20220831121852-470d229c5821 h1:SRkBXXkWzqRvl18qiS2pFFprMSG+Tai3Yl4pGXI3lVw= github.com/go-gost/x v0.0.0-20220902135350-6546f4a9056a h1:JIl1DqwRn6zah03azZTxFcrYgXKORjc2hmO5XMR5c5I=
github.com/go-gost/x v0.0.0-20220831121852-470d229c5821/go.mod h1:M0isfKoqaRXwKamcm71B6qK86NY3ZVP/3JXsXa++Rbg= github.com/go-gost/x v0.0.0-20220902135350-6546f4a9056a/go.mod h1:C/3ZC9B+JTAyWg8zvk2TAULZDQbKp6gsZK3Ce0lMQrE=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@ -424,8 +424,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=