void InspSocket::WantWrite()
{
- /** XXX:
- * The socket engine may only have each FD in the list ONCE.
- * This means we cant watch for write AND read at the same
- * time. We have to remove the READ fd, to insert the WRITE
- * fd. Once we receive our WRITE event (which WILL ARRIVE,
- * pretty much gauranteed) we switch back to watching for
- * READ events again.
- *
- * This behaviour may be fixed in a later version.
- */
- this->Instance->SE->DelFd(this);
+ this->Instance->SE->WantWrite(this);
this->WaitingForWriteEvent = true;
- if (!this->Instance->SE->AddFd(this))
- {
- this->Close();
- this->fd = -1;
- this->state = I_ERROR;
- this->OnError(I_ERR_NOMOREFDS);
- }
}
void InspSocket::SetQueues(int nfd)
/* Try and append the data to the back of the queue, and send it on its way
*/
outbuffer.push_back(data);
+ this->Instance->SE->WantWrite(this);
return (!this->FlushWriteBuffer());
}
}
}
}
+
+ if ((errno == EAGAIN) && (fd > -1))
+ {
+ this->Instance->SE->WantWrite(this);
+ }
+
return (fd < 0);
}
delete this->sock;
return;
}
- this->sock->FlushWriteBuffer();
}
bool InspSocket::Poll()
return false;
int incoming = -1;
- bool n = true;
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return false;
return true;
break;
case I_CONNECTED:
-
- if (this->WaitingForWriteEvent)
- {
- /* Switch back to read events */
- this->Instance->SE->DelFd(this);
- this->WaitingForWriteEvent = false;
- if (!this->Instance->SE->AddFd(this))
- return false;
-
- /* Trigger the write event */
- n = this->OnWriteReady();
- }
- else
- {
- /* Process the read event */
- n = this->OnDataReady();
- }
- /* Flush any pending, but not till after theyre done with the event
- * so there are less write calls involved.
- * Both FlushWriteBuffer AND the return result of OnDataReady must
- * return true for this to be ok.
- */
- if (this->FlushWriteBuffer())
- return false;
- return n;
+ /* Process the read event */
+ return this->OnDataReady();
break;
default:
break;
this->Close();
}
-void InspSocket::HandleEvent(EventType et)
+void InspSocket::HandleEvent(EventType et, int errornum)
{
- if (!this->Poll())
+ switch (et)
{
- this->Instance->SE->DelFd(this);
- this->Close();
- delete this;
+ case EVENT_ERROR:
+ this->Instance->SE->DelFd(this);
+ this->Close();
+ delete this;
+ return;
+ break;
+ case EVENT_READ:
+ if (!this->Poll())
+ {
+ this->Instance->SE->DelFd(this);
+ this->Close();
+ delete this;
+ return;
+ }
+ break;
+ case EVENT_WRITE:
+ if (this->WaitingForWriteEvent)
+ {
+ this->WaitingForWriteEvent = false;
+ if (!this->OnWriteReady())
+ {
+ this->Instance->SE->DelFd(this);
+ this->Close();
+ delete this;
+ return;
+ }
+ }
+ if (this->state == I_CONNECTING)
+ {
+ /* This might look wrong as if we should be actually calling
+ * with EVENT_WRITE, but trust me it is correct. There are some
+ * writeability-state things in the read code, because of how
+ * InspSocket used to work regarding write buffering in previous
+ * versions of InspIRCd. - Brain
+ */
+ this->HandleEvent(EVENT_READ);
+ return;
+ }
+ else
+ {
+ Instance->Log(DEBUG,"State=%d CONNECTED=%d", this->state, I_CONNECTED);
+ if (this->FlushWriteBuffer())
+ {
+ this->Instance->SE->DelFd(this);
+ this->Close();
+ delete this;
+ return;
+ }
+ }
+ break;
}
}