git » dnss » commit 94ba7d7

Split half-way

author Alberto Bertogli
2015-09-06 22:06:39 UTC
committer Alberto Bertogli
2015-09-06 22:06:39 UTC
parent cea85ab3a8d0aaf3e65af83d7d0b4ebf5f56d3a0

Split half-way

.gitignore +1 -0
dnsproxy.go +78 -0
dnss.go +17 -64
dnss.pb.go +136 -0
dnss.proto +13 -0
dnstogrpc/dnstogrpc.go +82 -0

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a01ee28
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.*.swp
diff --git a/dnsproxy.go b/dnsproxy.go
new file mode 100644
index 0000000..31a06b6
--- /dev/null
+++ b/dnsproxy.go
@@ -0,0 +1,78 @@
+// Generate the protobuf+grpc service.
+//go:generate protoc --go_out=plugins=grpc:. dnss.proto
+
+package main
+
+import (
+	"fmt"
+	"strings"
+	"sync"
+
+	"github.com/miekg/dns"
+)
+
+func questionsToString(qs []dns.Question) string {
+	var s []string
+	for _, q := range qs {
+		s = append(s, fmt.Sprintf("(%s %s %s)", q.Name,
+			dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]))
+	}
+	return "Q[" + strings.Join(s, " ") + "]"
+}
+
+func rrsToString(rrs []dns.RR) string {
+	var s []string
+	for _, rr := range rrs {
+		s = append(s, fmt.Sprintf("(%s)", rr))
+	}
+	return "RR[" + strings.Join(s, " ") + "]"
+
+}
+
+func L(w dns.ResponseWriter, r *dns.Msg) string {
+	return fmt.Sprintf("%v %v", w.RemoteAddr(), r.Id)
+}
+
+func Handler(w dns.ResponseWriter, r *dns.Msg) {
+	fmt.Printf("%v %v\n", L(w, r), questionsToString(r.Question))
+
+	// TODO: we should create our own IDs, in case different users pick the
+	// same id and we pass that upstream.
+
+	from_up, err := dns.Exchange(r, "8.8.8.8:53")
+	if err != nil {
+		fmt.Printf("%v  ERR: %v\n", L(w, r), err)
+		fmt.Printf("%v  UP: %v\n", L(w, r), from_up)
+	}
+
+	if from_up != nil {
+		if from_up.Rcode != dns.RcodeSuccess {
+			rcode := dns.RcodeToString[from_up.Rcode]
+			fmt.Printf("%v  !->  %v\n", L(w, r), rcode)
+
+		}
+		for _, rr := range from_up.Answer {
+			fmt.Printf("%v  ->  %v\n", L(w, r), rr)
+		}
+		w.WriteMsg(from_up)
+	}
+}
+
+func main() {
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(":5354", "udp", dns.HandlerFunc(Handler))
+		fmt.Printf("Exiting UDP: %v\n", err)
+	}()
+
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(":5354", "tcp", dns.HandlerFunc(Handler))
+		fmt.Printf("Exiting TCP: %v\n", err)
+	}()
+
+	wg.Wait()
+}
diff --git a/dnss.go b/dnss.go
index 56016d2..ea6df66 100644
--- a/dnss.go
+++ b/dnss.go
@@ -1,75 +1,28 @@
+// Generate the protobuf+grpc service.
+//go:generate protoc --go_out=plugins=grpc:. dnss.proto
+
 package main
 
 import (
-	"fmt"
-	"strings"
-	"sync"
+	"flag"
 
-	"github.com/miekg/dns"
+	"blitiri.com.ar/go/dnss/dnstogrpc"
+	"blitiri.com.ar/go/profile"
 )
 
-func questionsToString(qs []dns.Question) string {
-	var s []string
-	for _, q := range qs {
-		s = append(s, fmt.Sprintf("(%s %s %s)", q.Name,
-			dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]))
-	}
-	return "Q[" + strings.Join(s, " ") + "]"
-}
-
-func rrsToString(rrs []dns.RR) string {
-	var s []string
-	for _, rr := range rrs {
-		s = append(s, fmt.Sprintf("(%s)", rr))
-	}
-	return "RR[" + strings.Join(s, " ") + "]"
-
-}
-
-func L(w dns.ResponseWriter, r *dns.Msg) string {
-	return fmt.Sprintf("%v %v", w.RemoteAddr(), r.Id)
-}
-
-func Handler(w dns.ResponseWriter, r *dns.Msg) {
-	fmt.Printf("%v %v\n", L(w, r), questionsToString(r.Question))
-
-	// TODO: we should create our own IDs, in case different users pick the
-	// same id and we pass that upstream.
-
-	from_up, err := dns.Exchange(r, "8.8.8.8:53")
-	if err != nil {
-		fmt.Printf("%v  ERR: %v\n", L(w, r), err)
-		fmt.Printf("%v  UP: %v\n", L(w, r), from_up)
-	}
-
-	if from_up != nil {
-		if from_up.Rcode != dns.RcodeSuccess {
-			rcode := dns.RcodeToString[from_up.Rcode]
-			fmt.Printf("%v  !->  %v\n", L(w, r), rcode)
-
-		}
-		for _, rr := range from_up.Answer {
-			fmt.Printf("%v  ->  %v\n", L(w, r), rr)
-		}
-		w.WriteMsg(from_up)
-	}
-}
+var (
+	dnsaddr     = flag.String("dnsaddr", ":53", "address to listen on")
+	dnsupstream = flag.String("dnsupstream", "8.8.8.8:53", "upstream address")
+)
 
 func main() {
-	var wg sync.WaitGroup
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		err := dns.ListenAndServe(":5354", "udp", dns.HandlerFunc(Handler))
-		fmt.Printf("Exiting UDP: %v\n", err)
-	}()
+	flag.Parse()
 
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		err := dns.ListenAndServe(":5354", "tcp", dns.HandlerFunc(Handler))
-		fmt.Printf("Exiting TCP: %v\n", err)
-	}()
+	profile.Init()
 
-	wg.Wait()
+	dtg := &dnstogrpc.Server{
+		Addr:     *dnsaddr,
+		Upstream: *dnsupstream,
+	}
+	dtg.ListenAndServe()
 }
diff --git a/dnss.pb.go b/dnss.pb.go
new file mode 100644
index 0000000..0ffc7ba
--- /dev/null
+++ b/dnss.pb.go
@@ -0,0 +1,136 @@
+// Code generated by protoc-gen-go.
+// source: dnss.proto
+// DO NOT EDIT!
+
+/*
+Package dnss is a generated protocol buffer package.
+
+It is generated from these files:
+	dnss.proto
+
+It has these top-level messages:
+	GobMsg
+*/
+package dnss
+
+import proto "github.com/golang/protobuf/proto"
+
+import (
+	context "golang.org/x/net/context"
+	grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+
+type GobMsg struct {
+	// gob-encoded message.
+	// A horrible hack, but will do for now.
+	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (m *GobMsg) Reset()         { *m = GobMsg{} }
+func (m *GobMsg) String() string { return proto.CompactTextString(m) }
+func (*GobMsg) ProtoMessage()    {}
+
+func init() {
+}
+
+// Client API for DNSService service
+
+type DNSServiceClient interface {
+	Query(ctx context.Context, opts ...grpc.CallOption) (DNSService_QueryClient, error)
+}
+
+type dNSServiceClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewDNSServiceClient(cc *grpc.ClientConn) DNSServiceClient {
+	return &dNSServiceClient{cc}
+}
+
+func (c *dNSServiceClient) Query(ctx context.Context, opts ...grpc.CallOption) (DNSService_QueryClient, error) {
+	stream, err := grpc.NewClientStream(ctx, &_DNSService_serviceDesc.Streams[0], c.cc, "/.DNSService/Query", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &dNSServiceQueryClient{stream}
+	return x, nil
+}
+
+type DNSService_QueryClient interface {
+	Send(*GobMsg) error
+	Recv() (*GobMsg, error)
+	grpc.ClientStream
+}
+
+type dNSServiceQueryClient struct {
+	grpc.ClientStream
+}
+
+func (x *dNSServiceQueryClient) Send(m *GobMsg) error {
+	return x.ClientStream.SendProto(m)
+}
+
+func (x *dNSServiceQueryClient) Recv() (*GobMsg, error) {
+	m := new(GobMsg)
+	if err := x.ClientStream.RecvProto(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// Server API for DNSService service
+
+type DNSServiceServer interface {
+	Query(DNSService_QueryServer) error
+}
+
+func RegisterDNSServiceServer(s *grpc.Server, srv DNSServiceServer) {
+	s.RegisterService(&_DNSService_serviceDesc, srv)
+}
+
+func _DNSService_Query_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(DNSServiceServer).Query(&dNSServiceQueryServer{stream})
+}
+
+type DNSService_QueryServer interface {
+	Send(*GobMsg) error
+	Recv() (*GobMsg, error)
+	grpc.ServerStream
+}
+
+type dNSServiceQueryServer struct {
+	grpc.ServerStream
+}
+
+func (x *dNSServiceQueryServer) Send(m *GobMsg) error {
+	return x.ServerStream.SendProto(m)
+}
+
+func (x *dNSServiceQueryServer) Recv() (*GobMsg, error) {
+	m := new(GobMsg)
+	if err := x.ServerStream.RecvProto(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+var _DNSService_serviceDesc = grpc.ServiceDesc{
+	ServiceName: ".DNSService",
+	HandlerType: (*DNSServiceServer)(nil),
+	Methods:     []grpc.MethodDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Query",
+			Handler:       _DNSService_Query_Handler,
+			ServerStreams: true,
+			ClientStreams: true,
+		},
+	},
+}
diff --git a/dnss.proto b/dnss.proto
new file mode 100644
index 0000000..92d204c
--- /dev/null
+++ b/dnss.proto
@@ -0,0 +1,13 @@
+
+syntax = "proto3";
+
+message GobMsg {
+	// gob-encoded message.
+	// A horrible hack, but will do for now.
+	bytes data = 1;
+}
+
+service DNSService {
+	rpc Query(stream GobMsg) returns (stream GobMsg);
+}
+
diff --git a/dnstogrpc/dnstogrpc.go b/dnstogrpc/dnstogrpc.go
new file mode 100644
index 0000000..ced0d05
--- /dev/null
+++ b/dnstogrpc/dnstogrpc.go
@@ -0,0 +1,82 @@
+// DNS to GRPC.
+
+package dnstogrpc
+
+import (
+	"fmt"
+	"strings"
+	"sync"
+
+	"github.com/miekg/dns"
+)
+
+func questionsToString(qs []dns.Question) string {
+	var s []string
+	for _, q := range qs {
+		s = append(s, fmt.Sprintf("(%s %s %s)", q.Name,
+			dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]))
+	}
+	return "Q[" + strings.Join(s, " ") + "]"
+}
+
+func rrsToString(rrs []dns.RR) string {
+	var s []string
+	for _, rr := range rrs {
+		s = append(s, fmt.Sprintf("(%s)", rr))
+	}
+	return "RR[" + strings.Join(s, " ") + "]"
+
+}
+
+func l(w dns.ResponseWriter, r *dns.Msg) string {
+	return fmt.Sprintf("%v %v", w.RemoteAddr(), r.Id)
+}
+
+type Server struct {
+	Addr     string
+	Upstream string
+}
+
+func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
+	fmt.Printf("%v %v\n", l(w, r), questionsToString(r.Question))
+
+	// TODO: we should create our own IDs, in case different users pick the
+	// same id and we pass that upstream.
+
+	from_up, err := dns.Exchange(r, s.Upstream)
+	if err != nil {
+		fmt.Printf("%v  ERR: %v\n", l(w, r), err)
+		fmt.Printf("%v  UP: %v\n", l(w, r), from_up)
+	}
+
+	if from_up != nil {
+		if from_up.Rcode != dns.RcodeSuccess {
+			rcode := dns.RcodeToString[from_up.Rcode]
+			fmt.Printf("%v  !->  %v\n", l(w, r), rcode)
+
+		}
+		for _, rr := range from_up.Answer {
+			fmt.Printf("%v  ->  %v\n", l(w, r), rr)
+		}
+		w.WriteMsg(from_up)
+	}
+}
+
+func (s *Server) ListenAndServe() {
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(s.Addr, "udp", dns.HandlerFunc(s.Handler))
+		fmt.Printf("Exiting UDP: %v\n", err)
+	}()
+
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(s.Addr, "tcp", dns.HandlerFunc(s.Handler))
+		fmt.Printf("Exiting TCP: %v\n", err)
+	}()
+
+	wg.Wait()
+}