// selectProtocol is a helper that picks the tunnel protocol func selectProtocol( config *Config, serverEntry *protocol.ServerEntry) (selectedProtocol string, err error) { // TODO: properly handle protocols (e.g. FRONTED-MEEK-OSSH) vs. capabilities (e.g., {FRONTED-MEEK, OSSH}) // for now, the code is simply assuming that MEEK capabilities imply OSSH capability. if config.TunnelProtocol != "" { if !serverEntry.SupportsProtocol(config.TunnelProtocol) { return "", common.ContextError(fmt.Errorf("server does not have required capability")) } selectedProtocol = config.TunnelProtocol } else { // Pick at random from the supported protocols. This ensures that we'll eventually // try all possible protocols. Depending on network configuration, it may be the // case that some protocol is only available through multi-capability servers, // and a simpler ranked preference of protocols could lead to that protocol never // being selected. candidateProtocols := serverEntry.GetSupportedProtocols() if len(candidateProtocols) == 0 { return "", common.ContextError(fmt.Errorf("server does not have any supported capabilities")) } index, err := common.MakeSecureRandomInt(len(candidateProtocols)) if err != nil { return "", common.ContextError(err) } selectedProtocol = candidateProtocols[index] } return selectedProtocol, nil }
// MakeCompatibleServerEntry provides backwards compatibility with old server entries // which have a single meekFrontingDomain and not a meekFrontingAddresses array. // By copying this one meekFrontingDomain into meekFrontingAddresses, this client effectively // uses that single value as legacy clients do. func MakeCompatibleServerEntry(serverEntry *protocol.ServerEntry) *protocol.ServerEntry { if len(serverEntry.MeekFrontingAddresses) == 0 && serverEntry.MeekFrontingDomain != "" { serverEntry.MeekFrontingAddresses = append(serverEntry.MeekFrontingAddresses, serverEntry.MeekFrontingDomain) } return serverEntry }