bool EndpointPool::addEndpoint(Endpoint endpoint, int64_t penalty) { if (!endpoint.isRoutable()) return false; if (endpoint.getIP() == _localhost.getIP()) return false; endpoint.setTime(max((int64_t)0, (int64_t)endpoint.getTime() - penalty)); Endpoint found = endpoint; query("INSERT OR REPLACE INTO Endpoints VALUES (?, ?, ?, ?)", (int64_t)endpoint.getIP(), (int64_t)endpoint.getPort(), (int64_t)endpoint.getTime(), 0); return true; }
void ChatClient::handle_read_line(const boost::system::error_code& err, size_t bytes_transferred) { if (!err) { istream is(&_recv); string rx; do { char c; is >> noskipws >> c; if(c == '\r' || c == '\n') bytes_transferred--; else rx.push_back(c); } while (rx.size() < bytes_transferred); // cout << rx << endl; // _recv.consume(bytes_transferred); switch (_mode) { case wait_for_notice: { // look for "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname" in the line if (rx.find("Found your hostname") != string::npos || rx.find("using your IP address instead") != string::npos || rx.find("Couldn't look up your hostname") != string::npos || rx.find("ignoring hostname") != string::npos) { _mode = wait_for_motd; if (_endpointPool.getLocal().isRoutable() && !_proxy && !_name_in_use) _my_name = encodeAddress(_endpointPool.getLocal()); else _my_name = cformat("x%u", GetRand(1000000000)).text(); std::ostream txstream(&_send); txstream << "NICK " << _my_name << "\r"; txstream << "USER " << _my_name << " 8 * : " << _my_name << "\r"; async_write(_socket, _send, boost::bind(&ChatClient::handle_write_request, this, boost::asio::placeholders::error)); } break; } case wait_for_motd: { if (rx.find(" 004 ") != string::npos) { _mode = wait_for_ip; std::ostream txstream(&_send); txstream << "USERHOST " << _my_name << "\r"; async_write(_socket, _send, boost::bind(&ChatClient::handle_write_request, this, boost::asio::placeholders::error)); } else if (rx.find(" 433 ") != string::npos) { // log_debug("IRC name already in use\n"); _name_in_use = true; // close and rejoin _socket.close(); _mode = wait_for_notice; tcp::resolver::query query(_server, "irc"); // should we remove irc as service type ? _resolver.async_resolve(query, boost::bind(&ChatClient::handle_resolve, this, asio::placeholders::error, asio::placeholders::iterator)); return; } break; } case wait_for_ip: { if (rx.find(" 302 ") != string::npos) { _mode = in_chat_room; std::ostream txstream(&_send); // set my IP: vector<string> words; split(words, rx, is_any_of(" ")); if (words.size() > 3) { string str = words[3]; if (str.rfind("@") != string::npos) { string host = str.substr(str.rfind("@")+1); // Hybrid IRC used by lfnet always returns IP when you userhost yourself, // but in case another IRC is ever used this should work. log_debug("GetIPFromIRC() got userhost %s\n", host.c_str()); Endpoint endpoint(host, 0, true); if (endpoint.isValid()) { _endpointPool.setLocal(endpoint); _my_name = encodeAddress(endpoint); _notifier(); // this will start the Node... } if (_proxy) // re nick txstream << "NICK " << _my_name << "\r"; // now join the chat room if (_channels > 1) { // randomly join e.g. #bitcoin00-#bitcoin99 int channel_number = GetRandInt(_channels); stringstream ss; ss << setfill('0') << setw(2) << channel_number; txstream << "JOIN #" << _channel << ss.str() << "\r"; txstream << "WHO #" << _channel << ss.str() << "\r"; } else { txstream << "JOIN #" << _channel << "00\r"; txstream << "WHO #" << _channel << "00\r"; } async_write(_socket, _send, boost::bind(&ChatClient::handle_write_request, this, asio::placeholders::error)); break; } } } } case in_chat_room: { if (rx.empty() || rx.size() > 900) break; vector<string> words; split(words, rx, is_any_of(" ")); if (words.size() < 2) break; string name; if (words[0] == "PING") { string tx = rx; ostream txstream(&_send); tx[1] = 'O'; // change line to PONG tx += '\r'; txstream << tx; async_write(_socket, _send, boost::bind(&ChatClient::handle_write_request, this, asio::placeholders::error)); break; } if (words[1] == "352" && words.size() >= 8) { // index 7 is limited to 16 characters // could get full length name at index 10, but would be different from join messages name = words[7]; log_debug("IRC got who\n"); } if (words[1] == "JOIN" && words[0].size() > 1) { // :[email protected] JOIN :#channelname name = words[0].substr(1); size_t exclamation_pos = words[0].find("!"); if(exclamation_pos != string::npos) name = words[0].substr(1, exclamation_pos-1); // the 1, -1 is due to the colon // if (strchr(pszName, '!')) // *strchr(pszName, '!') = '\0'; log_debug("IRC got join\n"); } if (name[0] == 'u') { Endpoint endpoint; if (decodeAddress(name, endpoint)) { endpoint.setTime(GetAdjustedTime()); if (_endpointPool.addEndpoint(endpoint, 51 * 60)) { log_debug("IRC got new address: %s\n", endpoint.toString().c_str()); _notifier(); } // nGotIREndpointes++; } else { log_debug("IRC decode failed\n"); } } break; } default: break; } async_read_until(_socket, _recv, "\r\n", boost::bind(&ChatClient::handle_read_line, this, asio::placeholders::error, asio::placeholders::bytes_transferred)); }