Beispiel #1
0
ezResult ezTaskSystem::CancelTask(ezTask* pTask, ezOnTaskRunning::Enum OnTaskRunning)
{
  if (pTask->IsTaskFinished())
    return EZ_SUCCESS;

  EZ_PROFILE_SCOPE("CancelTask");

  EZ_ASSERT_DEV(pTask->m_BelongsToGroup.m_pTaskGroup->m_uiGroupCounter == pTask->m_BelongsToGroup.m_uiGroupCounter,
                "The task to be removed is in an invalid group.");

  // we set the cancel flag, to make sure that tasks that support canceling will terminate asap
  pTask->m_bCancelExecution = true;

  {
    EZ_LOCK(s_TaskSystemMutex);

    // if the task is still in the queue of its group, it had not yet been scheduled
    if (!pTask->m_bTaskIsScheduled && pTask->m_BelongsToGroup.m_pTaskGroup->m_Tasks.RemoveAndSwap(pTask))
    {
      // we set the task to finished, even though it was not executed
      pTask->m_bIsFinished = true;
      return EZ_SUCCESS;
    }

    // check if the task has already been scheduled for execution
    // if so, remove it from the work queue
    {
      for (ezUInt32 i = 0; i < ezTaskPriority::ENUM_COUNT; ++i)
      {
        auto it = s_Tasks[i].GetIterator();

        while (it.IsValid())
        {
          if (it->m_pTask == pTask)
          {
            s_Tasks[i].Remove(it);

            // we set the task to finished, even though it was not executed
            pTask->m_bIsFinished = true;

            // tell the system that one task of that group is 'finished', to ensure its dependencies will get scheduled
            TaskHasFinished(it->m_pTask, it->m_pBelongsToGroup);
            return EZ_SUCCESS;
          }

          ++it;
        }
      }
    }
  }

  // if we made it here, the task was already running
  // thus we just wait for it to finish

  if (OnTaskRunning == ezOnTaskRunning::WaitTillFinished)
    WaitForTask(pTask);

  return EZ_FAILURE;
}
Beispiel #2
0
void MumbleClient::ThreadFuncImpl()
{
	SetThreadName(-1, "[Mumble] Network Thread");

	while (true)
	{
		ClientTask task = WaitForTask();

		try
		{
			switch (task)
			{
				case ClientTask::BeginConnect:
				{
					const auto& address = m_connectionInfo.address;

					m_socket = socket(address.GetAddressFamily(), SOCK_STREAM, IPPROTO_TCP);

					int on = 1;
					setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));

					m_socketConnectEvent = WSACreateEvent();
					m_socketReadEvent = WSACreateEvent();

					WSAEventSelect(m_socket, m_socketConnectEvent, FD_CONNECT);

					u_long nonBlocking = 1;
					ioctlsocket(m_socket, FIONBIO, &nonBlocking);

					connect(m_socket, address.GetSocketAddress(), address.GetSocketAddressLength());

					trace("[mumble] connecting to %s...\n", address.ToString());

					break;
				}

				case ClientTask::EndConnect:
				{
					WSANETWORKEVENTS events = { 0 };
					WSAEnumNetworkEvents(m_socket, m_socketConnectEvent, &events);

					if (events.iErrorCode[FD_CONNECT_BIT])
					{
						// TODO: reconnecting?
						trace("[mumble] connecting failed: %d\n", events.iErrorCode[FD_CONNECT_BIT]);

						m_completionEvent.set_exception(std::runtime_error("Failed Mumble connection."));

						break;
					}

					WSACloseEvent(m_socketConnectEvent);
					m_socketConnectEvent = INVALID_HANDLE_VALUE;

					LARGE_INTEGER waitTime;
					waitTime.QuadPart = -20000000LL;

					SetWaitableTimer(m_idleEvent, &waitTime, 0, nullptr, nullptr, 0);

					m_handler.Reset();

					WSAEventSelect(m_socket, m_socketReadEvent, FD_READ);

					m_sessionManager = std::make_unique<Botan::TLS::Session_Manager_In_Memory>(m_rng);

					m_credentials = std::make_unique<MumbleCredentialsManager>();

					m_tlsClient = std::make_shared<Botan::TLS::Client>(*this,
																	   *(m_sessionManager.get()),
																	   *(m_credentials.get()),
																	   m_policy,
																	   m_rng,
																	   Botan::TLS::Server_Information()
																	   );

					m_connectionInfo.isConnected = true;

					break;
				}

				case ClientTask::Idle:
				{
					if (m_tlsClient->is_active() && m_connectionInfo.isConnected)
					{
						MumbleProto::Ping ping;
						ping.set_timestamp(msec().count());
						ping.set_tcp_ping_avg(m_tcpPingAverage);
						ping.set_tcp_ping_var(m_tcpPingVariance);
						ping.set_tcp_packets(m_tcpPingCount);

						Send(MumbleMessageType::Ping, ping);

						LARGE_INTEGER waitTime;
						waitTime.QuadPart = -50000000LL;

						SetWaitableTimer(m_idleEvent, &waitTime, 0, nullptr, nullptr, 0);
					}

					break;
				}

				case ClientTask::RecvData:
				{
					WSANETWORKEVENTS ne;
					WSAEnumNetworkEvents(m_socket, m_socketReadEvent, &ne);

					uint8_t buffer[16384];
					int len = recv(m_socket, (char*)buffer, sizeof(buffer), 0);

					if (len > 0)
					{
						std::unique_lock<std::recursive_mutex> lock(m_clientMutex);
						m_tlsClient->received_data(buffer, len);
					}
					else if (len == 0)
					{
						// TCP close, graceful?
						trace("[mumble] tcp close :(\n");
					}
					else
					{
						if (WSAGetLastError() != WSAEWOULDBLOCK)
						{
							// TCP close, error state
							trace("[mumble] tcp error :(\n");
						}
					}

					break;
				}

			}
		}
		catch (std::exception& e)
		{
			trace("lolexception %s", e.what());
		}
	}
}