void rfbClientConnectionGone(rfbClientPtr cl)
{
  int i;

  if (cl->prev)
    cl->prev->next = cl->next;
  else
    rfbClientHead = cl->next;
  if (cl->next)
    cl->next->prev = cl->prev;

  TimerFree(cl->alrTimer);
  TimerFree(cl->deferredUpdateTimer);
  TimerFree(cl->updateTimer);
  TimerFree(cl->congestionTimer);

#ifdef XVNC_AuthPAM
  rfbPAMEnd(cl);
#endif
  if (cl->login != NULL) {
    rfbLog("Client %s (%s) gone\n", cl->login, cl->host);
    free(cl->login);
  } else {
    rfbLog("Client %s gone\n", cl->host);
  }
  free(cl->host);

  ShutdownTightThreads();

  if (rfbAutoLosslessRefresh > 0.0) {
    REGION_UNINIT(pScreen, &cl->lossyRegion);
    REGION_UNINIT(pScreen, &cl->alrRegion);
    REGION_UNINIT(pScreen, &cl->alrEligibleRegion);
  }

  /* Release the compression state structures if any. */
  if (cl->compStreamInited == TRUE)
    deflateEnd(&(cl->compStream));

  for (i = 0; i < 4; i++) {
    if (cl->zsActive[i])
      deflateEnd(&cl->zsStruct[i]);
  }

  if (pointerClient == cl)
    pointerClient = NULL;

  REGION_UNINIT(pScreen, &cl->copyRegion);
  REGION_UNINIT(pScreen, &cl->modifiedRegion);

  rfbPrintStats(cl);

  if (cl->translateLookupTable) free(cl->translateLookupTable);

  rfbFreeZrleData(cl);

  if (cl->cutText)
    free(cl->cutText);

  InterframeOff(cl);

  i = cl->numDevices;
  while (i-- > 0)
    RemoveExtInputDevice(cl, 0);

  if (cl->captureFD >= 0)
    close(cl->captureFD);

  free(cl);

  if (rfbClientHead == NULL && rfbIdleTimeout > 0)
    IdleTimerSet();
}
void rfbClientConnectionGone(rfbClientPtr cl)
{
  int i;

  if (cl->prev)
    cl->prev->next = cl->next;
  else
    rfbClientHead = cl->next;
  if (cl->next)
    cl->next->prev = cl->prev;

  TimerFree(cl->alrTimer);
  TimerFree(cl->deferredUpdateTimer);
  TimerFree(cl->updateTimer);
  TimerFree(cl->congestionTimer);

#ifdef XVNC_AuthPAM
  rfbPAMEnd(cl);
#endif
  if (cl->login != NULL) {
    rfbLog("Client %s (%s) gone\n", cl->login, cl->host);
    free(cl->login);
  } else {
    rfbLog("Client %s gone\n", cl->host);
  }
  free(cl->host);

  ShutdownTightThreads();

  if (rfbAutoLosslessRefresh > 0.0) {
    REGION_UNINIT(pScreen, &cl->lossyRegion);
    REGION_UNINIT(pScreen, &cl->alrRegion);
    REGION_UNINIT(pScreen, &cl->alrEligibleRegion);
  }

   
  if (cl->compStreamInited == TRUE)
    deflateEnd(&(cl->compStream));

  for (i = 0; i < 4; i++) {
    if (cl->zsActive[i])
      deflateEnd(&cl->zsStruct[i]);
  }

  if (pointerClient == cl)
    pointerClient = NULL;

  REGION_UNINIT(pScreen, &cl->copyRegion);
  REGION_UNINIT(pScreen, &cl->modifiedRegion);

  rfbPrintStats(cl);

  if (cl->translateLookupTable) free(cl->translateLookupTable);

  rfbFreeZrleData(cl);

  if (cl->cutText)
    free(cl->cutText);

  InterframeOff(cl);

  i = cl->numDevices;
  while (i-- > 0)
    RemoveExtInputDevice(cl, 0);

  if (cl->captureFD >= 0)
    close(cl->captureFD);

  free(cl);

  if (rfbClientHead == NULL && rfbIdleTimeout > 0)
    IdleTimerSet();
}