| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | 
							- package main
 
- import (
 
- 	"context"
 
- 	"io"
 
- 	"net"
 
- 	"net/http"
 
- 	"strconv"
 
- 	"sync"
 
- 	"time"
 
- 	"github.com/VividCortex/ewma"
 
- )
 
- //bool connectionSucceed float32 time
 
- func tcping(ip net.IPAddr) (bool, float32) {
 
- 	startTime := time.Now()
 
- 	conn, err := net.DialTimeout("tcp", ip.String()+":"+strconv.Itoa(defaultTcpPort), tcpConnectTimeout)
 
- 	if err != nil {
 
- 		return false, 0
 
- 	} else {
 
- 		var endTime = time.Since(startTime)
 
- 		var duration = float32(endTime.Microseconds()) / 1000.0
 
- 		_ = conn.Close()
 
- 		return true, duration
 
- 	}
 
- }
 
- //pingReceived pingTotalTime
 
- func checkConnection(ip net.IPAddr) (int, float32) {
 
- 	pingRecv := 0
 
- 	var pingTime float32 = 0.0
 
- 	for i := 1; i <= failTime; i++ {
 
- 		pingSucceed, pingTimeCurrent := tcping(ip)
 
- 		if pingSucceed {
 
- 			pingRecv++
 
- 			pingTime += pingTimeCurrent
 
- 		}
 
- 	}
 
- 	return pingRecv, pingTime
 
- }
 
- //return Success packetRecv averagePingTime specificIPAddr
 
- func tcpingHandler(ip net.IPAddr, pingCount int, progressHandler func(e progressEvent)) (bool, int, float32, net.IPAddr) {
 
- 	ipCanConnect := false
 
- 	pingRecv := 0
 
- 	var pingTime float32 = 0.0
 
- 	for !ipCanConnect {
 
- 		pingRecvCurrent, pingTimeCurrent := checkConnection(ip)
 
- 		if pingRecvCurrent != 0 {
 
- 			ipCanConnect = true
 
- 			pingRecv = pingRecvCurrent
 
- 			pingTime = pingTimeCurrent
 
- 		} else {
 
- 			ip.IP[15]++
 
- 			if ip.IP[15] == 0 {
 
- 				break
 
- 			}
 
- 			break
 
- 		}
 
- 	}
 
- 	if ipCanConnect {
 
- 		progressHandler(AvailableIPFound)
 
- 		for i := failTime; i < pingCount; i++ {
 
- 			pingSuccess, pingTimeCurrent := tcping(ip)
 
- 			progressHandler(NormalPing)
 
- 			if pingSuccess {
 
- 				pingRecv++
 
- 				pingTime += pingTimeCurrent
 
- 			}
 
- 		}
 
- 		return true, pingRecv, pingTime / float32(pingRecv), ip
 
- 	} else {
 
- 		progressHandler(NoAvailableIPFound)
 
- 		return false, 0, 0, net.IPAddr{}
 
- 	}
 
- }
 
- func tcpingGoroutine(wg *sync.WaitGroup, mutex *sync.Mutex, ip net.IPAddr, pingCount int, csv *[]CloudflareIPData, control chan bool, progressHandler func(e progressEvent)) {
 
- 	defer wg.Done()
 
- 	success, pingRecv, pingTimeAvg, currentIP := tcpingHandler(ip, pingCount, progressHandler)
 
- 	if success {
 
- 		mutex.Lock()
 
- 		var cfdata CloudflareIPData
 
- 		cfdata.ip = currentIP
 
- 		cfdata.pingReceived = pingRecv
 
- 		cfdata.pingTime = pingTimeAvg
 
- 		cfdata.pingCount = pingCount
 
- 		*csv = append(*csv, cfdata)
 
- 		mutex.Unlock()
 
- 	}
 
- 	<-control
 
- }
 
- func GetDialContextByAddr(fakeSourceAddr string) func(ctx context.Context, network, address string) (net.Conn, error) {
 
- 	return func(ctx context.Context, network, address string) (net.Conn, error) {
 
- 		c, e := (&net.Dialer{}).DialContext(ctx, network, fakeSourceAddr)
 
- 		return c, e
 
- 	}
 
- }
 
- //bool : can download,float32 downloadSpeed
 
- func DownloadSpeedHandler(ip net.IPAddr) (bool, float32) {
 
- 	var client = http.Client{
 
- 		Transport:     nil,
 
- 		CheckRedirect: nil,
 
- 		Jar:           nil,
 
- 		Timeout:       0,
 
- 	}
 
- 	client.Transport = &http.Transport{
 
- 		DialContext: GetDialContextByAddr(ip.String() + ":443"),
 
- 	}
 
- 	response, err := client.Get(url)
 
- 	if err != nil {
 
- 		return false, 0
 
- 	} else {
 
- 		defer func() { _ = response.Body.Close() }()
 
- 		if response.StatusCode == 200 {
 
- 			timeStart := time.Now()
 
- 			timeEnd := timeStart.Add(downloadTestTime)
 
- 			contentLength := response.ContentLength
 
- 			buffer := make([]byte, downloadBufferSize)
 
- 			var contentRead int64 = 0
 
- 			var timeSlice = downloadTestTime / 100
 
- 			var timeCounter = 1
 
- 			var lastContentRead int64 = 0
 
- 			var nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
 
- 			e := ewma.NewMovingAverage()
 
- 			for contentLength != contentRead {
 
- 				var currentTime = time.Now()
 
- 				if currentTime.After(nextTime) {
 
- 					timeCounter += 1
 
- 					nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
 
- 					e.Add(float64(contentRead - lastContentRead))
 
- 					lastContentRead = contentRead
 
- 				}
 
- 				if currentTime.After(timeEnd) {
 
- 					break
 
- 				}
 
- 				bufferRead, err := response.Body.Read(buffer)
 
- 				contentRead += int64(bufferRead)
 
- 				if err != nil {
 
- 					if err != io.EOF {
 
- 						break
 
- 					} else {
 
- 						e.Add(float64(contentRead-lastContentRead) / (float64(nextTime.Sub(currentTime)) / float64(timeSlice)))
 
- 					}
 
- 				}
 
- 			}
 
- 			return true, float32(e.Value()) / (float32(downloadTestTime.Seconds()) / 100)
 
- 		} else {
 
- 			return false, 0
 
- 		}
 
- 	}
 
- }
 
 
  |