void EQStream::CheckTimeout(uint32 now, uint32 timeout) { bool outgoing_data = HasOutgoingData(); //up here to avoid recursive locking EQStreamState orig_state = GetState(); if (orig_state == CLOSING && !outgoing_data) { _log(NET__NET_TRACE, _L "Out of data in closing state, disconnecting." __L); _SendDisconnect(); SetState(DISCONNECTING); } else if (LastPacket && (now-LastPacket) > timeout) { switch(orig_state) { case CLOSING: //if we time out in the closing state, they are not acking us, just give up _log(NET__DEBUG, _L "Timeout expired in closing state. Moving to closed state." __L); _SendDisconnect(); SetState(CLOSED); break; case DISCONNECTING: //we timed out waiting for them to send us the disconnect reply, just give up. _log(NET__DEBUG, _L "Timeout expired in disconnecting state. Moving to closed state." __L); SetState(CLOSED); break; case CLOSED: _log(NET__DEBUG, _L "Timeout expired in closed state??" __L); break; case ESTABLISHED: //we timed out during normal operation. Try to be nice about it. //we will almost certainly time out again waiting for the disconnect reply, but oh well. _log(NET__DEBUG, _L "Timeout expired in established state. Closing connection." __L); _SendDisconnect(); SetState(DISCONNECTING); } } }
void EQStream::Close() { if(HasOutgoingData()) { //there is pending data, wait for it to go out. Log.Out(Logs::Detail, Logs::Netcode, _L "Stream requested to Close(), but there is pending data, waiting for it." __L); SetState(CLOSING); } else { //otherwise, we are done, we can drop immediately. _SendDisconnect(); Log.Out(Logs::Detail, Logs::Netcode, _L "Stream closing immediate due to Close()" __L); SetState(DISCONNECTING); } }
void EQStream::AdjustRates(uint32 average_delta) { #ifdef RETRANSMITS if (average_delta && (average_delta <= RuleI(EQStream, AverageDeltaMax))) { #else if (average_delta) { #endif MRate.lock(); RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; _log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); #ifdef RETRANSMITS } else { _log(NET__RATES, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, average_delta, RuleI(EQStream, AverageDeltaMax)); #endif } } void EQStream::Close() { if(HasOutgoingData()) { //there is pending data, wait for it to go out. _log(NET__DEBUG, _L "Stream requested to Close(), but there is pending data, waiting for it." __L); SetState(CLOSING); } else { //otherwise, we are done, we can drop immediately. _SendDisconnect(); _log(NET__DEBUG, _L "Stream closing immediate due to Close()" __L); SetState(DISCONNECTING); } } //this could be expanded to check more than the fitst opcode if //we needed more complex matching EQStream::MatchState EQStream::CheckSignature(const Signature *sig) { EQRawApplicationPacket *p = NULL; MatchState res = MatchNotReady; MInboundQueue.lock(); if (!InboundQueue.empty()) { //this is already getting hackish... p = InboundQueue.front(); if(sig->ignore_eq_opcode != 0 && p->opcode == sig->ignore_eq_opcode) { if(InboundQueue.size() > 1) { p = InboundQueue[1]; } else { p = NULL; } } if(p == NULL) { //first opcode is ignored, and nothing else remains... keep waiting } else if(p->opcode == sig->first_eq_opcode) { //opcode matches, check length.. if(p->size == sig->first_length) { _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x and length matched %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); res = MatchSuccessful; } else if(sig->first_length == 0) { _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x and length (%d) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); res = MatchSuccessful; } else { //opcode matched but length did not. _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x, but length %d did not match expected %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); res = MatchFailed; } } else { //first opcode did not match.. _log(NET__IDENT_TRACE, "%s:%d: First opcode 0x%x did not match expected 0x%x", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); res = MatchFailed; } } MInboundQueue.unlock(); return(res); }