示例#1
0
文件: gpio.go 项目: ungerik/go-bbio
func (gpio *GPIO) AddEdgeDetect(edge GPIOEdge) (chan bool, error) {
	gpio.RemoveEdgeDetect()

	err := gpio.SetDirection(GPIO_INPUT)
	if err != nil {
		return nil, err
	}
	err = gpio.SetEdge(edge)
	if err != nil {
		return nil, err
	}
	err = gpio.openValueFile()
	if err != nil {
		return nil, err
	}

	epfd, err := syscall.EpollCreate(1)
	if err != nil {
		return nil, err
	}

	event := &syscall.EpollEvent{
		Events: syscall.EPOLLIN | _EPOLLET | syscall.EPOLLPRI,
		Fd:     int32(gpio.value.Fd()),
	}
	err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, int(gpio.value.Fd()), event)
	if err != nil {
		syscall.Close(epfd)
		return nil, err
	}

	// / first time triggers with current state, so ignore
	_, err = syscall.EpollWait(epfd, make([]syscall.EpollEvent, 1), -1)
	if err != nil {
		syscall.Close(epfd)
		return nil, err
	}

	gpio.epfd.Set(epfd)

	valueChan := make(chan bool)
	go func() {
		for gpio.epfd.Get() != 0 {
			n, _ := syscall.EpollWait(epfd, make([]syscall.EpollEvent, 1), -1)
			if n > 0 {
				value, err := gpio.Value()
				if err == nil {
					valueChan <- value
				}
			}
		}
	}()
	return valueChan, nil
}
示例#2
0
文件: gpio_linux.go 项目: hagna/gpio
// setupEpoll sets up epoll for use
func setupEpoll() {
	var err error
	epollFD, err = syscall.EpollCreate1(0)
	if err != nil {
		fmt.Println("Unable to create epoll FD: ", err.Error())
		os.Exit(1)
	}

	go func() {

		var epollEvents [GPIOCount]syscall.EpollEvent

		for {
			numEvents, err := syscall.EpollWait(epollFD, epollEvents[:], -1)
			if err != nil {
				panic(fmt.Sprintf("EpollWait error: %s", err.Error()))
			}
			for i := 0; i < numEvents; i++ {
				if eventPin, exists := watchEventCallbacks[int(epollEvents[i].Fd)]; exists {
					if eventPin.initial {
						eventPin.initial = false
					} else {
						eventPin.callback()
					}
				}
			}
		}

	}()

}
/*-----------------------------------------------------------------------------
-- FUNCTION:    listen
--
-- DATE:        February 6, 2016
--
-- REVISIONS:	  February 10, 2016 - Modified for EPoll
--
-- DESIGNER:		Marc Vouve
--
-- PROGRAMMER:	Marc Vouve
--
-- INTERFACE:   func listen(srvInfo serverInfo)
--   srvInfo:   information about the overall application, IPC and networking
--
-- RETURNS:     void doesn't actually return.
--
-- NOTES:			This function handles Epoll in a foreverloop. This function never
--            exits
------------------------------------------------------------------------------*/
func listen(srvInfo serverInfo) {
	client := make(map[int]connectionInfo)
	epollFd, _ := syscall.EpollCreate1(0)
	events := make([]syscall.EpollEvent, epollQueueLen)
	addConnectionToEPoll(epollFd, srvInfo.listener)

	for {
		n, _ := syscall.EpollWait(epollFd, events[:], -1)
		for i := 0; i < n; i++ {
			if events[i].Events&(syscall.EPOLLHUP|syscall.EPOLLERR) != 0 {
				fmt.Println("Error on epoll")
				endConnection(srvInfo, client[int(events[i].Fd)])
			}
			if events[i].Fd == int32(srvInfo.listener) { // new connection
				newClient, err := newConnection(srvInfo.listener)
				if err == nil {
					srvInfo.serverConnection <- newConnectionConst
					client[newClient.FileDescriptor] = newClient
					addConnectionToEPoll(epollFd, newClient.FileDescriptor)
				}
			} else { // data to read from connection
				//  client[int(ev.Fd)] can not be used as an argument in handleData
				conn := client[int(events[i].Fd)]
				err := handleData(&conn)
				client[int(events[i].Fd)] = conn
				if err != nil {
					endConnection(srvInfo, client[int(events[i].Fd)])
				}
			}
		}
	}
}
示例#4
0
文件: interrupt.go 项目: kidoman/embd
func initEpollListener() *epollListener {
	fd, err := syscall.EpollCreate1(0)
	if err != nil {
		panic(fmt.Sprintf("Unable to create epoll: %v", err))
	}
	listener := &epollListener{fd: fd, interruptablePins: make(map[int]*interrupt)}

	go func() {
		var epollEvents [MaxGPIOInterrupt]syscall.EpollEvent

		for {
			n, err := syscall.EpollWait(listener.fd, epollEvents[:], -1)
			if err != nil {
				panic(fmt.Sprintf("EpollWait error: %v", err))
			}
			listener.mu.Lock()
			for i := 0; i < n; i++ {
				if irq, ok := listener.interruptablePins[int(epollEvents[i].Fd)]; ok {
					irq.Signal()
				}
			}
			listener.mu.Unlock()
		}
	}()
	return listener
}
示例#5
0
// loop blocks until either inotify or pipe file descriptor is ready for I/O.
// All read operations triggered by filesystem notifications are forwarded to
// one of the event's consumers. If pipe fd became ready, loop function closes
// all file descriptors opened by lazyinit method and returns afterwards.
func (i *inotify) loop(esch chan<- []*event) {
	epes := make([]syscall.EpollEvent, 1)
	fd := atomic.LoadInt32(&i.fd)
	for {
		switch _, err := syscall.EpollWait(i.epfd, epes, -1); err {
		case nil:
			switch epes[0].Fd {
			case fd:
				esch <- i.read()
				epes[0].Fd = 0
			case int32(i.pipefd[0]):
				i.Lock()
				defer i.Unlock()
				if err = syscall.Close(int(fd)); err != nil && err != syscall.EINTR {
					panic("notify: close(2) error " + err.Error())
				}
				atomic.StoreInt32(&i.fd, invalidDescriptor)
				if err = i.epollclose(); err != nil && err != syscall.EINTR {
					panic("notify: epollclose error " + err.Error())
				}
				close(esch)
				return
			}
		case syscall.EINTR:
			continue
		default: // We should never reach this line.
			panic("notify: epoll_wait(2) error " + err.Error())
		}
	}
}
示例#6
0
func listenPort(cReq chan<- []byte, epollFd int, reader *bufio.Reader) {
	events := make([]syscall.EpollEvent, 32)

	var buf []byte
	var err error

	for {
		if _, err := syscall.EpollWait(epollFd, events, -1); err != nil {
			log.Fatalln("Error receiving epoll events:", err)
		}

		buf, err = reader.ReadBytes('\x0a')
		switch err {
		case nil:
		case io.EOF:
			time.Sleep(time.Second * 1)
			continue
		default:
			log.Fatalln(err)
		}

		break
	}

	cReq <- buf
}
示例#7
0
func (ep *EPoll) Poll(timeout int) (int, error) {
	nfds, err := syscall.EpollWait(ep.fd, ep.events[0:], timeout)
	if err != nil {
		return 0, err
	}

	ep.nfds = nfds

	return nfds, nil
}
示例#8
0
func (gpio *GPIO) WaitForEdge(edge Edge) (value Value, err error) {
	if err = gpio.setEdge(edge); err != nil {
		return 0, err
	}
	if err = gpio.ensureValueFileIsOpen(); err != nil {
		return 0, err
	}

	epollFd := gpio.epollFd.Get()

	if epollFd == 0 {
		epollFd, err = syscall.EpollCreate(1)
		if err != nil {
			return 0, err
		}

		event := &syscall.EpollEvent{
			Events: syscall.EPOLLIN | syscall.EPOLLPRI | _EPOLLET,
			Fd:     int32(gpio.valueFile.Fd()),
		}
		err = syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, int(gpio.valueFile.Fd()), event)
		if err != nil {
			syscall.Close(epollFd)
			return 0, err
		}

		// first time triggers with current state, so ignore
		_, err = syscall.EpollWait(epollFd, dummyEpollEvents, -1)
		if err != nil {
			syscall.Close(epollFd)
			return 0, err
		}

		gpio.epollFd.Set(epollFd)
	}

	_, err = syscall.EpollWait(epollFd, dummyEpollEvents, -1)
	if err != nil {
		return 0, err
	}
	return gpio.Value()
}
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
	// Get an event.
	var evarray [1]syscall.EpollEvent
	ev := &evarray[0]
	var msec int = -1
	if nsec > 0 {
		msec = int((nsec + 1e6 - 1) / 1e6)
	}
	n, e := syscall.EpollWait(p.epfd, evarray[0:], msec)
	for e == syscall.EAGAIN || e == syscall.EINTR {
		n, e = syscall.EpollWait(p.epfd, evarray[0:], msec)
	}
	if e != 0 {
		return -1, 0, os.NewSyscallError("epoll_wait", e)
	}
	if n == 0 {
		return -1, 0, nil
	}
	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}
示例#10
0
func (p *Poller) WaitWrite(deadline time.Time) error {
	msec := -1
	if !deadline.IsZero() {
		d := deadline.Sub(time.Now())
		msec = int(d.Nanoseconds() / 1000000) // ms!? omg...
	}

	n, err := syscall.EpollWait(p.epfd, p.events[:], msec)
	if err != nil {
		return err
	}
	if n < 1 {
		return errTimeout
	}
	return nil
}
示例#11
0
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
	for len(p.waitEvents) == 0 {
		var msec int = -1
		if nsec > 0 {
			msec = int((nsec + 1e6 - 1) / 1e6)
		}

		s.Unlock()
		n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
		s.Lock()

		if e != nil {
			if e == syscall.EAGAIN || e == syscall.EINTR {
				continue
			}
			return -1, 0, os.NewSyscallError("epoll_wait", e)
		}
		if n == 0 {
			return -1, 0, nil
		}
		p.waitEvents = p.waitEventBuf[0:n]
	}

	ev := &p.waitEvents[0]
	p.waitEvents = p.waitEvents[1:]

	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}
示例#12
0
func Run(t *Tunnel) {
	var err error
	epollFd, err = syscall.EpollCreate(1024)
	if err != nil {
		logger.Log(logger.ERR, "Create epoll fd error [%s]", err)
		os.Exit(-2)
	}

	for _, step := range initStep {
		err = step.Action(t)
		if err != nil {
			fmt.Fprintf(os.Stderr, step.ErrFmt, err)
			os.Exit(-2)
		}
	}
	runTunnel = t

	events := make([]syscall.EpollEvent, 10, 10)
	for {
		en, err := syscall.EpollWait(epollFd, events, 1000)
		if err != nil {
			logger.Log(logger.ERR, "Wail epoll fd error [%s]", err)
			os.Exit(-2)
		}
		for i := 0; i < en; i++ {
			ee := events[i]
			if runTunnel.LFd == int(ee.Fd) {
				runTunnel.newConn()
				continue
			}
			tc, ok := fdTunnelConn[int(ee.Fd)]
			if !ok {
				continue
			}
			if ee.Events&syscall.EPOLLIN != 0 {
				tc.handleIn(int(ee.Fd))
			}
			if ee.Events&syscall.EPOLLOUT != 0 {
				tc.handleOut(int(ee.Fd))
			}
			if ee.Events&syscall.EPOLLHUP != 0 {
				tc.shutdown()
			}
		}
	}
}
示例#13
0
func inotify_observe_collect(buf []byte) map[string]int {
	epoll_buf := make([]syscall.EpollEvent, 1)
	collect := make(map[string]int)
	for {
		nread, _ := syscall.Read(inotify_fd, buf)
		for offset := 0; offset < nread; offset += event_size {
			event := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
			if syscall.IN_IGNORED == event.Mask {
				continue
			}
			collect[name_by_wd[event.Wd]] = 1
		}
		nevents, err := syscall.EpollWait(epoll_fd, epoll_buf, 500)
		if 0 >= nevents {
			if -1 == nevents {
				tabby_log("inotify_observe_collect: " + err.Error())
			}
			break
		}
	}
	return collect
}
示例#14
0
func poller() {
	debugf("Started.")
	events := make([]syscall.EpollEvent, 128)
	for {
		n, err := syscall.EpollWait(epfd, events, -1)
		if err != nil {
			if err == syscall.EINTR {
				continue
			}
			log.Panicf("poller: EpollWait: %s", err.Error())
		}
		for i := 0; i < n; i++ {
			ev := &events[i]
			if isReadEvent(ev) {
				epollEvent(ev, false)
			}
			if isWriteEvent(ev) {
				epollEvent(ev, true)
			}
		}
	}
}
示例#15
0
func (w *Watcher) epollEvents(epfd int, donePipe *os.File) {
	w.isRunning = true
	defer func() {
		syscall.Close(epfd)
		w.isRunning = false
		w.closed <- true
	}()
	events := make([]syscall.EpollEvent, EPOLL_MAX_EVENTS)
	doneFd := int32(donePipe.Fd())
	for {
		nevents, err := syscall.EpollWait(epfd, events, -1)
		if err != nil {
			w.Errors <- os.NewSyscallError("epoll_wait", err)
			continue
		}
		if nevents == 0 {
			continue
		}

		for i := 0; i < nevents; i++ {
			if events[i].Fd == doneFd {
				if err = donePipe.Close(); err != nil {
					w.Errors <- err
				}
				syscall.Close(w.fd)
				close(w.Events)
				close(w.Errors)
				return
			} else if events[i].Fd != int32(w.fd) {
				continue
			}
			if err = w.readEvents(); err != nil {
				w.Errors <- err
			}
		}
	}
}
示例#16
0
文件: io.go 项目: ninchat/zmq4chan
func (io *IO) eventLoop() {
	const mask = syscall.EPOLLIN | syscall.EPOLLERR | syscall.EPOLLHUP

	buf := make([]syscall.EpollEvent, epollEventBufferSize)

	for {
		n, err := syscall.EpollWait(io.epollFd, buf, -1)
		if err != nil {
			panic(err)
		}

		io.lock.Lock()

		for _, e := range buf[:n] {
			if e.Events&mask != 0 {
				if w := io.workers[e.Fd]; w != nil {
					w.notify()
				}
			}
		}

		io.lock.Unlock()
	}
}
示例#17
0
func (u *NetLinkProbe) start(nsPath string) {
	var context *common.NetNSContext
	var err error

	// Enter the network namespace if necessary
	if nsPath != "" {
		context, err = common.NewNetNsContext(nsPath)
		if err != nil {
			logging.GetLogger().Errorf("Failed to switch namespace: %s", err.Error())
			return
		}
	}

	// Both NewHandle and Subscribe need to done in the network namespace.
	h, err := netlink.NewHandle(syscall.NETLINK_ROUTE)
	if err != nil {
		logging.GetLogger().Errorf("Failed to create netlink handle: %s", err.Error())
		context.Close()
		return
	}
	defer h.Delete()

	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
	if err != nil {
		logging.GetLogger().Errorf("Failed to subscribe to netlink messages: %s", err.Error())
		context.Close()
		return
	}
	defer s.Close()

	u.ethtool, err = ethtool.NewEthtool()
	if err != nil {
		logging.GetLogger().Errorf("Failed to create ethtool object: %s", err.Error())
		context.Close()
		return
	}
	defer u.ethtool.Close()

	epfd, e := syscall.EpollCreate1(0)
	if e != nil {
		logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error())
		return
	}
	defer syscall.Close(epfd)

	// Leave the network namespace
	context.Close()

	u.wg.Add(1)
	defer u.wg.Done()

	atomic.StoreInt64(&u.state, common.RunningState)
	defer atomic.StoreInt64(&u.state, common.StoppedState)

	u.netlink = h
	u.initialize()

	fd := s.GetFd()
	err = syscall.SetNonblock(fd, true)
	if err != nil {
		logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}

	event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)}
	if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
		logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error())
		return
	}
	events := make([]syscall.EpollEvent, maxEpollEvents)

	for atomic.LoadInt64(&u.state) == common.RunningState {
		n, err := syscall.EpollWait(epfd, events[:], 1000)
		if err != nil {
			errno, ok := err.(syscall.Errno)
			if ok && errno != syscall.EINTR {
				logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error())
			}
			continue
		}
		if n == 0 {
			continue
		}

		msgs, err := s.Receive()
		if err != nil {
			if errno, ok := err.(syscall.Errno); !ok || !errno.Temporary() {
				logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error())
				return
			}
			time.Sleep(1 * time.Second)
			continue
		}

		for _, msg := range msgs {
			switch msg.Header.Type {
			case syscall.RTM_NEWLINK:
				link, err := netlink.LinkDeserialize(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error())
					continue
				}
				u.onLinkAdded(link)
			case syscall.RTM_DELLINK:
				link, err := netlink.LinkDeserialize(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error())
					continue
				}
				u.onLinkDeleted(link)
			case syscall.RTM_NEWADDR:
				addr, family, ifindex, err := parseAddr(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error())
					continue
				}
				u.onAddressAdded(addr, family, ifindex)
			case syscall.RTM_DELADDR:
				addr, family, ifindex, err := parseAddr(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error())
					continue
				}
				u.onAddressDeleted(addr, family, ifindex)
			}
		}
	}
}
示例#18
0
func (watcher *PinWatcher) pinHandler() {
	exf, exf_err := os.OpenFile("/sys/class/gpio/export", syscall.O_WRONLY, 0400)
	if exf_err != nil {
		log.Panicln("Error opening /sys/class/gpio/export:", exf_err)
	}
	_, ex_err := exf.WriteString(fmt.Sprintf("%d", watcher.pin))
	if ex_err != nil {
		log.Panicln("Error writing to /sys/class/gpio/export:", ex_err)
	}
	exf.Close()
	time.Sleep(time.Microsecond)

	edge_file := fmt.Sprintf("/sys/class/gpio/gpio%d/edge", watcher.pin)
	edgef, edgef_err := os.OpenFile(edge_file, syscall.O_WRONLY, 0400)
	if edgef_err != nil {
		log.Panicf("Error opening %s: %s\n", edge_file, edgef_err)
	}
	_, edge_err := edgef.WriteString("both")
	if edge_err != nil {
		log.Panicf("Error writing to %s: %s\n", edge_file, edge_err)
	}
	edgef.Close()
	time.Sleep(time.Microsecond)

	value_file := fmt.Sprintf("/sys/class/gpio/gpio%d/value", watcher.pin)
	irq_fd, irq_err := syscall.Open(value_file, syscall.O_RDONLY|syscall.O_NONBLOCK, syscall.S_IREAD)
	if irq_err != nil {
		log.Panicln("Error opening %s: %s\n", value_file, irq_err)
	}

	epfd, eperr := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
	if eperr != nil {
		log.Panicln("Error creating epoll:", eperr)
	}

	event := new(syscall.EpollEvent)
	event.Fd = int32(irq_fd)
	event.Events |= syscall.EPOLLPRI
	if ctlerr := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, irq_fd, event); ctlerr != nil {
		log.Panicln("Error on epoll control operation:", ctlerr)
	}

	var events_buffer [10]syscall.EpollEvent
	var buf [1]byte
	for !watcher.shutdown {
		n, werr := syscall.EpollWait(epfd, events_buffer[0:], 4000)
		if werr != nil {
			log.Println("Epoll error:", werr)
		} else if n == 1 {
			syscall.Seek(irq_fd, 0, 0)
			syscall.Read(irq_fd, buf[0:])
			log.Println("Interrupt!", events_buffer[0].Fd, events_buffer[0].Events, buf)
		} else {
			log.Println("Timeout")
		}
	}

	syscall.Close(irq_fd)

	unexf, unexf_err := os.OpenFile("/sys/class/gpio/unexport", syscall.O_WRONLY|syscall.O_SYNC, 0400)
	if unexf_err != nil {
		log.Panicln("Error opening /sys/class/gpio/unexport:", unexf_err)
	}
	_, unex_err := unexf.WriteString(fmt.Sprintf("%d", watcher.pin))
	if unex_err != nil {
		log.Panicln("Error writing to /sys/class/gpio/unexport:", unex_err)
	}

	unexf.Close()

	watcher.wg.Done()
}
示例#19
0
文件: fd_linux.go 项目: hkwi/blugo
func (self HciDev) Request(opcode OpCode, params ...Parameter) (Parameters, error) {
	req := make([]byte, 4)
	req[0] = HCI_COMMAND_PKT
	binary.LittleEndian.PutUint16(req[1:], uint16(opcode))

	if pbuf, err := Parameters(params).MarshalBinary(); err != nil {
		return nil, err
	} else {
		req[3] = uint8(len(pbuf))
		req = append(req, pbuf...)
	}

	if filter, err := GetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER); err != nil {
		return nil, err
	} else {
		defer SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter)
	}

	filter := &HciFilter{
		Type_mask:  1 << HCI_EVENT_PKT,
		Event_mask: FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE),
		Opcode:     opcode.Native(),
	}
	if opcode.Ogf() == OGF_LE_CTL {
		filter.Event_mask = FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE, EVT_LE_META_EVENT)
	}
	if err := SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter); err != nil {
		return nil, err
	}

	if n, err := self.Write(req); err != nil {
		return nil, err
	} else if n != len(req) {
		return nil, fmt.Errorf("write incomplete")
	}

	if efd, err := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil {
		return nil, err
	} else {
		defer syscall.Close(efd)

		var events [1]syscall.EpollEvent
		syscall.EpollCtl(efd, syscall.EPOLL_CTL_ADD, int(self), &syscall.EpollEvent{
			Events: syscall.EPOLLIN,
			Fd:     int32(self),
		})

		capture := make([]byte, 0, 258)
		buf := make([]byte, 258)
		for {
			if n, err := syscall.EpollWait(efd, events[:], 100); err != nil {
				return nil, err
			} else if n == 0 {
				continue
			}
			// todo: operation timeout

			if n, _, _, _, err := syscall.Recvmsg(int(self), buf, nil, syscall.MSG_DONTWAIT); err != nil {
				if errno, ok := err.(syscall.Errno); ok && errno.Temporary() {
					continue
				}
				return nil, err
			} else if n == 0 {
				continue
			} else {
				capture = append(capture, buf[:n]...)
			}
			if pkt, step := Parse(capture); step == 0 {
				continue
			} else if p, err := pkt.(EventPkt).Parse(); err != nil {
				continue
			} else {
				switch ev := p.(type) {
				case EvtCmdComplete:
					if ev.OpCode == uint16(opcode) {
						return opcode.Response(ev.Params)
					}
				case EvtCmdStatus:
					if ev.OpCode == uint16(opcode) && ev.Status != 0 {
						return nil, HciError(ev.Status)
					}
				case EvtLeMetaEvent:
					// todo: OGF_LE_CTL opcode expects this
				}
				capture = capture[step:]
			}
		}
		return nil, fmt.Errorf("should not reach")
	}
}
// EpollWait directly calls syscall.EpollWait
func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
	return syscall.EpollWait(epfd, events, msec)
}
示例#21
0
func (u *NetLinkTopoUpdater) start() {
	logging.GetLogger().Debug("Start NetLink Topo Updater for container: %s", u.Container.ID)

	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
	if err != nil {
		logging.GetLogger().Error("Failed to subscribe to netlink RTNLGRP_LINK messages: %s", err.Error())
		return
	}
	u.nlSocket = s

	fd := u.nlSocket.GetFd()

	err = syscall.SetNonblock(fd, true)
	if err != nil {
		logging.GetLogger().Error("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}

	epfd, e := syscall.EpollCreate1(0)
	if e != nil {
		logging.GetLogger().Error("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}
	defer syscall.Close(epfd)

	u.initialize()

	event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)}
	if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
		logging.GetLogger().Error("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}

	events := make([]syscall.EpollEvent, maxEpollEvents)

Loop:
	for {
		n, err := syscall.EpollWait(epfd, events[:], 1000)
		if err != nil {
			logging.GetLogger().Error("Failed to receive from netlink messages: %s", err.Error())
			continue
		}

		if n == 0 {
			select {
			case <-u.doneChan:
				logging.GetLogger().Debug("WHOU")

				break Loop
			default:
				continue
			}
		}

		msgs, err := s.Receive()
		if err != nil {
			logging.GetLogger().Error("Failed to receive from netlink messages: %s", err.Error())

			time.Sleep(1 * time.Second)
			continue
		}

		for _, msg := range msgs {
			switch msg.Header.Type {
			case syscall.RTM_NEWLINK:
				ifmsg := nl.DeserializeIfInfomsg(msg.Data)
				u.onLinkAdded(int(ifmsg.Index))
			case syscall.RTM_DELLINK:
				ifmsg := nl.DeserializeIfInfomsg(msg.Data)
				u.onLinkDeleted(int(ifmsg.Index))
			}
		}
	}

	u.nlSocket.Close()
}
示例#22
0
文件: linux.go 项目: hkwi/fdset
func NewFdset() *Fdset {
	self := &Fdset{
		rListener: make(map[int]fdListener),
		wListener: make(map[int]fdListener),
		rDeadline: make(map[int]time.Time),
		wDeadline: make(map[int]time.Time),
	}
	efd, e1 := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
	if e1 != nil {
		return nil
	}

	ctls, e2 := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, 0)
	if e2 != nil {
		return nil
	}
	self.ctl = ctls[0]
	self.rListener[ctls[1]] = fdDrain(ctls[1])

	go func() {
		defer func() {
			syscall.Close(ctls[1])
			self.Close()
		}()
		evs := make([]syscall.EpollEvent, 8)
		for {
			fds := make(map[int]uint32)
			for fd, _ := range self.rListener {
				fds[fd] |= syscall.EPOLLIN
			}
			for fd, _ := range self.wListener {
				fds[fd] |= syscall.EPOLLOUT
			}
			if len(fds) == 0 {
				break
			}

			have_tm := false
			var tm time.Time
			for _, t := range self.rDeadline {
				if !have_tm || t.Before(tm) {
					tm = t
				}
				have_tm = true
			}
			for _, t := range self.wDeadline {
				if !have_tm || t.Before(tm) {
					tm = t
				}
				have_tm = true
			}

			for fd, flags := range fds {
				if err := syscall.EpollCtl(efd, syscall.EPOLL_CTL_ADD, fd, &syscall.EpollEvent{
					Events: flags,
					Fd:     int32(fd),
				}); err != nil {
					if fd == int(ctls[1]) {
						// maybe ctrl closed
						return
					} else {
						log.Print(err)
						delete(fds, fd)
					}
				}
			}

			dur := time.Hour
			if have_tm {
				dur = tm.Sub(time.Now())
			}

			evLen := 0
			if dur > 0 {
				if n, err := syscall.EpollWait(efd, evs, int(dur/time.Millisecond)); err != nil {
					if eno, ok := err.(syscall.Errno); !ok || !eno.Temporary() {
						// notify fdset poll loop error
						for _, li := range self.wListener {
							li.FdListen(err)
						}
						for _, li := range self.rListener {
							li.FdListen(err)
						}
						return
					}
				} else {
					evLen = n
				}
			}

			if len(self.wDeadline) > 0 || len(self.rDeadline) > 0 {
				tm := time.Now()
				for fd, t := range self.wDeadline {
					if li, ok := self.wListener[fd]; ok {
						if t.Before(tm) {
							if !li.FdListen(Timeout(t)) {
								delete(self.wListener, fd)
							}
							delete(self.wDeadline, fd)
						}
					}
				}
				for fd, t := range self.rDeadline {
					if li, ok := self.rListener[fd]; ok {
						if t.Before(tm) {
							if !li.FdListen(Timeout(t)) {
								delete(self.rListener, fd)
							}
							delete(self.rDeadline, fd)
						}
					}
				}
			}
			for _, ev := range evs[:evLen] {
				if ev.Events&syscall.EPOLLOUT != 0 {
					if li, ok := self.wListener[int(ev.Fd)]; ok {
						if !li.FdListen(nil) {
							delete(self.wListener, int(ev.Fd))
						}
						delete(self.wDeadline, int(ev.Fd))
					}
				}
				if ev.Events&syscall.EPOLLIN != 0 {
					if li, ok := self.rListener[int(ev.Fd)]; ok {
						if !li.FdListen(nil) {
							delete(self.rListener, int(ev.Fd))
						}
						delete(self.rDeadline, int(ev.Fd))
					}
				}
			}
			for fd, _ := range fds {
				if err := syscall.EpollCtl(efd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
					panic(err)
				}
			}
		}
	}()
	return self
}
示例#23
0
文件: parent.go 项目: rhenium/poe
func doParent(mpid int, stdin_fd, stdout_fd, stderr_fd [2]int) resultPack {
	syscall.Close(stdin_fd[0])
	syscall.Close(stdout_fd[1])
	syscall.Close(stderr_fd[1])

	exit_chan := make(chan resultPack)

	if err := SetupScope(uint32(mpid)); err != nil {
		poePanic(err, "setup systemd scope unit failed")
	}

	go func() {
		runtime.LockOSThread()

		sig_chan := make(chan os.Signal, 1)
		signal.Notify(sig_chan, syscall.SIGCHLD)
		signal.Notify(sig_chan, syscall.SIGTERM)
		signal.Notify(sig_chan, syscall.SIGINT)

		if err := PtraceSeize(mpid, syscall.PTRACE_O_TRACECLONE|syscall.PTRACE_O_TRACEFORK|PTRACE_O_TRACESECCOMP|syscall.PTRACE_O_TRACEVFORK); err != nil {
			poePanic(error(err), "PTRACE_SEIZE failed")
		}

		for {
			sig := <-sig_chan
			switch sig {
			case syscall.SIGCHLD:
				if res := handleSigchld(mpid); res != nil {
					exit_chan <- *res
				}
			case syscall.SIGTERM, syscall.SIGINT:
				exit_chan <- resultPack{POE_TIMEDOUT, -1, "Supervisor terminated"}
			}
		}
	}()

	// TODO: output order is not preserved
	out_chan := make(chan childOutput, 1)
	go func() {
		epfd, err := syscall.EpollCreate1(0)
		if err != nil {
			poePanic(err, "epoll_create1 failed")
		}
		defer syscall.Close(epfd)

		event1 := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(stdout_fd[0]), Pad: 1} // Fd/Pad is epoll_data_t (userdata)
		if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, stdout_fd[0], &event1); err != nil {
			poePanic(err, "epoll_ctl (EPOLL_CTL_ADD) failed")
		}
		event2 := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(stderr_fd[0]), Pad: 2}
		if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, stderr_fd[0], &event2); err != nil {
			poePanic(err, "epoll_ctl (EPOLL_CTL_ADD) failed")
		}

		var events [32]syscall.EpollEvent
		for {
			en, err := syscall.EpollWait(epfd, events[:], -1)
			if err != nil {
				poePanic(err, "epoll_wait failed")
			}

			var buf [65536]byte // TODO: how to get PIPE_BUF?
			for ev := 0; ev < en; ev++ {
				for {
					n, err := syscall.Read(int(events[ev].Fd), buf[:])
					if err != nil {
						break
					}
					if n > 0 {
						nbuf := make([]byte, n)
						copy(nbuf, buf[:n])
						out_chan <- childOutput{int(events[ev].Pad), n, nbuf}
					}
				}
			}
		}
	}()

	go func() {
		for {
			out := <-out_chan
			var outbuf bytes.Buffer
			binary.Write(&outbuf, binary.LittleEndian, int32(out.fd))
			binary.Write(&outbuf, binary.LittleEndian, int32(out.n))
			if _, err := os.Stdout.Write(outbuf.Bytes()); err != nil {
				poePanic(err, "stdout write failed")
			}
			if _, err := os.Stdout.Write(out.buf); err != nil {
				poePanic(err, "stdout write failed")
			}
		}
	}()

	go func() {
		<-time.After(3 * time.Second)
		exit_chan <- resultPack{POE_TIMEDOUT, -1, ""}
	}()

	if _, err := syscall.Write(stdin_fd[1], []byte{0}); err != nil {
		poePanic(err, "write to stdin failed")
	}

	return <-exit_chan
}
示例#24
0
func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) {
	var family int
	var ra, la syscall.Sockaddr

	ip, err := net.ResolveIPAddr("ip", host)
	if err != nil {
		return nil, fmt.Errorf("invalid ip: %s", err)
	}
	l, err := net.ResolveIPAddr("ip", localAddr)
	if l == nil {
		return nil, fmt.Errorf("invalid local ip: %s", err)
	}
	if (ip.IP.To4() != nil) != (l.IP.To4() != nil) {
		return nil, fmt.Errorf("remote and local ip address family is not same")
	}
	switch {
	case ip.IP.To4() != nil:
		family = syscall.AF_INET
		i := &syscall.SockaddrInet4{
			Port: port,
		}
		for idx, _ := range i.Addr {
			i.Addr[idx] = ip.IP.To4()[idx]
		}
		ra = i
		j := &syscall.SockaddrInet4{}
		for idx, _ := range j.Addr {
			j.Addr[idx] = l.IP.To4()[idx]
		}
		la = j
	default:
		family = syscall.AF_INET6
		i := &syscall.SockaddrInet6{
			Port: port,
		}
		for idx, _ := range i.Addr {
			i.Addr[idx] = ip.IP[idx]
		}
		ra = i
		var zone uint32
		if l.Zone != "" {
			intf, err := net.InterfaceByName(l.Zone)
			if err != nil {
				return nil, err
			}
			zone = uint32(intf.Index)
		}
		j := &syscall.SockaddrInet6{
			ZoneId: zone,
		}
		for idx, _ := range j.Addr {
			j.Addr[idx] = l.IP[idx]
		}
		la = j
	}
	sotype := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC | syscall.SOCK_NONBLOCK
	proto := 0
	fd, err := syscall.Socket(family, sotype, proto)
	if err != nil {
		return nil, err
	}
	fi := os.NewFile(uintptr(fd), "")
	defer fi.Close()

	t, err := buildTcpMD5Sig(host, key)
	if err != nil {
		return nil, err
	}
	if _, _, e := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd),
		uintptr(syscall.IPPROTO_TCP), uintptr(TCP_MD5SIG),
		uintptr(unsafe.Pointer(&t)), unsafe.Sizeof(t), 0); e > 0 {
		return nil, os.NewSyscallError("setsockopt", e)
	}

	if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil {
		return nil, os.NewSyscallError("setsockopt", err)
	}
	if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil {
		return nil, os.NewSyscallError("setsockopt", err)
	}
	if err = syscall.Bind(fd, la); err != nil {
		return nil, os.NewSyscallError("bind", err)
	}

	tcpconn := func(fi *os.File) (*net.TCPConn, error) {
		conn, err := net.FileConn(fi)
		return conn.(*net.TCPConn), err
	}

	err = syscall.Connect(fd, ra)
	switch err {
	case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
		// do timeout handling
	case nil, syscall.EISCONN:
		return tcpconn(fi)
	default:
		return nil, os.NewSyscallError("connect", err)
	}

	epfd, e := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
	if e != nil {
		return nil, e
	}
	defer syscall.Close(epfd)

	var event syscall.EpollEvent
	events := make([]syscall.EpollEvent, 1)

	event.Events = syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLPRI
	event.Fd = int32(fd)
	if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
		return nil, e
	}

	for {
		nevents, e := syscall.EpollWait(epfd, events, msec)
		if e != nil {
			return nil, e
		}
		if nevents == 0 {
			return nil, fmt.Errorf("timeout")
		} else if nevents == 1 && events[0].Fd == int32(fd) {
			nerr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR)
			if err != nil {
				return nil, os.NewSyscallError("getsockopt", err)
			}
			switch err := syscall.Errno(nerr); err {
			case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
			case syscall.Errno(0), syscall.EISCONN:
				return tcpconn(fi)
			default:
				return nil, os.NewSyscallError("getsockopt", err)
			}
		} else {
			return nil, fmt.Errorf("unexpected epoll behavior")
		}
	}
}
示例#25
0
func (u *NetLinkProbe) start() {
	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
	if err != nil {
		logging.GetLogger().Errorf("Failed to subscribe to netlink RTNLGRP_LINK messages: %s", err.Error())
		return
	}
	u.nlSocket = s
	defer u.nlSocket.Close()

	fd := u.nlSocket.GetFd()

	err = syscall.SetNonblock(fd, true)
	if err != nil {
		logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}

	epfd, e := syscall.EpollCreate1(0)
	if e != nil {
		logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error())
		return
	}
	defer syscall.Close(epfd)

	u.initialize()

	event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)}
	if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
		logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error())
		return
	}

	events := make([]syscall.EpollEvent, maxEpollEvents)

	for u.running.Load() == true {
		n, err := syscall.EpollWait(epfd, events[:], 1000)
		if err != nil {
			errno, ok := err.(syscall.Errno)
			if ok && errno != syscall.EINTR {
				logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error())
			}
			continue
		}
		if n == 0 {
			continue
		}

		msgs, err := s.Receive()
		if err != nil {
			logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error())

			time.Sleep(1 * time.Second)
			continue
		}

		for _, msg := range msgs {
			switch msg.Header.Type {
			case syscall.RTM_NEWLINK:
				ifmsg := nl.DeserializeIfInfomsg(msg.Data)
				u.onLinkAdded(int(ifmsg.Index))
			case syscall.RTM_DELLINK:
				ifmsg := nl.DeserializeIfInfomsg(msg.Data)
				u.onLinkDeleted(int(ifmsg.Index))
			}
		}
	}
}
示例#26
0
func StartProxyServer(conf *ProxyConfig, proxy_log l4g.Logger) (err error) {
	logger = proxy_log

	var filter *IOFilterProtocol
	var netio *NetIOManager

	proxy := &ProxyServer{
		max_listen_fds: 1024,
		timeout:        1000,
		quit:           false,
		epoll_fd:       -1,
		events:         make([]syscall.EpollEvent, 100),
		sighnd:         make(chan os.Signal, 1),
	}

	if !parse_config(proxy, conf) {
		logger.Error("Failed to initialize proxy server.")
		goto Error
	}

	filter = NewIOFilterProtocol(conf)
	if filter == nil {
		logger.Error("Failed to initialize filter protocol.")
		goto Error
	} else {
		if filter.FilterEnabled() {
			go filter.MonitDiskUsage()
		}
	}

	netio = NewNetIOManager()
	netio.SetFilter(filter)

	proxy.epoll_fd, err = syscall.EpollCreate(proxy.max_listen_fds)
	if err != nil {
		logger.Critical("Failed to initialize epoll listener [%s].", err)
		goto Cleanup
	}
	netio.SetEpollFd(proxy.epoll_fd)

	err = netio.ProxyNetListen(&proxy.proxy_endpoint)
	if err != nil {
		logger.Critical("Failed to initialize server listener [%s].", err)
		goto Cleanup
	}

	setup_sighnd(proxy)

	logger.Info("Mongodb proxy server start.")

	for {
		wait_signal(proxy, syscall.SIGTERM)

		if proxy.quit {
			break
		}

		nfds, err := syscall.EpollWait(proxy.epoll_fd, proxy.events,
			proxy.timeout)
		if err != nil {
			logger.Critical("Failed to do epoll wait [%s].", err)
			break
		}

		for i := 0; i < nfds; i++ {
			fd := int(proxy.events[i].Fd)

			if netio.ProxyNetIsProxyServer(fd) {
				clientinfo, err := netio.ProxyNetAccept(&proxy.mongo_endpoint)
				if err != nil {
					logger.Critical("Failed to establish bridge between mongo client and server [%s].", err)
				} else {
					ipaddr, port := parse_sockaddr(clientinfo)
					logger.Debug("Succeed to establish bridge for client [%s:%d].", ipaddr, port)
				}
			} else {
				event := proxy.events[i].Events

				if event&syscall.EPOLLIN != 0 {
					errno := netio.ProxyNetRecv(fd)

					switch errno {
					case READ_ERROR:
						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							ipaddr, port := parse_sockaddr(sa)
							logger.Error("Failed to read data from [%s:%d].", ipaddr, port)
						}
					case SESSION_EOF:
						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							ipaddr, port := parse_sockaddr(sa)
							logger.Debug("One side [%s:%d] close the session.", ipaddr, port)
						}
					}

					if errno != NO_ERROR {
						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLOUT != 0 {
					errno := netio.ProxyNetSend(fd)

					switch errno {
					case WRITE_ERROR:
						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							ipaddr, port := parse_sockaddr(sa)
							logger.Error("Failed to write data to [%s:%d]", ipaddr, port)
						}
					case FILTER_BLOCK:
						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							ipaddr, port := parse_sockaddr(sa)
							logger.Error("Filter block request from client [%s:%d].", ipaddr, port)
						}
					}

					if errno != NO_ERROR {
						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLRDHUP != 0 {
					sa := netio.ProxyNetConnInfo(fd)
					if sa != nil {
						ipaddr, port := parse_sockaddr(sa)
						logger.Debug("shutdown connection with [%s:%d].", ipaddr, port)
						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLHUP != 0 {
					sa := netio.ProxyNetConnInfo(fd)
					if sa != nil {
						ipaddr, port := parse_sockaddr(sa)
						logger.Debug("shutdown connection with [%s:%d].", ipaddr, port)
						netio.ProxyNetClosePeers(fd)
					}
				}
			}
		}
	}

Cleanup:
	netio.DestroyNetIO()
Error:
	logger.Info("Mongodb proxy server quit.")
	logger.Close()
	return err
}
示例#27
0
func StartProxyServer(conf *ProxyConfig, proxy_log l4g.Logger) (err error) {
	logger = proxy_log

	var filter *IOFilterProtocol
	var netio *NetIOManager

	proxy := &ProxyServer{
		max_listen_fds: 1024,
		timeout:        1000,
		quit:           false,
		epoll_fd:       -1,
		events:         make([]syscall.EpollEvent, 100),
		sighnd:         make(chan os.Signal, 1),
	}

	if !parse_config(proxy, conf) {
		logger.Error("Failed to initialize proxy server.")
		goto Error
	}

	filter = NewIOFilterProtocol(conf)
	if filter == nil {
		logger.Error("Failed to initialize filter protocol.")
		goto Error
	} else {
		if filter.FilterEnabled() {
			go filter.MonitQuotaFiles()
			go filter.MonitQuotaDataSize()
		}
	}

	netio = NewNetIOManager()
	netio.SetFilter(filter)

	proxy.epoll_fd, err = syscall.EpollCreate(proxy.max_listen_fds)
	if err != nil {
		logger.Critical("Failed to initialize epoll listener [%s].", err)
		goto Cleanup
	}
	netio.SetEpollFd(proxy.epoll_fd)

	err = netio.ProxyNetListen(&proxy.proxy_endpoint)
	if err != nil {
		logger.Critical("Failed to initialize server listener [%s].", err)
		goto Cleanup
	}

	setup_sighnd(proxy)

	logger.Info("Mongodb proxy server start.")

	for {
		wait_signal(proxy, syscall.SIGTERM)

		if proxy.quit {
			break
		}

		nfds, err := syscall.EpollWait(proxy.epoll_fd, proxy.events,
			proxy.timeout)
		if err != nil {
			logger.Critical("Failed to do epoll wait [%s].", err)
			break
		}

		for i := 0; i < nfds; i++ {
			fd := int(proxy.events[i].Fd)

			if netio.ProxyNetIsProxyServer(fd) {
				clientinfo, err := netio.ProxyNetAccept(&proxy.mongo_endpoint)
				if err != nil {
					logger.Critical("Failed to establish bridge between mongo client and server [%s].", err)
				} else {
					addr, port := parse_sockaddr(clientinfo)
					logger.Debug("Succeed to establish bridge for client [%s:%d].", addr, port)
				}
			} else {
				event := proxy.events[i].Events

				if event&syscall.EPOLLIN != 0 {
					errno := netio.ProxyNetRecv(fd)

					if errno != NO_ERROR {
						var addr string
						var port int

						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							addr, port = parse_sockaddr(sa)
						}

						switch errno {
						case READ_ERROR:
							if sa != nil {
								logger.Error("Failed to read data from [%s:%d].", addr, port)
							}
						case SESSION_EOF:
							/* normal close */
							netio.ProxyNetFlush(fd)
							if sa != nil {
								logger.Debug("One side [%s:%d] close the session.", addr, port)
							}
						case UNKNOWN_ERROR:
							if sa != nil {
								logger.Debug("Unknown error during read happened at [%s:%d].", addr, port)
							}
						}

						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLOUT != 0 {
					errno := netio.ProxyNetSend(fd)

					if errno != NO_ERROR && errno != PARTIAL_SKB {
						var addr string
						var port int

						sa := netio.ProxyNetConnInfo(fd)
						if sa != nil {
							addr, port = parse_sockaddr(sa)
						}

						switch errno {
						case WRITE_ERROR:
							if sa != nil {
								logger.Error("Failed to write data to [%s:%d]", addr, port)
							}
						case FILTER_BLOCK:
							/*
							 * 'block' handler only happens on 'proxy->server' io write, here
							 * we need to log the 'client->proxy' connection information, if
							 * we call 'ConnInfo' method we get the 'proxy->server' connection,
							 * so we shall call 'OtherSideConnInfo' method here.
							 */
							sa = netio.ProxyNetOtherSideConnInfo(fd)
							if sa != nil {
								addr, port = parse_sockaddr(sa)
								logger.Error("Filter block request from client [%s:%d].", addr, port)
							}
						case UNKNOWN_ERROR:
							if sa != nil {
								logger.Debug("Unknown error during write happened at [%s:%d].", addr, port)
							}
						}

						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLRDHUP != 0 {
					netio.ProxyNetFlush(fd)
					sa := netio.ProxyNetConnInfo(fd)
					if sa != nil {
						ipaddr, port := parse_sockaddr(sa)
						logger.Debug("shutdown connection with [%s:%d].", ipaddr, port)
						netio.ProxyNetClosePeers(fd)
					}
				}

				if event&syscall.EPOLLHUP != 0 {
					netio.ProxyNetFlush(fd)
					sa := netio.ProxyNetConnInfo(fd)
					if sa != nil {
						ipaddr, port := parse_sockaddr(sa)
						logger.Debug("shutdown connection with [%s:%d].", ipaddr, port)
						netio.ProxyNetClosePeers(fd)
					}
				}
			}
		}
	}

Cleanup:
	netio.DestroyNetIO()
Error:
	logger.Info("Mongodb proxy server quit.")
	logger.Close()
	return err
}
示例#28
0
// Wait using epoll.
// Returns true if something is ready to be read,
// false if there is not.
func (poller *fdPoller) wait() (bool, error) {
	// 3 possible events per fd, and 2 fds, makes a maximum of 6 events.
	// I don't know whether epoll_wait returns the number of events returned,
	// or the total number of events ready.
	// I decided to catch both by making the buffer one larger than the maximum.
	events := make([]syscall.EpollEvent, 7)
	for {
		n, errno := syscall.EpollWait(poller.epfd, events, -1)
		if n == -1 {
			if errno == syscall.EINTR {
				continue
			}
			return false, errno
		}
		if n == 0 {
			// If there are no events, try again.
			continue
		}
		if n > 6 {
			// This should never happen. More events were returned than should be possible.
			return false, errors.New("epoll_wait returned more events than I know what to do with")
		}
		ready := events[:n]
		epollhup := false
		epollerr := false
		epollin := false
		for _, event := range ready {
			if event.Fd == int32(poller.fd) {
				if event.Events&syscall.EPOLLHUP != 0 {
					// This should not happen, but if it does, treat it as a wakeup.
					epollhup = true
				}
				if event.Events&syscall.EPOLLERR != 0 {
					// If an error is waiting on the file descriptor, we should pretend
					// something is ready to read, and let syscall.Read pick up the error.
					epollerr = true
				}
				if event.Events&syscall.EPOLLIN != 0 {
					// There is data to read.
					epollin = true
				}
			}
			if event.Fd == int32(poller.pipe[0]) {
				if event.Events&syscall.EPOLLHUP != 0 {
					// Write pipe descriptor was closed, by us. This means we're closing down the
					// watcher, and we should wake up.
				}
				if event.Events&syscall.EPOLLERR != 0 {
					// If an error is waiting on the pipe file descriptor.
					// This is an absolute mystery, and should never ever happen.
					return false, errors.New("Error on the pipe descriptor.")
				}
				if event.Events&syscall.EPOLLIN != 0 {
					// This is a regular wakeup, so we have to clear the buffer.
					err := poller.clearWake()
					if err != nil {
						return false, err
					}
				}
			}
		}

		if epollhup || epollerr || epollin {
			return true, nil
		}
		return false, nil
	}
}