github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/v5cfg/root.go (about)

     1  package v5cfg
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  
     8  	"github.com/golang/protobuf/proto"
     9  	"google.golang.org/protobuf/types/known/anypb"
    10  
    11  	core "github.com/v2fly/v2ray-core/v5"
    12  	"github.com/v2fly/v2ray-core/v5/app/dispatcher"
    13  	"github.com/v2fly/v2ray-core/v5/app/proxyman"
    14  	"github.com/v2fly/v2ray-core/v5/common/platform"
    15  	"github.com/v2fly/v2ray-core/v5/common/serial"
    16  	"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon"
    17  	"github.com/v2fly/v2ray-core/v5/infra/conf/geodata"
    18  	"github.com/v2fly/v2ray-core/v5/infra/conf/synthetic/log"
    19  )
    20  
    21  func (c RootConfig) BuildV5(ctx context.Context) (proto.Message, error) {
    22  	config := &core.Config{
    23  		App: []*anypb.Any{
    24  			serial.ToTypedMessage(&dispatcher.Config{}),
    25  			serial.ToTypedMessage(&proxyman.InboundConfig{}),
    26  			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
    27  		},
    28  	}
    29  
    30  	var logConfMsg *anypb.Any
    31  	if c.LogConfig != nil {
    32  		logConfMsgUnpacked, err := loadHeterogeneousConfigFromRawJSON("service", "log", c.LogConfig)
    33  		if err != nil {
    34  			return nil, newError("failed to parse Log config").Base(err)
    35  		}
    36  		logConfMsg = serial.ToTypedMessage(logConfMsgUnpacked)
    37  	} else {
    38  		logConfMsg = serial.ToTypedMessage(log.DefaultLogConfig())
    39  	}
    40  	// let logger module be the first App to start,
    41  	// so that other modules could print log during initiating
    42  	config.App = append([]*anypb.Any{logConfMsg}, config.App...)
    43  
    44  	if c.RouterConfig != nil {
    45  		routerConfig, err := loadHeterogeneousConfigFromRawJSON("service", "router", c.RouterConfig)
    46  		if err != nil {
    47  			return nil, newError("failed to parse Router config").Base(err)
    48  		}
    49  		config.App = append(config.App, serial.ToTypedMessage(routerConfig))
    50  	}
    51  
    52  	if c.DNSConfig != nil {
    53  		dnsApp, err := loadHeterogeneousConfigFromRawJSON("service", "dns", c.DNSConfig)
    54  		if err != nil {
    55  			return nil, newError("failed to parse DNS config").Base(err)
    56  		}
    57  		config.App = append(config.App, serial.ToTypedMessage(dnsApp))
    58  	}
    59  
    60  	for _, rawInboundConfig := range c.Inbounds {
    61  		ic, err := rawInboundConfig.BuildV5(ctx)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		config.Inbound = append(config.Inbound, ic.(*core.InboundHandlerConfig))
    66  	}
    67  
    68  	for _, rawOutboundConfig := range c.Outbounds {
    69  		ic, err := rawOutboundConfig.BuildV5(ctx)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  		config.Outbound = append(config.Outbound, ic.(*core.OutboundHandlerConfig))
    74  	}
    75  
    76  	for serviceName, service := range c.Services {
    77  		servicePackedConfig, err := loadHeterogeneousConfigFromRawJSON("service", serviceName, service)
    78  		if err != nil {
    79  			return nil, newError(fmt.Sprintf("failed to parse %v config in Services", serviceName)).Base(err)
    80  		}
    81  		config.App = append(config.App, serial.ToTypedMessage(servicePackedConfig))
    82  	}
    83  	return config, nil
    84  }
    85  
    86  func loadJSONConfig(data []byte) (*core.Config, error) {
    87  	rootConfig := &RootConfig{}
    88  
    89  	err := json.Unmarshal(data, rootConfig)
    90  	if err != nil {
    91  		return nil, newError("unable to load json").Base(err)
    92  	}
    93  
    94  	buildctx := cfgcommon.NewConfigureLoadingContext(context.Background())
    95  
    96  	geoloadername := platform.NewEnvFlag("v2ray.conf.geoloader").GetValue(func() string {
    97  		return "standard"
    98  	})
    99  
   100  	if loader, err := geodata.GetGeoDataLoader(geoloadername); err == nil {
   101  		cfgcommon.SetGeoDataLoader(buildctx, loader)
   102  	} else {
   103  		return nil, newError("unable to create geo data loader ").Base(err)
   104  	}
   105  
   106  	message, err := rootConfig.BuildV5(buildctx)
   107  	if err != nil {
   108  		return nil, newError("unable to build config").Base(err)
   109  	}
   110  	return message.(*core.Config), nil
   111  }