So I'm trying to get the File Handle on a socket in windows.
Using like the following:
address, err := net.ResolveTCPAddr("tcp", "192.168.9.144:8080")
if err != nil {
fmt.Println(err)
}
conn, err := net.DialTCP("tcp", nil, address)
fmt.Println("Connected")
// conn, err := net.DialTCP("tcp", nil, address)
if err != nil {
fmt.Println("Can't conenct")
log.Fatal(err)
}
conn.File()
conn.Fd()
conn.File() Fails and states it's not supported by windows
Next I tried to use the windows api function _get_osfhandle
var (
procGetOSfHandle = msvcrt.NewProc("_get_osfhandle")
)
func GetOSfHandle(fd uintptr) (uintptr, error) {
value, _, err := procGetOSfHandle.Call(fd)
return value, err
}
hand, _ := GetOSfHandle(uintptr(unsafe.Pointer(conn)))
hand returns 4294967295 which turns out to be not real as in "xff\xff\xff\xff"
I then tried just to use the windows API for socket and ran into an issue with WSARecv. This is the following code used:
var d syscall.WSAData
syscall.WSAStartup(uint32(0x202), &d)
fd, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
addr := syscall.SockaddrInet4{Port: 8080, Addr: [4]byte{192, 168, 9, 144}}
var buf [4]byte
syscall.Connect(fd, &addr)
dataBuf := syscall.WSABuf{Len: uint32(4), Buf: &buf[0]}
o := syscall.Overlapped{}
flags := uint32(0)
qty := uint32(0)
syscall.WSARecv(fd, &dataBuf, 1, &qty, &flags, &o, nil)
fmt.Println(buf)
The code connects but I don't see and data received. It seems I don't seem to have the WSARecv options correct.
Any help would be greatly appreciated.
Related
I'm trying to do simple UNIX socket communication with a service using GO. For testing I've created a socket like so:
$ nc -vlU /tmp/sock
Bound on /tmp/sock
Listening on /tmp/sock
And in GO, I net.Dial and try to write something, then read. I see the written data in the nc console, so I know that is working. But the net.Conn.Read operation appears non-blocking and will return immediately with zero length. From everything I've read and the example I've seen, this operation should block.
buf := make([]byte, 0, 4096)
ctl, err := net.Dial("unix", "/tmp/sock")
for {
ctl.Write([]byte("test write\n"))
n, err := ctl.Read(buf)
fmt.Printf("Len:%v, Data:%v, err:%v", n, buf, err)
}
I see the connection come through and data written ...
Connection received on /tmp/sock
test write
test write
test write
test write
...
But the GO console loops without blocking, reporting a zero length and no error
Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
...
And of course if I type anything into the nc console nothing interesting happens in the GO program output.
Any idea what I'm doing wrong?
short answer
buf := make([]byte, 0, 4096)
this code make a buffer with len=0!!!
do it like
buf := make([]byte, 4096)
example
this is some example i used, and they all works.
In practice, socket read and write should happen in two goroutines
package main
import (
"bufio"
"fmt"
"io"
"net"
"time"
)
func main() {
buf := make([]byte, 0, 4096)
fmt.Println(buf)
main03()
}
func main01() {
// nc -vlU /tmp/sock0120
ctl, err := net.Dial("unix", "/tmp/sock0120")
if err != nil {
fmt.Println(err)
return
}
reader := bufio.NewReader(ctl)
for {
time.Sleep(time.Second)
ctl.Write([]byte("test write\n"))
msg, err := reader.ReadString('\n')
fmt.Printf("Len:%v, Data:%v, err:%v\n", len(msg), msg, err)
}
}
func main02() {
// nc -vlU /tmp/sock0120
buf := make([]byte, 4)
ctl, err := net.Dial("unix", "/tmp/sock0120")
if err != nil {
fmt.Println(err)
return
}
reader := bufio.NewReader(ctl)
for {
time.Sleep(time.Second)
ctl.Write([]byte("test write\n"))
n, err := io.ReadFull(reader, buf)
fmt.Printf("Len:%v, Data:%v, err:%v\n", n, buf, err)
}
}
func main03() {
// nc -vlU /tmp/sock0120
buf := make([]byte, 4)
ctl, err := net.Dial("unix", "/tmp/sock0120")
if err != nil {
fmt.Println(err)
return
}
for {
time.Sleep(time.Second)
ctl.Write([]byte("test write\n"))
n, err := ctl.Read(buf)
fmt.Printf("Len:%v, Data:%v, err:%v\n", n, buf, err)
}
}
I'm trying to download and decrypt HLS streams by using io.ReadFull to process the data in chunks to conserve memory:
Irrelevant parts of code has been left out for simplicity.
func main() {
f, _ := os.Create(out.ts)
for _, v := range mediaPlaylist {
resp, _ := http.Get(v.URI)
for {
r, err := decryptHLS(key, iv, resp.Body)
if err != nil && err == io.EOF {
break
else if err != nil && err != io.ErrUnexpectedEOF {
panic(err)
}
io.Copy(f, r)
}
}
}
func decryptHLS(key []byte, iv []byte, r io.Reader) (io.Reader, error) {
block, _ := aes.NewCipher(key)
buf := make([]byte, 8192)
mode := cipher.NewCBCDecrypter(block, iv)
n, err := io.ReadFull(r, buf)
if err != nil && err != io.ErrUnexpectedEOF {
return nil, err
}
mode.CryptBlocks(buf, buf)
return bytes.NewReader(buf[:n]), err
}
At first this seems to work as file size is correct and no errors during download,
but the video is corrupted. Not completely as the file is still recognized as a video, but image and sound is distorted.
If I change the code to use ioutil.ReadAll instead, the final video files will no longer be corrupted:
func main() {
f, _ := os.Create(out.ts)
for _, v := range mediaPlaylist {
resp, _ := http.Get(v.URI)
segment, _ := ioutil.ReadAll(resp.Body)
r, _ := decryptHLS(key, iv, &segment)
io.Copy(f, r)
}
}
func decryptHLS(key []byte, iv []byte, s *[]byte) io.Reader {
block, _ := aes.NewCipher(key)
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(*s, *s)
return bytes.NewReader(*s)
}
Any ideas why it works correctly when reading the entire segment into memory, and not when using io.ReadFull and processing it in chunks?
Internally, CBCDecrypter makes a copy of your iv, so subsequent blocks start with the initial IV rather than the one that's been mutated by previous decryptions.
Create the decrypter once, and you should be able to keep re-using it to decrypt block by block (assuming the block size is a multiple of the block size expected by this crypto algorithm).
// SetReadLimit sets the maximum size for a message read from the peer. If a
// message exceeds the limit, the connection sends a close message to the peer
// and returns ErrReadLimit to the application.
func (c *Conn) SetReadLimit(limit int64) {
c.readLimit = limit
}
What is the unit of limit? KB? MB ?
Based on the sources of gorilla/websocket, it's in bytes.
const readLimit = 512
message := make([]byte, readLimit+1)
.....
rc.SetReadLimit(readLimit)
Here is the full unit test:
func TestReadLimit(t *testing.T) {
const readLimit = 512
message := make([]byte, readLimit+1)
var b1, b2 bytes.Buffer
wc := newConn(&fakeNetConn{Writer: &b1}, false, 1024, readLimit-2, nil, nil, nil)
rc := newTestConn(&b1, &b2, true)
rc.SetReadLimit(readLimit)
// Send message at the limit with interleaved pong.
w, _ := wc.NextWriter(BinaryMessage)
w.Write(message[:readLimit-1])
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
w.Write(message[:1])
w.Close()
// Send message larger than the limit.
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
op, _, err := rc.NextReader()
if op != BinaryMessage || err != nil {
t.Fatalf("1: NextReader() returned %d, %v", op, err)
}
op, r, err := rc.NextReader()
if op != BinaryMessage || err != nil {
t.Fatalf("2: NextReader() returned %d, %v", op, err)
}
_, err = io.Copy(ioutil.Discard, r)
if err != ErrReadLimit {
t.Fatalf("io.Copy() returned %v", err)
}
}
This does not seem to be well-documented indeed, but according to the corresponding test it is in bytes. I'd assume that to be a default unit anyway.
The relevant test code:
// Send message at the limit with interleaved pong.
w, _ := wc.NextWriter(BinaryMessage)
w.Write(message[:readLimit-1])
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
w.Write(message[:1])
w.Close()
// Send message larger than the limit.
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
// ...
_, err = io.Copy(ioutil.Discard, r)
if err != ErrReadLimit {
t.Fatalf("io.Copy() returned %v", err)
}
I'm confusing about the reassignment of the err variable for errors in Go.
For example, I tend to be doing this:
err1 := Something()
checkErr(err1)
str, err2 := SomethingElse()
checkErr(err2)
err3 := SomethingAgain()
checkErr(err3)
But I'm always losing track of this and have millions of useless err variables floating around that I don't need, and it makes the code messy and confusing.
But then if I do this:
err := Something()
checkErr(err)
str, err := SomethingElse()
checkErr(err)
err := SomethingAgain()
checkErr(err)
...it gets angry and says err is already assigned.
But if I do this:
var err error
err = Something()
checkErr(err)
str, err = SomethingElse()
checkErr(err)
err = SomethingAgain()
checkErr(err)
...it doesn't work because str needs to be assigned with :=
Am I missing something?
you're almost there... at the left side of := there needs to be at least one newly create variable. But if you don't declare err in advance, the compiler tries to create it on each instance of :=, which is why you get the first error. so this would work, for example:
package main
import "fmt"
func foo() (string, error) {
return "Bar", nil
}
func main() {
var err error
s1, err := foo()
s2, err := foo()
fmt.Println(s1,s2,err)
}
or in your case:
//we declare it first
var err error
//this is a normal assignment
err = Something()
checkErr(err)
// here, the compiler knows that only str is a newly declared variable
str, err := SomethingElse()
checkErr(err)
// and again...
err = SomethingAgain()
checkErr(err)
I’ve written a short program in Go to communicate with a sensor through a serial port:
package main
import (
"fmt"
"github.com/tarm/goserial"
"time"
)
func main() {
c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 9600}
s, err := serial.OpenPort(c)
if err != nil {
fmt.Println(err)
}
_, err = s.Write([]byte("\x16\x02N0C0 G A\x03\x0d\x0a"))
if err != nil {
fmt.Println(err)
}
time.Sleep(time.Second/2)
buf := make([]byte, 40)
n, err := s.Read(buf)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(buf[:n]))
s.Close()
}
It works fine, but after writing to the port I have to wait about half a second before I can start reading from it. I would like to use a while-loop instead of time.Sleep to read all incoming data. My attempt doesn’t work:
buf := make([]byte, 40)
n := 0
for {
n, _ := s.Read(buf)
if n > 0 {
break
}
}
fmt.Println(string(buf[:n]))
I guess buf gets overwritten after every loop pass. Any suggestions?
Your problem is that Read() will return whenever it has some data - it won't wait for all the data. See the io.Reader specification for more info
What you want to do is read until you reach some delimiter. I don't know exactly what format you are trying to use, but it looks like maybe \x0a is the end delimiter.
In which case you would use a bufio.Reader like this
reader := bufio.NewReader(s)
reply, err := reader.ReadBytes('\x0a')
if err != nil {
panic(err)
}
fmt.Println(reply)
Which will read data until the first \x0a.
I guess buf gets overwritten after every loop pass. Any suggestions?
Yes, buf will get overwritten with every call to Read().
A timeout on the file handle would be the approach I would take.
s, _ := os.OpenFile("/dev/ttyS0", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
t := syscall.Termios{
Iflag: syscall.IGNPAR,
Cflag: syscall.CS8 | syscall.CREAD | syscall.CLOCAL | syscall.B115200,
Cc: [32]uint8{syscall.VMIN: 0, syscall.VTIME: uint8(20)}, //2.0s timeout
Ispeed: syscall.B115200,
Ospeed: syscall.B115200,
}
// syscall
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(s.Fd()),
uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&t)),
0, 0, 0)
// Send message
n, _ := s.Write([]byte("Test message"))
// Receive reply
for {
buf := make([]byte, 128)
n, err = s.Read(buf)
if err != nil { // err will equal io.EOF
break
}
fmt.Printf("%v\n", string(buf))
}
Also note, if there is no more data read and there is no error, os.File.Read() will return an error of io.EOF,
as you can see here.