I am having difficulty connecting my program to my local host. After doing some debugging I found that my problem is my listener and dialer. They aren't "talking". Could someone assist me in figuring out the problem.
client
func NewServer(httpAddr string , remoteAddr string , webdirect string, cacheInterval time.Duration) (*Server, error) {
conn, err := grpc.DialContext( context.Background(),"localhost:8080", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
//return nil, err
log.Fatalf("Unable to connect to server: %v", err)
}
defer conn.Close()
// make a grpc pb client
client := pb.NewClicksClient(conn)
return &APIServer{
grpcConn: conn,
clicks: client,
webdirect: webdirect,
httpAddr: httpAddr,
cache: Cache{
loop: sync2.NewCycle(cacheInterval),
},
}, nil
}
server
func Start(ctx context.Context, remoteAddr string) error {
lis, err := net.Listen("tcp", "localhost: 8080")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
clicks := &ClicksDatabase{}
s := grpc.NewServer()
pb.RegisterClicksServer(s, clicks)
log.Println("Serving gRPC on 0.0.0.0:8080")
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
return s.Serve(lis)
}
Replace localhost: 8080 with just :8080 in your net.Listen
Related
I'm trying to use a custom DialTLS Function in the http.Transport whilst using a HTTP proxy at the same time.
This is what I tried so far but whenever I configure the HTTP proxy it doesn't use the custom DialTLS Function :
tr, err := NewTransport("771,4865-4866-4867-49196-49195-49188-49187-49162-49161-52393-49200-49199-49192-49191-49172-49171-52392-157-156-61-60-53-47-49160-49170-10,65281-0-23-13-5-18-16-11-51-45-43-10-21,29-23-24-25,0")
if err != nil {
print(err)
}
tr.Proxy = http.ProxyURL(proxyURL)
tr.DisableKeepAlives = true
httpclient := &http.Client{Transport: tr, Timeout: 2 * time.Second}
proxyURL, err := url.Parse(fmt.Sprintf("http://%s", "127.0.0.1:80"))
if err != nil {
return errors.New("invalid proxy")
}
I have looked into the docs for the http.Transport and I found nothing that can help. Incase this is also required this is the custom DialTLS function I'm using:
dialtls := func(network, addr string) (net.Conn, error) {
dialConn, err := net.Dial(network, addr)
if err != nil {
return nil, err
}
config.ServerName = strings.Split(addr, ":")[0]
uTLSConn := tls.UClient(dialConn, config, tls.HelloCustom)
if err := uTLSConn.ApplyPreset(spec); err != nil {
return nil, err
}
if err := uTLSConn.Handshake(); err != nil {
return nil, err
}
return uTLSConn, nil
}
I'm trying to change the ja3 fingerprint a.k.a tls config. If anyone knows how I could achieve this please let me know
I am trying to set up a way to communicate between a central server running Go an a fleet of IoT devices (also running Go).
For each device, it connects to to the central server through a persistent TCPConn. These devices are behind a router(s). The central server saves that connection and sends/receives messages through it. Right now, this is fully functional and works.
However, now the message passing is getting complicated enough that the utility provided by HTTP rather than pure TCP is becoming necessary.
I have attempted to write a version of http.Transport that returns said connection. However, I am unable to provide and return a valid connection from the the Dial/DialContext functions.
IoT Device
func main() {
http.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
tcpAddr, err := net.ResolveTCPAddr("tcp", "###.###.###.###:8533")
if err != nil {
panic(err)
}
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
panic(err)
}
err = conn.SetKeepAlive(true)
if err != nil {
panic(err)
}
err = conn.SetKeepAlivePeriod(time.Second * 10)
if err != nil {
panic(err)
}
fmt.Println("Listening")
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
Central Server
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp", port)
if err != nil {
panic(err)
}
listener, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
panic(err)
}
conn, err := listener.AcceptTCP()
if err != nil {
panic(err)
}
fmt.Println("Received conn, attempting to send HTTP through connection")
dialFunc := func(network, addr string) (net.Conn, error) {
return conn, nil
}
t := http.Transport{
Dial: dialFunc,
}
client := http.Client{
Transport: &t,
}
fmt.Println("Making request")
res, err := client.Get("http://www.shouldNotMatter.com:8080/foo") // HANGS HERE
if err != nil {
fmt.Println(err)
}
fmt.Println("Received response")
defer res.Body.Close()
if res.StatusCode == http.StatusOK {
bodyBytes, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
bodyString := string(bodyBytes)
fmt.Println(bodyString)
} else {
fmt.Println(res)
}
}
Upon using a debugger to see where it hangs, it seems that it gets stuck in a select statement during the pconn roundtrip. Line 2420 in https://golang.org/src/net/http/transport.go?s=3397:10477
Create a type that returns an existing connection from a dial method:
type connDialer struct {
c net.Conn
}
func (cd connDialer) Dial(network, addr string) (net.Conn, error) {
return cd.c, nil
}
Use the dial method value in a transport:
client := http.Client{Transport: &http.Transport{Dial: connDialer{c}.Dial}}
where c is the existing net.Conn.
Try it on the playground (it works for at one request. It will fail when the client dials a second connection).
The overall approach is fragile. Consider using WebSockets, gRPC or other protocols that are designed to support bi-directional communication.
You missed the code on the client code. The client makes an idle connection to the server and does nothing with it so the connection will definitely hang up. You need to pass the connection to the HTTP server. This can be achieved by using net/http.Serve and passing a net.Listener to it.
type connListener struct {
conn net.Conn
ch chan struct{}
}
func (c connListener) Accept() (Conn, error) {
if c.conn != nil {
conn := c.conn
c.conn = nil
return conn, nil
}
<-c.ch
return nil, errors.New("listener closed")
}
func (c connListener) Close() error {
close(c.ch)
return nil
}
func (c connListener) Addr() net.Addr {
return c.conn.LocalAddr()
}
// call it like this
http.Serve(connListener{conn, make(chan struct{})}, nil)
BTW are you having the client connect to the server and then reverse the connection, making the client behave like an HTTP server and the server behave like the HTTP client? You might want to google "reverse http" for some information on this.
I need a golang client that can upgrade from an http get response to a websocket connection.
I have a JS client that works and I've seen direct ws client connections but I have to upgrade from http. I have tried looking for other 3GL solutions (Java, C#, Python) but I need to be able to implement the upgrade in Go. I have seen Dart detaching the socket and creating a websocket from it.
WebSocket.fromUpgradedSocket
I noticed Client does not support Hijack but the discussion didn't get me anywhere.
I am using github.com/gorilla/websocket but can change that if it helps.
Server:
func main() {
srv := Srv{}
count = 0
http.HandleFunc("/", srv.handleRoot)
http.HandleFunc("/ws", srv.handleWs)
log.Fatal(http.ListenAndServe(":5002", nil))
}
func (tool *Srv) handleRoot(w http.ResponseWriter, r *http.Request) {
webSocketKey := hdr.Get("Sec-WebSocket-Key")
log.Printf("Socket key = '%v'", webSocketKey)
secWsAccept := computeAcceptKey(webSocketKey)
log.Printf("Accept = '%v'", secWsAccept)
w.Header().Add("sec-websocket-accept", secWsAccept)
w.Header().Add("upgrade", "websockt")
w.Header().Add("connection", "upgrade")
w.WriteHeader(101)
}
func (tool *Srv) handleWs(w http.ResponseWriter, r *http.Request) {
var upgrader = websocket.Upgrader{}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatalf("Websocket fatal error. %v", err)
}
tool.conn = conn
go tool.serviceWsRequests()
}
func (tool *Srv) serviceWsRequests() {
for {
log.Printf("starting ws")
req := request{}
err := tool.conn.ReadJSON(&req)
if err != nil {
log.Printf("Failed to decode ws message. %v", err)
break
}
fmt.Printf("Got request. %v\n", req)
if req.Method == "ping" {
fmt.Printf("Param=%v\n", req.Parameters)
}
}
}
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
func computeAcceptKey(challengeKey string) string {
h := sha1.New()
h.Write([]byte(challengeKey))
h.Write(keyGUID)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
Client:
func main() {
tr := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
}
client := &http.Client{
Transport: tr,
// Do NOT follow redirects
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
wsKey, err := generateKey()
if err != nil {
log.Printf("Cannot generate challenge key %v", err)
}
// Get request for ws upgrade.
req, err := http.NewRequest("GET", "http://localhost:5002", nil)
req.Header.Add("Connection", "Upgrade")
req.Header.Add("Upgrade", "websocket")
req.Header.Add("Sec-WebSocket-Version", "13")
req.Header.Add("Sec-WebSocket-Key", wsKey)
log.Printf("ws key '%v'", wsKey)
resp, err := client.Do(req)
if err != nil {
log.Printf("Get error %v", err)
}
defer func() {
if resp != nil {
err = resp.Body.Close()
}
}()
log.Printf("Status='%v', proto='%v'", resp.Status, resp.Proto)
body, err := ioutil.ReadAll(resp.Body)
hdr := resp.Header
for k, v := range hdr{
log.Printf("%v : %v", k, v)
}
log.Printf("Body = %v", string(body))
resp, err = http.Get("ws://localhost:5002/ws")
if err != nil {
log.Printf("Error '%v'", err)
}
}
func generateKey() (string, error) {
p := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, p); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(p), nil
}
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
func computeAcceptKey(challengeKey string) string {
h := sha1.New()
h.Write([]byte(challengeKey))
h.Write(keyGUID)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
I get an error
Error 'Get ws://localhost:5002/ws: unsupported protocol scheme "ws"'
Which doesn't surprise me because I haven't upgraded the connection.
So how do I go an upgrade in Go?
Use the Gorilla client to dial websocket connections:
func main() {
c, _ , err := websocket.DefaultDialer.Dial("ws://localhost:5002/ws", nil)
if err != nil {
// handle error
}
defer c.Close()
// do something with c, a *websocket.Conn
}
The Dial method issues a GET to the server requesting an upgrade to the WebSocket protocol. On successful completion of the upgrade, Dial returns a *websocket.Conn.
I have a long running app that I'd like to monitor in real time. HAR files allow me to do this after the fact, but as they are an "archive", they don't allow me to do this in real time.
Is their anyway to stream the "events" array of the HAR file so I can process them as they are generated?
This can be firefox or chrome.
So with some help from https://github.com/mafredri/cdp/tree/master/example/screencast I figured out how to do this in go with chrome's debugger api
What this code doesn't do is tie the request body to the response (where it isn't available), but as I show the RequestID will be consistent so if one serializes event processing (say via locking) one can save the body and use it when the response event is seen.
package main
import (
"context"
"log"
"github.com/mafredri/cdp"
"github.com/mafredri/cdp/cdpcmd"
"github.com/mafredri/cdp/devtool"
"github.com/mafredri/cdp/rpcc"
)
func main() {
if err := run(); err != nil {
panic(err)
}
}
func run() error {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
devt := devtool.New("http://localhost:9222")
page, err := devt.Get(ctx, devtool.Page)
if err != nil {
return err
}
conn, err := rpcc.DialContext(ctx, page.WebSocketDebuggerURL)
if err != nil {
return err
}
defer conn.Close()
c := cdp.NewClient(conn)
err = c.Page.Enable(ctx)
if err != nil {
return err
}
loadEventFired, err := c.Page.LoadEventFired(ctx)
if err != nil {
return err
}
_, err = c.Page.Navigate(ctx, cdpcmd.NewPageNavigateArgs("https://github.com/"))
if err != nil {
return err
}
_, err = loadEventFired.Recv()
if err != nil {
return err
}
loadEventFired.Close()
a := &cdpcmd.NetworkEnableArgs{}
a.SetMaxResourceBufferSize(32000)
a.SetMaxTotalBufferSize(96000)
err = c.Network.Enable(ctx, a)
responseEvents, err := c.Network.ResponseReceived(ctx)
requestEvents, err := c.Network.RequestWillBeSent(ctx)
go func() {
defer responseEvents.Close()
for {
ev, err := responseEvents.Recv()
if err != nil {
log.Printf("Failed to receive network event: %v", err)
return
}
log.Printf("requestid = %v, url = %v", ev.RequestID, ev.Response.URL)
}
}()
go func() {
defer requestEvents.Close()
for {
ev, err := requestEvents.Recv()
if err != nil {
log.Printf("Failed to receive network event: %v", err)
return
}
log.Printf("requestid = %v, url = %v", ev.RequestID, ev.Request.URL)
}
}()
select {}
return nil
}
I am trying to modify my echo server program in order to create a chat client. Currently, I have my server listening to a port when I start up my client. Then, the client can type and send a message to the server and the server will echo it back.
However, I would like to be able to connect 2 clients to 2 different ports and let the clients send messages to each other over the server. Is there any way I could do this? I am assuming that the first step would be to listen to 2 ports instead of one.
Here is what I have so far.
Server:
package main
import (
"fmt"
"log"
"net"
)
func main() {
fmt.Println("The server is listening on Port 3000")
listener, _ := net.Listen("tcp", "localhost:3000")
//listener2, _ := net.Listen("tcp", "localhost:8080")
defer listener.Close()
//defer listener2.Close()
// Listen for connections
for {
conn, _ := listener.Accept()
//conn2, _ := listener2.Accept()
fmt.Println("New connection found!")
go listenConnection(conn)
//go listenConnection(conn2)
}
}
//Listen for messages and reply
func listenConnection(conn net.Conn) {
fmt.Println("Yay")
for {
buffer := make([]byte, 1400)
dataSize, err := conn.Read(buffer)
if err != nil {
fmt.Println("Connection has closed")
return
}
//This is the message you received
data := buffer[:dataSize]
fmt.Print("Received message: ", string(data))
// Send the message back
_, err = conn.Write(data)
if err != nil {
log.Fatalln(err)
}
fmt.Print("Message sent: ", string(data))
}
}
Client:
package main
import (
"fmt"
"log"
"net"
"bufio"
"os"
)
func main() {
conn, err := net.Dial("tcp", "localhost:3000")
if err != nil {
log.Fatalln(err)
}
for {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter text: ")
text, _ := reader.ReadString('\n')
_, err = conn.Write([]byte(text))
if err != nil {
log.Fatalln(err)
}
for {
buffer := make([]byte, 1400)
dataSize, err := conn.Read(buffer)
if err != nil {
fmt.Println("The connection has closed!")
return
}
data := buffer[:dataSize]
fmt.Println("Received message: ", string(data))
break
}
}
}
Is there any way to listen to 2 clients (ports) on 1 server and let them communicate? Is it possible to do this with both clients on the same port? I tried adding another listener in the Server program, but I commented those lines out for now as they did not work. I will appreciate any help!
The server code in the question handles multiple clients on the same port.
To work with two ports, create two listeners and run the accept loops for these listeners in separate goroutines:
func main() {
fmt.Println("The server is listening on Port 3000")
listener, err := net.Listen("tcp", "localhost:3000")
if err != nil {
log.Fatal(err)
}
listener2, err := net.Listen("tcp", "localhost:8080")
if err != nil {
log.Fatal(err)
}
go acceptLoop(listener)
acceptLoop(listener2) // run in the main goroutine
}
func acceptLoop(l net.Listener) {
defer l.Close()
for {
c, err := l.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("New connection found!")
go listenConnection(c)
}
}
Also, don't ignore errors. The code in this answer handles errors by calling log.Fatal. That may or may not be appropriate for your application.