func extractHosts(hbs []byte) ([]string, int, error) { var sl []string pos, total := 0, 0 for i := 0; i < len(hbs); i++ { if len(sl) > 0 && sl[len(sl)-1] == "0.0.0.0:0" { logger.LogSteamInfo("0.0.0.0:0 detected. Got %d total hosts.", total-1) break } if pos+6 > len(hbs) { logger.LogSteamInfo("Got %d total hosts.", total) break } host, err := parseIP(hbs[pos : pos+6]) if err != nil { logger.LogAppErrorf("Error parsing host: %s", err) } else { sl = append(sl, host) total++ } // host:port = 6 bytes pos = pos + 6 } return sl, total, nil }
// NewMasterWebQuery initiates a new Steam "Master" server query using the Steam Web API for a // given filter, returning a MasterQuery struct containing the hosts retrieved in the event of // success or an empty struct and an error in the event of failure. func NewMasterWebQuery(filter filters.Filter) (MasterQuery, error) { sl, err := getServersWeb(filter) if err != nil { return MasterQuery{}, err } logger.LogSteamInfo("*** Retrieved %d %s servers.", len(sl), filter.Game.Name) return MasterQuery{Servers: sl}, nil }
func getServers(filter filters.Filter) ([]string, error) { maxHosts := config.Config.SteamConfig.MaximumHostsToReceive var serverlist []string var c net.Conn var err error retrieved := 0 addr := "0.0.0.0:0" c, err = net.DialTimeout("udp", masterServerHost, time.Duration(QueryTimeout)*time.Second) if err != nil { logger.LogSteamError(ErrHostConnection(err.Error())) return nil, ErrHostConnection(err.Error()) } defer c.Close() c.SetDeadline(time.Now().Add(time.Duration(QueryTimeout) * time.Second)) for { s, err := queryMasterServer(c, addr, filter) if err != nil { // usually timeout - Valve throttles >30 UDP packets (>6930 servers) per min logger.WriteDebug("Master query error, likely due to Valve throttle/timeout :%s", err) break } // get hosts:ports beginning after header (0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x0A) ips, total, err := extractHosts(s[6:]) if err != nil { return nil, logger.LogAppErrorf("Error when extracting addresses: %s", err) } retrieved = retrieved + total if retrieved >= maxHosts { logger.LogSteamInfo("Max host limit of %d reached!", maxHosts) logger.WriteDebug("Max host limit of %d reached!", maxHosts) break } logger.LogSteamInfo("%d hosts retrieved so far from master.", retrieved) logger.WriteDebug("%d hosts retrieved so far from master.", retrieved) for _, ip := range ips { serverlist = append(serverlist, ip) } if (serverlist[len(serverlist)-1]) != "0.0.0.0:0" { logger.LogSteamInfo("More hosts need to be retrieved. Last IP was: %s", serverlist[len(serverlist)-1]) logger.WriteDebug("More hosts need to be retrieved. Last IP was: %s", serverlist[len(serverlist)-1]) addr = serverlist[len(serverlist)-1] } else { logger.LogSteamInfo("IP retrieval complete!") logger.WriteDebug("IP retrieval complete!") break } } // remove 0.0.0.0:0 if len(serverlist) != 0 { if serverlist[len(serverlist)-1] == "0.0.0.0:0" { serverlist = serverlist[:len(serverlist)-1] } } return serverlist, nil }