示例#1
0
void SocketService::run(void)
{
	timeout_t timer, expires;
	SocketPort *port;
	unsigned char buf;

#ifdef 	USE_POLL
	
	Poller			  mfd;
	pollfd			* p_ufd;
	int				  lastcount = 0;

	// initialize ufd in all attached ports :
	// probably don't need this but it can't hurt.
	enterMutex();
	port = first;
	while(port)
	{
		port->ufd = 0;
		port = port->next;
	}
	leaveMutex();
	
#else
	struct timeval timeout, *tvp;
	fd_set inp, out, err;
	FD_ZERO(&inp);
	FD_ZERO(&out);
	FD_ZERO(&err);
	int so;
#endif


	setCancel(cancelDeferred);
	for(;;)
	{
		timer = TIMEOUT_INF;
		while(1 == ::read(iosync[0], (char *)&buf, 1))
		{
			if(buf)
			{
				onUpdate(buf);
				continue;
			}

			setCancel(cancelImmediate);
			sleep(TIMEOUT_INF);
			exit();
		}

#ifdef	USE_POLL

		bool	reallocate = false;
		
		MUTEX_START
		onEvent();
		port = first;
		while(port)
		{
			onCallback(port);
			if ( ( p_ufd = port->ufd ) ) {

				if ( ( POLLHUP | POLLNVAL ) & p_ufd->revents ) {
					// Avoid infinite loop from disconnected sockets
					port->detect_disconnect = false;
					p_ufd->events &= ~POLLHUP;

					SocketPort* p = port;
					port = port->next;
					detach(p);
					reallocate = true;
					p->disconnect();
					continue;
				}
	
				if ( ( POLLIN | POLLPRI ) & p_ufd->revents )
					port->pending();
	
				if ( POLLOUT & p_ufd->revents )
					port->output();

			} else {
				reallocate = true;
			}

retry:
			expires = port->getTimer();

			if(expires > 0)
				if(expires < timer)
					timer = expires;

			if(!expires)
			{
				port->endTimer();
				port->expired();
				goto retry;
			}

			port = port->next;
		}

		//
		// reallocate things if we saw a ServerPort without
		// ufd set !
		if ( reallocate || ( ( count + 1 ) != lastcount ) ) {
			lastcount = count + 1;
			p_ufd = mfd.getList( count + 1 );
	
			// Set up iosync polling
			p_ufd->fd = iosync[0];
			p_ufd->events = POLLIN | POLLHUP;
			p_ufd ++;
			
			port = first;
			while(port)
			{
				p_ufd->fd = port->so;
				p_ufd->events =
					( port->detect_disconnect ? POLLHUP : 0 )
					| ( port->detect_output ? POLLOUT : 0 )
					| ( port->detect_pending ? POLLIN : 0 )
				;
				port->ufd = p_ufd;
				p_ufd ++;
				port = port->next;
			}
		}
		MUTEX_END
		poll( mfd.getList(), lastcount, timer );

#else
		MUTEX_START
		onEvent();
		port = first;
		while(port)
		{
			onCallback(port);
			so = port->so;
			if(FD_ISSET(so, &err)) {
				port->detect_disconnect = false;
				
				SocketPort* p = port;
				port = port->next;
				p->disconnect();
				continue;
			}

			if(FD_ISSET(so, &inp))
				port->pending();

			if(FD_ISSET(so, &out))
				port->output();

retry:
			expires = port->getTimer();
			if(expires > 0)
				if(expires < timer)
					timer = expires;

			// if we expire, get new scheduling now

			if(!expires)
			{
				port->endTimer();
				port->expired();
				goto retry;
			}

			port = port->next;
		}

		FD_ZERO(&inp);
		FD_ZERO(&out);
		FD_ZERO(&err);
		FD_SET(iosync[0],&inp);
		port = first;
		while(port)
		{
			so = port->so;
			if(port->detect_pending)
				FD_SET(so, &inp);

			if(port->detect_output)
				FD_SET(so, &out);

			if(port->detect_disconnect)
				FD_SET(so, &err);

			port = port->next;
		}
		
		MUTEX_END
		if(timer == TIMEOUT_INF)
			tvp = NULL;
		else
		{
			tvp = &timeout;
			timeout.tv_sec = timer / 1000;
			timeout.tv_usec = (timer % 1000) * 1000;
		}
		select(hiwater, &inp, &out, &err, tvp);		
#endif
	}
}						
示例#2
0
static Port *
OpenPortInternal(const DeviceConfig &config, DataHandler &handler)
{
  const TCHAR *path = NULL;
  TCHAR buffer[MAX_PATH];

  switch (config.port_type) {
  case DeviceConfig::PortType::DISABLED:
    return NULL;

  case DeviceConfig::PortType::SERIAL:
    if (config.path.empty())
      return NULL;

    path = config.path.c_str();
    break;

  case DeviceConfig::PortType::RFCOMM:
#ifdef ANDROID
    if (config.bluetooth_mac.empty()) {
      LogStartUp(_T("No Bluetooth MAC configured"));
      return NULL;
    }

    return OpenAndroidBluetoothPort(config.bluetooth_mac, handler);
#else
    LogStartUp(_T("Bluetooth not available on this platform"));
    return NULL;
#endif

  case DeviceConfig::PortType::RFCOMM_SERVER:
#ifdef ANDROID
    return OpenAndroidBluetoothServerPort(handler);
#else
    LogStartUp(_T("Bluetooth not available on this platform"));
    return NULL;
#endif

  case DeviceConfig::PortType::IOIOUART:
#if defined(ANDROID) && defined(IOIOLIB)
    if (config.ioio_uart_id >= AndroidIOIOUartPort::getNumberUarts()) {
      LogStartUp(_T("No IOIOUart configured in profile"));
      return NULL;
    }

    return OpenAndroidIOIOUartPort(config.ioio_uart_id, config.baud_rate,
                                   handler);
#else
    LogStartUp(_T("IOIO Uart not available on this platform or version"));
    return NULL;
#endif

  case DeviceConfig::PortType::AUTO:
    if (!detect_gps(buffer, sizeof(buffer))) {
      LogStartUp(_T("no GPS detected"));
      return NULL;
    }

    LogStartUp(_T("GPS detected: %s"), buffer);

    path = buffer;
    break;

  case DeviceConfig::PortType::INTERNAL:
    break;

  case DeviceConfig::PortType::TCP_LISTENER: {
    TCPPort *port = new TCPPort(handler);
    if (!port->Open(config.tcp_port)) {
      delete port;
      return NULL;
    }

    return port;
  }

  case DeviceConfig::PortType::UDP_LISTENER: {
    SocketPort *port = new SocketPort(handler);
    if (!port->OpenUDPListener(config.tcp_port)) {
      delete port;
      return NULL;
    }

    return port;
  }

  case DeviceConfig::PortType::PTY: {
#if defined(HAVE_POSIX) && !defined(ANDROID)
    if (config.path.empty())
      return NULL;

    if (unlink(config.path.c_str()) < 0 && errno != ENOENT)
      return NULL;

    TTYPort *port = new TTYPort(handler);
    const char *slave_path = port->OpenPseudo();
    if (slave_path == NULL) {
      delete port;
      return NULL;
    }

    if (symlink(slave_path, config.path.c_str()) < 0) {
      delete port;
      return NULL;
    }

    return port;
#else
    return NULL;
#endif
  }
  }

  if (path == NULL)
    return NULL;

#ifdef HAVE_POSIX
  TTYPort *port = new TTYPort(handler);
#else
  SerialPort *port = new SerialPort(handler);
#endif
  if (!port->Open(path, config.baud_rate)) {
    delete port;
    return NULL;
  }

  return port;
}
示例#3
0
static Port *
OpenPortInternal(const DeviceConfig &config, PortListener *listener,
                 DataHandler &handler)
{
  const TCHAR *path = nullptr;
  TCHAR buffer[MAX_PATH];

  switch (config.port_type) {
  case DeviceConfig::PortType::DISABLED:
    return nullptr;

  case DeviceConfig::PortType::SERIAL:
    if (config.path.empty())
      return nullptr;

    path = config.path.c_str();
    break;

  case DeviceConfig::PortType::RFCOMM:
#ifdef ANDROID
    if (config.bluetooth_mac.empty()) {
      LogFormat("No Bluetooth MAC configured");
      return nullptr;
    }

    return OpenAndroidBluetoothPort(config.bluetooth_mac, listener, handler);
#else
    LogFormat("Bluetooth not available on this platform");
    return nullptr;
#endif

  case DeviceConfig::PortType::RFCOMM_SERVER:
#ifdef ANDROID
    return OpenAndroidBluetoothServerPort(listener, handler);
#else
    LogFormat("Bluetooth not available on this platform");
    return nullptr;
#endif

  case DeviceConfig::PortType::IOIOUART:
#if defined(ANDROID)
    if (config.ioio_uart_id >= AndroidIOIOUartPort::getNumberUarts()) {
      LogFormat("No IOIOUart configured in profile");
      return nullptr;
    }

    return OpenAndroidIOIOUartPort(config.ioio_uart_id, config.baud_rate,
                                   listener, handler);
#else
    LogFormat("IOIO Uart not available on this platform or version");
    return nullptr;
#endif

  case DeviceConfig::PortType::AUTO:
    if (!DetectGPS(buffer, sizeof(buffer))) {
      LogFormat("no GPS detected");
      return nullptr;
    }

    LogFormat(_T("GPS detected: %s"), buffer);

    path = buffer;
    break;

  case DeviceConfig::PortType::INTERNAL:
  case DeviceConfig::PortType::DROIDSOAR_V2:
  case DeviceConfig::PortType::NUNCHUCK:
  case DeviceConfig::PortType::I2CPRESSURESENSOR:
  case DeviceConfig::PortType::IOIOVOLTAGE:
    break;

  case DeviceConfig::PortType::TCP_CLIENT: {
    const WideToUTF8Converter ip_address(config.ip_address);
    if (!ip_address.IsValid())
      return nullptr;

    auto port = new TCPClientPort(listener, handler);
    if (!port->Connect(ip_address, config.tcp_port)) {
      delete port;
      return nullptr;
    }

    return port;
  }

  case DeviceConfig::PortType::TCP_LISTENER: {
    TCPPort *port = new TCPPort(listener, handler);
    if (!port->Open(config.tcp_port)) {
      delete port;
      return nullptr;
    }

    return port;
  }

  case DeviceConfig::PortType::UDP_LISTENER: {
    SocketPort *port = new SocketPort(listener, handler);
    if (!port->OpenUDPListener(config.tcp_port)) {
      delete port;
      return nullptr;
    }

    return port;
  }

  case DeviceConfig::PortType::PTY: {
#if defined(HAVE_POSIX) && !defined(ANDROID)
    if (config.path.empty())
      return nullptr;

    if (unlink(config.path.c_str()) < 0 && errno != ENOENT)
      return nullptr;

    TTYPort *port = new TTYPort(listener, handler);
    const char *slave_path = port->OpenPseudo();
    if (slave_path == nullptr) {
      delete port;
      return nullptr;
    }

    if (symlink(slave_path, config.path.c_str()) < 0) {
      delete port;
      return nullptr;
    }

    return port;
#else
    return nullptr;
#endif
  }
  }

  if (path == nullptr)
    return nullptr;

#ifdef HAVE_POSIX
  TTYPort *port = new TTYPort(listener, handler);
#else
  SerialPort *port = new SerialPort(listener, handler);
#endif
  if (!port->Open(path, config.baud_rate)) {
    delete port;
    return nullptr;
  }

  return port;
}
示例#4
0
void SocketService::run(void)
{
	timeout_t timer, expires;
	SocketPort *port;
	unsigned char buf;

#ifndef WIN32
#ifdef 	USE_POLL

	Poller			  mfd;
	pollfd			* p_ufd;
	int				  lastcount = 0;

	// initialize ufd in all attached ports :
	// probably don't need this but it can't hurt.
	enterMutex();
	port = first;
	while(port) {
		port->ufd = 0;
		port = port->next;
	}
	leaveMutex();

#else
	struct timeval timeout, *tvp;
	fd_set inp, out, err;
	FD_ZERO(&inp);
	FD_ZERO(&out);
	FD_ZERO(&err);
	int so;
#endif
#else // WIN32
	int numHandle = 0;
	HANDLE hv[MAXIMUM_WAIT_OBJECTS];
#endif


#ifdef WIN32
	// FIXME: needed ?
	ResetEvent(sync->GetSync());
#endif

	setCancel(cancelDeferred);
	for(;;) {
		timer = TIMEOUT_INF;
#ifndef WIN32
		while(1 == ::read(iosync[0], (char *)&buf, 1)) {
#else
		for(;;) {
			int f = sync->getFlag();
			if (f < 0)
				break;

			buf = f;
#endif
			if(buf) {
				onUpdate(buf);
				continue;
			}

			setCancel(cancelImmediate);
			sleep(TIMEOUT_INF);
			exit();
		}

#ifndef WIN32
#ifdef	USE_POLL

		bool	reallocate = false;

		MUTEX_START
		onEvent();
		port = first;
		while(port) {
			onCallback(port);
			if ( ( p_ufd = port->ufd ) ) {

				if ( ( POLLHUP | POLLNVAL ) & p_ufd->revents ) {
					// Avoid infinite loop from disconnected sockets
					port->detect_disconnect = false;
					p_ufd->events &= ~POLLHUP;

					SocketPort* p = port;
					port = port->next;
					detach(p);
					reallocate = true;
					p->disconnect();
					continue;
				}

				if ( ( POLLIN | POLLPRI ) & p_ufd->revents )
					port->pending();

				if ( POLLOUT & p_ufd->revents )
					port->output();

			} else {
				reallocate = true;
			}

retry:
			expires = port->getTimer();

			if(expires > 0)
				if(expires < timer)
					timer = expires;

			if(!expires) {
				port->endTimer();
				port->expired();
				goto retry;
			}

			port = port->next;
		}

		//
		// reallocate things if we saw a ServerPort without
		// ufd set !
		if ( reallocate || ( ( count + 1 ) != lastcount ) ) {
			lastcount = count + 1;
			p_ufd = mfd.getList( count + 1 );

			// Set up iosync polling
			p_ufd->fd = iosync[0];
			p_ufd->events = POLLIN | POLLHUP;
			p_ufd ++;

			port = first;
			while(port) {
				p_ufd->fd = port->so;
				p_ufd->events =
					( port->detect_disconnect ? POLLHUP : 0 )
					| ( port->detect_output ? POLLOUT : 0 )
					| ( port->detect_pending ? POLLIN : 0 )
				;
				port->ufd = p_ufd;
				p_ufd ++;
				port = port->next;
			}
		}
		MUTEX_END
		poll( mfd.getList(), lastcount, timer );

#else
		MUTEX_START
		onEvent();
		port = first;
		while(port) {
			onCallback(port);
			so = port->so;
			if(FD_ISSET(so, &err)) {
				port->detect_disconnect = false;

				SocketPort* p = port;
				port = port->next;
				p->disconnect();
				continue;
			}

			if(FD_ISSET(so, &inp))
				port->pending();

			if(FD_ISSET(so, &out))
				port->output();

retry:
			expires = port->getTimer();
			if(expires > 0)
				if(expires < timer)
					timer = expires;

			// if we expire, get new scheduling now

			if(!expires) {
				port->endTimer();
				port->expired();
				goto retry;
			}

			port = port->next;
		}

		FD_ZERO(&inp);
		FD_ZERO(&out);
		FD_ZERO(&err);
		FD_SET(iosync[0],&inp);
		port = first;
		while(port) {
			so = port->so;
			if(port->detect_pending)
				FD_SET(so, &inp);

			if(port->detect_output)
				FD_SET(so, &out);

			if(port->detect_disconnect)
				FD_SET(so, &err);

			port = port->next;
		}

		MUTEX_END
		if(timer == TIMEOUT_INF)
			tvp = NULL;
		else {
			tvp = &timeout;
			timeout.tv_sec = timer / 1000;
			timeout.tv_usec = (timer % 1000) * 1000;
		}
		select(hiwater, &inp, &out, &err, tvp);
#endif
#else // WIN32
		MUTEX_START
		onEvent();

		hv[0] = sync->GetSync();
		numHandle = 1;
		port = first;
		while(port) {
			onCallback(port);

			long events = 0;

			if(port->detect_pending)
				events |= FD_READ;

			if(port->detect_output)
				events |= FD_WRITE;

			if(port->detect_disconnect)
				events |= FD_CLOSE;

			// !!! ignore some socket on overflow !!!
			if (events && numHandle < MAXIMUM_WAIT_OBJECTS) {
				WSAEventSelect(port->so,port->event,events);
				hv[numHandle++] = port->event;
			}

retry:
			expires = port->getTimer();
			if(expires > 0)
				if(expires < timer)
					timer = expires;

			// if we expire, get new scheduling now

			if(!expires) {
				port->endTimer();
				port->expired();
				goto retry;
			}

			port = port->next;
		}

		MUTEX_END

		// FIXME: handle thread cancellation correctly
		DWORD res = WaitForMultipleObjects(numHandle,hv,FALSE,timer);
		switch (res) {
		case WAIT_OBJECT_0:
			break;
		case WAIT_TIMEOUT:
			break;
		default:
			// FIXME: handle failures (detach SocketPort)
			if (res >= WAIT_OBJECT_0+1 && res <= WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) {
				int curr = res - (WAIT_OBJECT_0);
				WSANETWORKEVENTS events;

				// search port
				MUTEX_START
				port = first;
				while(port) {
					if (port->event == hv[curr])
						break;
					port = port->next;
				}
				MUTEX_END

				// if port not found ignore
				if (!port || port->event != hv[curr])
					break;

				WSAEnumNetworkEvents(port->so,port->event,&events);

				if(events.lNetworkEvents & FD_CLOSE) {
					port->detect_disconnect = false;
					port->disconnect();
					continue;
				}

				if(events.lNetworkEvents & FD_READ)
					port->pending();

				if(events.lNetworkEvents & FD_WRITE)
					port->output();
			}
		}
#endif
	}
					}