static void findReflector( const wxString& rptrCall, IRCDDBAppPrivate * d )
{
  wxString zonerp_cs;
  wxString ipAddr;

#define MAXIPV4ADDR 5
  struct sockaddr_in addr[MAXIPV4ADDR];
  unsigned int numAddr = 0;

  char host_name[80];

  wxString host = rptrCall.Mid(0,6) + wxT(".reflector.ircddb.net");

  safeStringCopy(host_name, host.mb_str(wxConvUTF8), sizeof host_name);

  if (getAllIPV4Addresses(host_name, 0, &numAddr, addr, MAXIPV4ADDR) == 0)
  {
    if (numAddr > 0)
    {
      unsigned char * a = (unsigned char *) &addr[0].sin_addr;

      ipAddr = wxString::Format(wxT("%d.%d.%d.%d"), a[0], a[1], a[2], a[3]);
      zonerp_cs = rptrCall;
      zonerp_cs.SetChar(7, wxT('G'));
    }
  }
  

  IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER"));
  m2->addParam(rptrCall);
  m2->addParam(zonerp_cs);
  m2->addParam(ipAddr);
  d->replyQ.putMessage(m2);
}
Exemple #2
0
wxThread::ExitCode IRCClient::Entry ()
{
  unsigned int numAddr;

#define MAXIPV4ADDR 10
  struct sockaddr_in addr[MAXIPV4ADDR];

  struct sockaddr_in myaddr;

  int state = 0;
  int timer = 0;
  int sock = 0;
  unsigned int currentAddr = 0;

  int result;


  numAddr = 0;

  result = getAllIPV4Addresses(local_addr, 0, &numAddr, &myaddr, 1);

  if ((result != 0) || (numAddr != 1))
  {
    wxLogVerbose(wxT("IRCClient::Entry: local address not parseable, using 0.0.0.0"));
    memset(&myaddr, 0x00, sizeof(struct sockaddr_in));
  }

  while (true)
  {

    if (timer > 0)
    {
      timer --;
    }

    switch (state)
    {
    case 0:
      if (terminateThread)
      {
	wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
	return 0;
      }
      
      if (timer == 0)
      {
	timer = 30;

	if (getAllIPV4Addresses(host_name, port, &numAddr, addr, MAXIPV4ADDR) == 0)
	{
	  wxLogVerbose(wxT("IRCClient::Entry: number of DNS entries %d"), numAddr);
	  if (numAddr > 0)
	  {
	    currentAddr = 0;
	    state = 1;
	    timer = 0;
	  }
	}
      }
      break;

    case 1:
      if (terminateThread)
      {
	wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
	return 0;
      }
      
      if (timer == 0)
      {
	sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (sock < 0)
	{
	  wxLogSysError(wxT("IRCClient::Entry: socket"));
	  timer = 30;
	  state = 0;
	}
	else
	{
#if defined(__WINDOWS__)
	  u_long nonBlock = 1UL;
	  if (ioctlsocket( sock, FIONBIO, &nonBlock ) != 0)
	  {
	    wxLogSysError(wxT("IRCClient::Entry: ioctlsocket"));
	    closesocket(sock);
	    timer = 30;
	    state = 0;
	  }
#else
	  if (fcntl( sock, F_SETFL, O_NONBLOCK ) < 0)
	  {
	    wxLogSysError(wxT("IRCClient::Entry: fcntl"));
	    close(sock);
	    timer = 30;
	    state = 0;
	  }
#endif
	  else
	  {
	    unsigned char * h = (unsigned char *) &(myaddr.sin_addr);
	    int res;

	    if ((h[0] != 0) || (h[1] != 0) || (h[2] != 0) || (h[3] != 0))
	    {
	      wxLogVerbose(wxT("IRCClient::Entry: bind: local address %d.%d.%d.%d"), 
		   h[0], h[1], h[2], h[3]);
	    }

	    res = bind(sock, (struct sockaddr *) &myaddr, sizeof (struct sockaddr_in));

	    if (res != 0)
	    {

		wxLogSysError(wxT("IRCClient::Entry: bind"));
#if defined(__WINDOWS__)
		closesocket(sock);
#else
		close(sock);
#endif
		state = 0;
		timer = 30;
		break;
	    }


	    h = (unsigned char *) &(addr[currentAddr].sin_addr);
	    wxLogVerbose(wxT("IRCClient::Entry: trying to connect to %d.%d.%d.%d"), 
		   h[0], h[1], h[2], h[3]);
		
	    res = connect(sock, (struct sockaddr *) (addr + currentAddr), sizeof (struct sockaddr_in));

	    if (res == 0)
	    {
	      wxLogVerbose(wxT("IRCClient::Entry: connected"));
	      state = 4;
	    }
	    else 
	    { 
#if defined(__WINDOWS__)
	      if (WSAGetLastError() == WSAEWOULDBLOCK)
#else
	      if (errno == EINPROGRESS)
#endif
	      {
		wxLogVerbose(wxT("IRCClient::Entry: connect in progress"));
		state = 3;
		timer = 10;  // 5 second timeout
	      }
	      else
	      {
		wxLogSysError(wxT("IRCClient::Entry: connect"));
#if defined(__WINDOWS__)
		closesocket(sock);
#else
		close(sock);
#endif
		currentAddr ++;
		if (currentAddr >= numAddr)
		{
		  state = 0;
		  timer = 30;
		}
		else
		{
		  state = 1;
		  timer = 4;
		}
	      }
	    }
	  } // connect
	}
      }
      break;
    
    case 3:
      {
	struct timeval tv;
	tv.tv_sec = 0; 
	tv.tv_usec = 0; 

	fd_set myset;
	FD_ZERO(&myset);
#if defined(__WINDOWS__)
	FD_SET((unsigned int)sock, &myset);
#else
	FD_SET(sock, &myset);
#endif

	int res = select(sock+1, NULL, &myset, NULL, &tv); 
	if (res < 0)
	{
	  wxLogSysError(wxT("IRCClient::Entry: select"));
#if defined(__WINDOWS__)
	  closesocket(sock);
#else
	  close(sock);
#endif
	  state = 0;
	  timer = 30;
	}
	else if (res > 0) // connect is finished
	{
#if defined(__WINDOWS__)
	  int val_len;
#else
	  socklen_t val_len;
#endif
	  int value;

	  val_len = sizeof value;

	  if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &value, &val_len) < 0)
	  {
	     wxLogSysError(wxT("IRCClient::Entry: getsockopt"));
#if defined(__WINDOWS__)
	     closesocket(sock);
#else
	     close(sock);
#endif
	     state = 0;
	     timer = 30;
	  }
	  else
	  {
	    if (value != 0)
	    {
	      wxLogWarning(wxT("IRCClient::Entry: SO_ERROR=%d"), value);
#if defined(__WINDOWS__)
	      closesocket(sock);
#else
	      close(sock);
#endif
	      currentAddr ++;
	      if (currentAddr >= numAddr)
	      {
		state = 0;
		timer = 30;
	      }
	      else
	      {
		state = 1;
		timer = 2;
	      }
	    }
	    else
	    {
	      wxLogVerbose(wxT("IRCClient::Entry: connected2"));
	      state = 4;
	    }
	  }

	}
	else if (timer == 0)
	{  // select timeout and timer timeout
	  wxLogVerbose(wxT("IRCClient::Entry: connect timeout"));
#if defined(__WINDOWS__)
	  closesocket(sock);
#else
	  close(sock);
#endif
	  currentAddr ++;
	  if (currentAddr >= numAddr)
	  {
	    state = 0;
	    timer = 30;
	  }
	  else
	  {
	    state = 1; // open new socket
	    timer = 2;
	  }
	}

      }
      break;

    case 4:
      {
	recvQ = new IRCMessageQueue();
	sendQ = new IRCMessageQueue();

	recv = new IRCReceiver(sock, recvQ);
	recv->startWork();

	proto->setNetworkReady(true);
	state = 5;
	timer = 0;

      }
      break;


    case 5:
      if (terminateThread)
      {
	state = 6;
      }
      else
      {

	if (recvQ -> isEOF())
	{
	  timer = 0;
	  state = 6;
	}
	else if (proto -> processQueues(recvQ, sendQ) == false)
	{
	  timer = 0;
	  state = 6;
	}

	while ((state == 5) && sendQ->messageAvailable())
	{
	  IRCMessage * m = sendQ -> getMessage();

	  wxString out;

	  m -> composeMessage ( out );

	  char buf[200];
	  safeStringCopy(buf, out.mb_str(wxConvUTF8), sizeof buf);
	  int len = strlen(buf);

	  if (buf[len - 1] == 10)  // is there a NL char at the end?
	  {
	    int r = send(sock, buf, len, 0);

	    if (r != len)
	    {
	      wxLogVerbose(wxT("IRCClient::Entry: short write %d < %d"), r, len);

	      timer = 0;
	      state = 6;
	    }
/*	    else
	    {
	      wxLogVerbose(wxT("write %d bytes (") + out + wxT(")"), len );
	    } */
	  }
	  else
	  {
	      wxLogVerbose(wxT("IRCClient::Entry: no NL at end, len=%d"), len);

	      timer = 0;
	      state = 6;
	  }

	  delete m;
	}
      }
      break;

    case 6:
      {
	if (app != NULL)
	{
	  app->setSendQ(NULL);
	  app->userListReset();
	}

	proto->setNetworkReady(false);
	recv->stopWork();

	wxThread::Sleep(2000);

	delete recv;
	delete recvQ;
	delete sendQ;

#if defined(__WINDOWS__)
	closesocket(sock);
#else
	close(sock);
#endif

	if (terminateThread) // request to end the thread
	{
	  wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
	  return 0;
	}

	timer = 30;
	state = 0;  // reconnect to IRC server
      }
      break;

    }

    wxThread::Sleep(500);

  }

  return 0;
}