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); }
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; }