-
- #ifndef IPV6
- snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin_port), ntohs(laddr.sin_port));
- #else
- snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin6_port), ntohs(laddr.sin6_port));
- #endif
-
- this->Write(req);
-
- return true;
- }
-
- virtual void OnClose()
- {
- /* There used to be a check against the fd table here, to make sure the user hadn't been
- * deleted but not yet had their socket closed or something along those lines, dated june
- * 2006. Since we added the global cull list and such, I don't *think* that is necessary
- * anymore. If you're getting odd crashes here, that's probably why ;) -Special */
-
- if (*user->ident == '~' && user->GetExt("ident_socket"))
- user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
-
- user->Shrink("ident_socket");
- Instance->next_call = Instance->Time();
- }
-
- virtual void OnError(InspSocketError e)
- {
- // Quick check to make sure that this hasn't been sent ;)
- if (*user->ident == '~' && user->GetExt("ident_socket"))
- user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
-
- user->Shrink("ident_socket");
- Instance->next_call = Instance->Time();
- }
-
- virtual bool OnDataReady()
- {
- char *ibuf = this->Read();
- if (!ibuf)
- return false;
-
- // We don't really need to buffer for incomplete replies here, since IDENT replies are
- // extremely short - there is *no* sane reason it'd be in more than one packet
-
- irc::sepstream sep(ibuf, ':');
- std::string token;
- for (int i = 0; sep.GetToken(token); i++)
- {
- // We only really care about the 4th portion
- if (i < 3)
+
+ /* Build request in the form 'localport,remoteport\r\n' */
+ int req_size;
+ if (user->client_sa.sa.sa_family == AF_INET6)
+ req_size = snprintf(req, sizeof(req), "%d,%d\r\n",
+ ntohs(user->client_sa.in6.sin6_port), ntohs(user->server_sa.in6.sin6_port));
+ else
+ req_size = snprintf(req, sizeof(req), "%d,%d\r\n",
+ ntohs(user->client_sa.in4.sin_port), ntohs(user->server_sa.in4.sin_port));
+
+ /* Send failed if we didnt write the whole ident request --
+ * might as well give up if this happens!
+ */
+ if (ServerInstance->SE->Send(this, req, req_size, 0) < req_size)
+ done = true;
+ }
+
+ virtual void HandleEvent(EventType et, int errornum = 0)
+ {
+ switch (et)
+ {
+ case EVENT_READ:
+ /* fd readable event, received ident response */
+ ReadResponse();
+ break;
+ case EVENT_WRITE:
+ /* fd writeable event, successfully connected! */
+ OnConnected();
+ break;
+ case EVENT_ERROR:
+ /* fd error event, ohshi- */
+ ServerInstance->Logs->Log("m_ident",DEBUG,"EVENT_ERROR");
+ /* We *must* Close() here immediately or we get a
+ * huge storm of EVENT_ERROR events!
+ */
+ Close();
+ done = true;
+ break;
+ }
+ }
+
+ void Close()
+ {
+ /* Remove ident socket from engine, and close it, but dont detatch it
+ * from its parent user class, or attempt to delete its memory.
+ */
+ if (GetFd() > -1)
+ {
+ ServerInstance->Logs->Log("m_ident",DEBUG,"Close ident socket %d", GetFd());
+ ServerInstance->SE->DelFd(this);
+ ServerInstance->SE->Close(GetFd());
+ this->SetFd(-1);
+ }
+ }
+
+ bool HasResult()
+ {
+ return done;
+ }
+
+ void ReadResponse()
+ {
+ /* We don't really need to buffer for incomplete replies here, since IDENT replies are
+ * extremely short - there is *no* sane reason it'd be in more than one packet
+ */
+ char ibuf[MAXBUF];
+ int recvresult = ServerInstance->SE->Recv(this, ibuf, MAXBUF-1, 0);
+
+ /* Close (but don't delete from memory) our socket
+ * and flag as done since the ident lookup has finished
+ */
+ Close();
+ done = true;
+
+ /* Cant possibly be a valid response shorter than 3 chars,
+ * because the shortest possible response would look like: '1,1'
+ */
+ if (recvresult < 3)
+ return;
+
+ ServerInstance->Logs->Log("m_ident",DEBUG,"ReadResponse()");
+
+ /* Truncate at the first null character, but first make sure
+ * there is at least one null char (at the end of the buffer).
+ */
+ ibuf[recvresult] = '\0';
+ std::string buf(ibuf);
+
+ /* <2 colons: invalid
+ * 2 colons: reply is an error
+ * >3 colons: there is a colon in the ident
+ */
+ if (std::count(buf.begin(), buf.end(), ':') != 3)
+ return;
+
+ std::string::size_type lastcolon = buf.rfind(':');
+
+ /* Truncate the ident at any characters we don't like, skip leading spaces */
+ for (std::string::const_iterator i = buf.begin()+lastcolon+1; i != buf.end(); ++i)
+ {
+ if (result.size() == ServerInstance->Config->Limits.IdentMax)
+ /* Ident is getting too long */
+ break;
+
+ if (*i == ' ')