bool Beacon::StartActiveSession(const IpAddr &remoteAddr, const IpAddr &localAddr) { Session *session = NULL; LogAssert(m_scheduler->IsMainThread()); session = findInSourceMap(remoteAddr, localAddr); if (session) { if (session->IsActiveSession()) return true; if (!session->UpgradeToActiveSession()) { LogOptional(Log::Session, "Failed to upgrade Session id=%u for %s to %s is to an active session.", session->GetId(), localAddr.ToString(), remoteAddr.ToString() ); return false; } LogOptional(Log::Session, "Session id=%u for %s to %s is now an active session.", session->GetId(), localAddr.ToString(), remoteAddr.ToString() ); return true; } else { session = addSession(remoteAddr, localAddr); if (!session) return false; LogOptional(Log::Session, "Manually added new session for %s to %s id=%u.", localAddr.ToString(), remoteAddr.ToString(), session->GetId()); if (!session->StartActiveSession(remoteAddr, localAddr)) { LogOptional(Log::Session, "Failed to start active session id=%u for %s to %s.", session->GetId(), localAddr.ToString(), remoteAddr.ToString() ); return false; } LogOptional(Log::Session, "Session id=%u for %s to %s is started as an active session.", session->GetId(), localAddr.ToString(), remoteAddr.ToString() ); return true; } }
void Stop() { LogAssert(m_scheduler->IsMainThread()); if (m_stopped) LogOptional(Log::TimerDetail, "Stopping ignored on stopped timer %s", m_name); else { // Remove us from active timers list. (Must remove before changing timer.) SchedulerBase::timer_set_it found = m_activeTimers->find(this); if (found != m_activeTimers->end()) m_activeTimers->erase(found); m_stopped = true; LogOptional(Log::TimerDetail, "Stopping timer %s. (%zu timers)", m_name, m_activeTimers->size()); } }
/** * Called by the Scheduler to mark the timer as stopped and run its action. Will * Remove the timer from the active list. * */ void ExpireTimer() { LogAssert(!m_stopped); Stop(); LogOptional(Log::TimerDetail, "Expired timer %s calling callback", m_name); m_callback(this, m_userdata); }
void Beacon::KillSession(Session *session) { if (!LogVerify(session)) return; LogAssert(m_scheduler->IsMainThread()); LogVerify(1 == m_discMap.erase(session->GetLocalDiscriminator())); LogVerify(1 == m_IdMap.erase(session->GetId())); LogVerify(1 == m_sourceMap.erase(SourceMapKey(session->GetRemoteAddress(), session->GetLocalAddress()))); LogOptional(Log::Session, "Removed session %s to %s id=%d.", session->GetLocalAddress().ToString(), session->GetRemoteAddress().ToString(), session->GetId()); delete session; }
/** * Changes the start and expire time for the timer. * * @param startTime - The time of the last timer start. May be m_startTime. * @param micro - Time to expire from startTime in microseconds. * * @return bool - false on failure. */ bool setExpireTime(const struct timespec &startTime, uint64_t micro) { bool expireChange, startChange; TimeSpec expireTime(startTime); expireTime += TimeSpec(TimeSpec::Microsec, micro); startChange = (m_startTime != startTime); expireChange = (m_stopped || m_expireTime != expireTime); //LogOptional(Log::Temp, "Timer %s before change %zu items",m_name, m_activeTimers->size()); if (!expireChange && !startChange) { LogOptional(Log::TimerDetail, "Timer %s no change. %" PRIu64 " microseconds. Expires:%jd:%09ld", m_name, micro, (intmax_t)expireTime.tv_sec, expireTime.tv_nsec ); return true; } LogOptional(Log::TimerDetail, "%s timer %s for %" PRIu64 " microseconds from %jd:%09ld. Expires:%jd:%09ld", m_stopped ? "Starting": startChange ? "Resetting":"Advancing", m_name, micro, (intmax_t)startTime.tv_sec, startTime.tv_nsec, (intmax_t)expireTime.tv_sec, expireTime.tv_nsec ); // Start time does not effect sorting in active timer list, so we can set it now. // Stopped also should not matter. if (startChange) m_startTime = startTime; m_stopped = false; if (expireChange) { SchedulerBase::timer_set_it found = m_activeTimers->find(this); if (found != m_activeTimers->end()) { if (!willTimerBeSorted(found, expireTime)) { m_activeTimers->erase(found); found = m_activeTimers->end(); // cause it to be added back } } // Actually set the time m_expireTime = expireTime; if (found == m_activeTimers->end()) { try { m_activeTimers->insert(this); } catch (std::exception &e) { m_stopped = true; gLog.Message(Log::Error, "Failed to add timer: %s.", e.what()); return false; } } } //LogOptional(Log::Temp, "Timer %s after change %zu items",m_name, m_activeTimers->size()); return true; }
void Beacon::handleListenSocket(Socket &socket) { SockAddr sourceAddr; IpAddr destIpAddr, sourceIpAddr; uint8_t ttl; BfdPacket packet; bool found; Session *session = NULL; if (!m_packet.DoRecvMsg(socket)) { gLog.ErrnoError(m_packet.GetLastError(), "Error receiving on BFD listen socket"); return; } sourceAddr = m_packet.GetSrcAddress(); if (!LogVerify(sourceAddr.IsValid())) return; sourceIpAddr = IpAddr(sourceAddr); destIpAddr = m_packet.GetDestAddress(); if (!destIpAddr.IsValid()) { gLog.LogError("Could not get destination address for packet from %s.", sourceAddr.ToString()); return; } ttl = m_packet.GetTTLorHops(&found); if (!found) { gLog.LogError("Could not get ttl for packet from %s.", sourceAddr.ToString()); return; } LogOptional(Log::Packet, "Received bfd packet %zu bytes from %s to %s", m_packet.GetDataSize(), sourceAddr.ToString(), destIpAddr.ToString()); // // Check ip specific stuff. See draft-ietf-bfd-v4v6-1hop-11.txt // // Port if (m_strictPorts) { if (sourceAddr.Port() < bfd::MinSourcePort) // max port is max value, so no need to check { LogOptional(Log::Discard, "Discard packet: bad source port %s to %s", sourceAddr.ToString(), destIpAddr.ToString()); return; } } // TTL assumes that all control packets are from neighbors. if (ttl != 255) { gLog.Optional(Log::Discard, "Discard packet: bad ttl/hops %hhu", ttl); return; } if (!Session::InitialProcessControlPacket(m_packet.GetData(), m_packet.GetDataSize(), packet)) { gLog.Optional(Log::Discard, "Discard packet"); return; } // We have a (partially) valid packet ... now find the correct session. if (packet.header.yourDisc != 0) { DiscMapIt found = m_discMap.find(packet.header.yourDisc); if (found == m_discMap.end()) { if (gLog.LogTypeEnabled(Log::DiscardDetail)) Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr); gLog.Optional(Log::Discard, "Discard packet: no session found for yourDisc <%u>.", packet.header.yourDisc); return; } session = found->second; if (session->GetRemoteAddress() != sourceIpAddr) { if (gLog.LogTypeEnabled(Log::DiscardDetail)) Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr); LogOptional(Log::Discard, "Discard packet: mismatched yourDisc <%u> and ip <from %s to %s>.", packet.header.yourDisc, sourceAddr.ToString(), destIpAddr.ToString()); return; } } else { // No discriminator session = findInSourceMap(sourceIpAddr, destIpAddr); if (NULL == session) { // No session yet .. create one !? if (!m_allowAnyPassiveIP && m_allowedPassiveIP.find(sourceIpAddr) == m_allowedPassiveIP.end()) { if (gLog.LogTypeEnabled(Log::DiscardDetail)) Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr); LogOptional(Log::Discard, "Ignoring unauthorized bfd packets from %s", sourceAddr.ToString()); return; } session = addSession(sourceIpAddr, destIpAddr); if (!session) return; if (!session->StartPassiveSession(sourceAddr, destIpAddr)) { gLog.LogError("Failed to add new session for local %s to remote %s id=%d.", destIpAddr.ToString(), sourceAddr.ToString(), session->GetId()); KillSession(session); } LogOptional(Log::Session, "Added new session for local %s to remote %s id=%d.", destIpAddr.ToString(), sourceAddr.ToString(), session->GetId()); } } // // We have a session that can handle the rest. // session->ProcessControlPacket(packet, sourceAddr.Port()); }