void KillClient ( unsigned int clientID ) //this is the nice disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_disconnect_later(iter->second, 0); clients.erase(iter); } }
void Network::DeInitialize(){ _mutex.lock(); if (IsServer()) enet_host_destroy(_host); else enet_peer_disconnect_later(_peer,0); _isConnected = false; _isServer = false; StopThreads(); _mutex.unlock(); }
void Peer::disconnect() { //enet_peer_disconnect_now(peer, 0); enet_peer_disconnect_later(peer, 0); }
int enet_lua_api enet_lua_peer_disconnect_later(lua_State* L) { ENetPeer** udata = luaL_checkudata(L, 1, "_enet.peer"); enet_peer_disconnect_later(*udata, 0); return 0; }
void Tunneld::promiseChannelCleanup(ToxTunChannel *chan) { qDebug()<<chan<<sender(); QObject *snderobj = (QObject*)sender(); QTimer *repeat_timer = NULL; qDebug()<<snderobj->objectName()<<snderobj->metaObject()->className(); if (chan == NULL) { repeat_timer = (QTimer*)snderobj; assert(repeat_timer != NULL); int conid = repeat_timer->property("conid").toInt(); if (!m_conid_chans.contains(conid)) { qDebug()<<"maybe too late repeat check self sock close timer event"; repeat_timer->deleteLater(); return; } chan = m_conid_chans[conid]; assert(chan != NULL); } else { // snderobj is ENetPoll or QTcpSocket } QTcpSocket *sock = chan->m_sock; ENetPeer *enpeer = chan->m_enpeer; ////////// QHash<QString, bool> promise_results; promise_results["sock_closed"] = chan->sock_closed; // promise_results["enet_closed"] = chan->enet_closed; promise_results["peer_sock_closed"] = chan->peer_sock_closed; bool promise_result = true; for (auto it = promise_results.begin(); it != promise_results.end(); it ++) { QString key = it.key(); bool val = it.value(); promise_result = promise_result && val; } if (true) { // 检测对方最近的回包情况 if (!promise_result && repeat_timer == NULL && promise_results["peer_sock_closed"] && !promise_results["sock_closed"]) { qDebug()<<"here"; if (chan->last_recv_peer_pkt_time == QDateTime()) { qDebug()<<"maybe can close socket right now, because recv nothing forever"; } QTimer *t = new QTimer(); t->setInterval(500); t->setSingleShot(true); t->setProperty("conid", QVariant(chan->m_conid)); // // QObject::connect(t, &QTimer::timeout, this, &Tunneld::promiseChannelCleanup, Qt::QueuedConnection); QObject::connect(t, SIGNAL(timeout()), this, SLOT(promiseChannelCleanup()), Qt::QueuedConnection); qDebug()<<"start repeat check sock close timer:"; t->start(); } if (!promise_result && repeat_timer != NULL && promise_results["peer_sock_closed"] && !promise_results["sock_closed"]) { // QDateTime now_time = QDateTime::currentDateTime(); uint32_t last_recv_to_now_time = chan->last_recv_peer_pkt_time.msecsTo(now_time); qDebug()<<"here:"<<last_recv_to_now_time<<enpeer->lastReceiveTime; if (last_recv_to_now_time > 7000) { qDebug()<<"last recv to now, force close self socket:"<<last_recv_to_now_time <<enpeer->incomingPeerID<<enpeer->outgoingPeerID; // 不能直接关闭,要在当前函数执行完后,即下一次事件的时候开始执行。 QTimer::singleShot(1, sock, &QTcpSocket::close); // QTimer *t = new QTimer(); // t->setSingleShot(true); // QObject::connect(t, &QTimer::timeout, sock, &QTcpSocket::close, Qt::QueuedConnection); // t->start(1); repeat_timer->deleteLater(); } else { repeat_timer->start(); } } } if (!promise_result) { qDebug()<<"promise nooooot satisfied:"<<promise_results<<chan->m_conid; return; } chan->promise_close_time = QDateTime::currentDateTime(); qDebug()<<"promise satisfied."<<chan->m_conid; ///// do cleanup bool force_closed = chan->force_closed; // enpeer->toxchan = NULL; // cleanup peerRemoveChan(enpeer, chan); this->m_sock_chans.remove(sock); // this->m_enpeer_chans.remove(enpeer); this->m_conid_chans.remove(chan->m_conid); delete chan; sock->disconnect(); sock->deleteLater(); if (repeat_timer != NULL) repeat_timer->deleteLater(); qDebug()<<"curr chan size:"<<this->m_sock_chans.count()<<this->m_conid_chans.count(); if (force_closed) { return; } // 延时关闭enet_peer QTimer *t = new QTimer(); auto later_close_timeout = [enpeer, t]() { qDebug()<<enpeer<<enpeer->state; if (enpeer->state != ENET_PEER_STATE_CONNECTED) { qDebug()<<"warning, peer currently not connected:"<<enpeer->incomingPeerID; } if (! (enet_list_empty (& enpeer -> outgoingReliableCommands) && enet_list_empty (& enpeer -> outgoingUnreliableCommands) && enet_list_empty (& enpeer -> sentReliableCommands))) { qDebug()<<"warning, maybe has unsent packet:"<<enpeer->incomingPeerID; } qDebug()<<"last recv time:"<<enpeer->incomingPeerID <<enetx_time_diff(enpeer->lastReceiveTime, enet_time_get()); qDebug()<<"restore peer timeout, ping interval"; enet_peer_timeout(enpeer, ENET_PEER_TIMEOUT_LIMIT*2, ENET_PEER_TIMEOUT_MINIMUM*2, ENET_PEER_TIMEOUT_MAXIMUM*2); enet_peer_ping_interval(enpeer, ENET_PEER_PING_INTERVAL*2); // enet_peer_disconnect_now(enpeer, qrand()); enet_peer_disconnect_later(enpeer, qrand()); t->deleteLater(); }; qDebug()<<"last recv time:"<<enpeer->incomingPeerID <<enetx_time_diff(enpeer->lastReceiveTime, enet_time_get()); // QTimer::singleShot(5678, later_close_timeout); t->setInterval(5678); t->setSingleShot(true); QObject::connect(t, &QTimer::timeout, later_close_timeout); t->start(); }
// called from ---NETPLAY--- thread void NetPlayServer::ThreadFunc() { while (m_do_loop) { // update pings every so many seconds if ((m_ping_timer.GetTimeElapsed() > 1000) || m_update_pings) { m_ping_key = Common::Timer::GetTimeMs(); sf::Packet spac; spac << (MessageId)NP_MSG_PING; spac << m_ping_key; m_ping_timer.Start(); SendToClients(spac); m_update_pings = false; } ENetEvent netEvent; int net; if (m_traversal_client) m_traversal_client->HandleResends(); net = enet_host_service(m_server, &netEvent, 1000); while (!m_async_queue.Empty()) { { std::lock_guard<std::recursive_mutex> lkp(m_crit.players); SendToClients(m_async_queue.Front()); } m_async_queue.Pop(); } if (net > 0) { switch (netEvent.type) { case ENET_EVENT_TYPE_CONNECT: { ENetPeer* accept_peer = netEvent.peer; unsigned int error; { std::lock_guard<std::recursive_mutex> lkg(m_crit.game); error = OnConnect(accept_peer); } if (error) { sf::Packet spac; spac << (MessageId)error; // don't need to lock, this client isn't in the client map Send(accept_peer, spac); if (netEvent.peer->data) { delete (PlayerId*)netEvent.peer->data; netEvent.peer->data = nullptr; } enet_peer_disconnect_later(accept_peer, 0); } } break; case ENET_EVENT_TYPE_RECEIVE: { sf::Packet rpac; rpac.append(netEvent.packet->data, netEvent.packet->dataLength); auto it = m_players.find(*(PlayerId*)netEvent.peer->data); Client& client = it->second; if (OnData(rpac, client) != 0) { // if a bad packet is received, disconnect the client std::lock_guard<std::recursive_mutex> lkg(m_crit.game); OnDisconnect(client); if (netEvent.peer->data) { delete (PlayerId*)netEvent.peer->data; netEvent.peer->data = nullptr; } } enet_packet_destroy(netEvent.packet); } break; case ENET_EVENT_TYPE_DISCONNECT: { std::lock_guard<std::recursive_mutex> lkg(m_crit.game); if (!netEvent.peer->data) break; auto it = m_players.find(*(PlayerId*)netEvent.peer->data); if (it != m_players.end()) { Client& client = it->second; OnDisconnect(client); if (netEvent.peer->data) { delete (PlayerId*)netEvent.peer->data; netEvent.peer->data = nullptr; } } } break; default: break; } } } // close listening socket and client sockets for (auto& player_entry : m_players) { delete (PlayerId*)player_entry.second.socket->data; player_entry.second.socket->data = nullptr; enet_peer_disconnect(player_entry.second.socket, 0); } }