package door import ( "bufio" "bytes" "log" "syscall" "time" "unicode" ) var ReaderInterval = time.Duration(200) * time.Millisecond var ReaderTimeval syscall.Timeval = syscall.Timeval{0, 200} // syscall.FdSet clear all func clearAll(fdSetPtr *syscall.FdSet) { for index := range (*fdSetPtr).Bits { (*fdSetPtr).Bits[index] = 0 } } // syscall.FdSet set fd func set(fdSetPtr *syscall.FdSet, fd int) { (*fdSetPtr).Bits[fd/64] |= 1 << uint64(fd%64) } /* func main() { var text string = "\x1b\u2415\xff" var buffer []byte = []byte(text) var readbuffer = bytes.NewBuffer(buffer) // bytes.Buffer{} // readbuffer.Write(buffer) var runeread = bufio.NewReaderSize(readbuffer, 1) //for readbuffer.Len() > 0 { for { r, _, err := runeread.ReadRune() if err != nil { break } if r == unicode.ReplacementChar { runeread.UnreadRune() b, _ := runeread.ReadByte() fmt.Printf("BYTE %#v\n", b) } else { fmt.Printf("%#v\n", r) } } */ const READ_SIZE = 16 // go routine Reader for input // This "times out" every ReaderTimeval func Reader(d *Door) { // I need non-blocking reads here. // I'm not really using either of these things. // d.readerFile = os.NewFile(uintptr(d.READFD), "Door FD") // d.runereader = bufio.NewReaderSize(d.readerFile, 1) defer func() { log.Printf("~Reader\n") if d.ReaderCanClose { d.wg.Done() } }() defer func() { if err := recover(); err != nil { log.Printf("Reader: %#v\n", err) } }() var fdset syscall.FdSet var readone []byte = make([]byte, READ_SIZE) //make([]byte, 0, READ_SIZE) // read 1 byte var readbuffer bytes.Buffer // NewBuffer(readone) var runeread = bufio.NewReaderSize(&readbuffer, 1) // var buffer []byte = make([]byte, 0) // unicode read buffer for { clearAll(&fdset) set(&fdset, d.READFD) v, err := syscall.Select(d.READFD+1, &fdset, nil, nil, &ReaderTimeval) if err == syscall.EINTR { continue } // log.Printf("Select: %#v / %#v\n", v, err) if v == -1 { log.Printf("Reader ERR: %#v\n", err) d.readerMutex.Lock() if !d.ReaderClosed { d.ReaderClosed = true close(d.readerChannel) } return } if v == 0 { // timeout /* if len(buffer) > 0 { timeoutCount++ input, size = utf8.DecodeRune(buffer) if input != utf8.RuneError { d.readerChannel <- input for size > 0 { ArrayDelete(&buffer, 0) size-- } timeoutCount = 0 } else { b, _ := ArrayDelete(&buffer, 0) d.readerChannel <- rune(b) } } else { timeoutCount = 0 } */ continue } log.Println("syscall.Read:", len(readone), cap(readone)) // The buffer used here must have len & cap to size you want to read. r, err := syscall.Read(d.READFD, readone) if r == -1 { log.Println("Read -1 (closed)") d.readerMutex.Lock() defer d.readerMutex.Unlock() if !d.ReaderClosed { d.ReaderClosed = true d.Disconnected = true close(d.readerChannel) } return } if r == 0 { log.Printf("Select said ready, but: %#v %#v\n", r, err) d.readerMutex.Lock() defer d.readerMutex.Unlock() if !d.ReaderClosed { d.ReaderClosed = true d.Disconnected = true close(d.readerChannel) } return } // readone = readone[:r] if DEBUG_INPUT { log.Printf("Reader << %d, %#v\n", r, readone[:r]) } // Is this unicode? readbuffer.Write(readone[:r]) // reset // readone = readone[0:0] log.Println("readone:", len(readone), cap(readone)) var input rune RuneRead: input, _, err = runeread.ReadRune() if err != nil { log.Printf("ReadRune: %#v\n", err) // errors EOF continue } if input == unicode.ReplacementChar { runeread.UnreadRune() b, _ := runeread.ReadByte() if DEBUG_INPUT { log.Printf("Reader (byte) >> %x\n", b) } d.readerChannel <- rune(b) } else { if DEBUG_INPUT { log.Printf("Reader >> %x\n", input) } d.readerChannel <- input } goto RuneRead // buffer = append(buffer, readone[0]) /* Take2: input, size = utf8.DecodeRune(buffer) if input != utf8.RuneError { d.readerChannel <- input for size > 0 { ArrayDelete(&buffer, 0) size-- } if len(buffer) > 0 { goto Take2 } timeoutCount = 0 } else { // Not a valid rune continue } */ // d.readerChannel <- rune(buffer[0]) } }