package door import ( "bufio" "bytes" "io" "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) } const READ_SIZE = 16 // Size of read buffer // go routine Reader for input // This "times out" every ReaderTimeval func Reader(d *Door) { // I need non-blocking reads here. 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 readbuffer [READ_SIZE]byte var runebuffer bytes.Buffer var runeread = bufio.NewReaderSize(&runebuffer, 1) 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 continue } // The buffer used here must have len & cap to size you want to read. // use [BUFF_SIZE]byte for readone r, err := syscall.Read(d.READFD, readbuffer[:]) if r == -1 { log.Println("syscall.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 } if DEBUG_INPUT { log.Printf("Reader << %d, %#v\n", r, readbuffer[:r]) } runebuffer.Write(readbuffer[:r]) var input rune // Is this unicode? err = nil for err == nil { //RuneRead: input, _, err = runeread.ReadRune() if err == io.EOF { continue } if err != nil { log.Printf("ReadRune: %#v\n", err) // errors EOF continue // break for loop } 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]) } }