예제 #1
0
func doSelect(nfd int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, timeout *syscall.Timeval) (changed bool, err error) {
	err = syscall.Select(nfd, r, w, e, timeout)
	if err != nil {
		return false, err
	}
	return true, nil
}
예제 #2
0
파일: filter.go 프로젝트: ziutek/dvb
// WaitRead returns true if f can be readed without blocking or false if not or
// error.
func (s *syn) WaitRead(f *os.File) (bool, error) {
	pfd := s.pr.Fd()
	ffd := f.Fd()
	nfd := 1
	if pfd < ffd {
		nfd += int(ffd)
	} else {
		nfd += int(pfd)
	}
	s.m.Lock()
	for {
		var r fdset
		r.Set(ffd)
		r.Set(pfd)
		n, err := syscall.Select(nfd, r.Sys(), nil, nil, nil)
		if err != nil {
			return false, err
		}
		if n > 0 {
			if r.IsSet(pfd) {
				// Command waits for access f.
				s.m.Unlock()
				return false, nil
			}
			return true, nil
		}
	}
}
예제 #3
0
파일: api3.go 프로젝트: ziutek/dvb
// WaitEvent can return dvb.ErrOverflow. If deadline is non zero time WaitEvent
// returns true if it doesn't receive any event up to deatline.
func (f API3) WaitEvent(ev *Event, deadline time.Time) (bool, error) {
	fd := f.Fd()
	if !deadline.IsZero() {
		timeout := deadline.Sub(time.Now())
		if timeout <= 0 {
			return true, nil
		}
		var r syscall.FdSet
		r.Bits[fd/64] = 1 << (fd % 64)
		tv := syscall.NsecToTimeval(int64(timeout))
		n, err := syscall.Select(int(fd+1), &r, nil, nil, &tv)
		if err != nil {
			return false, Error{"get", "event (select)", err}
		}
		if n == 0 {
			return true, nil
		}
	}
	_, _, e := syscall.Syscall(
		syscall.SYS_IOCTL,
		fd,
		_FE_GET_EVENT,
		uintptr(unsafe.Pointer(ev)),
	)
	if e != 0 {
		if e == syscall.EOVERFLOW {
			return false, dvb.ErrOverflow
		}
		return false, Error{"get", "event", e}
	}
	return false, nil
}
예제 #4
0
func main() {
	var (
		rset, wset, eset            syscall.FdSet
		still_running, curl_timeout int = 0, 0
		err                         error
	)

	ch1 := curl.EasyInit()
	ch2 := curl.EasyInit()

	ch1.Setopt(curl.OPT_URL, "http://www.163.com")
	ch1.Setopt(curl.OPT_HEADER, 0)
	ch1.Setopt(curl.OPT_VERBOSE, true)
	ch2.Setopt(curl.OPT_URL, "http://www.baidu.com")
	ch2.Setopt(curl.OPT_HEADER, 0)
	ch2.Setopt(curl.OPT_VERBOSE, true)

	mh := curl.MultiInit()

	mh.AddHandle(ch1)
	mh.AddHandle(ch2)

	for {
		FD_ZERO(&rset)
		FD_ZERO(&wset)
		FD_ZERO(&eset)

		timeout := syscall.Timeval{Sec: 1, Usec: 0}
		curl_timeout, err = mh.Timeout()
		if err != nil {
			fmt.Printf("Error multi_timeout: %s\n", err)
		}
		if curl_timeout >= 0 {
			timeout.Sec = int64(curl_timeout / 1000)
			if timeout.Sec > 1 {
				timeout.Sec = 1
			} else {
				timeout.Usec = int64((curl_timeout % 1000)) * 1000
			}
		}

		max_fd, err := mh.Fdset(&rset, &wset, &eset)
		if err != nil {
			fmt.Printf("Error FDSET: %s\n", err)
		}

		_, err = syscall.Select(int(max_fd+1), &rset, &wset, &eset, &timeout)
		if err != nil {
			fmt.Printf("Error select: %s\n", err)
		} else {
			still_running, err = mh.Perform()
			if still_running > 0 {
				fmt.Printf("Still running: %d\n", still_running)
			} else {
				break
			}
		}
	}

}
예제 #5
0
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
	if p.nReady == 0 {
		var timeout *syscall.Timeval
		var tv syscall.Timeval
		timeout = nil
		if nsec > 0 {
			tv = syscall.NsecToTimeval(nsec)
			timeout = &tv
		}

		var n, e int
		var tmpReadFds, tmpWriteFds syscall.FdSet_t
		for {
			// Temporary syscall.FdSet_ts into which the values are copied
			// because select mutates the values.
			tmpReadFds = *p.readFds
			tmpWriteFds = *p.writeFds

			n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
			if e != syscall.EINTR {
				break
			}
		}
		if e != 0 {
			return -1, 0, os.NewSyscallError("select", e)
		}
		if n == 0 {
			return -1, 0, nil
		}

		p.nReady = n
		*p.readyReadFds = tmpReadFds
		*p.readyWriteFds = tmpWriteFds
		p.lastFd = 0
	}

	flag := false
	for i := p.lastFd; i < p.maxFd+1; i++ {
		if syscall.FDIsSet(i, p.readyReadFds) {
			flag = true
			mode = 'r'
			syscall.FDClr(i, p.readyReadFds)
		} else if syscall.FDIsSet(i, p.readyWriteFds) {
			flag = true
			mode = 'w'
			syscall.FDClr(i, p.readyWriteFds)
		}
		if flag {
			if !syscall.FDIsSet(i, p.repeatFds) {
				p.DelFD(i, mode)
			}
			p.nReady--
			p.lastFd = i
			return i, mode, nil
		}
	}

	// Will not reach here.  Just to shut up the compiler.
	return -1, 0, nil
}
예제 #6
0
func uxSelect(nfd int, r, w, e *fdSet, tv *syscall.Timeval) (n int, err error) {
	return syscall.Select(nfd,
		(*syscall.FdSet)(r),
		(*syscall.FdSet)(w),
		(*syscall.FdSet)(e),
		tv)
}
예제 #7
0
파일: xlib.go 프로젝트: evmar/smash
// waitUntilReadable blocks until fd is readable.
func waitUntilReadable(fd int) error {
	var fds syscall.FdSet
	fds.Bits[0] = 1 << uint(fd)
	for {
		_, err := syscall.Select(fd+1, &fds, nil, nil, nil)
		if err != nil {
			if err == EINTR {
				continue
			}
			return err
		}
		return nil // readable
	}
}
예제 #8
0
파일: output.go 프로젝트: knz/reg
func output(fd uintptr, out <-chan string, outready chan<- bool) {

	set := syscall.FdSet{}
	for {
		set.Bits[fd/64] = int32(fd) % 64
		err := syscall.Select(int(fd+1), nil, &set, nil, nil)
		Assert(err == nil, "Select() for write on fd ", fd, ":", err)

		outready <- true
		cmd := <-out
		_, err = syscall.Write(int(fd), []byte(cmd))
		Assert(err == nil, "Write() on fd ", fd, ":", err)
	}
}
예제 #9
0
파일: watcher.go 프로젝트: hbdlb/gpio
func (w *Watcher) fdSelect() {
	timeval := &syscall.Timeval{
		Sec:  1,
		Usec: 0,
	}
	fdset := w.fds.FdSet()
	n, err := syscall.Select(int(w.fds[0]+1), nil, nil, fdset, timeval)
	if err != nil {
		fmt.Printf("failed to call syscall.Select, %s", err)
		os.Exit(1)
	}
	if n != 0 {
		w.notify(fdset)
	}
}
예제 #10
0
func uxSelect(nfd int, r, w, e *fdSet, tv *syscall.Timeval) (n int, err error) {
	// The Go syscall.Select for the BSD unixes is buggy. It
	// returns only the error and not the number of active file
	// descriptors. To cope with this, we return "nfd" as the
	// number of active file-descriptors. This can cause
	// significant performance degradation but there's nothing
	// else we can do.
	err = syscall.Select(nfd,
		(*syscall.FdSet)(r),
		(*syscall.FdSet)(w),
		(*syscall.FdSet)(e),
		tv)
	if err != nil {
		return 0, err
	}
	return nfd, nil
}
예제 #11
0
func Select(nfds int, readFds, writeFds *syscall.FdSet, timespec *Timespec) (int, error) {
	timeout := &syscall.Timeval{Sec: int64(timespec.Sec), Usec: int32(timespec.Nsec / 1000)}
	if err := syscall.Select(nfds, readFds, writeFds, nil, timeout); err != nil {
		return 0, err
	} else {
		max := 0
		read := Fdset32{readFds.Bits}
		write := Fdset32{writeFds.Bits}
		fds := append(read.Fds(), write.Fds()...)
		for _, v := range fds {
			if v > max {
				max = v
			}
		}
		return max + 1, nil
	}
}
예제 #12
0
func packetReader(t *DarwinTunTap) {
	var exit bool
	packet := make([]byte, 65535)
	fds := new(syscall.FdSet)
	fd := int(t.file.Fd())
	FD_SET(fd, fds)

	for {
		// On Mac OS X, reading from the tun/tap device will do strange
		// things.  We need to use syscall.Select.
		syscall.Select(fd+1, fds, nil, nil, nil)

		// We need to check whether we're to exit here - before the .Read() call
		// below, since the syscall above could have been terminated by the
		// closure of the associated fd.  We do a non-blocking select that will
		// fall through to the default case if there is nothing to read from our
		// exit channel to determine this.
		select {
		case exit = <-t.exit:
		default:
		}
		if exit {
			log.Printf("Exit signal received\n")
			break
		}

		n, err := t.file.Read(packet)
		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("Error reading from tuntap: %s\n", err)

			// This wait is to stop us from getting stuck in an infinite loop
			// of reads that all error, and consuming 100% CPU forever.
			<-time.After(100 * time.Millisecond)
			continue
		}

		t.packets <- packet[0:n]
	}

	// This needs to be the last thing in the function.
	log.Printf("Done")
	t.finished <- true
}
/*-----------------------------------------------------------------------------
-- FUNCTION:    read
--
-- DATE:        February 6, 2016
--
-- REVISIONS:	  February 11, 2016 - Modified for select
--
-- DESIGNER:		Marc Vouve
--
-- PROGRAMMER:	Marc Vouve
--
-- INTERFACE:   func fdSET(p *syscall.FdSet, i int)
--
-- RETURNS:    void
--
-- NOTES:			reimplementation of C macro
------------------------------------------------------------------------------*/
func serverInstance(srvInfo serverInfo) {
	var fdSet, rSet syscall.FdSet
	client := make(map[int]connectionInfo)
	highClient := srvInfo.listener

	fdZERO(&fdSet)
	fdSET(&fdSet, srvInfo.listener)

	for {
		copy(rSet.Bits[:], fdSet.Bits[:])
		_, err := syscall.Select(highClient+1, &rSet, nil, nil, nil)
		if err != nil {
			log.Println("err", err)
			return // block shouldn't be hit under normal conditions. If it does something is really wrong.
		}
		if fdISSET(&rSet, srvInfo.listener) { // new client
			newClient, err := newConnection(srvInfo.listener)
			if err == nil {
				client[newClient.FileDescriptor] = newClient
				fdSET(&fdSet, newClient.FileDescriptor)
				srvInfo.serverConnection <- 1
				if newClient.FileDescriptor > highClient {
					highClient = newClient.FileDescriptor
				}
			}
		}
		for conn := range client {
			socketfd := client[conn].FileDescriptor
			if fdISSET(&rSet, socketfd) { // existing connection
				connect := client[conn]
				err := handleData(&connect)
				client[conn] = connect
				if err != nil {
					if err != io.EOF {
						log.Println(err)
					}
					fdCLEAR(&fdSet, client[conn].FileDescriptor)
					endConnection(srvInfo, client[conn])
					delete(client, conn)
				}
			}
		}
	}
}
예제 #14
0
파일: gpio.go 프로젝트: cswank/quimby
func (g *GPIO) Wait() (bool, error) {
	if g.fd == 0 {
		fd, err := syscall.Open(g.valuePath, syscall.O_RDONLY, 0666)
		if err != nil {
			return false, err
		}
		g.fd = fd
		g.fdSet = new(syscall.FdSet)
		FD_SET(g.fd, g.fdSet)
		g.buf = make([]byte, 64)
		syscall.Read(g.fd, g.buf)
	}
	syscall.Select(g.fd+1, nil, nil, g.fdSet, nil)
	syscall.Seek(g.fd, 0, 0)
	_, err := syscall.Read(g.fd, g.buf)
	if err != nil {
		return false, err
	}
	return string(g.buf[:2]) == "1\n", nil
}
예제 #15
0
파일: select.go 프로젝트: simple555a/junk
func (p *poller) loop(timeout time.Duration) error {
	var rset, wset syscall.FdSet
	var numfd int
	set(&rset, p.pr.Fd(), &numfd)
	tv := toTimeval(timeout)
	n, err := syscall.Select(numfd+1, &rset, &wset, nil, &tv)
	if err != nil {
		return err
	}
	for fd := uintptr(0); n > 0 && fd <= uintptr(numfd); fd++ {
		if isset(&rset, fd) {
			n--
			log.Println(fd, "read")
		}
		if isset(&wset, fd) {
			n--
			log.Println(fd, "write")
		}
	}
	return nil
}
예제 #16
0
func waitWithTimeout(socket int, timeout time.Duration) (state SocketState, err error) {
	wfdset := &syscall.FdSet{}

	FD_ZERO(wfdset)
	FD_SET(wfdset, socket)

	timeval := syscall.NsecToTimeval(int64(timeout))

	syscall.Select(socket+1, nil, wfdset, nil, &timeval)

	errcode, err := syscall.GetsockoptInt(socket, syscall.SOL_SOCKET, syscall.SO_ERROR)
	if err != nil {
		state = SocketError
		return
	}

	if errcode == int(syscall.EHOSTUNREACH) {
		state = SocketNotReached
		return
	}

	if errcode == int(syscall.ECONNREFUSED) {
		state = SocketPortClosed
		return
	}

	if errcode != 0 {
		state = SocketError
		err = fmt.Errorf("Connect Error: %v", errcode)
		return
	}

	if FD_ISSET(wfdset, socket) {
		state = SocketConnected
	} else {
		state = SocketTimedOut
	}
	return
}
예제 #17
0
// Read reads from serial port. Port must be opened before calling this method.
// It is blocked until all data received or timeout after p.timeout.
func (p *port) Read(b []byte) (n int, err error) {
	var rfds syscall.FdSet

	fd := int(p.file.Fd())
	fdSet(fd, &rfds)

	var tv *syscall.Timeval
	if p.timeout > 0 {
		timeout := syscall.NsecToTimeval(p.timeout.Nanoseconds())
		tv = &timeout
	}
	if err = syscall.Select(fd+1, &rfds, nil, nil, tv); err != nil {
		err = fmt.Errorf("serial: could not select: %v", err)
		return
	}
	if !fdIsSet(fd, &rfds) {
		// Timeout
		err = ErrTimeout
		return
	}
	n, err = p.file.Read(b)
	return
}
예제 #18
0
파일: streaming.go 프로젝트: yubo/dea_ng
// Returns errors (if any) triggered by the inotify subsystem or when reading
// the file. Errors when writing to the writer are ignored.
func streamFile(writer io.Writer, path string, maxIdleTime uint32) error {
	handle, err := os.Open(path)
	if err != nil {
		return err
	}

	_, err = handle.Seek(0, os.SEEK_END)
	if err != nil {
		handle.Close()
		return err
	}

	reader := bufio.NewReader(handle)
	readBuffer := make([]byte, 4096)

	inotifyFd, err := syscall.InotifyInit()
	if err != nil {
		handle.Close()
		return err
	}

	watchDesc, err := syscall.InotifyAddWatch(inotifyFd, path,
		syscall.IN_MODIFY)
	if err != nil {
		syscall.Close(inotifyFd)
		handle.Close()
		return err
	}

	eventsBuffer := make([]byte, syscall.SizeofInotifyEvent*4096)

	selectMaxIdleTime := syscall.Timeval{}
	selectMaxIdleTime.Sec = int64(maxIdleTime)

	inotifyFdSet := syscall.FdSet{}
	lastWriteTime := time.Now()

	canScan := true
	for canScan && !timeout(lastWriteTime, maxIdleTime) {
		clearAll(&inotifyFdSet)
		set(&inotifyFdSet, inotifyFd)
		_, err := syscall.Select(inotifyFd+1, &inotifyFdSet,
			nil, nil, &selectMaxIdleTime)

		if err != nil {
			break
		}

		if !isSet(&inotifyFdSet, inotifyFd) {
			continue
		}

		numEventsBytes, err := syscall.Read(inotifyFd, eventsBuffer[0:])
		if numEventsBytes < syscall.SizeofInotifyEvent {
			if numEventsBytes < 0 {
				err = errors.New("inotify: read failed.")
			} else {
				err = errors.New("inotify: short read.")
			}

			break
		}

		var offset uint32 = 0
		for offset <= uint32(numEventsBytes-syscall.SizeofInotifyEvent) {
			event := (*syscall.InotifyEvent)(unsafe.
				Pointer(&eventsBuffer[offset]))

			n, err := reader.Read(readBuffer)
			if err != nil {
				// Ignore the EOF error and continue polling
				// the file until timeout.
				if err == io.EOF {
					err = nil
				}
				break
			}

			buffer := make([]byte, n)
			for index := 0; index < n; index++ {
				buffer[index] = readBuffer[index]
			}

			_, err = writer.Write(buffer)
			if err != nil {
				// Stop scanning for updates to the file.
				canScan = false
				// Ignore the write error.
				err = nil
				break
			}

			lastWriteTime = time.Now()
			// Move to the next event.
			offset += syscall.SizeofInotifyEvent + event.Len
		}
	}

	// The inotify watch gets automatically removed by the inotify system
	// when the file is removed. If the above loop times out, but the file
	// is removed only just before the if block below is executed, then the
	// removal of the watch below will throw an error as the watch
	// descriptor is obsolete. We ignore this error because it is harmless.
	syscall.InotifyRmWatch(inotifyFd, uint32(watchDesc))

	// Though we return the first error that occured, we still need to
	// attempt to close all the file descriptors.
	inotifyCloseErr := syscall.Close(inotifyFd)
	handleCloseErr := handle.Close()

	if err != nil {
		return err
	} else if inotifyCloseErr != nil {
		return inotifyCloseErr
	}

	return handleCloseErr
}
예제 #19
0
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
	if p.nReady == 0 {
		var timeout *syscall.Timeval
		var tv syscall.Timeval
		timeout = nil
		if nsec > 0 {
			tv = syscall.NsecToTimeval(nsec)
			timeout = &tv
		}

		var n int
		var e error
		var tmpReadFds, tmpWriteFds syscall.FdSet
		for {
			if p.closed {
				return -1, 0, errors.New("pollster closed")
			}

			// Temporary syscall.FdSet's into which the values are copied
			// because select mutates the values.
			tmpReadFds = *p.readFds
			tmpWriteFds = *p.writeFds

			s.Unlock()
			n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
			s.Lock()

			if e != syscall.EINTR {
				break
			}
		}
		if e == syscall.EBADF {
			// Some file descriptor has been closed.
			tmpReadFds = syscall.FdSet{}
			tmpWriteFds = syscall.FdSet{}
			n = 0
			for i := 0; i < p.maxFd+1; i++ {
				if syscall.FDIsSet(i, p.readFds) {
					var s syscall.Stat_t
					if syscall.Fstat(i, &s) == syscall.EBADF {
						syscall.FDSet(i, &tmpReadFds)
						n++
					}
				} else if syscall.FDIsSet(i, p.writeFds) {
					var s syscall.Stat_t
					if syscall.Fstat(i, &s) == syscall.EBADF {
						syscall.FDSet(i, &tmpWriteFds)
						n++
					}
				}
			}
		} else if e != nil {
			return -1, 0, os.NewSyscallError("select", e)
		}
		if n == 0 {
			return -1, 0, nil
		}

		p.nReady = n
		*p.readyReadFds = tmpReadFds
		*p.readyWriteFds = tmpWriteFds
		p.lastFd = 0
	}

	flag := false
	for i := p.lastFd; i < p.maxFd+1; i++ {
		if syscall.FDIsSet(i, p.readyReadFds) {
			flag = true
			mode = 'r'
			syscall.FDClr(i, p.readyReadFds)
		} else if syscall.FDIsSet(i, p.readyWriteFds) {
			flag = true
			mode = 'w'
			syscall.FDClr(i, p.readyWriteFds)
		}
		if flag {
			if !syscall.FDIsSet(i, p.repeatFds) {
				p.DelFD(i, mode)
			}
			p.nReady--
			p.lastFd = i
			return i, mode, nil
		}
	}

	// Will not reach here.  Just to shut up the compiler.
	return -1, 0, nil
}
예제 #20
0
func Select(nfd int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, timeout *syscall.Timeval) error {
	_, err := syscall.Select(nfd, r, w, e, timeout)
	return err
}
예제 #21
0
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *syscall.Timeval) error {
	_, err := syscall.Select(nfd, r.s(), w.s(), e.s(), timeout)
	return err
}
예제 #22
0
파일: select_linux.go 프로젝트: yubo/gotty
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
	_, err := syscall.Select(n, (*syscall.FdSet)(r), (*syscall.FdSet)(w), (*syscall.FdSet)(e), timeout)
	return err
}
예제 #23
0
func selectFds(n int, r, w, e *syscall.FdSet, t *syscall.Timeval) (errno int) {
	_, errno = syscall.Select(n, r, w, e, t)
	return
}
예제 #24
0
파일: select_bsd.go 프로젝트: Mrhjx2/elvish
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *syscall.Timeval) (err error) {
	return syscall.Select(nfd, r.s(), w.s(), e.s(), timeout)
}
예제 #25
0
func cgcNativeSelect(nfds int, readFds, writeFds *syscall.FdSet, timespec *posix.Timespec) (int, error) {
	// TODO: 32-bit vs 64-bit
	timeout := &syscall.Timeval{Sec: int64(timespec.Sec), Usec: int64(timespec.Nsec / 1000)}
	return syscall.Select(nfds, readFds, writeFds, nil, timeout)
}
예제 #26
0
func (sock fd) connectTimeout(addr ax25Addr, timeout time.Duration) (err error) {
	if timeout == 0 {
		return sock.connect(addr)
	}
	if err = syscall.SetNonblock(int(sock), true); err != nil {
		return err
	}

	err = sock.connect(addr)
	if err == nil {
		return nil // Connected
	} else if err != syscall.EINPROGRESS {
		return fmt.Errorf("Unable to connect: %s", err)
	}

	// Shamelessly stolen from src/pkg/exp/inotify/inotify_linux.go:
	//
	// Create fdSet, taking into consideration that
	// 64-bit OS uses Bits: [16]int64, while 32-bit OS uses Bits: [32]int32.
	// This only support File Descriptors up to 1024
	//
	if sock > 1024 {
		panic(fmt.Errorf("connectTimeout: File Descriptor >= 1024: %v", sock))
	}
	fdset := new(syscall.FdSet)
	fElemSize := 32 * 32 / len(fdset.Bits)
	fdset.Bits[int(sock)/fElemSize] |= 1 << uint(int(sock)%fElemSize)
	//
	// Thanks!
	//

	// Wait or timeout
	var n int
	var tv syscall.Timeval
	for {
		tv = syscall.NsecToTimeval(int64(timeout))
		n, err = syscall.Select(int(sock)+1, nil, fdset, nil, &tv)
		if n < 0 && err != syscall.EINTR {
			return fmt.Errorf("Unable to connect: %s", err)
		} else if n > 0 {
			/* TODO: verify that connection is OK
			 * lon = sizeof(int);
			 * if (getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
			 *   fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
			 *   exit(0);
			 * }
			 * // Check the value returned...
			 * if (valopt) {
			 *   fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt));
			 *   exit(0);
			 * }
			 */
			break
		} else {
			return fmt.Errorf("Unable to connect: timeout")
		}
	}

	syscall.SetNonblock(int(sock), false)
	return
}
예제 #27
0
파일: udpping1.go 프로젝트: JeremyOT/zmq4
func main() {

	log.SetFlags(log.Lshortfile)

	//  Create UDP socket
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
	if err != nil {
		log.Fatalln(err)
	}

	//  Ask operating system to let us do broadcasts from socket
	if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil {
		log.Fatalln(err)
	}

	//  Bind UDP socket to local port so we can receive pings
	if err := syscall.Bind(fd, &syscall.SockaddrInet4{Port: PING_PORT_NUMBER, Addr: [4]byte{0, 0, 0, 0}}); err != nil {
		log.Fatalln(err)
	}

	buffer := make([]byte, PING_MSG_SIZE)

	//  We use syscall.Select to wait for activity on the UDP socket.
	//  We send a beacon once a second, and we collect and report
	//  beacons that come in from other nodes:

	rfds := &syscall.FdSet{}
	timeout := &syscall.Timeval{}

	//  Send first ping right away
	ping_at := time.Now()

	bcast := &syscall.SockaddrInet4{Port: PING_PORT_NUMBER, Addr: [4]byte{255, 255, 255, 255}}
	for {
		dur := int64(ping_at.Sub(time.Now()) / time.Microsecond)
		if dur < 0 {
			dur = 0
		}
		timeout.Sec, timeout.Usec = dur/1000000, dur%1000000
		FD_ZERO(rfds)
		FD_SET(rfds, fd)
		_, err := syscall.Select(fd+1, rfds, nil, nil, timeout)
		if err != nil {
			log.Fatalln(err)
		}

		//  Someone answered our ping
		if FD_ISSET(rfds, fd) {
			_, addr, err := syscall.Recvfrom(fd, buffer, 0)
			if err != nil {
				log.Fatalln(err)
			}
			a := addr.(*syscall.SockaddrInet4)
			fmt.Printf("Found peer %v.%v.%v.%v:%v\n", a.Addr[0], a.Addr[1], a.Addr[2], a.Addr[3], a.Port)
		}
		if time.Now().After(ping_at) {
			//  Broadcast our beacon
			fmt.Println("Pinging peers...")
			buffer[0] = '!'
			if err := syscall.Sendto(fd, buffer, 0, bcast); err != nil {
				log.Fatalln(err)
			}
			ping_at = time.Now().Add(PING_INTERVAL)
		}
	}

}
예제 #28
0
func nativeSelect(nfds int, readfds, writefds, errorfds *syscall.FdSet, timeout *syscall.Timeval) error {
	_, err := syscall.Select(nfds, readfds, writefds, errorfds, timeout)
	return err
}
예제 #29
0
func Select(nfds int, readFds, writeFds *syscall.FdSet, timespec *Timespec) (int, error) {
	return syscall.Select(nfds, readFds, writeFds, nil, timespec.Native())
}
예제 #30
0
// readEvents reads from the inotify file descriptor, converts the
// received events into Event objects and sends them via the Event channel
func (w *Watcher) readEvents() {
	var buf [syscall.SizeofInotifyEvent * 4096]byte

	// Timeout after 500 milliseconds when waiting for events
	// so we can reliably close the Watcher
	timeout := int64(500e6)
	readFds := newFdSet(w.fd)
	for {
		var n int
		var err error
		select {
		// See if there is a message on the "done" channel
		case <-w.done:
		// Otherwise select fd with timeout
		default:
			tmpSet := *readFds
			timeval := syscall.NsecToTimeval(timeout)
			n, err = syscall.Select(w.fd+1, &tmpSet, nil, nil, &timeval)
			if n == 1 {
				n, err = syscall.Read(w.fd, buf[0:])
			} else if err != nil {
				w.Error <- err
			} else {
				continue
			}
		}

		// If EOF or a "done" message is received
		if n == 0 {
			goto done
		}
		if n < 0 {
			w.Error <- os.NewSyscallError("read", err)
			continue
		}
		if n < syscall.SizeofInotifyEvent {
			w.Error <- errors.New("inotify: short read in readEvents()")
			continue
		}

		var offset uint32 = 0
		// We don't know how many events we just read into the buffer
		// While the offset points to at least one whole event...
		for offset <= uint32(n-syscall.SizeofInotifyEvent) {
			// Point "raw" to the event in the buffer
			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
			event := new(Event)
			event.Mask = uint32(raw.Mask)
			event.Cookie = uint32(raw.Cookie)
			nameLen := uint32(raw.Len)
			// If the event happened to the watched directory or the watched file, the kernel
			// doesn't append the filename to the event, but we would like to always fill the
			// the "Name" field with a valid filename. We retrieve the path of the watch from
			// the "paths" map.
			w.mu.Lock()
			event.Name = w.paths[int(raw.Wd)]
			// Check if the the watch was removed
			if event.Mask&IN_IGNORED != 0 {
				// remove stale watch
				delete(w.watches, event.Name)
				delete(w.paths, int(raw.Wd))
			}
			w.mu.Unlock()
			if nameLen > 0 {
				// Point "bytes" at the first byte of the filename
				bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
				// The filename is padded with NUL bytes. TrimRight() gets rid of those.
				event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
			}
			// Send the event on the events channel
			w.Event <- event

			// Move to the next event in the buffer
			offset += syscall.SizeofInotifyEvent + nameLen
		}
	}
done:
	w.isClosed = true // keep API behaviour consistent when EOF was read
	err := syscall.Close(w.fd)
	if err != nil {
		w.Error <- os.NewSyscallError("close", err)
	}
	close(w.Event)
	close(w.Error)
	for path, watch := range w.watches {
		delete(w.watches, path)
		delete(w.paths, int(watch.wd))
	}
}