How to write in tinygo bluetooth with response? - go

I'm trying to use Tinygo Bluetooth to connect to a Timeflip v2 (https://github.com/DI-GROUP/TimeFlip.Docs/blob/master/Hardware/TimeFlip%20BLE%20protocol%20ver4_02.06.2020.md).
The API documentation says, that I need to login (which is a write to f1196f57-71a4-11e6-bdf4-0800200c9a66, followed by a read on f1196f53-71a4-11e6-bdf4-0800200c9a66 for checking the result of the login).
The only thing I see in TinyGo for DeviceCharacteristics is WriteWithoutResponse (https://pkg.go.dev/github.com/tinygo-org/bluetooth#DeviceCharacteristic.WriteWithoutResponse).
When I use this, it looks like having no affect on the result.
package main
import (
"log"
"strconv"
"tinygo.org/x/bluetooth"
)
var adapter = bluetooth.DefaultAdapter
const (
timeFlipService = "f1196f50-71a4-11e6-bdf4-0800200c9a66"
commandOutCharacteristic = "f1196f53-71a4-11e6-bdf4-0800200c9a66"
passwordCharacteristic = "f1196f57-71a4-11e6-bdf4-0800200c9a66"
)
func main() {
if err := adapter.Enable(); err != nil {
log.Fatalln(err)
}
ch := make(chan bluetooth.ScanResult, 1)
log.Println("scanning...")
if err := adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
log.Println(device)
if device.LocalName() == "TimeFlip v2.0" {
log.Println("found timeflip")
if err := adapter.StopScan(); err != nil {
log.Println(err)
}
ch <- device
}
}); err != nil {
log.Fatalln(err)
}
var device *bluetooth.Device
select {
case result := <-ch:
var err error
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
if err != nil {
log.Fatalln(err)
}
log.Println("connected to ", result.Address.String())
}
defer func() {
if err := device.Disconnect(); err != nil {
log.Println(err)
} else {
log.Println("disconnected")
}
}()
tfService, _ := bluetooth.ParseUUID(timeFlipService)
srvcs, err := device.DiscoverServices([]bluetooth.UUID{tfService})
if err != nil {
log.Fatalln(err)
}
buf := make([]byte, 20)
password, _ := bluetooth.ParseUUID(passwordCharacteristic)
cmdOut, _ := bluetooth.ParseUUID(commandOutCharacteristic)
for _, srvc := range srvcs {
log.Println("- service", srvc.UUID().String())
chars, err := srvc.DiscoverCharacteristics([]bluetooth.UUID{password, cmdOut})
if err != nil {
log.Println(err)
}
var pwChar bluetooth.DeviceCharacteristic
var cmdOutChar bluetooth.DeviceCharacteristic
for _, char := range chars {
log.Println("-- characteristic", char.UUID().String())
switch char.UUID() {
case password:
pwChar = char
case cmdOut:
cmdOutChar = char
}
}
rightPassword := []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30}
_, err = pwChar.WriteWithoutResponse(rightPassword)
if err != nil {
log.Println(" ", err.Error())
}
n, err := cmdOutChar.Read(buf)
if err != nil {
log.Println(" ", err.Error())
} else {
log.Println(" data bytes", strconv.Itoa(n))
log.Println(" value =", buf[:n])
}
wrongPassword := []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x31}
_, err = pwChar.WriteWithoutResponse(wrongPassword)
if err != nil {
log.Println(" ", err.Error())
}
n, err = cmdOutChar.Read(buf)
if err != nil {
log.Println(" ", err.Error())
} else {
log.Println(" data bytes", strconv.Itoa(n))
log.Println(" value =", buf[:n])
}
}
}
results in
scanning...
{7A:05:BF:06:97:D6 -61 0xc00029c1e0}
{C6:D8:C0:F7:A7:3C -57 0xc00029c480}
found timeflip
connected to C6:D8:C0:F7:A7:3C
- service f1196f50-71a4-11e6-bdf4-0800200c9a66
-- characteristic f1196f57-71a4-11e6-bdf4-0800200c9a66
-- characteristic f1196f53-71a4-11e6-bdf4-0800200c9a66
data bytes 1
value = [1]
data bytes 1
value = [1]
disconnected
At least one of the results should be 0x02 (invalid password).
Could somebody give me a hint?

Related

Golang socks5 proxy client

I'm trying to make a proxy:
I need to listen to port 1080 (socks 5), and complete a request to a destination using an external ip:port socks 5, I managed to open this connection with the external ip, but I don't know how I could complete the request to the target destination using that external ip.
could someone help me with this?
package main
import (
"bufio"
"errors"
"fmt"
"io"
"log"
"net"
)
const (
ConnectCommand = uint8(1)
BindCommand = uint8(2)
AssociateCommand = uint8(3)
ipv4Address = uint8(1)
fqdnAddress = uint8(3)
ipv6Address = uint8(4)
)
type AddrSpec struct {
FQDN string
IP net.IP
Port int
}
func main() {
l, err := net.Listen("tcp", "127.0.0.1:1080")
if err != nil {
fmt.Print(err)
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
fmt.Print(err)
}
go handle(conn)
}
}
func handle(conn net.Conn) {
defer func() {
_ = conn.Close()
}()
bufConn := bufio.NewReader(conn)
version := []byte{0}
if _, err := bufConn.Read(version); err != nil {
log.Fatalf("cannot read version: %s", err.Error())
}
if version[0] != uint8(5) {
log.Fatalf("unsupported SOCKS version: %v", version)
}
socks5ExternalConn, err := net.Dial("tcp", externalSOCKS5Proxy())
if err != nil {
log.Printf("Connection error: %s", err.Error())
}
dest, err := readAddrSpec(bufConn)
if err != nil {
}
// how i can send request to server with external conn?
}
func externalSOCKS5Proxy() string {
return "externalip:externalport"
}
func readAddrSpec(r io.Reader) (*AddrSpec, error) {
d := &AddrSpec{}
// Get the address type
addrType := []byte{0}
if _, err := r.Read(addrType); err != nil {
return nil, err
}
// Handle on a per type basis
switch addrType[0] {
case ipv4Address:
addr := make([]byte, 4)
if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
return nil, err
}
d.IP = net.IP(addr)
case ipv6Address:
addr := make([]byte, 16)
if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
return nil, err
}
d.IP = net.IP(addr)
case fqdnAddress:
if _, err := r.Read(addrType); err != nil {
return nil, err
}
addrLen := int(addrType[0])
fqdn := make([]byte, addrLen)
if _, err := io.ReadAtLeast(r, fqdn, addrLen); err != nil {
return nil, err
}
d.FQDN = string(fqdn)
default:
return nil, errors.New("unrecognizedAddrType")
}
// Read the port
port := []byte{0, 0}
if _, err := io.ReadAtLeast(r, port, 2); err != nil {
return nil, err
}
d.Port = (int(port[0]) << 8) | int(port[1])
return d, nil
}

Can we send request form server to client and get response through quic/http3?

I'm using quic-go to implement my thought, I need the server to forwardly send request to client to get response, just like we do that client sends request to web server commonly. But with quic-go, after connection is setup, can server initialize streams to send request to client and get responses? I did a trying but haven't made it work. The code below is from the echo.go of example dir, the two parts between comment lines are added by me.
package main
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"log"
"math/big"
"github.com/lucas-clemente/quic-go"
)
const addr = "localhost:4242"
const message = "foobar"
// We start a server echoing data on the first stream the client opens,
// then connect with a client, send the message, and wait for its receipt.
func main() {
go func() { log.Fatal(echoServer()) }()
err := clientMain()
if err != nil {
panic(err)
}
}
// Start a server that echos all data on the first stream opened by the client
func echoServer() error {
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
if err != nil {
return err
}
conn, err := listener.Accept(context.Background())
if err != nil {
return err
}
stream, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
// Echo through the loggingWriter
_, err = io.Copy(loggingWriter{stream}, stream)
if err != nil {
panic(err)
}
//------------------------------
stream1, err := conn.OpenStream()
if err != nil {
panic(err)
}
message := "aaaaa"
fmt.Printf("2-Server: Sending '%s'\n", message)
_, err = stream1.Write([]byte(message))
//------------------------------
return err
}
func clientMain() error {
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
conn, err := quic.DialAddr(addr, tlsConf, nil)
if err != nil {
return err
}
stream, err := conn.OpenStreamSync(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: Sending '%s'\n", message)
_, err = stream.Write([]byte(message))
if err != nil {
return err
}
buf := make([]byte, len(message))
_, err = io.ReadFull(stream, buf)
if err != nil {
return err
}
fmt.Printf("Client: Got '%s'\n", buf)
err = stream.Close()
if err != nil {
return err
}
//-------------------------------
for {
stream1, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
buf1 := make([]byte, len(message))
_, err = io.ReadFull(stream1, buf1)
if err != nil {
panic(err)
}
fmt.Printf("2-Client: Got '%s'\n", buf1)
err = stream1.Close()
if err != nil {
panic(err)
}
}
//-------------------------------
return nil
}
// A wrapper for io.Writer that also logs the message.
type loggingWriter struct{ io.Writer }
func (w loggingWriter) Write(b []byte) (int, error) {
fmt.Printf("Server: Got '%s'\n", string(b))
return w.Writer.Write(b)
}
// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"quic-echo-example"},
}
}
You are close.
Notice how the server writes, then returns, it reaches out to log.Fatal before the client had a chance to read and handle the data.
Take care to the message variable, one is 6 length long, the other one is only 5 length long.
Properly close your stream, the server was not ending it ending before handing over;
package main
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"log"
"math/big"
"github.com/lucas-clemente/quic-go"
)
const addr = "localhost:4242"
const message = "foobar"
// We start a server echoing data on the first stream the client opens,
// then connect with a client, send the message, and wait for its receipt.
func main() {
go func() {
err := echoServer()
if err != nil {
log.Println(err)
}
}()
err := clientMain()
if err != nil {
panic(err)
}
}
// Start a server that echos all data on the first stream opened by the client
func echoServer() error {
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
if err != nil {
return err
}
conn, err := listener.Accept(context.Background())
if err != nil {
return err
}
stream, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
// Echo through the loggingWriter
_, err = io.Copy(loggingWriter{stream}, stream)
if err != nil {
log.Println(err)
return err
}
//------------------------------
fmt.Printf("Server: open stream\n")
stream1, err := conn.OpenStream()
if err != nil {
return err
}
fmt.Printf("2-Server: Sending '%s'\n", message)
var n int
n, err = stream1.Write([]byte(message))
fmt.Printf("Server: write %v %v\n", n, err)
stream1.Close()
//------------------------------
return err
}
func clientMain() error {
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
conn, err := quic.DialAddr(addr, tlsConf, nil)
if err != nil {
return err
}
stream, err := conn.OpenStreamSync(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: Sending '%s'\n", message)
_, err = stream.Write([]byte(message))
if err != nil {
return err
}
buf := make([]byte, len(message))
_, err = io.ReadFull(stream, buf)
if err != nil {
return err
}
fmt.Printf("Client: Got '%s'\n", buf)
err = stream.Close()
if err != nil {
return err
}
//-------------------------------
for {
fmt.Printf("Client: accept stream\n")
stream1, err := conn.AcceptStream(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: got stream %v\n", err)
buf1 := make([]byte, len(message))
_, err = io.ReadFull(stream1, buf1)
if err != nil {
return err
}
fmt.Printf("2-Client: Got '%s'\n", buf1)
err = stream1.Close()
if err != nil {
return err
}
break
}
//-------------------------------
return nil
}
// A wrapper for io.Writer that also logs the message.
type loggingWriter struct{ io.Writer }
func (w loggingWriter) Write(b []byte) (int, error) {
fmt.Printf("Server: Got '%s'\n", string(b))
return w.Writer.Write(b)
}
// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"quic-echo-example"},
}
}

How to use TLS Conn.Read to read a large size of data

I'm trying with tls.Conn i.e, conn.Read from golang crypto/tls to read a large size of data. However when all the data is read out, then the program will never stop. Why? My simplified code is as follow:
// server
func main() {
log.SetFlags(log.Lshortfile)
cer, err := tls.LoadX509KeyPair("server.pem", "server.key")
if err != nil {
log.Println(err)
return
}
config := &tls.Config{Certificates: []tls.Certificate{cer}}
ln, err := tls.Listen("tcp", ":2000", config)
if err != nil {
log.Println(err)
return
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 0)
tmp := make([]byte, 1000)
totalSize := 0
for {
n, err := conn.Read(tmp) //after read all the data, server stucked here
totalSize += n
if err != nil {
if err != io.EOF {
log.Printf("prover: conn: read: %s", err)
}
break
}
buf = append(buf, tmp[:n]...)
}
n, err := conn.Write([]byte("finished"))
if err != nil {
log.Println(n, err)
return
}
}
The logic of the client:
// client
func main() {
log.SetFlags(log.Lshortfile)
conf := &tls.Config{
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", "127.0.0.1:2000", conf)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
writeData := make([]byte, 4096)
n, err := conn.Write(writeData)
if err != nil {
log.Println(n, err)
return
}
fmt.Println("finish writing")
buf := make([]byte, 4096)
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
}
fmt.Print("finish reading")
}
How can I read a large size of data in the server and after the data is completely read out, then the server will send a response to the client. I tried with net.Conn (TCPConn), this logic works. WHy?

I have got panic: runtime error: invalid memory address or nil pointer dereference in Golang

panic: runtime error: invalid memory address or nil pointer dereference
when i add
statusCOD, err := c.route.FindStatusCODByOrigin(ctx, req.Origin)
if err != nil {
if err != sql.ErrNoRows {
ddlogger.Log(ctx, span, "Find status cod destination and cod origin", err)
errChan <- err
return
}
}
if statusCOD != nil {
IsCODOrigin = statusCOD.IsCODOrigin
IsCODDestination = statusCOD.IsCODDestination
}
in this func
for i, v := range detailShipments {
var dtPackage repo.PackageBaseModel
go func(idx int, vShipment repo.ShipmentDetailBaseModel, dataShipmentNew repo.ShipmentCODCreateModel) {
defer wg1.Done()
randomID := commonString.RandomWithCustomCharList(c.config.ShipmentCODIDRandom, c.config.ShipmentIDCharlist)
shipmentID := fmt.Sprintf("%s%s", prefix, randomID)
dataShipmentNew.ShipmentBaseModel.ShipmentID = strings.ToUpper(shipmentID)
dataShipmentNew.ShipmentDetailBaseModel = vShipment
var commodityName string
sCategory, err := c.shipmentCategoryRepo.FindOneShipmentCategoryByID(ctx, vShipment.ShipmentCategoryID.Int64)
if err != err && err != sql.ErrNoRows {
ddlogger.Log(ctx, span, "shipmentService-CreateShipmentCOD "+shipmentID, " Failed shipmentCategoryRepo.FindOneShipmentCategoryByID", err)
} else {
if sCategory != nil {
commodityName = sCategory.CommodityName.String
}
}
req := &repo.TariffRequestModelV2{
Origin: form.DetailSender.Origin,
Destination: vShipment.Destination,
Weight: vShipment.GrossWeight / 1000,
Commodity: commodityName,
GoodsValue: int64(vShipment.GoodValues.Float64),
IsInsurance: vShipment.IsInsurance.Bool,
Product: vShipment.ProductType,
Width: vShipment.DimensionWidth.Float64,
Height: vShipment.DimensionHeight.Float64,
Length: vShipment.DimensionLength.Float64,
IsCOD: true,
CODValue: vShipment.CODValue.Float64,
}
tariff, err := c.coreSystemRepo.CheckTariffV3(ctx, req)
if err != nil {
ddlogger.Log(ctx, span, "[shipmentService-CreateShipmentCOD [coreSystemRepo.CheckTariffV3]]", err)
errChan <- err
return
}
statusCOD, err := c.route.FindStatusCODByOrigin(ctx, req.Origin)
if err != nil {
if err != sql.ErrNoRows {
ddlogger.Log(ctx, span, "Find status cod destination and cod origin", err)
errChan <- err
return
}
}
if statusCOD != nil {
IsCODOrigin = statusCOD.IsCODOrigin
IsCODDestination = statusCOD.IsCODDestination
}
................
}
wg1.Wait()
close(shipmentChan)
close(errChan)
close(amountChan)
It looks like you just created the pointer, and it doesn't point to any memory spaces, you can check all the variables in your new code to find it. e.g. ctx

Client stuck when trying to read with io.CopyN() in golang

I am trying to make TCP server for transferring files. I am suing io.CopyN for reading and writing. From server side, I am sending files to client so from server side, it sends perfectly all bytes but Client side after reading a couple of 1000000 bytes it stuck. sometimes it works fine and sometimes it gets stuck. I am using 300 MB pdf to test. Any help, code, and output is like below.
server
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"strconv"
"strings"
)
func main() {
ls, err := net.Listen("tcp", ":1234")
errFunc(err)
defer ls.Close()
conn, _ := ls.Accept()
defer conn.Close()
for {
file, err := os.Open(strings.TrimSpace("./" + "Mag" + ".pdf"))
errFunc(err)
defer file.Close()
fileInfo, err := file.Stat()
errFunc(err)
size := fileInfo.Size()
numberOfTime := size / 1000000
leftByte := size - numberOfTime*1000000
numberOfTimeString := strconv.Itoa(int(numberOfTime))
leftByteString := strconv.Itoa(int(leftByte))
fmt.Println("1000000 times : ", numberOfTimeString)
fmt.Println("Left Bytes : ", leftByteString)
_, err = fmt.Fprintf(conn, numberOfTimeString+"\n")
errFunc(err)
_, err = fmt.Fprintf(conn, leftByteString+"\n")
errFunc(err)
fileWriter := io.Writer(conn)
for i := 0; i < int(numberOfTime); i++ {
n, err := io.CopyN(conn, file, 1000000)
if i >= 30 {
fmt.Println(err, n)
}
}
n, err := io.CopyN(fileWriter, file, leftByte+1)
if err == io.EOF {
fmt.Println(err, n)
}
fmt.Printf("Succefully bytes sent : %v \n\n\n\n\n", n)
file.Close()
}
}
func errFunc(err error) {
if err != nil {
log.Fatal(err)
}
}
client
package main
import (
"bufio"
"fmt"
"io"
"net"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
)
func main() {
c := make(chan os.Signal, 15)
signal.Notify(c, syscall.SIGINT)
go func() {
for {
s := <-c
switch s {
case syscall.SIGINT:
os.Exit(1)
}
}
}()
conn, _ := net.Dial("tcp", ":1234")
defer conn.Close()
connReadWrite := bufio.NewReader(io.Reader(conn))
var i int
var filename string
for {
i++
nu := strconv.Itoa(i)
filename = "image" + nu + ".pdf"
file, err := os.Create(filename)
defer file.Close()
numberOfTimeString, err := connReadWrite.ReadString('\n')
if err != nil {
fmt.Println(err)
}
println("1000000 times :", numberOfTimeString)
numberOfTimeString = strings.TrimSuffix(numberOfTimeString, "\n")
numberOfTime, err := strconv.Atoi(numberOfTimeString)
if err != nil {
fmt.Println(err)
}
leftByteString, err := connReadWrite.ReadString('\n')
if err != nil {
println(err)
}
println("Left Bytes :", leftByteString)
leftByteString = strings.TrimSuffix(leftByteString, "\n")
leftByte, err := strconv.Atoi(leftByteString)
if err != nil {
panic(err)
}
fmt.Println("After convert in Num :", numberOfTime, leftByte)
newFileWriter := io.Writer(file)
newFileReader := io.Reader(conn)
for i := 0; i < numberOfTime; i++ {
n, err := io.CopyN(newFileWriter, newFileReader, 1000000)
if i >= 30 {
errFun(err, n)
}
}
n, err := io.CopyN(newFileWriter, newFileReader, int64(leftByte))
errFun(err, n)
fmt.Printf("sucessfully Transfered ---> \n\n\n\n\n\n")
}
}
func errFun(err error, n int64) {
if err == io.EOF {
fmt.Println("End of file : ", n)
return
} else if n == 0 {
fmt.Println("n is : ", n)
return
} else if err != nil {
fmt.Println(err)
return
}
fmt.Println(err, " : ", n)
}
input/output
from server side first we are sending number of bytes it need to readand then client side it gets a number of bytes it needs to read and then I am sending the file and then it read. In the picture, I was able to send one-time second time it got stuck sometimes it stuck first time too.I am able to send number of byte from server side second time too but as you can see it don't read that numeber, it read something "%PDF..." and it even don't print "100000 times : " correctly it prints "%???00 times :" I just don’t understand this
enter image description here
I believe the issue is that you're using a bytes.Buffer in the client:
connReadWrite := bufio.NewReader(io.Reader(conn))
But you aren't using it later with the CopyN:
newFileWriter := io.Writer(file)
newFileReader := io.Reader(conn)
for i := 0; i < numberOfTime; i++ {
_, err := io.CopyN(newFileWriter, newFileReader, 1000000)
if err != nil {
log.Fatalln(err)
}
}
Using:
newFileWriter := io.Writer(file)
for i := 0; i < numberOfTime; i++ {
_, err := io.CopyN(file, connReadWrite, 1000000)
if err != nil {
log.Fatalln(err)
}
}
May fix it.
If you have control over the protocol you are using to send the file, I recommend doing something simpler. For example using the big-endian int64 length prefix.
Send:
func sendFile(name string, conn net.Conn) error {
f, err := os.Open(name)
if err != nil {
return err
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return err
}
sz := fi.Size()
buf := bufio.NewWriter(conn)
err = binary.Write(buf, binary.BigEndian, sz)
if err != nil {
return err
}
_, err = io.CopyN(buf, f, sz)
if err != nil {
return err
}
return buf.Flush()
}
Receive:
func recvFile(name string, conn net.Conn) error {
f, err := os.Create(name)
if err != nil {
return err
}
defer f.Close()
buf := bufio.NewReader(conn)
var sz int64
err = binary.Read(buf, binary.BigEndian, &sz)
if err != nil {
return err
}
_, err = io.CopyN(f, buf, sz)
if err != nil {
return err
}
return nil
}

Resources