// 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 }