void TSockSys::OnTimeOut(uv_timer_t* TimerHnd, int Status) { // check we have timer IAssert(SockSys.IsTimer((uint64)TimerHnd)); // get socket id const uint64 SockId = SockSys.TimerHndToSockIdH.GetDat((uint64)TimerHnd); IAssert(SockSys.IsSock(SockId)); // get socket event const uint64 SockHnd = (uint64)SockSys.SockIdToHndH.GetDat(SockId); const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); PSockEvent SockEvent; if (SockSys.IsSockEvent(SockEventId)) { SockEvent = SockSys.GetSockEvent(SockEventId); // execute callback if (Status == 0) { SockEvent->OnTimeOut(SockId); } else { TStr ErrMsg = (Status == -1) ? "SockSys.OnTimeOut: " + SockSys.GetLastErr() : "SockSys.OnTimeOut: Error in socket timeout"; SockEvent->OnError(SockId, Status, ErrMsg); } } else { SaveToErrLog("SockSys.OnTimeOut: Socket without SockEvent"); } // cleanup uv_close((uv_handle_t*)TimerHnd, NULL); // remove shortcuts SockSys.SockIdToTimerHndH.DelKey(SockId); SockSys.TimerHndToSockIdH.DelKey((uint64)TimerHnd); }
void TSockSys::OnWrite(uv_write_t *WriteHnd, int Status) { // cast to our write request object to get access to buffer uv_write_req_t* _WriteHnd = (uv_write_req_t*)WriteHnd; // get socket handle uv_tcp_t* SockHnd = (uv_tcp_t*)WriteHnd->handle; IAssert(SockSys.IsSockHnd((uint64)SockHnd)); // free buffer and write handle free(_WriteHnd->Buffer.base); free(_WriteHnd); // get socket id const uint64 SockId = SockSys.SockHndToIdH.GetDat((uint64)SockHnd); IAssert(SockSys.IsSock(SockId)); // get socket event const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); PSockEvent SockEvent; if (SockSys.IsSockEvent(SockEventId)) { SockEvent = SockSys.GetSockEvent(SockEventId); } else { SaveToErrLog("SockSys.OnWrite: Socket without SockEvent"); return; } // execute callback if (Status == 0) { SockEvent->OnWrite(SockId); } else { TStr ErrMsg = (Status == -1) ? "SockSys.OnWrite: " + SockSys.GetLastErr() : "SockSys.OnWrite: Error writing to socket"; SockEvent->OnError(SockId, Status, ErrMsg); } }
void TSockSys::OnAccept(uv_stream_t* ServerSockHnd, int Status) { // get socket handle uv_tcp_t* SockHnd = (uv_tcp_t*)ServerSockHnd; IAssert(SockSys.IsSockHnd((uint64)SockHnd)); // get socket id const uint64 SockId = SockSys.SockHndToIdH.GetDat((uint64)SockHnd); IAssert(SockSys.IsSock(SockId)); // get socket event const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); PSockEvent SockEvent; if (SockSys.IsSockEvent(SockEventId)) { SockEvent = SockSys.GetSockEvent(SockEventId); } else { SaveToErrLog("SockSys.OnAccept: Socket without SockEvent"); return; } // check for success status if (Status == 0) { // create a new socket for client connection PSock ClientSock = TSock::New(SockEvent); // get client socket handle uv_tcp_t* ClientSockHnd = SockSys.SockIdToHndH.GetDat(ClientSock->GetSockId()); // accept request const int AcceptResCd = uv_accept(ServerSockHnd, (uv_stream_t*)ClientSockHnd); // start listening for incoming data if (AcceptResCd == 0) { int ReadStartResCd = uv_read_start((uv_stream_t*)ClientSockHnd, TSockSys::OnAlloc, TSockSys::OnRead); // execute callback if (ReadStartResCd == 0) { SockEvent->OnAccept(ClientSock->GetSockId(), ClientSock); } else { TStr ErrMsg = (Status == -1) ? "SockSys.OnAccept: Error starting read " + SockSys.GetLastErr() : "SockSys.OnAccept: Error starting read"; SockEvent->OnError(SockId, ReadStartResCd, ErrMsg); } } else { // handle errors TStr ErrMsg = (Status == -1) ? "SockSys.OnAccept: Error accepting new connection " + SockSys.GetLastErr() : "SockSys.OnAccept: Error accepting new connection"; SockEvent->OnError(SockId, AcceptResCd, ErrMsg); } } else { TStr ErrMsg = (Status == -1) ? "SockSys.OnAccept: Error connecting" + SockSys.GetLastErr() : "SockSys.OnAccept: Error connecting"; SockEvent->OnError(SockId, Status, ErrMsg); } }
void TSockSys::OnRead(uv_stream_t* SockHnd, ssize_t BufferLen, uv_buf_t Buffer) { //TODO: check if we need to close _SockHnd //uv_tcp_t* _SockHnd = (uv_tcp_t*)SockHnd; // get socket handle IAssert(SockSys.IsSockHnd((uint64)SockHnd)); // get socket id const uint64 SockId = SockSys.SockHndToIdH.GetDat((uint64)SockHnd); IAssert(SockSys.IsSock(SockId)); // get socket event const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); PSockEvent SockEvent; if (SockSys.IsSockEvent(SockEventId)) { SockEvent = SockSys.GetSockEvent(SockEventId); } else { // cleanup (using delete as it was created in OnAlloc with new) delete[] Buffer.base; SaveToErrLog("SockSys.OnRead: Socket without SockEvent"); return; } // execute callback if (BufferLen > 0) { // we got data, move the ownership of buffer to TMIn PSIn SIn = TMIn::New(Buffer.base, (int)BufferLen, true); // send SockEvent->OnRead(SockId, SIn); } else { uv_err_code Status = uv_last_error(SockSys.Loop).code; // no data, might be error or end of stream if (Status == UV_EOF) { // no more data, close the socket handle SockEvent->OnReadEof(SockId); SockSys.DelIfSockTimer(SockId); } else if (Status == UV_EAGAIN) { // we'll wait } else { // error TStr ErrMsg = "SockSys.OnRead: " + SockSys.GetLastErr(); SockEvent->OnError(SockId, Status, ErrMsg); } // cleanup (using delete as it was created in OnAlloc with new) delete[] Buffer.base; } }
void TSockSys::OnClose(uv_handle_t* SockHnd) { // check if we know about the socket if (SockSys.IsSockHnd((uint64)SockHnd)) { // get socket id const uint64 SockId = SockSys.SockHndToIdH.GetDat((uint64)SockHnd); // execute callback const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); if (SockSys.IsSockEvent(SockEventId)) { PSockEvent SockEvent = SockSys.GetSockEvent(SockEventId); SockEvent->OnClose(SockId); } // delete socket shortcuts SockSys.DelIfSockTimer(SockId); SockSys.SockIdToHndH.DelKey(SockId); SockSys.SockHndToIdH.DelKey((uint64)SockHnd); SockSys.SockHndToEventIdH.DelKey((uint64)SockHnd); // marke note that it's already closed SockSys.ClosedSockIdSet.DelIfKey(SockId); } }
void TSockSys::OnConnect(uv_connect_t* ConnectHnd, int Status) { // get socket handle uv_tcp_t* SockHnd = (uv_tcp_t*)ConnectHnd->handle; IAssert(SockSys.IsSockHnd((uint64)SockHnd)); // cleanup free(ConnectHnd); // get socket id const uint64 SockId = SockSys.SockHndToIdH.GetDat((uint64)SockHnd); IAssert(SockSys.IsSock(SockId)); // get socket event const uint64 SockEventId = SockSys.SockHndToEventIdH.GetDat((uint64)SockHnd); PSockEvent SockEvent; if (SockSys.IsSockEvent(SockEventId)) { SockEvent = SockSys.GetSockEvent(SockEventId); } else { SaveToErrLog("SockSys.OnConnect: Socket without SockEvent"); return; } // execute callback if (Status == 0) { SockEvent->OnConnect(SockId); } else { TStr ErrMsg = (Status == -1) ? "SockSys.OnConnect: " + SockSys.GetLastErr() : "SockSys.OnConnect: Error connecting"; SockEvent->OnError(SockId, Status, ErrMsg); return; } // start listening for incoming data int ResCd = uv_read_start((uv_stream_t*)SockHnd, TSockSys::OnAlloc, TSockSys::OnRead); // check for errors if (ResCd != 0) { TStr ErrMsg = (Status == -1) ? "SockSys.OnConnect: " + SockSys.GetLastErr() : "SockSys.OnConnect: Error establishing read callbacks"; SockEvent->OnError(SockId, ResCd, ErrMsg); } }