Esempio n. 1
0
int freerds_listener_main_loop(xrdpListener* self)
{
	DWORD status;
	DWORD nCount;
	HANDLE events[32];
	HANDLE TermEvent;
	freerdp_listener* listener;

	listener = (freerdp_listener*) self;

	listener->Open(listener, NULL, 3389);

	TermEvent = g_get_term_event();

	while (1)
	{
		nCount = 0;
		events[nCount++] = TermEvent;

		if (listener->GetEventHandles(listener, events, &nCount) < 0)
		{
			fprintf(stderr, "Failed to get FreeRDP file descriptor\n");
			break;
		}

		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

		if (WaitForSingleObject(TermEvent, 0) == WAIT_OBJECT_0)
		{
			break;
		}

		if (listener->CheckFileDescriptor(listener) != TRUE)
		{
			fprintf(stderr, "Failed to check FreeRDP file descriptor\n");
			break;
		}
	}

	listener->Close(listener);

	return 0;
}
Esempio n. 2
0
/* wait for incoming connections */
int APP_CC
xrdp_listen_main_loop(struct xrdp_listen* self)
{
  int error;
  int robjs_count;
  int cont;
  char port[8];
  tbus robjs[8];
  tbus term_obj;
  tbus sync_obj;
  tbus sck_obj;
  tbus done_obj;
  struct xrdp_process* process;

  self->status = 1;
  xrdp_listen_get_port(port, sizeof(port));
  self->sck = g_tcp_socket();
  g_tcp_set_non_blocking(self->sck);
  error = g_tcp_bind(self->sck, port);
  if (error != 0)
  {
    g_writeln("bind error in xrdp_listen_main_loop");
    g_tcp_close(self->sck);
    self->status = -1;
    return 1;
  }
  error = g_tcp_listen(self->sck);
  if (error == 0)
  {
    term_obj = g_get_term_event();
    sync_obj = g_get_sync_event();
    sck_obj = g_create_wait_obj_from_socket(self->sck, 0);
    done_obj = self->pro_done_event;
    cont = 1;
    while (cont)
    {
      /* build the wait obj list */
      robjs_count = 0;
      robjs[robjs_count++] = term_obj;
      robjs[robjs_count++] = sync_obj;
      robjs[robjs_count++] = sck_obj;
      robjs[robjs_count++] = done_obj;
      /* wait */
      if (g_obj_wait(robjs, robjs_count, 0, 0, -1) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(term_obj)) /* term */
      {
        break;
      }
      if (g_is_wait_obj_set(sync_obj)) /* sync */
      {
        g_reset_wait_obj(sync_obj);
        g_loop();
      }
      if (g_is_wait_obj_set(sck_obj)) /* incomming connection */
      {
        error = g_tcp_accept(self->sck);
        if ((error == -1) && g_tcp_last_error_would_block(self->sck))
        {
          /* should not get here */
          g_sleep(100);
        }
        else if (error == -1)
        {
          /* error, should not get here */
          break;
        }
        else
        {
          process = xrdp_process_create(self, self->pro_done_event);
          if (xrdp_listen_add_pro(self, process) == 0)
          {
            /* start thread */
            process->sck = error;
            g_process = process;
            tc_thread_create(xrdp_process_run, 0);
            tc_sem_dec(g_process_sem); /* this will wait */
          }
          else
          {
            xrdp_process_delete(process);
          }
        }
      }
      if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
      {
        g_reset_wait_obj(done_obj);
        xrdp_listen_delete_done_pro(self);
      }
    }
    /* stop listening */
    g_delete_wait_obj_from_socket(sck_obj);
    g_tcp_close(self->sck);
    /* second loop to wait for all process threads to close */
    cont = 1;
    while (cont)
    {
      if (self->process_list->count == 0)
      {
        break;
      }
      /* build the wait obj list */
      robjs_count = 0;
      robjs[robjs_count++] = sync_obj;
      robjs[robjs_count++] = done_obj;
      /* wait */
      if (g_obj_wait(robjs, robjs_count, 0, 0, -1) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(sync_obj)) /* sync */
      {
        g_reset_wait_obj(sync_obj);
        g_loop();
      }
      if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
      {
        g_reset_wait_obj(done_obj);
        xrdp_listen_delete_done_pro(self);
      }
    }
  }
  else
  {
    DEBUG(("listen error in xrdp_listen_main_loop"));
  }
  self->status = -1;
  return 0;
}
Esempio n. 3
0
int APP_CC
xrdp_process_main_loop(struct xrdp_process* self)
{
  int robjs_count;
  int wobjs_count;
  int cont;
  int timeout = 0;
  tbus robjs[32];
  tbus wobjs[32];
  tbus term_obj;

  DEBUG(("xrdp_process_main_loop"));
  self->status = 1;
  self->server_trans->trans_data_in = xrdp_process_data_in;
  self->server_trans->callback_data = self;
  self->session = libxrdp_init((tbus)self, self->server_trans);
  /* this callback function is in xrdp_wm.c */
  self->session->callback = callback;
  /* this function is just above */
  self->session->is_term = xrdp_is_term;
  if (libxrdp_process_incomming(self->session) == 0)
  {
    term_obj = g_get_term_event();
    cont = 1;
    while (cont)
    {
      /* build the wait obj list */
      timeout = -1;
      robjs_count = 0;
      wobjs_count = 0;
      robjs[robjs_count++] = term_obj;
      robjs[robjs_count++] = self->self_term_event;
      xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count,
                            wobjs, &wobjs_count, &timeout);
      trans_get_wait_objs(self->server_trans, robjs, &robjs_count, &timeout);
      /* wait */
      if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(term_obj)) /* term */
      {
        break;
      }
      if (g_is_wait_obj_set(self->self_term_event))
      {
        break;
      }
      if (xrdp_wm_check_wait_objs(self->wm) != 0)
      {
        break;
      }
      if (trans_check_wait_objs(self->server_trans) != 0)
      {
        break;
      }
    }
    libxrdp_disconnect(self->session);
  }
  xrdp_process_mod_end(self);
  libxrdp_exit(self->session);
  self->session = 0;
  self->status = -1;
  g_set_wait_obj(self->done_event);
  return 0;
}
Esempio n. 4
0
/* wait for incoming connections */
int APP_CC
xrdp_listen_main_loop(struct xrdp_listen *self)
{
    int error;
    int robjs_count;
    int cont;
    int timeout = 0;
    char port[128];
    char address[256];
    tbus robjs[8];
    tbus term_obj;
    tbus sync_obj;
    tbus done_obj;
    int tcp_nodelay;
    int tcp_keepalive;
    int bytes;

    self->status = 1;

    if (xrdp_listen_get_port_address(port, sizeof(port),
                                     address, sizeof(address),
                                     &tcp_nodelay, &tcp_keepalive,
                                     self->startup_params) != 0)
    {
        log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
        self->status = -1;
        return 1;
    }

    if (port[0] == '/')
    {
        /* set UDS mode */
        self->listen_trans->mode = TRANS_MODE_UNIX;
        /* not valid with UDS */
        tcp_nodelay = 0;
    }

    /* Create socket */
    error = trans_listen_address(self->listen_trans, port, address);

    if (error == 0)
    {
        if (tcp_nodelay)
        {
            if (g_tcp_set_no_delay(self->listen_trans->sck))
            {
                log_message(LOG_LEVEL_ERROR,"Error setting tcp_nodelay");
            }
        }

        if (tcp_keepalive)
        {
            if (g_tcp_set_keepalive(self->listen_trans->sck))
            {
                log_message(LOG_LEVEL_ERROR,"Error setting tcp_keepalive");
            }
        }

        if (self->startup_params->send_buffer_bytes > 0)
        {
            bytes = self->startup_params->send_buffer_bytes;
            log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
                        bytes);
            if (g_sck_set_send_buffer_bytes(self->listen_trans->sck,
                                            bytes) != 0)
            {
                log_message(LOG_LEVEL_ERROR, "error setting send buffer");
            }
            else
            {
                if (g_sck_get_send_buffer_bytes(self->listen_trans->sck,
                                                &bytes) != 0)
                {
                    log_message(LOG_LEVEL_ERROR, "error getting send buffer");
                }
                else
                {
                    log_message(LOG_LEVEL_INFO, "send buffer set to %d bytes", bytes);
                }
            }
        }

        if (self->startup_params->recv_buffer_bytes > 0)
        {
            bytes = self->startup_params->recv_buffer_bytes;
            log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
                        bytes);
            if (g_sck_set_recv_buffer_bytes(self->listen_trans->sck,
                                            bytes) != 0)
            {
                log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
            }
            else
            {
                if (g_sck_get_recv_buffer_bytes(self->listen_trans->sck,
                                                &bytes) != 0)
                {
                    log_message(LOG_LEVEL_ERROR, "error getting recv buffer");
                }
                else
                {
                    log_message(LOG_LEVEL_INFO, "recv buffer set to %d bytes", bytes);
                }
            }
        }

        self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
        self->listen_trans->callback_data = self;
        term_obj = g_get_term_event(); /*Global termination event */
        sync_obj = g_get_sync_event();
        done_obj = self->pro_done_event;
        cont = 1;

        while (cont)
        {
            /* build the wait obj list */
            robjs_count = 0;
            robjs[robjs_count++] = term_obj;
            robjs[robjs_count++] = sync_obj;
            robjs[robjs_count++] = done_obj;
            timeout = -1;

            /* if (self->listen_trans != 0) */
            {
                if (trans_get_wait_objs(self->listen_trans, robjs,
                                        &robjs_count) != 0)
                {
                    log_message(LOG_LEVEL_ERROR,"Listening socket is in wrong state we "
                              "terminate listener");
                    break;
                }
            }

            /* wait - timeout -1 means wait indefinitely*/
            if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
            {
                /* error, should not get here */
                g_sleep(100);
            }

            if (g_is_wait_obj_set(term_obj)) /* termination called */
            {
                break;
            }

            /* some function must be processed by this thread */
            if (g_is_wait_obj_set(sync_obj))
            {
                g_reset_wait_obj(sync_obj);
                g_process_waiting_function(); /* run the function */
            }

            if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
            {
                g_reset_wait_obj(done_obj);
                /* a process has died remove it from lists*/
                xrdp_listen_delete_done_pro(self);
            }

            /* Run the callback when accept() returns a new socket*/
            if (trans_check_wait_objs(self->listen_trans) != 0)
            {
                break;
            }
        }

        /* stop listening */
        trans_delete(self->listen_trans);
        self->listen_trans = 0;
        /* second loop to wait for all process threads to close */
        cont = 1;

        while (cont)
        {
            if (self->process_list->count == 0)
            {
                break;
            }

            timeout = -1;
            /* build the wait obj list */
            robjs_count = 0;
            robjs[robjs_count++] = sync_obj;
            robjs[robjs_count++] = done_obj;

            /* wait - timeout -1 means wait indefinitely*/
            if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
            {
                /* error, should not get here */
                g_sleep(100);
            }

            /* some function must be processed by this thread */
            if (g_is_wait_obj_set(sync_obj))
            {
                g_reset_wait_obj(sync_obj);
                g_process_waiting_function(); /* run the function that is waiting*/
            }

            if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
            {
                g_reset_wait_obj(done_obj);
                xrdp_listen_delete_done_pro(self);
            }
        }
    }
    else
    {
        log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, possible port "
                  "already in use");
    }

    self->status = -1;
    return 0;
}
Esempio n. 5
0
int APP_CC
xrdp_process_main_loop(struct xrdp_process* self)
{
  int robjs_count;
  int wobjs_count;
  int cont;
  int timeout;
  tbus robjs[32];
  tbus wobjs[32];
  tbus term_obj;
  tbus sck_obj;

  self->status = 1;
  self->session = libxrdp_init((long)self, self->sck);
  /* this callback function is in xrdp_wm.c */
  self->session->callback = callback;
  /* this function is just above */
  self->session->is_term = xrdp_is_term;
  g_tcp_set_non_blocking(self->sck);
  g_tcp_set_no_delay(self->sck);
  if (libxrdp_process_incomming(self->session) == 0)
  {
    term_obj = g_get_term_event();
    sck_obj = g_create_wait_obj_from_socket(self->sck, 0);
    cont = 1;
    while (cont)
    {
      /* build the wait obj list */
      timeout = -1;
      robjs_count = 0;
      wobjs_count = 0;
      robjs[robjs_count++] = term_obj;
      robjs[robjs_count++] = sck_obj;
      robjs[robjs_count++] = self->self_term_event;
      xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count,
                            wobjs, &wobjs_count, &timeout);
      /* wait */
      if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(term_obj)) /* term */
      {
        break;
      }
      if (g_is_wait_obj_set(self->self_term_event))
      {
        break;
      }
      if (g_is_wait_obj_set(sck_obj)) /* incomming client data */
      {
        if (xrdp_process_loop(self) != 0)
        {
          break;
        }
      }
      if (xrdp_wm_check_wait_objs(self->wm) != 0)
      {
        break;
      }
    }
    g_delete_wait_obj_from_socket(sck_obj);
    libxrdp_disconnect(self->session);
  }
  xrdp_process_mod_end(self);
  libxrdp_exit(self->session);
  self->session = 0;
  g_tcp_close(self->sck);
  self->status = -1;
  g_set_wait_obj(self->done_event);
  return 0;
}
Esempio n. 6
0
int APP_CC
xrdp_process_main_loop(struct xrdp_process *self)
{
    int robjs_count;
    int wobjs_count;
    int cont;
    int timeout = 0;
    tbus robjs[32];
    tbus wobjs[32];
    tbus term_obj;

    DEBUG(("xrdp_process_main_loop"));
    self->status = 1;
    self->server_trans->extra_flags = 0;
    self->server_trans->header_size = 0;
    self->server_trans->no_stream_init_on_data_in = 1;
    self->server_trans->trans_data_in = xrdp_process_data_in;
    self->server_trans->callback_data = self;
    init_stream(self->server_trans->in_s, 8192 * 4);
    self->session = libxrdp_init((tbus)self, self->server_trans);
    self->server_trans->si = &(self->session->si);
    self->server_trans->my_source = XRDP_SOURCE_CLIENT;
    /* this callback function is in xrdp_wm.c */
    self->session->callback = callback;
    /* this function is just above */
    self->session->is_term = xrdp_is_term;

    if (libxrdp_process_incoming(self->session) == 0)
    {
        init_stream(self->server_trans->in_s, 32 * 1024);

        term_obj = g_get_term_event();
        cont = 1;

        while (cont)
        {
            /* build the wait obj list */
            timeout = -1;
            robjs_count = 0;
            wobjs_count = 0;
            robjs[robjs_count++] = term_obj;
            robjs[robjs_count++] = self->self_term_event;
            xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count,
                                  wobjs, &wobjs_count, &timeout);
            trans_get_wait_objs_rw(self->server_trans, robjs, &robjs_count,
                                   wobjs, &wobjs_count, &timeout);
            /* wait */
            if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
            {
                /* error, should not get here */
                g_sleep(100);
            }

            if (g_is_wait_obj_set(term_obj)) /* term */
            {
                break;
            }

            if (g_is_wait_obj_set(self->self_term_event))
            {
                break;
            }

            if (xrdp_wm_check_wait_objs(self->wm) != 0)
            {
                break;
            }

            if (trans_check_wait_objs(self->server_trans) != 0)
            {
                break;
            }
        }
        /* send disconnect message if possible */
        libxrdp_disconnect(self->session);
    }
    else
    {
        g_writeln("xrdp_process_main_loop: libxrdp_process_incoming failed");
        /* this will try to send a disconnect,
           maybe should check that connection got far enough */
        libxrdp_disconnect(self->session);
    }
    /* Run end in module */
    xrdp_process_mod_end(self);
    libxrdp_exit(self->session);
    self->session = 0;
    self->status = -1;
    g_set_wait_obj(self->done_event);
    return 0;
}
Esempio n. 7
0
/* wait for incoming connections */
int APP_CC
xrdp_listen_main_loop(struct xrdp_listen* self)
{
  int error;
  int robjs_count;
  int cont;
  int timeout = 0;
  char port[8];
  char address[256];
  tbus robjs[8];
  tbus term_obj;
  tbus sync_obj;
  tbus sck_obj;
  tbus done_obj;

  self->status = 1;
  if (xrdp_listen_get_port_address(port, sizeof(port),
                                   address, sizeof(address)) != 0)
  {
    g_writeln("xrdp_listen_main_loop: xrdp_listen_get_port failed");
    self->status = -1;
    return 1;
  }
  error = trans_listen_address(self->listen_trans, port, address);
  if (error == 0)
  {
    self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
    self->listen_trans->callback_data = self;
    term_obj = g_get_term_event();
    sync_obj = g_get_sync_event();
    done_obj = self->pro_done_event;
    cont = 1;
    while (cont)
    {
      /* build the wait obj list */
      robjs_count = 0;
      robjs[robjs_count++] = term_obj;
      robjs[robjs_count++] = sync_obj;
      robjs[robjs_count++] = done_obj;
      timeout = -1;
      if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count,
                              &timeout) != 0)
      {
        break;
      }
      /* wait */
      if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(term_obj)) /* term */
      {
        break;
      }
      if (g_is_wait_obj_set(sync_obj)) /* sync */
      {
        g_reset_wait_obj(sync_obj);
        g_loop();
      }
      if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
      {
        g_reset_wait_obj(done_obj);
        xrdp_listen_delete_done_pro(self);
      }
      if (trans_check_wait_objs(self->listen_trans) != 0)
      {
        break;  
      }
    }
    /* stop listening */
    trans_delete(self->listen_trans);
    self->listen_trans = 0;
    /* second loop to wait for all process threads to close */
    cont = 1;
    while (cont)
    {
      if (self->process_list->count == 0)
      {
        break;
      }
      /* build the wait obj list */
      robjs_count = 0;
      robjs[robjs_count++] = sync_obj;
      robjs[robjs_count++] = done_obj;
      /* wait */
      if (g_obj_wait(robjs, robjs_count, 0, 0, -1) != 0)
      {
        /* error, should not get here */
        g_sleep(100);
      }
      if (g_is_wait_obj_set(sync_obj)) /* sync */
      {
        g_reset_wait_obj(sync_obj);
        g_loop();
      }
      if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
      {
        g_reset_wait_obj(done_obj);
        xrdp_listen_delete_done_pro(self);
      }
    }
  }
  else
  {
    DEBUG(("listen error in xrdp_listen_main_loop"));
  }
  self->status = -1;
  return 0;
}
Esempio n. 8
0
int xrdp_listen_main_loop(xrdpListener* self)
{
	int i;
	int fds;
	int max_fds;
	int robjc;
	int wobjc;
	long sync_obj;
	long term_obj;
	long robjs[32];
	int itimeout;
	int rcount;
	void* rfds[32];
	fd_set rfds_set;
	freerdp_listener* listener;

	ZeroMemory(rfds, sizeof(rfds));
	listener = (freerdp_listener*) self;

	listener->Open(listener, NULL, 3389);

	term_obj = g_get_term_event();
	sync_obj = g_get_sync_event();

	while (1)
	{
		rcount = 0;

		robjc = 0;
		wobjc = 0;
		itimeout = -1;

		robjs[robjc++] = term_obj;
		robjs[robjc++] = sync_obj;

		if (listener->GetFileDescriptor(listener, rfds, &rcount) != TRUE)
		{
			fprintf(stderr, "Failed to get FreeRDP file descriptor\n");
			break;
		}

		max_fds = 0;
		FD_ZERO(&rfds_set);

		for (i = 0; i < rcount; i++)
		{
			fds = (int)(long)(rfds[i]);

			if (fds > max_fds)
				max_fds = fds;

			FD_SET(fds, &rfds_set);
		}

		for (i = 0; i < robjc; i++)
		{
			fds = robjs[i];

			if (fds > max_fds)
				max_fds = fds;

			FD_SET(fds, &rfds_set);
		}

		if (max_fds == 0)
			break;

		if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
		{
			/* these are not really errors */
			if (!((errno == EAGAIN) ||
				(errno == EWOULDBLOCK) ||
				(errno == EINPROGRESS) ||
				(errno == EINTR))) /* signal occurred */
			{
				fprintf(stderr, "select failed\n");
				break;
			}
		}

		if (listener->CheckFileDescriptor(listener) != TRUE)
		{
			fprintf(stderr, "Failed to check FreeRDP file descriptor\n");
			break;
		}

		if (g_is_wait_obj_set(term_obj))
		{
			break;
		}

		if (g_is_wait_obj_set(sync_obj))
		{
			g_reset_wait_obj(sync_obj);
			g_process_waiting_function();
		}
	}

	listener->Close(listener);

	return 0;
}
Esempio n. 9
0
void* freerds_connection_main_thread(void* arg)
{
	DWORD status;
	DWORD nCount;
	HANDLE events[32];
	HANDLE ClientEvent;
	HANDLE ChannelEvent;
	HANDLE LocalTermEvent;
	HANDLE GlobalTermEvent;
	HANDLE NotificationEvent;
	rdsConnection* connection;
	rdpSettings* settings;
	rdsBackendConnector* connector = NULL;
	freerdp_peer* client = (freerdp_peer*) arg;
	BOOL disconnected = FALSE;
#ifndef WIN32
	sigset_t set;
	int ret;
#endif

	fprintf(stderr, "We've got a client %s\n", client->hostname);

	connection = (rdsConnection*) client->context;
	settings = client->settings;

	app_context_add_connection(connection);
	freerds_generate_certificate(settings);

	settings->RdpSecurity = FALSE;
	settings->TlsSecurity = TRUE;

	/**
	 * Disable NLA Security for now.
	 * TODO: make this a configurable option.
	 */
	settings->NlaSecurity = FALSE;

	client->Capabilities = freerds_peer_capabilities;
	client->PostConnect = freerds_peer_post_connect;
	client->Activate = freerds_peer_activate;

	client->Initialize(client);

	freerds_input_register_callbacks(client->input);

	client->update->SurfaceFrameAcknowledge = freerds_update_frame_acknowledge;
	client->update->SuppressOutput = freerds_suppress_output;

	ClientEvent = client->GetEventHandle(client);
	ChannelEvent = WTSVirtualChannelManagerGetEventHandle(connection->vcm);

	GlobalTermEvent = g_get_term_event();
	LocalTermEvent = connection->TermEvent;
	NotificationEvent = MessageQueue_Event(connection->notifications);
#ifndef WIN32
	sigemptyset(&set);
	sigaddset(&set, SIGPIPE);
	ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
	if (0 != ret)
		fprintf(stderr, "couldn't block SIGPIPE\n");
#endif
	while (1)
	{
		nCount = 0;
		events[nCount++] = ClientEvent;
		events[nCount++] = ChannelEvent;
		events[nCount++] = GlobalTermEvent;
		events[nCount++] = LocalTermEvent;
		events[nCount++] = NotificationEvent;

		if (client->activated)
		{
			connector = (rdsBackendConnector*) connection->connector;

			if (connector && connector->GetEventHandles)
				connector->GetEventHandles((rdsBackend *)connector, events, &nCount);
		}

		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

		if (WaitForSingleObject(GlobalTermEvent, 0) == WAIT_OBJECT_0)
		{
			fprintf(stderr, "GlobalTermEvent\n");
			break;
		}

		if (WaitForSingleObject(LocalTermEvent, 0) == WAIT_OBJECT_0)
		{
			fprintf(stderr, "LocalTermEvent\n");
			break;
		}

		if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
		{
			if (client->CheckFileDescriptor(client) != TRUE)
			{
				fprintf(stderr, "Failed to check freerdp file descriptor\n");
				break;
			}
		}

		if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
		{
			if (WTSVirtualChannelManagerCheckFileDescriptor(connection->vcm) != TRUE)
			{
				fprintf(stderr, "WTSVirtualChannelManagerCheckFileDescriptor failure\n");
				break;
			}
		}

		if (client->activated)
		{
			if (connector && connector->CheckEventHandles)
			{
				if (connector->CheckEventHandles((rdsBackend *)connector) < 0)
				{
					fprintf(stderr, "ModuleClient->CheckEventHandles failure\n");
					break;
				}
			}
		}
		if (WaitForSingleObject(NotificationEvent, 0) == WAIT_OBJECT_0)
		{
			wMessage message;

			MessageQueue_Peek(connection->notifications, (void *)(&message), TRUE);

			if (!freerds_client_process_notification(connection, &message))
				break;
		}
	}

	fprintf(stderr, "Client %s disconnected.\n", client->hostname);

	if (connection->connector)
	{
		freerds_connector_free(connection->connector);
		connection->connector = 0;

		freerds_icp_DisconnectUserSession(connection->id, &disconnected);
	}
	client->Disconnect(client);
	app_context_remove_connection(connection->id);

	freerdp_peer_context_free(client);
	freerdp_peer_free(client);

	return NULL;
}