programs for edns, svcb, https support measurement
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.log
|
||||||
12
go.mod
Normal file
12
go.mod
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module edns_svcb
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require github.com/miekg/dns v1.1.58
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
|
golang.org/x/net v0.20.0 // indirect
|
||||||
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
|
golang.org/x/tools v0.17.0 // indirect
|
||||||
|
)
|
||||||
11
go.sum
Normal file
11
go.sum
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||||
|
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||||
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
38
main.go
Normal file
38
main.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"edns_svcb/method"
|
||||||
|
"edns_svcb/utils"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var input_file string
|
||||||
|
flag.StringVar(&input_file, "input", "", "input file name")
|
||||||
|
flag.Parse()
|
||||||
|
input_pool := make(chan string, 500)
|
||||||
|
result_pool := make(chan method.CombinedResult)
|
||||||
|
var test_tasks sync.WaitGroup
|
||||||
|
var process_tasks sync.WaitGroup
|
||||||
|
|
||||||
|
logfilename := "test/" + time.Now().Format("2006-01-02_15-04-05") + ".log"
|
||||||
|
logfile, err := os.OpenFile(logfilename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to create log file: ", err)
|
||||||
|
}
|
||||||
|
defer logfile.Close()
|
||||||
|
logger := log.New(logfile, "", log.LstdFlags)
|
||||||
|
|
||||||
|
go utils.RetrieveLines(input_pool, input_file)
|
||||||
|
method.CombinedMeasurement(input_pool, result_pool, 500, &test_tasks, logger)
|
||||||
|
process_tasks.Add(1)
|
||||||
|
go method.CombinedResultProcess(result_pool, &process_tasks)
|
||||||
|
test_tasks.Wait()
|
||||||
|
close(result_pool)
|
||||||
|
process_tasks.Wait()
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
123
method/combined.go
Normal file
123
method/combined.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package method
|
||||||
|
|
||||||
|
import (
|
||||||
|
"edns_svcb/utils"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CombinedResult struct {
|
||||||
|
Alive bool
|
||||||
|
EDNSSupport bool
|
||||||
|
SVCBSupport bool
|
||||||
|
HTTPSSupport bool
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func CombinedMeasurement(ip_pool chan string, result_pool chan CombinedResult, routine_num int, wg *sync.WaitGroup, logger *log.Logger) {
|
||||||
|
for i := 0; i < routine_num; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go CombinedTestRoutine(ip_pool, result_pool, wg, logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CombinedTestRoutine(ip_pool chan string, result_pool chan CombinedResult, wg *sync.WaitGroup, logger *log.Logger) {
|
||||||
|
for {
|
||||||
|
if ip, ok := <-ip_pool; ok {
|
||||||
|
addr := ip + ":53"
|
||||||
|
res := CombinedTest(addr)
|
||||||
|
result_pool <- res
|
||||||
|
if res.Err != nil {
|
||||||
|
logger.Printf("%v : failed ( %v )", ip, res.Err)
|
||||||
|
} else {
|
||||||
|
logger.Printf("%v : alive %v edns %v svcb %v https %v", ip, res.Alive, res.EDNSSupport, res.SVCBSupport, res.HTTPSSupport)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CombinedTest(addr string) CombinedResult {
|
||||||
|
result := CombinedResult{}
|
||||||
|
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.com", RD: true})
|
||||||
|
if err != nil {
|
||||||
|
return CombinedResult{Err: err}
|
||||||
|
}
|
||||||
|
result.Alive = true
|
||||||
|
|
||||||
|
//edns support
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.com", EDNS: true, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Extra) > 0 {
|
||||||
|
if _, ok := res.Extra[0].(*dns.OPT); ok {
|
||||||
|
result.EDNSSupport = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.Err = err
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// svcb support
|
||||||
|
res, err = utils.DNSQuery(addr, utils.DNSOptions{Domain: "_dns.resolver.arpa", Qtype: dns.TypeSVCB, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) > 0 {
|
||||||
|
if _, ok := res.Answer[0].(*dns.SVCB); ok {
|
||||||
|
result.SVCBSupport = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.Err = err
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// https support
|
||||||
|
res, err = utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeHTTPS, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) > 0 {
|
||||||
|
if _, ok := res.Answer[0].(*dns.HTTPS); ok {
|
||||||
|
result.HTTPSSupport = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.Err = err
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func CombinedResultProcess(result_pool chan CombinedResult, wg *sync.WaitGroup) {
|
||||||
|
alive_cnt := 0
|
||||||
|
edns_cnt := 0
|
||||||
|
svcb_cnt := 0
|
||||||
|
https_cnt := 0
|
||||||
|
for {
|
||||||
|
if res, ok := <-result_pool; ok {
|
||||||
|
if res.Err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if res.Alive {
|
||||||
|
alive_cnt++
|
||||||
|
}
|
||||||
|
if res.EDNSSupport {
|
||||||
|
edns_cnt++
|
||||||
|
}
|
||||||
|
if res.SVCBSupport {
|
||||||
|
svcb_cnt++
|
||||||
|
}
|
||||||
|
if res.HTTPSSupport {
|
||||||
|
https_cnt++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("EDNS support Test: alive %v edns %v svcb %v https %v\n", alive_cnt, edns_cnt, svcb_cnt, https_cnt)
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
76
method/edns.go
Normal file
76
method/edns.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package method
|
||||||
|
|
||||||
|
import (
|
||||||
|
"edns_svcb/utils"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestResult struct {
|
||||||
|
Alive bool
|
||||||
|
Support bool
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func EDNSSupportMeasurement(ip_pool chan string, result_pool chan TestResult, routine_num int, wg *sync.WaitGroup, logger *log.Logger) {
|
||||||
|
for i := 0; i < routine_num; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go EDNSSupportTestRoutine(ip_pool, result_pool, wg, logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EDNSSupportTestRoutine(ip_pool chan string, result_pool chan TestResult, wg *sync.WaitGroup, logger *log.Logger) {
|
||||||
|
for {
|
||||||
|
if ip, ok := <-ip_pool; ok {
|
||||||
|
addr := ip + ":53"
|
||||||
|
res := EDNSSupportTest(addr)
|
||||||
|
result_pool <- res
|
||||||
|
if res.Err != nil {
|
||||||
|
logger.Printf("%v : failed ( %v )", ip, res.Err)
|
||||||
|
} else {
|
||||||
|
logger.Printf("%v : alive %v support %v", ip, res.Alive, res.Support)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func EDNSSupportTest(addr string) TestResult {
|
||||||
|
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||||
|
if err != nil {
|
||||||
|
return TestResult{Err: err}
|
||||||
|
}
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", EDNS: true, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Extra) == 1 {
|
||||||
|
if _, ok := res.Extra[0].(*dns.OPT); ok {
|
||||||
|
return TestResult{Alive: true, Support: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TestResult{Alive: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EDNSSupportResultProcess(result_pool chan TestResult, wg *sync.WaitGroup) {
|
||||||
|
alive_cnt := 0
|
||||||
|
valid_cnt := 0
|
||||||
|
for {
|
||||||
|
if res, ok := <-result_pool; ok {
|
||||||
|
if res.Alive {
|
||||||
|
alive_cnt++
|
||||||
|
}
|
||||||
|
if res.Support {
|
||||||
|
valid_cnt++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("EDNS support Test: alive %v support %v\n", alive_cnt, valid_cnt)
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
63
method/svcb.go
Normal file
63
method/svcb.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package method
|
||||||
|
|
||||||
|
import (
|
||||||
|
"edns_svcb/utils"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HTTPSSupportTest(addr string) TestResult {
|
||||||
|
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||||
|
if err != nil {
|
||||||
|
return TestResult{Err: err}
|
||||||
|
}
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeHTTPS, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) == 1 {
|
||||||
|
if _, ok := res.Extra[0].(*dns.HTTPS); ok {
|
||||||
|
return TestResult{Alive: true, Support: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TestResult{Alive: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SVCBSupportTest(addr string) TestResult {
|
||||||
|
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||||
|
if err != nil {
|
||||||
|
return TestResult{Err: err}
|
||||||
|
}
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeSVCB, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) == 1 {
|
||||||
|
if _, ok := res.Extra[0].(*dns.SVCB); ok {
|
||||||
|
return TestResult{Alive: true, Support: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TestResult{Alive: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HTTPSRecordTest(addr, domain string) bool {
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: domain, Qtype: dns.TypeHTTPS, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) > 0 {
|
||||||
|
if _, ok := res.Answer[0].(*dns.HTTPS); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SVCBRecordTest(addr, domain string) bool {
|
||||||
|
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: domain, Qtype: dns.TypeSVCB, RD: true})
|
||||||
|
if err == nil {
|
||||||
|
if len(res.Answer) > 0 {
|
||||||
|
if _, ok := res.Answer[0].(*dns.SVCB); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
100
test/test-input
Normal file
100
test/test-input
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
1.0.0.1
|
||||||
|
1.0.0.2
|
||||||
|
1.0.0.3
|
||||||
|
1.0.0.19
|
||||||
|
1.0.66.192
|
||||||
|
1.0.72.68
|
||||||
|
1.0.77.169
|
||||||
|
1.0.79.90
|
||||||
|
1.0.81.135
|
||||||
|
1.0.84.117
|
||||||
|
1.0.91.59
|
||||||
|
1.0.91.149
|
||||||
|
1.0.97.194
|
||||||
|
1.0.103.132
|
||||||
|
1.0.106.125
|
||||||
|
1.0.123.53
|
||||||
|
1.0.141.2
|
||||||
|
1.0.141.7
|
||||||
|
1.0.141.23
|
||||||
|
1.0.141.31
|
||||||
|
1.0.141.32
|
||||||
|
1.0.141.36
|
||||||
|
1.0.141.46
|
||||||
|
1.0.141.49
|
||||||
|
1.0.141.54
|
||||||
|
1.0.141.55
|
||||||
|
1.0.141.59
|
||||||
|
1.0.141.62
|
||||||
|
1.0.141.64
|
||||||
|
1.0.141.67
|
||||||
|
1.0.141.69
|
||||||
|
1.0.141.72
|
||||||
|
1.0.141.75
|
||||||
|
1.0.141.76
|
||||||
|
1.0.141.77
|
||||||
|
1.0.141.79
|
||||||
|
1.0.141.85
|
||||||
|
1.0.141.86
|
||||||
|
1.0.141.92
|
||||||
|
1.0.141.101
|
||||||
|
1.0.141.103
|
||||||
|
1.0.141.110
|
||||||
|
1.0.141.114
|
||||||
|
1.0.141.117
|
||||||
|
1.0.141.126
|
||||||
|
1.0.141.135
|
||||||
|
1.0.141.143
|
||||||
|
1.0.141.145
|
||||||
|
1.0.141.152
|
||||||
|
1.0.141.164
|
||||||
|
1.0.141.167
|
||||||
|
1.0.141.174
|
||||||
|
1.0.141.177
|
||||||
|
1.0.141.179
|
||||||
|
1.0.141.180
|
||||||
|
1.0.141.191
|
||||||
|
1.0.141.203
|
||||||
|
1.0.141.204
|
||||||
|
1.0.141.211
|
||||||
|
1.0.141.223
|
||||||
|
1.0.141.238
|
||||||
|
1.0.141.242
|
||||||
|
1.0.141.244
|
||||||
|
1.0.141.247
|
||||||
|
1.0.141.250
|
||||||
|
1.0.141.252
|
||||||
|
1.0.141.253
|
||||||
|
1.0.144.8
|
||||||
|
1.0.144.27
|
||||||
|
1.0.144.34
|
||||||
|
1.0.144.36
|
||||||
|
1.0.144.38
|
||||||
|
1.0.144.47
|
||||||
|
1.0.144.48
|
||||||
|
1.0.144.50
|
||||||
|
1.0.144.51
|
||||||
|
1.0.144.52
|
||||||
|
1.0.144.55
|
||||||
|
1.0.144.73
|
||||||
|
1.0.144.74
|
||||||
|
1.0.144.78
|
||||||
|
1.0.144.99
|
||||||
|
1.0.144.112
|
||||||
|
1.0.144.127
|
||||||
|
1.0.144.130
|
||||||
|
1.0.144.150
|
||||||
|
1.0.144.164
|
||||||
|
1.0.144.167
|
||||||
|
1.0.144.172
|
||||||
|
1.0.144.177
|
||||||
|
1.0.144.178
|
||||||
|
1.0.144.181
|
||||||
|
1.0.144.182
|
||||||
|
1.0.144.183
|
||||||
|
1.0.144.186
|
||||||
|
1.0.144.193
|
||||||
|
1.0.144.197
|
||||||
|
1.0.144.206
|
||||||
|
1.0.144.207
|
||||||
|
1.0.144.224
|
||||||
62
utils/dns_utils.go
Normal file
62
utils/dns_utils.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// dns utils
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DNSOptions struct {
|
||||||
|
Domain string
|
||||||
|
RD bool
|
||||||
|
Qclass uint16
|
||||||
|
Qtype uint16
|
||||||
|
EDNS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the question section of a dns packet
|
||||||
|
func questionMaker(domain string, qclass uint16, qtype uint16) *dns.Question {
|
||||||
|
return &dns.Question{Name: dns.Fqdn(domain), Qtype: qtype, Qclass: qclass}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build a specific query message
|
||||||
|
func queryMaker(domain string, rd bool, qclass uint16, qtype uint16, edns bool) *dns.Msg {
|
||||||
|
msg := new(dns.Msg)
|
||||||
|
msg.Id = dns.Id()
|
||||||
|
msg.RecursionDesired = rd
|
||||||
|
msg.Question = make([]dns.Question, 1)
|
||||||
|
msg.Question[0] = *questionMaker(domain, qclass, qtype)
|
||||||
|
if edns {
|
||||||
|
msg = msg.SetEdns0(1232, false)
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// query and receive the response
|
||||||
|
// addr must contain dest port
|
||||||
|
// func DNSQuery(addr string, domain string, rd bool, qclass uint16, qtype uint16, edns bool) (*dns.Msg, error) {
|
||||||
|
func DNSQuery(addr string, opt DNSOptions) (*dns.Msg, error) {
|
||||||
|
if opt.Qclass == 0 {
|
||||||
|
opt.Qclass = 1
|
||||||
|
}
|
||||||
|
if opt.Qtype == 0 {
|
||||||
|
opt.Qtype = 1
|
||||||
|
}
|
||||||
|
msg := queryMaker(opt.Domain, opt.RD, opt.Qclass, opt.Qtype, opt.EDNS)
|
||||||
|
res, err := dns.Exchange(msg, addr)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func AsyncDNSQuery(addr string, domain string, rd bool, qclass uint16, qtype uint16, edns bool) error {
|
||||||
|
msg := queryMaker(domain, rd, qclass, qtype, edns)
|
||||||
|
client := dns.Client{Net: "udp"}
|
||||||
|
conn, err := client.Dial(addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
err = conn.WriteMsg(msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
31
utils/other_utils.go
Normal file
31
utils/other_utils.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
_ "encoding/json"
|
||||||
|
_ "fmt"
|
||||||
|
"io"
|
||||||
|
_ "net"
|
||||||
|
_ "net/http"
|
||||||
|
"os"
|
||||||
|
_ "strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RetrieveLines(pool chan string, filename string) {
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
//fmt.Println("reading file ...")
|
||||||
|
reader := bufio.NewReader(f)
|
||||||
|
for {
|
||||||
|
s, err := reader.ReadString('\n')
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s = strings.Trim(s, "\n")
|
||||||
|
pool <- s
|
||||||
|
}
|
||||||
|
close(pool)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user