I am trying to make an HTTP/HTTPS proxy with Golang like this link.
This is all my code :
First get command from browser. If it's CONNECT mean HTTPS and make simple TCP socket and let browser continue it. then pipe each connection together.
package main
import (
"bufio"
"fmt"
"net"
"strings"
)
func main() {
fmt.Println("Start server...")
ln, _ := net.Listen("tcp", ":8000")
conn, _ := ln.Accept()
handleSocket(conn)
}
func handleSocket(client_to_proxy net.Conn) {
message, e := bufio.NewReader(client_to_proxy).ReadString('\n')
message = strings.ReplaceAll(message, "\r\n", "")
if e != nil {
fmt.Println("ERROR1 ", e)
return
}
splited := strings.Split(message, " ")
host := strings.Split(splited[1], ":")
if splited[0] == "CONNECT" {
proxy_to_server, e := net.Dial("tcp", splited[1])
if e != nil {
fmt.Println("ERROR2 ", e)
return
}
lenn, e := client_to_proxy.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
if e != nil {
fmt.Println("ERROR8 ", e)
return
}
fmt.Println(lenn)
readAll(client_to_proxy, proxy_to_server)
} else if splited[0] == "GET" {
remote_conn, e := net.Dial("tcp", strings.Replace(splited[1][:len(splited[1])-1], "http://", "", 2)+":80")
if e != nil {
fmt.Println("ERROR7 ", e)
return
}
_, e = remote_conn.Write([]byte("GET / " + splited[2] + "\r\n" + "Host: " + host[0] + "\r\n\r\n"))
if e != nil {
fmt.Println("ERROR6 ", e)
return
}
writeAll(client_to_proxy, remote_conn)
}
}
func writeAll(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 32*1024)
for {
readLeng, err := proxy_to_server.Read(buffer)
if err != nil {
fmt.Println("ERROR9 ", err)
return
}
if readLeng > 0 {
_, err := client_to_proxy.Write(buffer)
if err != nil {
fmt.Println("ERR4 ", err)
return
}
}
}
}
func readAll(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 32*1024)
go writeAll(client_to_proxy, proxy_to_server)
for {
read, err := client_to_proxy.Read(buffer)
if err != nil {
return
}
if read > 0 {
_, err := proxy_to_server.Write(buffer)
if err != nil {
fmt.Println("ERR5 ", err)
return
}
}
}
}
It works OK with HTTP but when trying for HTTPS in Firefox, I receive this error:
Secure Connection Failed
An error occurred during a connection to www.google.com. SSL received a record with an incorrect Message Authentication Code.
Error code: SSL_ERROR_BAD_MAC_READ
Like all HTTP requests the CONNECT request starts with a multi-line request header which ends with a line consisting of only \r\n. But you only read the first line of it:
message, e := bufio.NewReader(client_to_proxy).ReadString('\n')
The rest of the request is send to the server, which likely returns some error, since this is not the expected start of a TLS handshake. This start of a TLS handshake only comes after the request header. The error returned by the server is then forwarded to the client and interpreted as TLS message - which is seen as a corrupt message, hence "bad mac".
readAll(client_to_proxy, proxy_to_server)
Instead of forwarding all remaining data (i.e. everything except the first line of the request) to the server you need to first read the full request header and only then forward everything between client and server.
Many Thanks to #steffen-ullrich, This is final solution for who comes later. works for http/https:
package main
import (
"fmt"
"net"
"strings"
)
func main() {
fmt.Println("Start server...")
ln, _ := net.Listen("tcp", ":8000")
for {
conn, _ := ln.Accept()
handleSocket(conn)
}
}
func handleSocket(client_to_proxy net.Conn) {
buffer := make([]byte, 32*1024)
_, e := client_to_proxy.Read(buffer)
if e != nil {
fmt.Println("ERROR1 ", e)
return
}
message := string(buffer)
a := strings.Count(message, "\r\n")
fmt.Println(message)
fmt.Println(a)
if e != nil {
fmt.Println("ERROR1 ", e)
return
}
splited := strings.Split(message, " ")
//host := strings.Split(splited[1], ":")
if splited[0] == "CONNECT" {
//message = strings.Replace(message, "CONNECT", "GET", 1)
proxy_to_server, e := net.Dial("tcp", splited[1])
if e != nil {
fmt.Println("ERROR2 ", e)
return
}
//_, e = proxy_to_server.Write([]byte(message))
//if e != nil {
// fmt.Println("ERROR2 ", e)
// return
//}
lenn, e := client_to_proxy.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
if e != nil {
fmt.Println("ERROR8 ", e)
return
}
fmt.Println(lenn)
read443(client_to_proxy, proxy_to_server)
} else if splited[0] == "GET" {
host1 := strings.Replace(splited[1], "http://", "", 1)
host2 := host1[:len(host1)-1]
var final_host string
if strings.LastIndexAny(host2, "/") > 0 {
final_host = host2[:strings.LastIndexAny(host2, "/")]
} else {
final_host = host2
}
proxy_to_server, e := net.Dial("tcp", final_host+":80")
if e != nil {
fmt.Println("ERROR7 ", e)
return
}
_, e = proxy_to_server.Write([]byte(message))
if e != nil {
fmt.Println("ERROR6 ", e)
return
}
write80(client_to_proxy, proxy_to_server)
}
}
func write80(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 64*1024)
readLeng, err := proxy_to_server.Read(buffer)
if err != nil {
fmt.Println("ERROR9 ", err)
return
}
fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := client_to_proxy.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR4 ", err)
return
}
}
go read80(client_to_proxy, proxy_to_server)
for {
readLeng, err := proxy_to_server.Read(buffer)
if err != nil {
fmt.Println("ERROR10 ", err)
return
}
fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := client_to_proxy.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR4 ", err)
return
}
}
}
}
func read80(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 32*1024)
for {
readLeng, err := client_to_proxy.Read(buffer)
if err != nil {
return
}
fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := proxy_to_server.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR5 ", err)
return
}
}
}
}
func write443(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 32*1024)
for {
readLeng, err := proxy_to_server.Read(buffer)
if err != nil {
fmt.Println("ERROR10 ", err)
return
}
fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := client_to_proxy.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR4 ", err)
return
}
}
}
}
func read443(client_to_proxy net.Conn, proxy_to_server net.Conn) {
buffer := make([]byte, 32*1024)
readLeng, err := client_to_proxy.Read(buffer)
if err != nil {
return
}
fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := proxy_to_server.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR5 ", err)
return
}
}
go write443(client_to_proxy, proxy_to_server)
for {
readLeng, err := client_to_proxy.Read(buffer)
if err != nil {
return
}
fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")
fmt.Println(string(buffer[:readLeng]))
if readLeng > 0 {
_, err := proxy_to_server.Write(buffer[:readLeng])
if err != nil {
fmt.Println("ERR5 ", err)
return
}
}
}
}
Related
Go version: go1.14.4 darwin/amd64
TCP server
package main
import (
"fmt"
"io"
"net"
"time"
)
const (
maxBufLen int = 4 * 1024
)
type Server struct {
}
func (s *Server) Start() {
listener, err := net.Listen("tcp", "localhost:9001")
if err != nil {
panic(err)
}
var connections []net.Conn
defer func() {
for _, conn := range connections {
// ignore
_ = conn.Close()
}
}()
// loop...
for {
connected, err := listener.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() {
// temporary err will bi ignored
continue
} else {
fmt.Println(err)
return
}
}
go handleConn(connected, true)
connections = append(connections, connected)
}
}
func handleConn(conn net.Conn, server bool) {
buf := make([]byte, maxBufLen)
for {
// read
setTimeout(conn)
_, err := conn.Read(buf)
if err != nil {
if ne, ok := err.(net.Error); ok && (ne.Timeout() || ne.Temporary()) {
fmt.Println("need continue...")
continue
}
if err == io.EOF {
fmt.Println("EOF")
break
}
// other...
panic(err)
}
// handle recv msg.
s := string(buf)
if server {
//fmt.Println("server recv req ", s)
} else {
fmt.Println("client recv resp ", s)
}
if server {
output := "hi " + s
ob := []byte(output)
_, err := conn.Write(ob)
if err != nil {
fmt.Println(err)
break
}
}
}
}
func setTimeout(conn net.Conn) {
setErr := conn.SetReadDeadline(time.Now().Add(20 * time.Second))
if setErr != nil {
panic(setErr)
}
}
TCP client
package main
import (
"net"
"time"
)
type Client struct {
Exit chan struct{}
}
func (c *Client) Start() {
conn, err := net.Dial("tcp", "localhost:9001")
if err != nil {
panic(err)
}
defer conn.Close()
go handleWrite(conn)
go handleConn(conn, false)
<-c.Exit
}
func handleWrite(conn net.Conn) {
for {
input := "carryxyh"
_, err := conn.Write([]byte(input))
if err != nil {
panic(err)
}
<-time.After(100 * time.Second)
}
}
Main function
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
type Starter interface {
Start()
}
func main() {
var s Server
var c Client
go s.Start()
go c.Start()
sigs := make(chan os.Signal)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
c.Exit <- struct{}{}
fmt.Println("exit")
}
Running package main will print :
client recv resp hi carryxyh
client recv resp carryxyh
Printed twice. But from the program point of view, the server only writes information to the client once, and the content of the information should be hi carryxyh. But the client printed carryxyh in addition to hi carryxyh, which made me very confused.
During the investigation, I accidentally modified a line of code, and the program immediately returned to normal:
modeifycode
As shown above, I modified the server response information: output := "hi "+ s => output := "hi ", at this time the program only prints client recv resp hi.
This makes me completely confused, can anyone help me solve this problem? It would be better if there is a troubleshooting idea.
enter image description here
这里你忽略了读取的字节长度,可能返回0字节,你又把buf的内容 又回写给client了.
_, err := conn.Read(buf) 改成 bytesRead, err := conn.Read(buf) ;
if bytesRead <= 0 { // 没有buf 可以读取 }
--
eg:
if bytesRead == 0 && err == nil {
err = io.EOF
log.Errorf("[network] ReadOnce maybe always return (0, nil) and causes dead loop, Connection = %d, Local Address = %+v, Remote Address = %+v",
c.id, c.rawConnection.LocalAddr(), c.RemoteAddr())
}
I am using golang net/smtp to send mails
Whenever I send to my smtp server I need to capture the response from the server
Especially the DSN
For example my local smtp server gives a "ok queued as " at the end of the mail
I need to capture this and print in the logs
How can I do this
package main
import (
"log"
"net/smtp"
)
func sendEmail(msg []byte) {
c, err := smtp.Dial("localhost:25")
if err != nil {
log.Fatal(err)
}
if err := c.Mail("sender#example.org"); err != nil {
log.Fatal(err)
}
if err := c.Rcpt("recipient#example.net"); err != nil {
log.Fatal(err)
}
wc, err := c.Data()
if err != nil {
log.Fatal(err)
}
_, err = wc.Write(msg)
if err != nil {
log.Fatal(err)
}
//How do I get the response here ??
err = wc.Close()
if err != nil {
log.Fatal(err)
}
err = c.Quit()
if err != nil {
log.Fatal(err)
}
}
As mentioned in the comments you can use c.Text.ReadResponse():
package main
import (
"net/smtp"
)
func sendEmail(msg []byte) (code int, message string, err error) {
c, err := smtp.Dial("localhost:25")
if err != nil {
return
}
defer c.Quit() // make sure to quit the Client
if err = c.Mail("sender#example.org"); err != nil {
return
}
if err = c.Rcpt("recipient#example.net"); err != nil {
return
}
wc, err := c.Data()
if err != nil {
return
}
defer wc.Close() // make sure WriterCloser gets closed
_, err = wc.Write(msg)
if err != nil {
return
}
code, message, err = c.Text.ReadResponse(0)
return
}
The code, message and any err are now passed to the caller, don't use log.Fatal throughout your code, handle the error on the calling side.
package main
import (
"net/smtp"
)
func sendEmail(msg []byte) (code int, message string, err error) {
c, err := smtp.Dial("localhost:25")
if err != nil {
return
}
defer c.Quit() // make sure to quit the Client
if err = c.Mail("sender#example.org"); err != nil {
return
}
if err = c.Rcpt("recipient#example.net"); err != nil {
return
}
wc, err := c.Data()
if err != nil {
return
}
_, err = wc.Write(msg)
if err != nil {
return
}
code, message, err = closeData(c)
if err != nil {
return 0, "", err
}
return code, message, err
}
func closeData(client *smtp.Client) error {
d := &dataCloser{
c: client,
WriteCloser: client.Text.DotWriter(),
}
return d.Close()
}
type dataCloser struct {
c *smtp.Client
io.WriteCloser
}
func (d *dataCloser) Close() (int, string, error) {
d.WriteCloser.Close() // make sure WriterCloser gets closed
code, message, err := d.c.Text.ReadResponse(250)
fmt.Printf("Message %v, Error %v\n", message, err)
return code, message, err
}
I'm trying to write a simple sockets based go server. I'm just wondering how does the connection.Read below knows when to stop reading.
(Note: this is not my code, I copied it from Unix Sockets in Go as example)
package main
import (
"log"
"net"
)
func echoServer(c net.Conn) {
for {
buf := make([]byte, 512)
nr, err := c.Read(buf)
if err != nil {
return
}
data := buf[0:nr]
println("Server got:", string(data))
_, err = c.Write(data)
if err != nil {
log.Fatal("Write: ", err)
}
}
}
func main() {
l, err := net.Listen("unix", "/tmp/echo.sock")
if err != nil {
log.Fatal("listen error:", err)
}
for {
fd, err := l.Accept()
if err != nil {
log.Fatal("accept error:", err)
}
go echoServer(fd)
}
}
Is it the EOF character or there's something else?
It would be really helpful if someone can point me to a link official go docs. Thanks.
This is the implementation of the default Read method on net.Conn.Read:
// Read implements the Conn Read method.
func (c *conn) Read(b []byte) (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
n, err := c.fd.Read(b)
if err != nil && err != io.EOF {
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
}
return n, err
}
This is the implementation of the c.fd.Read(b) that is called within the function above:
func (fd *netFD) Read(p []byte) (n int, err error) {
if err := fd.readLock(); err != nil {
return 0, err
}
defer fd.readUnlock()
if len(p) == 0 {
// If the caller wanted a zero byte read, return immediately
// without trying. (But after acquiring the readLock.) Otherwise
// syscall.Read returns 0, nil and eofError turns that into
// io.EOF.
// TODO(bradfitz): make it wait for readability? (Issue 15735)
return 0, nil
}
if err := fd.pd.prepareRead(); err != nil {
return 0, err
}
if fd.isStream && len(p) > 1<<30 {
p = p[:1<<30]
}
for {
n, err = syscall.Read(fd.sysfd, p)
if err != nil {
n = 0
if err == syscall.EAGAIN {
if err = fd.pd.waitRead(); err == nil {
continue
}
}
}
err = fd.eofError(n, err)
break
}
if _, ok := err.(syscall.Errno); ok {
err = os.NewSyscallError("read", err)
}
return
}
So, yes, an EOF will make it stop reading. But so will plenty of other non-nil errors.
It will stop reading when its underlying implementation hits any error.
Error may be an actual I/O error, or it could be the operating system signaling connection closed with io.EOF, or it could be a timeout, so on.
I'm working on porting some existing Python code to Go. One bit is in charge of sending emails through Exchange server (SMTP + STARTTLS). Existing (simplified) code looks like this:
import smtplib
client = smtplib.SMTP("exchangeserver.com")
client.starttls()
client.login('user', 'password')
client.sendmail('user#exchangeserver.com',
['otheruser1#exchangeserver.com', 'otheruser2#exchangeserver.com'],
'..message..')
I'd like to do the same thing with Go, help is appreciated - thanks.
Edited:
Here is an example using the tls connection setup. I don't have one to test against, so it fails on my end connecting, but I suspect this is what you need to make it work
package main
import (
"crypto/tls"
"fmt"
"log"
"net/smtp"
)
func main() {
var (
host = "smtp.google.com"
port = 587
from = "foo#bar.com"
password = "baz"
to = []string{"bin#bar.com"}
msg = []byte("This is my message")
auth = smtp.PlainAuth("", from, password, "smtp.gmail.com")
)
serverAddr := fmt.Sprintf("%s:%d", host, port)
conn, err := tls.Dial("tcp", serverAddr, nil)
if err != nil {
log.Printf("Error Dialing %s\n", err)
return
}
client, err := smtp.NewClient(conn, host)
if err != nil {
log.Printf("Error SMTP connection: %s\n", err)
return
}
if ok, _ := client.Extension("AUTH"); ok {
if err := client.Auth(auth); err != nil {
log.Printf("Error during AUTH %s\n", err)
return
}
}
if err := client.Mail(from); err != nil {
log.Printf("Error: %s\n", err)
return
}
for _, addr := range to {
if err := client.Rcpt(addr); err != nil {
log.Printf("Error: %s\n", err)
return
}
}
w, err := client.Data()
if err != nil {
log.Printf("Error: %s\n", err)
return
}
_, err = w.Write(msg)
if err != nil {
log.Printf("Error: %s\n", err)
return
}
err = w.Close()
if err != nil {
log.Printf("Error: %s\n", err)
return
}
client.Quit()
}
I think something like this might work. You'll have to make the appropriate changes for server, user/password, etc. Let me know if you need more help.
package main
import (
"fmt"
"log"
"net/smtp"
)
func main() {
to := "foo#foo.com"
from := "bin#baz.com"
password := "myPassword"
subject := "subject line of email"
msg := "a one-line email message"
emailTemplate := `To: %s
Subject: %s
%s
`
body := fmt.Sprintf(emailTemplate, to, subject, msg)
auth := smtp.PlainAuth("", from, password, "smtp.gmail.com")
err := smtp.SendMail(
"smtp.gmail.com:587",
auth,
from,
[]string{to},
[]byte(body),
)
if err != nil {
log.Fatal(err)
}
}
To expand on Cory LaNou's answer, you can use StartTLS on a normal net.Conn. You need to define a tls.Config and then use that to upgrade the connection to use TLS.
The example below is based on Cory's answer and also steals some code from the crypto/tls test files for creating the RSA cert and private key. In production you'd obviously replace these with real certs and keys.
It may require some customization of the variables, as well as some changes to the tls.Config to suit your environment.
package main
import (
"crypto/rsa"
"crypto/tls"
"encoding/hex"
"fmt"
"log"
"math/big"
"net"
"net/smtp"
)
func main() {
var (
host = "smtp.myexchange.com"
port = 587
from = "sender#example.org"
password = "password"
to = []string{"recipient#example.org"}
msg = []byte("This is my message")
auth = smtp.PlainAuth("", from, password, "smtp.myexchange.com")
)
conf := new(tls.Config)
conf.Certificates = make([]tls.Certificate, 1)
conf.Certificates[0].Certificate = [][]byte{testRSACertificate}
conf.Certificates[0].PrivateKey = testRSAPrivateKey
conf.CipherSuites = []uint16{tls.TLS_RSA_WITH_RC4_128_SHA}
conf.InsecureSkipVerify = true
conf.MinVersion = tls.VersionSSL30
conf.MaxVersion = tls.VersionTLS10
serverAddr := fmt.Sprintf("%s:%d", host, port)
conn, err := net.Dial("tcp", serverAddr)
if err != nil {
log.Printf("Error Dialing %s\n", err)
return
}
client, err := smtp.NewClient(conn, host)
if err != nil {
log.Printf("Error SMTP connection: %s\n", err)
return
}
if err = client.StartTLS(conf); err != nil {
log.Printf("Error performing StartTLS: %s\n", err)
return
}
if ok, _ := client.Extension("AUTH"); ok {
if err := client.Auth(auth); err != nil {
log.Printf("Error during AUTH %s\n", err)
return
}
}
if err := client.Mail(from); err != nil {
log.Printf("Error: %s\n", err)
return
}
for _, addr := range to {
if err := client.Rcpt(addr); err != nil {
log.Printf("Error: %s\n", err)
return
}
}
w, err := client.Data()
if err != nil {
log.Printf("Error: %s\n", err)
return
}
_, err = w.Write(msg)
if err != nil {
log.Printf("Error: %s\n", err)
return
}
err = w.Close()
if err != nil {
log.Printf("Error: %s\n", err)
return
}
client.Quit()
}
// Code below from http://golang.org/src/pkg/crypto/tls/handshake_server_test.go
func bigFromString(s string) *big.Int {
ret := new(big.Int)
ret.SetString(s, 10)
return ret
}
func fromHex(s string) []byte {
b, _ := hex.DecodeString(s)
return b
}
var testRSACertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
var testRSAPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
E: 65537,
},
D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
Primes: []*big.Int{
bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
},
}
Playground
I'm trying to make a simple echo client and server that uses Unix sockets. In this example, the connection seems to be unidirectional. The server can receive data from the client, but it can't send the data back. If I use tcp connections instead, it works great. Does anyone know what's wrong?
Server
package main
import "net"
import "fmt"
func echoServer(c net.Conn) {
for {
buf := make([]byte, 512)
nr, err := c.Read(buf)
if err != nil {
return
}
data := buf[0:nr]
fmt.Printf("Received: %v", string(data))
_, err = c.Write(data)
if err != nil {
panic("Write: " + err.String())
}
}
}
func main() {
l, err := net.Listen("unix", "/tmp/echo.sock")
if err != nil {
println("listen error", err.String())
return
}
for {
fd, err := l.Accept()
if err != nil {
println("accept error", err.String())
return
}
go echoServer(fd)
}
}
Client
package main
import "net"
import "time"
func main() {
c,err := net.Dial("unix","", "/tmp/echo.sock")
if err != nil {
panic(err.String())
}
for {
_,err := c.Write([]byte("hi\n"))
if err != nil {
println(err.String())
}
time.Sleep(1e9)
}
}
In your example client, you don't seem to be reading the result from the server. When I add code to do that, I see the results from the server.
Also, take a look at how I used defer and break to make the reader goroutine exit.
Server
package main
import (
"log"
"net"
)
func echoServer(c net.Conn) {
for {
buf := make([]byte, 512)
nr, err := c.Read(buf)
if err != nil {
return
}
data := buf[0:nr]
println("Server got:", string(data))
_, err = c.Write(data)
if err != nil {
log.Fatal("Write: ", err)
}
}
}
func main() {
l, err := net.Listen("unix", "/tmp/echo.sock")
if err != nil {
log.Fatal("listen error:", err)
}
for {
fd, err := l.Accept()
if err != nil {
log.Fatal("accept error:", err)
}
go echoServer(fd)
}
}
Client
package main
import (
"io"
"log"
"net"
"time"
)
func reader(r io.Reader) {
buf := make([]byte, 1024)
for {
n, err := r.Read(buf[:])
if err != nil {
return
}
println("Client got:", string(buf[0:n]))
}
}
func main() {
c, err := net.Dial("unix", "/tmp/echo.sock")
if err != nil {
panic(err)
}
defer c.Close()
go reader(c)
for {
_, err := c.Write([]byte("hi"))
if err != nil {
log.Fatal("write error:", err)
break
}
time.Sleep(1e9)
}
}