From d0eb73e20c50fd7cf0d8ecaffb4eedd8a76c919b Mon Sep 17 00:00:00 2001
From: Pawan Rawal <pawan0201@gmail.com>
Date: Wed, 13 Apr 2016 10:58:30 +0530
Subject: [PATCH] Adding support for client.

Client establishes a TCP connection with server. Sends a sample query and parses response.
Server listens to client, handles the query and sends back response.
---
 client/go/main.go | 66 +++++++++++++++++++++++++++++++++++++++++++++
 server/main.go    | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 client/go/main.go

diff --git a/client/go/main.go b/client/go/main.go
new file mode 100644
index 00000000..f2d5d870
--- /dev/null
+++ b/client/go/main.go
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 DGraph Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"net"
+
+	"github.com/dgraph-io/dgraph/x"
+)
+
+var glog = x.Log("client")
+
+var port = flag.String("port", "3000", "Port to communicate with server")
+
+func main() {
+
+	var q0 = `
+  {
+    user(_xid_:alice) {
+      follows {
+        _xid_
+        status
+      }
+      _xid_
+      status
+    }
+  }
+`
+
+	conn, err := net.Dial("tcp", "127.0.0.1:"+*port)
+	if err != nil {
+		glog.Fatalf("While running server: %v", err)
+	}
+
+	fmt.Println("sending data", []byte(q0))
+	_, err = conn.Write([]byte(q0))
+	if err != nil {
+		x.Err(glog, err).Fatal("Error in writing to server")
+	}
+
+	reply := []byte{}
+	_, err = conn.Read(reply)
+	if err != nil {
+		x.Err(glog, err).Fatal("Error in reading response from server")
+	}
+	fmt.Println(string(reply))
+
+	conn.Close()
+
+}
diff --git a/server/main.go b/server/main.go
index 8a7c90dd..720a1785 100644
--- a/server/main.go
+++ b/server/main.go
@@ -21,6 +21,7 @@ import (
 	"flag"
 	"fmt"
 	"io/ioutil"
+	"net"
 	"net/http"
 	"runtime"
 	"strings"
@@ -195,6 +196,72 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
 	fmt.Fprint(w, string(js))
 }
 
+func pbQueryHandler(q []byte) (pb []byte, rerr error) {
+	fmt.Println("in pbQueryHandler")
+	glog.WithField("q", string(q)).Debug("Query received.")
+	gq, _, err := gql.Parse(string(q))
+	if err != nil {
+		x.Err(glog, err).Error("While parsing query")
+		return pb, err
+	}
+
+	sg, err := query.ToSubGraph(gq)
+	if err != nil {
+		x.Err(glog, err).Error("While conversion to internal format")
+		return pb, err
+	}
+	glog.WithField("q", string(q)).Debug("Query parsed.")
+
+	rch := make(chan error)
+	go query.ProcessGraph(sg, rch)
+	err = <-rch
+	if err != nil {
+		x.Err(glog, err).Error("While executing query")
+		return pb, err
+	}
+
+	glog.WithField("q", string(q)).Debug("Graph processed.")
+	pb, err = sg.ToProtocolBuffer()
+	if err != nil {
+		x.Err(glog, err).Error("While converting to Json.")
+		return pb, err
+	}
+
+	return pb, err
+}
+
+func runServerForClient(address string) error {
+	ln, err := net.Listen("tcp", address)
+	if err != nil {
+		glog.Fatalf("While running server for client: %v", err)
+		return err
+	}
+	glog.WithField("address", ln.Addr()).Info("Client Worker listening")
+
+	go func() {
+		for {
+			cxn, err := ln.Accept()
+			if err != nil {
+				glog.Fatalf("listen(%q): %s\n", address, err)
+				return
+			}
+			glog.WithField("local", cxn.LocalAddr()).
+				WithField("remote", cxn.RemoteAddr()).
+				Debug("Client Worker accepted connection")
+
+			q := make([]byte, 1024000)
+			// Move to separate function
+			go func(c net.Conn) {
+				_, _ = c.Read(q)
+				fmt.Println("query received: ", string(q))
+				r, _ := pbQueryHandler(q)
+				c.Write(r)
+			}(cxn)
+		}
+	}()
+	return nil
+}
+
 func main() {
 	flag.Parse()
 	if !flag.Parsed() {
@@ -239,6 +306,8 @@ func main() {
 
 	worker.Connect(addrs)
 
+	runServerForClient(":3000")
+
 	http.HandleFunc("/query", queryHandler)
 	glog.WithField("port", *port).Info("Listening for requests...")
 	if err := http.ListenAndServe(":"+*port, nil); err != nil {
-- 
GitLab