mirror of https://github.com/PentHertz/srsLTE.git
simplified NAS rrc connection request procedure
move non-type-specific methods of proc_t to its base class. procedure state machine was simplified via a future-type. Now procedures dont get stuck until the user reads the procedure outcome. made the NAS procedures more event trigger/reaction-based.
This commit is contained in:
parent
8864787f59
commit
f2d88e5a5b
|
@ -30,23 +30,23 @@
|
|||
|
||||
namespace srslte {
|
||||
|
||||
enum class proc_state_t { on_going, success, error, inactive };
|
||||
enum class proc_outcome_t { repeat, yield, success, error };
|
||||
|
||||
/**************************************************************************************
|
||||
* helper functions for overloading
|
||||
* helper functions for method optional overloading
|
||||
************************************************************************************/
|
||||
namespace detail {
|
||||
// used by proc_manager to call proc finally() method only if it exists
|
||||
template <class T>
|
||||
auto optional_complete(T* obj, int is_success) -> decltype(obj->on_complete(is_success))
|
||||
// used by proc_t<T> to call T::then() method only if it exists
|
||||
template <typename T, typename ProcResult>
|
||||
auto optional_then(T* obj, const ProcResult& result) -> decltype(obj->then(result))
|
||||
{
|
||||
obj->on_complete(is_success);
|
||||
obj->then(result);
|
||||
}
|
||||
inline auto optional_complete(...) -> void
|
||||
inline auto optional_then(...) -> void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
// used by proc_t<T> to call proc T::clear() method only if it exists
|
||||
template <class T>
|
||||
auto optional_clear(T* obj) -> decltype(obj->clear())
|
||||
{
|
||||
|
@ -56,27 +56,34 @@ inline auto optional_clear(...) -> void
|
|||
{
|
||||
// do nothing
|
||||
}
|
||||
template <class T>
|
||||
auto get_result_type(const T& obj) -> decltype(obj.get_result());
|
||||
inline auto get_result_type(...) -> void;
|
||||
} // namespace detail
|
||||
|
||||
/**************************************************************************************
|
||||
* class: callback_list_t
|
||||
* class: callback_group_t<Args...>
|
||||
* Bundles several callbacks with callable interface "void(Args...)".
|
||||
* Calls to operator(Args&&...) call all the registered callbacks.
|
||||
* Two methods to register a callback - call it once, or always call it.
|
||||
************************************************************************************/
|
||||
|
||||
template <typename Func>
|
||||
class callback_list_t
|
||||
template <typename... Args>
|
||||
class callback_group_t
|
||||
{
|
||||
public:
|
||||
using id_type = uint32_t;
|
||||
using callback_t = Func;
|
||||
// register new callbacks
|
||||
id_type call_once(callback_t f_)
|
||||
using callback_id_t = uint32_t;
|
||||
using callback_t = std::function<void(Args...)>;
|
||||
|
||||
//! register callback, that gets called once
|
||||
callback_id_t on_next_call(callback_t f_)
|
||||
{
|
||||
uint32_t idx = get_new_callback();
|
||||
func_list[idx].func = std::move(f_);
|
||||
func_list[idx].call_always = false;
|
||||
return idx;
|
||||
}
|
||||
id_type call_always(callback_t f_)
|
||||
callback_id_t on_every_call(callback_t f_)
|
||||
{
|
||||
uint32_t idx = get_new_callback();
|
||||
func_list[idx].func = std::move(f_);
|
||||
|
@ -85,11 +92,12 @@ public:
|
|||
}
|
||||
|
||||
// call all callbacks
|
||||
void run(bool is_success)
|
||||
template <typename... ArgsRef>
|
||||
void operator()(const ArgsRef&... args)
|
||||
{
|
||||
for (auto& f : func_list) {
|
||||
if (f.active) {
|
||||
f.func(is_success);
|
||||
f.func(args...);
|
||||
if (not f.call_always) {
|
||||
f.active = false;
|
||||
}
|
||||
|
@ -112,19 +120,89 @@ private:
|
|||
|
||||
struct call_item_t {
|
||||
bool active;
|
||||
std::function<void(bool)> func;
|
||||
callback_t func;
|
||||
bool call_always;
|
||||
};
|
||||
std::vector<call_item_t> func_list;
|
||||
};
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_itf_t
|
||||
* class: proc_result_t
|
||||
* Stores the result of a procedure run. Can optionally contain a value T, in case of a
|
||||
* successful run.
|
||||
**************************************************************************************/
|
||||
|
||||
namespace detail {
|
||||
struct proc_result_base_t {
|
||||
bool is_success() const { return state == result_state_t::value; }
|
||||
bool is_error() const { return state == result_state_t::error; }
|
||||
bool is_complete() const { return state != result_state_t::none; }
|
||||
void set_val() { state = result_state_t::value; }
|
||||
void set_error() { state = result_state_t::error; }
|
||||
void clear() { state = result_state_t::none; }
|
||||
|
||||
protected:
|
||||
enum class result_state_t { none, value, error } state = result_state_t::none;
|
||||
};
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct proc_result_t : public detail::proc_result_base_t {
|
||||
const T* value() const { return state == result_state_t::value ? &t : nullptr; }
|
||||
void set_val(const T& t_)
|
||||
{
|
||||
proc_result_base_t::set_val();
|
||||
t = t_;
|
||||
}
|
||||
template <typename Proc>
|
||||
void extract_val(Proc& p)
|
||||
{
|
||||
set_val(p.get_result());
|
||||
}
|
||||
|
||||
protected:
|
||||
T t;
|
||||
};
|
||||
template <>
|
||||
struct proc_result_t<void> : public detail::proc_result_base_t {
|
||||
template <typename Proc>
|
||||
void extract_val(Proc& p)
|
||||
{
|
||||
set_val();
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_future_t
|
||||
* Contains a pointer to the result of a procedure run. This pointer gets updated with
|
||||
* the actual result once the procedure completes.
|
||||
**************************************************************************************/
|
||||
template <typename ResultType>
|
||||
class proc_future_t
|
||||
{
|
||||
public:
|
||||
proc_future_t() = default;
|
||||
explicit proc_future_t(const std::shared_ptr<proc_result_t<ResultType> >& p_) : ptr(p_) {}
|
||||
bool is_error() const { return ptr->is_error(); }
|
||||
bool is_success() const { return ptr->is_success(); }
|
||||
bool is_complete() const { return ptr->is_complete(); }
|
||||
const ResultType* value() const { return is_success() ? ptr->value() : nullptr; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<proc_result_t<ResultType> > ptr;
|
||||
};
|
||||
using proc_future_state_t = proc_future_t<void>;
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_base_t
|
||||
* Provides a polymorphic interface for resumable procedures. This base can then be used
|
||||
* by a procedure manager container via the virtual method "proc_itf_t::run()".
|
||||
* With methods:
|
||||
* - run() - executes a procedure, returning true if the procedure is still running
|
||||
* or false, if it has completed
|
||||
* by a "proc_manager_list_t" via the virtual method "proc_base_t::run()".
|
||||
* With public methods:
|
||||
* - run() - executes proc_t<T>::step(), and updates procedure state.
|
||||
* - is_busy()/is_idle() - tells if procedure is currently running. Busy procedures
|
||||
* cannot be re-launched
|
||||
* - then() - called automatically when a procedure has finished. Useful for actions
|
||||
* upon procedure completion, like sending back a response or logging.
|
||||
* With protected methods:
|
||||
* - step() - method overriden by child class that will be called by run(). step()
|
||||
* executes a procedure "action" based on its current internal state,
|
||||
* and return a proc_outcome_t variable with possible values:
|
||||
|
@ -133,77 +211,88 @@ private:
|
|||
* recall step() again (probably the procedure state has changed)
|
||||
* - error - the procedure has finished unsuccessfully
|
||||
* - success - the procedure has completed successfully
|
||||
* - finally() - called automatically when a procedure has finished. Useful for actions
|
||||
* upon procedure completion, like sending back a response.
|
||||
* - set_proc_state() / is_#() - setter and getters for current procedure state
|
||||
************************************************************************************/
|
||||
class proc_manager_itf_t
|
||||
class proc_base_t
|
||||
{
|
||||
public:
|
||||
virtual bool run() = 0;
|
||||
virtual ~proc_manager_itf_t() = default;
|
||||
};
|
||||
virtual ~proc_base_t() = default;
|
||||
|
||||
template <typename T>
|
||||
struct proc_result_t;
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_manager_t<T>
|
||||
* Manages the lifetime, of a procedure T, including its alloc, launching,
|
||||
* and reset back to initial, uninit state once the procedure has been
|
||||
* completed and the user has extracted its results.
|
||||
* Every procedure starts in inactive state, and finishes with success or error.
|
||||
* Can only be re-launched when a procedure T becomes inactive.
|
||||
* It uses a unique_ptr<T> to allow the use of procedures that are forward declared.
|
||||
* It provides the following methods:
|
||||
* - run() - calls T::step() and update the procedure state.
|
||||
* - launch() - initializes the procedure T by calling T::init(...). Handles the case
|
||||
* of failed initialization, and forbids the initialization of procedures
|
||||
* that are already active.
|
||||
* - pop() - extracts the result of the procedure if it has finished, and sets
|
||||
* proc_t<T> back to inactive
|
||||
* - trigger_event(Event) - used for handling external events. The procedure T will
|
||||
* have to define a method "trigger_event(Event)" as well,
|
||||
* specifying how each event type should be handled.
|
||||
************************************************************************************/
|
||||
template <class T>
|
||||
class proc_t final : public proc_manager_itf_t
|
||||
{
|
||||
using complete_callback_list_t = callback_list_t<std::function<void(bool)> >;
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit proc_t(Args&&... args) : proc_impl_ptr(new T(std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
bool run() override
|
||||
//! common proc::run() interface. Returns true if procedure is still running
|
||||
bool run()
|
||||
{
|
||||
proc_outcome_t outcome = proc_outcome_t::repeat;
|
||||
while (is_running() and outcome == proc_outcome_t::repeat) {
|
||||
outcome = proc_impl_ptr->step();
|
||||
while (is_busy() and outcome == proc_outcome_t::repeat) {
|
||||
outcome = step();
|
||||
handle_outcome(outcome);
|
||||
}
|
||||
return is_running();
|
||||
return is_busy();
|
||||
}
|
||||
|
||||
void clear()
|
||||
//! interface to check if proc is still running
|
||||
bool is_busy() const { return proc_state == proc_status_t::on_going; }
|
||||
bool is_idle() const { return proc_state == proc_status_t::idle; }
|
||||
|
||||
protected:
|
||||
enum class proc_status_t { idle, on_going };
|
||||
virtual proc_outcome_t step() = 0;
|
||||
virtual void run_then(bool is_success) = 0;
|
||||
|
||||
void handle_outcome(proc_outcome_t outcome)
|
||||
{
|
||||
// resets procedure and sets proc_t back to inactive
|
||||
detail::optional_clear(proc_impl_ptr.get());
|
||||
proc_state = proc_state_t::inactive;
|
||||
if (outcome == proc_outcome_t::error or outcome == proc_outcome_t::success) {
|
||||
bool success = outcome == proc_outcome_t::success;
|
||||
run_then(success);
|
||||
}
|
||||
}
|
||||
|
||||
const T* get() const { return proc_impl_ptr.get(); }
|
||||
bool is_active() const { return proc_state != proc_state_t::inactive; }
|
||||
bool is_complete() const { return proc_state == proc_state_t::success or proc_state == proc_state_t::error; }
|
||||
T* release() { return proc_impl_ptr.release(); }
|
||||
proc_status_t proc_state = proc_status_t::idle;
|
||||
};
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_t<T, ResultType>
|
||||
* Manages the lifetime of a procedure of type T, including its alloc, launching,
|
||||
* and reset back to "inactive" state once the procedure has been completed.
|
||||
* The result of a procedure run is of type "proc_result_t<ResultType>". ResultType has
|
||||
* to coincide with the type returned by the method "T::get_result()".
|
||||
* There are three main ways to use the result of a procedure run:
|
||||
* - "T::then(const proc_result_t<T>&)" - method in T that runs on completion, and
|
||||
* gets as argument the result of the run
|
||||
* - "proc_t<T>::get_future()" - returns a proc_future_t<T> which the user can use
|
||||
* directly to check the result of a run
|
||||
* - "proc_t<T>::then/then_always()" - provide dynamically a continuation task, for
|
||||
* instance, by providing a lambda
|
||||
* It uses a unique_ptr<T> to allow the use of procedures that are forward declared.
|
||||
************************************************************************************/
|
||||
|
||||
// Implementation of the Procedure Manager functionality, including launching, trigger events, clearing
|
||||
template <class T, typename ResultType = void>
|
||||
class proc_t : public proc_base_t
|
||||
{
|
||||
public:
|
||||
// cannot derive automatically this type
|
||||
using result_type = ResultType;
|
||||
using proc_result_type = proc_result_t<result_type>;
|
||||
using proc_future_type = proc_future_t<result_type>;
|
||||
using then_callback_list_t = callback_group_t<proc_result_type>;
|
||||
using callback_t = typename then_callback_list_t::callback_t;
|
||||
using callback_id_t = typename then_callback_list_t::callback_id_t;
|
||||
|
||||
template <typename... Args>
|
||||
explicit proc_t(Args&&... args) : proc_ptr(new T(std::forward<Args>(args)...))
|
||||
{
|
||||
static_assert(std::is_same<result_type, decltype(detail::get_result_type(std::declval<T>()))>::value,
|
||||
"The types \"proc_t::result_type\" and the return of T::get_result() have to match");
|
||||
}
|
||||
|
||||
const T* get() const { return proc_ptr.get(); }
|
||||
T* release() { return proc_ptr.release(); }
|
||||
|
||||
//! method to handle external events. "T" must have the method "T::react(const Event&)" for the trigger to take effect
|
||||
template <class Event>
|
||||
void trigger_event(Event&& e)
|
||||
void trigger(Event&& e)
|
||||
{
|
||||
if (is_running()) {
|
||||
proc_outcome_t outcome = proc_impl_ptr->trigger_event(std::forward<Event>(e));
|
||||
if (is_busy()) {
|
||||
proc_outcome_t outcome = proc_ptr->react(std::forward<Event>(e));
|
||||
handle_outcome(outcome);
|
||||
if (outcome == proc_outcome_t::repeat) {
|
||||
run();
|
||||
|
@ -211,87 +300,106 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//! returns an object which the user can use to check if the procedure has ended.
|
||||
proc_future_type get_future()
|
||||
{
|
||||
if (future_result == nullptr) {
|
||||
future_result = std::make_shared<proc_result_type>(proc_result);
|
||||
}
|
||||
return proc_future_type{future_result};
|
||||
}
|
||||
|
||||
//! methods to schedule continuation tasks
|
||||
callback_id_t then(const callback_t& c) { return complete_callbacks.on_next_call(c); }
|
||||
callback_id_t then_always(const callback_t& c) { return complete_callbacks.on_every_call(c); }
|
||||
|
||||
//! launch a procedure, returning true if successful or running and false if it error or it failed to launch
|
||||
template <class... Args>
|
||||
bool launch(Args&&... args)
|
||||
{
|
||||
if (is_active()) {
|
||||
// if already active
|
||||
if (is_busy()) {
|
||||
return false;
|
||||
}
|
||||
proc_state = proc_state_t::on_going;
|
||||
proc_outcome_t init_ret = proc_impl_ptr->init(std::forward<Args>(args)...);
|
||||
proc_state = proc_base_t::proc_status_t::on_going;
|
||||
proc_outcome_t init_ret = proc_ptr->init(std::forward<Args>(args)...);
|
||||
handle_outcome(init_ret);
|
||||
switch (init_ret) {
|
||||
case proc_outcome_t::error:
|
||||
handle_outcome(init_ret);
|
||||
clear();
|
||||
return false;
|
||||
case proc_outcome_t::success:
|
||||
handle_outcome(init_ret);
|
||||
// does not reset, and returns true
|
||||
break;
|
||||
case proc_outcome_t::repeat:
|
||||
run(); // call run right away
|
||||
break;
|
||||
case proc_outcome_t::yield:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
proc_result_t<T> pop();
|
||||
|
||||
// on_complete interface
|
||||
complete_callback_list_t::id_type then(const complete_callback_list_t::callback_t& c)
|
||||
{
|
||||
return complete_callbacks.call_once(c);
|
||||
}
|
||||
complete_callback_list_t::id_type then_always(const complete_callback_list_t::callback_t& c)
|
||||
{
|
||||
return complete_callbacks.call_always(c);
|
||||
}
|
||||
|
||||
protected:
|
||||
friend proc_result_t<T>;
|
||||
bool is_running() const { return proc_state == proc_state_t::on_going; }
|
||||
void handle_outcome(proc_outcome_t outcome)
|
||||
proc_outcome_t step() final { return proc_ptr->step(); }
|
||||
|
||||
void run_then(bool is_success) final
|
||||
{
|
||||
if (outcome == proc_outcome_t::error or outcome == proc_outcome_t::success) {
|
||||
bool success = outcome == proc_outcome_t::success;
|
||||
proc_state = success ? proc_state_t::success : proc_state_t::error;
|
||||
detail::optional_complete(proc_impl_ptr.get(), success);
|
||||
complete_callbacks.run(success);
|
||||
// update result state
|
||||
if (is_success) {
|
||||
proc_result.extract_val(*proc_ptr);
|
||||
} else {
|
||||
proc_result.set_error();
|
||||
}
|
||||
// call T::then() if it exists
|
||||
detail::optional_then(proc_ptr.get(), proc_result);
|
||||
// signal continuations
|
||||
complete_callbacks(proc_result);
|
||||
// propagate proc_result to future if it exists, and release future
|
||||
if (future_result != nullptr) {
|
||||
*future_result = proc_result;
|
||||
future_result.reset();
|
||||
}
|
||||
// reset the current result, to prepare it for a new run.
|
||||
proc_result.clear();
|
||||
// back to inactive
|
||||
detail::optional_clear(proc_ptr.get());
|
||||
proc_state = proc_status_t::idle;
|
||||
}
|
||||
|
||||
proc_state_t proc_state = proc_state_t::inactive;
|
||||
std::unique_ptr<T> proc_impl_ptr;
|
||||
complete_callback_list_t complete_callbacks;
|
||||
std::unique_ptr<T> proc_ptr;
|
||||
proc_result_type proc_result;
|
||||
std::shared_ptr<proc_result_type> future_result; //! used if get_future() itf is used.
|
||||
then_callback_list_t complete_callbacks;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct proc_result_t {
|
||||
explicit proc_result_t(proc_t<T>* parent_) : parent(parent_) {}
|
||||
~proc_result_t()
|
||||
/**************************************************************************************
|
||||
* class: event_handler_t<Args...>
|
||||
* Bundles several proc_managers together with same trigger(Args...) itf.
|
||||
* Once trigger(...) is called, all registered proc_managers get triggered
|
||||
* as well.
|
||||
************************************************************************************/
|
||||
// NOTE: Potential improvements: a method "trigger_during_this_run" that unregisters the handler
|
||||
// once the procedure run is finished.
|
||||
template <typename EventType>
|
||||
class event_handler_t
|
||||
{
|
||||
if (parent->is_complete()) {
|
||||
parent->clear();
|
||||
public:
|
||||
using callback_id_t = typename callback_group_t<EventType>::callback_id_t;
|
||||
|
||||
template <typename Proc, typename ResultType>
|
||||
callback_id_t on_next_trigger(proc_t<Proc, ResultType>& p)
|
||||
{
|
||||
return callbacks.on_next_call([&p](EventType&& ev) { p.trigger(std::forward<EventType>(ev)); });
|
||||
}
|
||||
|
||||
template <typename Proc, typename ResultType>
|
||||
callback_id_t on_every_trigger(proc_t<Proc, ResultType>& p)
|
||||
{
|
||||
return callbacks.on_every_call([&p](EventType&& ev) { p.trigger(std::forward<EventType>(ev)); });
|
||||
}
|
||||
const T* proc() const { return parent->is_complete() ? parent->proc_impl_ptr.get() : nullptr; }
|
||||
bool is_success() const { return parent->proc_state == proc_state_t::success; }
|
||||
bool is_error() const { return parent->proc_state == proc_state_t::error; }
|
||||
bool is_complete() const { return parent->is_complete(); }
|
||||
|
||||
void trigger(EventType&& ev) { callbacks(std::forward<EventType>(ev)); }
|
||||
|
||||
private:
|
||||
proc_t<T>* parent;
|
||||
callback_group_t<EventType> callbacks;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
proc_result_t<T> proc_t<T>::pop()
|
||||
{
|
||||
return proc_result_t<T>{this};
|
||||
}
|
||||
|
||||
/**************************************************************************************
|
||||
* class: func_proc_t
|
||||
* A proc used to store lambda functions and other function pointers as a step()
|
||||
|
@ -308,106 +416,52 @@ private:
|
|||
std::function<proc_outcome_t()> step_func;
|
||||
};
|
||||
|
||||
/**************************************************************************************
|
||||
* class: query_proc_t
|
||||
* A helper proc_impl_t whose step()/finally() are no op, but has a trigger_event() that
|
||||
* signals that the method has finished and store a result of type OutcomeType.
|
||||
************************************************************************************/
|
||||
template <class OutcomeType>
|
||||
class query_proc_t
|
||||
{
|
||||
public:
|
||||
proc_outcome_t init() { return proc_outcome_t::yield; }
|
||||
proc_outcome_t step() { return proc_outcome_t::yield; }
|
||||
|
||||
proc_outcome_t trigger_event(const OutcomeType& outcome_)
|
||||
{
|
||||
outcome = outcome_;
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
|
||||
const OutcomeType& result() const { return outcome; }
|
||||
|
||||
private:
|
||||
OutcomeType outcome;
|
||||
};
|
||||
|
||||
/**************************************************************************************
|
||||
* class: proc_manager_list_t
|
||||
* Stores procedure managers and, when run() is called, calls sequentially all
|
||||
* the stored procedures run() method, and removes the procedures if they have
|
||||
* completed.
|
||||
* There are different ways to add a procedure to the list:
|
||||
* already completed.
|
||||
* There are two ways to add a procedure to the list:
|
||||
* - add_proc(...) - adds a proc_t<T>, and once the procedure has completed, takes it
|
||||
* out of the container without resetting it back to its initial state
|
||||
* or deleting. This is useful, if the user wants to extract the
|
||||
* procedure result after it has been taken off the manager list.
|
||||
* "proc" variable has to outlive its completion
|
||||
* - consume_proc(...) - receives a proc_t<T> as a rvalue, and calls the proc_t<T>
|
||||
* destructor once the procedure has ended. Useful, for procedures
|
||||
* for which the user is not interested in the result, or reusing
|
||||
* - defer_proc(...) - same as add_proc(...), but once the procedure has finished, it
|
||||
* automatically sets the procedure back to its initial state.
|
||||
* Useful if the user is not interested in handling the result
|
||||
* - defer_task(...) - same as consume_proc(...) but takes a function pointer that
|
||||
* out of the container. In case a r-value ref is passed, this class
|
||||
* calls its destructor.
|
||||
* - add_task(...) - same as add_proc(...) but takes a function pointer that
|
||||
* specifies a proc_impl_t step() function
|
||||
************************************************************************************/
|
||||
class proc_manager_list_t
|
||||
{
|
||||
using proc_deleter_t = std::function<void(proc_manager_itf_t*)>;
|
||||
using proc_obj_t = std::unique_ptr<proc_manager_itf_t, proc_deleter_t>;
|
||||
|
||||
template <typename T>
|
||||
struct recycle_deleter_t {
|
||||
void operator()(proc_manager_itf_t* p)
|
||||
{
|
||||
if (p != nullptr) {
|
||||
T* Tp = static_cast<T*>(p);
|
||||
Tp->clear();
|
||||
// just resets back to inactive, and does not dealloc
|
||||
}
|
||||
}
|
||||
};
|
||||
using proc_deleter_t = std::function<void(proc_base_t*)>;
|
||||
using proc_obj_t = std::unique_ptr<proc_base_t, proc_deleter_t>;
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
void add_proc(proc_t<T>& proc)
|
||||
template <typename T, typename ResultType>
|
||||
void add_proc(proc_t<T, ResultType>& proc)
|
||||
{
|
||||
if (proc.is_complete()) {
|
||||
if (proc.is_idle()) {
|
||||
return;
|
||||
}
|
||||
proc_obj_t ptr(&proc, [](proc_manager_itf_t* p) { /* do nothing */ });
|
||||
proc_obj_t ptr(&proc, [](proc_base_t* p) { /* do nothing */ });
|
||||
proc_list.push_back(std::move(ptr));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void consume_proc(proc_t<T>&& proc)
|
||||
// since it receives a r-value, it calls the default destructor
|
||||
template <class T, typename ResultType>
|
||||
void add_proc(proc_t<T, ResultType>&& proc)
|
||||
{
|
||||
if (proc.is_complete()) {
|
||||
if (proc.is_idle()) {
|
||||
return;
|
||||
}
|
||||
proc_obj_t ptr(new proc_t<T>(std::move(proc)), std::default_delete<proc_manager_itf_t>());
|
||||
proc_obj_t ptr(new proc_t<T, ResultType>(std::move(proc)), std::default_delete<proc_base_t>());
|
||||
proc_list.push_back(std::move(ptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void defer_proc(proc_t<T>& proc)
|
||||
{
|
||||
if (proc.is_complete()) {
|
||||
proc.clear();
|
||||
return;
|
||||
}
|
||||
proc_obj_t ptr(&proc, recycle_deleter_t<proc_t<T> >());
|
||||
proc_list.push_back(std::move(ptr));
|
||||
}
|
||||
|
||||
bool defer_task(std::function<proc_outcome_t()> step_func)
|
||||
bool add_task(std::function<proc_outcome_t()> step_func)
|
||||
{
|
||||
proc_t<func_proc_t> proc(std::move(step_func));
|
||||
if (not proc.launch()) {
|
||||
return false;
|
||||
}
|
||||
consume_proc(std::move(proc));
|
||||
add_proc(std::move(proc));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,14 +196,15 @@ public:
|
|||
typedef enum { BARRING_NONE = 0, BARRING_MO_DATA, BARRING_MO_SIGNALLING, BARRING_MT, BARRING_ALL } barring_t;
|
||||
virtual void left_rrc_connected() = 0;
|
||||
virtual void set_barring(barring_t barring) = 0;
|
||||
virtual void paging(srslte::s_tmsi_t* ue_identity) = 0;
|
||||
virtual bool paging(srslte::s_tmsi_t* ue_identity) = 0;
|
||||
virtual bool is_attached() = 0;
|
||||
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||
virtual uint32_t get_k_enb_count() = 0;
|
||||
virtual bool get_k_asme(uint8_t* k_asme_, uint32_t n) = 0;
|
||||
virtual uint32_t get_ipv4_addr() = 0;
|
||||
virtual bool get_ipv6_addr(uint8_t* ipv6_addr) = 0;
|
||||
virtual void plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
virtual void
|
||||
plmn_search_completed(const rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
int nof_plmns) = 0;
|
||||
virtual bool connection_request_completed(bool outcome) = 0;
|
||||
virtual void run_tti(uint32_t tti) = 0;
|
||||
|
@ -213,7 +214,7 @@ public:
|
|||
class nas_interface_ue
|
||||
{
|
||||
public:
|
||||
virtual void start_attach_request(srslte::proc_state_t* proc_result, srslte::establishment_cause_t cause_) = 0;
|
||||
virtual void start_attach_request(srslte::proc_result_t<void>* proc_result, srslte::establishment_cause_t cause_) = 0;
|
||||
virtual bool detach_request(const bool switch_off) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
printf("TestObj copy ctor called: {%s,%d} <- {%s,%d}!!!\n", to_string(state), id, to_string(other.state), other.id);
|
||||
id = other.id;
|
||||
state = obj_state_t::copy_ctor;
|
||||
counters = other.counters;
|
||||
copy_counter++;
|
||||
}
|
||||
TestObj(TestObj&& other) noexcept
|
||||
|
@ -67,6 +68,7 @@ public:
|
|||
printf("TestObj move ctor called: {%s,%d} <- {%s,%d}!!!\n", to_string(state), id, to_string(other.state), other.id);
|
||||
id = other.id;
|
||||
state = obj_state_t::move_ctor;
|
||||
counters = other.counters;
|
||||
other.state = obj_state_t::from_move_ctor;
|
||||
move_counter++;
|
||||
}
|
||||
|
@ -84,6 +86,7 @@ public:
|
|||
other.id);
|
||||
id = other.id;
|
||||
state = other.state;
|
||||
counters = other.counters;
|
||||
copy_counter++;
|
||||
return *this;
|
||||
}
|
||||
|
@ -97,6 +100,7 @@ public:
|
|||
if (&other != this) {
|
||||
id = other.id;
|
||||
state = other.state;
|
||||
counters = other.counters;
|
||||
other.state = obj_state_t::from_move_assign;
|
||||
move_counter++;
|
||||
}
|
||||
|
@ -105,6 +109,11 @@ public:
|
|||
|
||||
obj_state_t state = obj_state_t::default_ctor;
|
||||
int id = 0;
|
||||
struct stats_t {
|
||||
int then_counter = 0;
|
||||
int reset_counter = 0;
|
||||
};
|
||||
mutable stats_t counters;
|
||||
static int copy_counter;
|
||||
static int move_counter;
|
||||
static int dtor_counter;
|
||||
|
@ -133,7 +142,6 @@ public:
|
|||
return proc_outcome_t::error;
|
||||
}
|
||||
obj.id = a_;
|
||||
reset_called = false;
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
proc_outcome_t step()
|
||||
|
@ -143,13 +151,19 @@ public:
|
|||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
void on_complete(bool is_success) { printf("TestObj %d stop() was called\n", obj.id); }
|
||||
void then(const srslte::proc_result_t<int>& result) const
|
||||
{
|
||||
printf("TestObj %d then() was called\n", obj.id);
|
||||
obj.counters.then_counter++;
|
||||
}
|
||||
|
||||
const char* name() const { return "custom proc"; }
|
||||
void clear()
|
||||
{
|
||||
reset_called = true;
|
||||
printf("TestObj was reset\n");
|
||||
}
|
||||
int get_result() const { return obj.id; }
|
||||
|
||||
TestObj obj;
|
||||
const int ctor_value = 5;
|
||||
|
@ -165,54 +179,64 @@ public:
|
|||
proc_outcome_t init()
|
||||
{
|
||||
exit_val = "init";
|
||||
event_val = "";
|
||||
counter = 0;
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
proc_outcome_t step()
|
||||
{
|
||||
if (counter++ > 5) {
|
||||
exit_val = "success";
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
void on_complete(bool is_success)
|
||||
// trigger itf
|
||||
struct event_t {
|
||||
std::string event_val;
|
||||
};
|
||||
proc_outcome_t react(const event_t& event)
|
||||
{
|
||||
if (is_success) {
|
||||
exit_val = "success";
|
||||
} else {
|
||||
exit_val = "fail";
|
||||
}
|
||||
event_val = event.event_val;
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
std::string get_result() const { return exit_val; }
|
||||
|
||||
std::string exit_val = "";
|
||||
std::string event_val = "";
|
||||
int counter = 0;
|
||||
};
|
||||
|
||||
static_assert(std::is_same<typename srslte::proc_t<custom_proc, int>::result_type, int>::value,
|
||||
"Failed derivation of result type");
|
||||
static_assert(std::is_same<typename srslte::proc_t<custom_proc, std::string>::result_type, std::string>::value,
|
||||
"Failed derivation of result type");
|
||||
|
||||
int test_local_1()
|
||||
{
|
||||
/*
|
||||
* Description: Test if a procedure is cleaned automatically after is lifetime has ended
|
||||
*/
|
||||
new_test();
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_t<custom_proc> proc;
|
||||
TESTASSERT(not proc.is_active());
|
||||
srslte::proc_t<custom_proc, int> proc;
|
||||
TESTASSERT(proc.is_idle() and not proc.is_busy())
|
||||
|
||||
proc.launch(1);
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
TESTASSERT(not proc.get()->reset_called);
|
||||
TESTASSERT(not proc.is_idle() and proc.is_busy())
|
||||
TESTASSERT(not proc.get()->reset_called)
|
||||
|
||||
while (proc.run()) {
|
||||
}
|
||||
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(proc.is_complete());
|
||||
TESTASSERT(proc.is_idle() and not proc.is_busy())
|
||||
TESTASSERT(proc.get()->obj.counters.then_counter == 1)
|
||||
TESTASSERT(proc.get()->reset_called) // Proc is ready to be reused
|
||||
|
||||
const custom_proc& procobj = *proc.get();
|
||||
TESTASSERT(procobj.obj.id == 1);
|
||||
TESTASSERT(proc.is_active());
|
||||
printf("clear() being called\n");
|
||||
proc.clear();
|
||||
TESTASSERT(not proc.is_active());
|
||||
TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused
|
||||
TESTASSERT(proc.get()->ctor_value == 5);
|
||||
TESTASSERT(procobj.obj.id == 1)
|
||||
TESTASSERT(not proc.is_busy() and proc.is_idle())
|
||||
TESTASSERT(proc.get()->ctor_value == 5)
|
||||
|
||||
printf("EXIT\n");
|
||||
TESTASSERT(TestObj::copy_counter == 0);
|
||||
|
@ -225,38 +249,34 @@ int test_callback_1()
|
|||
{
|
||||
/*
|
||||
* Description: Test a procedure inserted in a manager list via "proc_manager_list_t::add_proc(...)"
|
||||
* - check if the proc is not cleared automatically after it finished (need to check the result)
|
||||
* - check if pop() works as expected, and resets proc after proc_result_t<T> goes out of scope
|
||||
* - check if the proc is cleared automatically after it finished
|
||||
* - check if the proc_future value is correctly updated
|
||||
* - check if creating a new future does not affect previous one
|
||||
*/
|
||||
new_test();
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<custom_proc> proc;
|
||||
TESTASSERT(not proc.is_active());
|
||||
srslte::proc_t<custom_proc, int> proc;
|
||||
TESTASSERT(not proc.is_busy() and proc.is_idle())
|
||||
|
||||
TESTASSERT(proc.launch(2));
|
||||
TESTASSERT(proc.launch(2))
|
||||
callbacks.add_proc(proc); // We have to call pop() explicitly to take the result
|
||||
TESTASSERT(callbacks.size() == 1);
|
||||
TESTASSERT(callbacks.size() == 1)
|
||||
srslte::proc_future_t<int> proc_fut = proc.get_future();
|
||||
|
||||
while (callbacks.size() > 0) {
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
TESTASSERT(not proc_fut.is_complete())
|
||||
TESTASSERT(proc.is_busy())
|
||||
callbacks.run();
|
||||
}
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(proc.is_complete());
|
||||
TESTASSERT(proc.is_idle());
|
||||
TESTASSERT(proc_fut.is_success() and *proc_fut.value() == 2)
|
||||
TESTASSERT(proc.get()->obj.id == 2)
|
||||
TESTASSERT(proc.get()->obj.counters.then_counter == 1)
|
||||
TESTASSERT(proc.get()->reset_called) // Proc is ready to be reused
|
||||
|
||||
TESTASSERT(proc.get()->obj.id == 2);
|
||||
TESTASSERT(proc.is_active());
|
||||
{
|
||||
printf("pop being called\n");
|
||||
srslte::proc_result_t<custom_proc> ret = proc.pop();
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(ret.is_success());
|
||||
// proc::reset() is finally called
|
||||
}
|
||||
TESTASSERT(not proc.is_active());
|
||||
TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused
|
||||
srslte::proc_future_t<int> proc_fut2 = proc.get_future();
|
||||
TESTASSERT(not proc_fut2.is_complete() and proc_fut.is_complete())
|
||||
|
||||
printf("EXIT\n");
|
||||
TESTASSERT(TestObj::copy_counter == 0);
|
||||
|
@ -268,25 +288,25 @@ int test_callback_1()
|
|||
int test_callback_2()
|
||||
{
|
||||
/*
|
||||
* Description: Test a procedure inserted in a manager list via "proc_manager_list_t::consume_proc(...)"
|
||||
* Description: Test a procedure inserted in a manager list as an r-value
|
||||
* - check if the proc disappears automatically after it finished
|
||||
*/
|
||||
new_test();
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<custom_proc> proc;
|
||||
TESTASSERT(not proc.is_active());
|
||||
srslte::proc_t<custom_proc, int> proc;
|
||||
TESTASSERT(not proc.is_busy());
|
||||
srslte::proc_future_t<int> fut = proc.get_future();
|
||||
|
||||
TESTASSERT(proc.launch(3));
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
callbacks.consume_proc(std::move(proc));
|
||||
TESTASSERT(proc.is_busy());
|
||||
callbacks.add_proc(std::move(proc));
|
||||
TESTASSERT(callbacks.size() == 1);
|
||||
|
||||
while (callbacks.size() > 0) {
|
||||
callbacks.run();
|
||||
}
|
||||
// since the proc was consumed, it is erased without the need for pop()
|
||||
TESTASSERT(fut.is_success() and *fut.value() == 3)
|
||||
|
||||
printf("EXIT\n");
|
||||
TESTASSERT(TestObj::copy_counter == 0);
|
||||
|
@ -296,42 +316,6 @@ int test_callback_2()
|
|||
}
|
||||
|
||||
int test_callback_3()
|
||||
{
|
||||
/*
|
||||
* Description: Test a procedure inserted in a manager list via "proc_manager_list_t::defer_proc(...)"
|
||||
* - check if the proc is cleared automatically after it finished
|
||||
*/
|
||||
new_test();
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<custom_proc> proc;
|
||||
TESTASSERT(not proc.is_active());
|
||||
|
||||
proc.launch(4);
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
callbacks.defer_proc(proc); // we still have access to proc, but we do not need to call pop()
|
||||
TESTASSERT(callbacks.size() == 1);
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
|
||||
while (callbacks.size() > 0) {
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
callbacks.run();
|
||||
}
|
||||
TESTASSERT(not proc.is_active());
|
||||
TESTASSERT(not proc.is_complete());
|
||||
TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused
|
||||
|
||||
printf("EXIT\n");
|
||||
TESTASSERT(TestObj::copy_counter == 0);
|
||||
TESTASSERT(TestObj::move_counter == 0);
|
||||
TESTASSERT(TestObj::dtor_counter == 0); // handler not yet destructed
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_callback_4()
|
||||
{
|
||||
/*
|
||||
* Description: Test for Lambda procedure types
|
||||
|
@ -344,7 +328,7 @@ int test_callback_4()
|
|||
int* counter = new int(5);
|
||||
|
||||
{
|
||||
callbacks.defer_task([counter]() {
|
||||
callbacks.add_task([counter]() {
|
||||
printf("current counter=%d\n", *counter);
|
||||
if (--(*counter) == 0) {
|
||||
return proc_outcome_t::success;
|
||||
|
@ -357,14 +341,13 @@ int test_callback_4()
|
|||
callbacks.run();
|
||||
}
|
||||
|
||||
// printf("counter=%d\n", counter);
|
||||
TESTASSERT(*counter == 0);
|
||||
delete counter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_callback_5()
|
||||
int test_callback_4()
|
||||
{
|
||||
/*
|
||||
* Description: Test if finished procedure does not get added to the dispatch list
|
||||
|
@ -372,15 +355,15 @@ int test_callback_5()
|
|||
new_test();
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<custom_proc> proc;
|
||||
srslte::proc_t<custom_proc, int> proc;
|
||||
TESTASSERT(proc.launch(5));
|
||||
while (proc.run()) {
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(proc.is_busy());
|
||||
}
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(not proc.get()->reset_called);
|
||||
TESTASSERT(proc.is_complete());
|
||||
callbacks.defer_proc(proc);
|
||||
TESTASSERT(proc.is_idle());
|
||||
TESTASSERT(proc.get()->obj.counters.then_counter == 1)
|
||||
TESTASSERT(proc.get()->reset_called);
|
||||
callbacks.add_proc(proc);
|
||||
TESTASSERT(callbacks.size() == 0); // do not add finished callbacks
|
||||
|
||||
return 0;
|
||||
|
@ -389,47 +372,79 @@ int test_callback_5()
|
|||
int test_complete_callback_1()
|
||||
{
|
||||
/*
|
||||
* Description: Test if on_complete() callbacks are correctly called
|
||||
* Description: Test if then() callbacks are correctly called
|
||||
*/
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<custom_proc2_t> proc;
|
||||
srslte::proc_t<custom_proc2_t, std::string> proc;
|
||||
|
||||
std::string run_result;
|
||||
auto continuation_task = [&run_result](bool is_success) { run_result = is_success ? "SUCCESS" : "FAILURE"; };
|
||||
std::string results[] = {"", "SUCCESS", "", "SUCCESS", "SUCCESS", "SUCCESS"};
|
||||
auto continuation_task = [&run_result](const srslte::proc_result_t<std::string>& e) {
|
||||
run_result = e.is_success() ? "SUCCESS" : "FAILURE";
|
||||
};
|
||||
const std::string results[] = {"", "SUCCESS", "", "SUCCESS", "SUCCESS", "SUCCESS"};
|
||||
for (uint32_t i = 0; i < 6; ++i) {
|
||||
run_result = "";
|
||||
if (i == 1) {
|
||||
TESTASSERT(proc.then(continuation_task) == 0);
|
||||
TESTASSERT(proc.then(continuation_task) == 0)
|
||||
} else if (i == 3) {
|
||||
TESTASSERT(proc.then_always(continuation_task) == 0);
|
||||
TESTASSERT(proc.then_always(continuation_task) == 0)
|
||||
}
|
||||
|
||||
srslte::proc_future_t<std::string> fut = proc.get_future();
|
||||
TESTASSERT(proc.launch());
|
||||
TESTASSERT(proc.get()->exit_val == "init");
|
||||
TESTASSERT(proc.get()->exit_val == "init")
|
||||
while (proc.run()) {
|
||||
TESTASSERT(proc.get()->exit_val == "init");
|
||||
TESTASSERT(proc.is_active());
|
||||
TESTASSERT(proc.get()->exit_val == "init")
|
||||
TESTASSERT(proc.is_busy())
|
||||
}
|
||||
TESTASSERT(proc.is_active() and proc.is_complete());
|
||||
srslte::proc_result_t<custom_proc2_t> ret = proc.pop();
|
||||
TESTASSERT(ret.is_success() and ret.proc()->exit_val == "success");
|
||||
TESTASSERT(proc.is_idle() and proc.get()->exit_val == "success")
|
||||
TESTASSERT(fut.is_success() and *fut.value() == "success")
|
||||
|
||||
TESTASSERT(run_result == results[i]);
|
||||
TESTASSERT(run_result == results[i])
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_event_handler_1()
|
||||
{
|
||||
/*
|
||||
* Description: Test if event handler calls trigger for multiple procedures
|
||||
*/
|
||||
printf("\n--- Test %s ---\n", __func__);
|
||||
srslte::proc_t<custom_proc2_t, std::string> proc, proc2;
|
||||
srslte::event_handler_t<custom_proc2_t::event_t> ev_handler;
|
||||
|
||||
TESTASSERT(proc.launch())
|
||||
TESTASSERT(proc2.launch())
|
||||
TESTASSERT(proc.is_busy() and proc2.is_busy())
|
||||
TESTASSERT(proc.get()->exit_val == "init" and proc2.get()->exit_val == "init")
|
||||
TESTASSERT(proc.get()->event_val.empty() and proc2.get()->event_val.empty())
|
||||
|
||||
ev_handler.on_next_trigger(proc);
|
||||
ev_handler.on_every_trigger(proc2);
|
||||
|
||||
ev_handler.trigger(custom_proc2_t::event_t{"event1"});
|
||||
TESTASSERT(proc.get()->event_val == "event1" and proc.get()->event_val == "event1")
|
||||
ev_handler.trigger(custom_proc2_t::event_t{"event2"});
|
||||
TESTASSERT(proc.get()->event_val == "event1" and proc2.get()->event_val == "event2")
|
||||
|
||||
printf("Procedures correctly triggered by event handler\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(test_local_1() == 0);
|
||||
TESTASSERT(test_callback_1() == 0);
|
||||
TESTASSERT(test_callback_2() == 0);
|
||||
TESTASSERT(test_callback_3() == 0);
|
||||
TESTASSERT(test_callback_4() == 0);
|
||||
TESTASSERT(test_callback_5() == 0);
|
||||
TESTASSERT(test_complete_callback_1() == 0);
|
||||
TESTASSERT(test_local_1() == 0)
|
||||
TESTASSERT(test_callback_1() == 0)
|
||||
TESTASSERT(test_callback_2() == 0)
|
||||
TESTASSERT(test_callback_3() == 0)
|
||||
TESTASSERT(test_callback_4() == 0)
|
||||
TESTASSERT(test_complete_callback_1() == 0)
|
||||
TESTASSERT(test_event_handler_1() == 0)
|
||||
|
||||
std::cout << "\n---------------\nResult: Success\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -624,10 +624,10 @@ private:
|
|||
class process_pcch_proc;
|
||||
class go_idle_proc;
|
||||
class cell_reselection_proc;
|
||||
srslte::proc_t<cell_search_proc> cell_searcher;
|
||||
srslte::proc_t<cell_search_proc, phy_interface_rrc_lte::cell_search_ret_t> cell_searcher;
|
||||
srslte::proc_t<si_acquire_proc> si_acquirer;
|
||||
srslte::proc_t<serving_cell_config_proc> serv_cell_cfg;
|
||||
srslte::proc_t<cell_selection_proc> cell_selector;
|
||||
srslte::proc_t<cell_selection_proc, cs_result_t> cell_selector;
|
||||
srslte::proc_t<go_idle_proc> idle_setter;
|
||||
srslte::proc_t<process_pcch_proc> pcch_processor;
|
||||
srslte::proc_t<connection_request_proc> conn_req_proc;
|
||||
|
|
|
@ -41,9 +41,9 @@ public:
|
|||
explicit cell_search_proc(rrc* parent_);
|
||||
srslte::proc_outcome_t init();
|
||||
srslte::proc_outcome_t step();
|
||||
srslte::proc_outcome_t trigger_event(const cell_search_event_t& event);
|
||||
srslte::proc_outcome_t react(const cell_search_event_t& event);
|
||||
|
||||
phy_interface_rrc_lte::cell_search_ret_t get_cs_ret() const { return search_result.cs_ret; }
|
||||
phy_interface_rrc_lte::cell_search_ret_t get_result() const { return search_result.cs_ret; }
|
||||
static const char* name() { return "Cell Search"; }
|
||||
|
||||
private:
|
||||
|
@ -51,10 +51,10 @@ private:
|
|||
|
||||
// conts
|
||||
rrc* rrc_ptr;
|
||||
srslte::log* log_h;
|
||||
|
||||
// state vars
|
||||
cell_search_event_t search_result;
|
||||
srslte::proc_future_t<void> si_acquire_fut;
|
||||
state_t state;
|
||||
};
|
||||
|
||||
|
@ -100,16 +100,19 @@ private:
|
|||
// state variables
|
||||
enum class search_state_t { next_sib, si_acquire } search_state;
|
||||
uint32_t req_idx = 0;
|
||||
srslte::proc_future_t<void> si_acquire_fut;
|
||||
};
|
||||
|
||||
class rrc::cell_selection_proc
|
||||
{
|
||||
public:
|
||||
using cell_selection_complete_ev = srslte::proc_result_t<cs_result_t>;
|
||||
|
||||
explicit cell_selection_proc(rrc* parent_);
|
||||
srslte::proc_outcome_t init();
|
||||
srslte::proc_outcome_t step();
|
||||
void on_complete(bool is_success);
|
||||
cs_result_t get_cs_result() const { return cs_result; }
|
||||
void then(const srslte::proc_result_t<cs_result_t>& proc_result) const;
|
||||
cs_result_t get_result() const { return cs_result; }
|
||||
static const char* name() { return "Cell Selection"; }
|
||||
|
||||
private:
|
||||
|
@ -119,13 +122,14 @@ private:
|
|||
|
||||
// consts
|
||||
rrc* rrc_ptr;
|
||||
srslte::log* log_h;
|
||||
|
||||
// state variables
|
||||
enum class search_state_t { cell_selection, cell_config, cell_search };
|
||||
cs_result_t cs_result;
|
||||
search_state_t state;
|
||||
uint32_t neigh_index;
|
||||
srslte::proc_future_t<phy_interface_rrc_lte::cell_search_ret_t> cell_search_fut;
|
||||
srslte::proc_future_t<void> serv_cell_cfg_fut;
|
||||
};
|
||||
|
||||
class rrc::plmn_search_proc
|
||||
|
@ -134,7 +138,7 @@ public:
|
|||
explicit plmn_search_proc(rrc* parent_);
|
||||
srslte::proc_outcome_t init();
|
||||
srslte::proc_outcome_t step();
|
||||
void on_complete(bool is_success);
|
||||
void then(const srslte::proc_result_t<void>& result) const;
|
||||
static const char* name() { return "PLMN Search"; }
|
||||
|
||||
private:
|
||||
|
@ -145,22 +149,17 @@ private:
|
|||
// state variables
|
||||
found_plmn_t found_plmns[MAX_FOUND_PLMNS];
|
||||
int nof_plmns = 0;
|
||||
srslte::proc_future_t<phy_interface_rrc_lte::cell_search_ret_t> cell_search_fut;
|
||||
};
|
||||
|
||||
class rrc::connection_request_proc
|
||||
{
|
||||
public:
|
||||
struct cell_selection_complete {
|
||||
bool is_success;
|
||||
cs_result_t cs_result;
|
||||
};
|
||||
|
||||
explicit connection_request_proc(rrc* parent_);
|
||||
srslte::proc_outcome_t
|
||||
init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_);
|
||||
srslte::proc_outcome_t init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_);
|
||||
srslte::proc_outcome_t step();
|
||||
void on_complete(bool is_success);
|
||||
srslte::proc_outcome_t trigger_event(const cell_selection_complete& e);
|
||||
void then(const srslte::proc_result_t<void>& result);
|
||||
srslte::proc_outcome_t react(const cell_selection_proc::cell_selection_complete_ev& e);
|
||||
static const char* name() { return "Connection Request"; }
|
||||
|
||||
private:
|
||||
|
@ -174,6 +173,7 @@ private:
|
|||
// state variables
|
||||
enum class state_t { cell_selection, config_serving_cell, wait_t300 } state;
|
||||
cs_result_t cs_ret;
|
||||
srslte::proc_future_t<void> serv_cfg_fut;
|
||||
};
|
||||
|
||||
class rrc::process_pcch_proc
|
||||
|
@ -186,7 +186,7 @@ public:
|
|||
explicit process_pcch_proc(rrc* parent_);
|
||||
srslte::proc_outcome_t init(const asn1::rrc::paging_s& paging_);
|
||||
srslte::proc_outcome_t step();
|
||||
srslte::proc_outcome_t trigger_event(paging_complete e);
|
||||
srslte::proc_outcome_t react(paging_complete e);
|
||||
static const char* name() { return "Process PCCH"; }
|
||||
|
||||
private:
|
||||
|
@ -198,6 +198,7 @@ private:
|
|||
// vars
|
||||
uint32_t paging_idx = 0;
|
||||
enum class state_t { next_record, nas_paging, serv_cell_cfg } state;
|
||||
srslte::proc_future_t<void> serv_cfg_fut;
|
||||
};
|
||||
|
||||
class rrc::go_idle_proc
|
||||
|
@ -225,6 +226,8 @@ public:
|
|||
|
||||
private:
|
||||
rrc* rrc_ptr;
|
||||
|
||||
srslte::proc_future_t<cs_result_t> cell_selection_fut;
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
// RRC interface
|
||||
void left_rrc_connected();
|
||||
void paging(srslte::s_tmsi_t* ue_identity);
|
||||
bool paging(srslte::s_tmsi_t* ue_identity);
|
||||
void set_barring(barring_t barring);
|
||||
void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu);
|
||||
uint32_t get_k_enb_count();
|
||||
|
@ -60,13 +60,11 @@ public:
|
|||
bool get_ipv6_addr(uint8_t* ipv6_addr);
|
||||
|
||||
// UE interface
|
||||
void start_attach_request(srslte::proc_state_t* result, srslte::establishment_cause_t cause_) final;
|
||||
void start_attach_request(srslte::proc_result_t<void>* result, srslte::establishment_cause_t cause_) final;
|
||||
bool detach_request(const bool switch_off) final;
|
||||
|
||||
void plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
void plmn_search_completed(const rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
int nof_plmns) final;
|
||||
bool start_connection_request(srslte::establishment_cause_t establish_cause,
|
||||
srslte::unique_byte_buffer_t ded_info_nas);
|
||||
bool connection_request_completed(bool outcome) final;
|
||||
|
||||
// timer callback
|
||||
|
@ -261,6 +259,7 @@ private:
|
|||
class rrc_connect_proc
|
||||
{
|
||||
public:
|
||||
using rrc_connect_complete_ev = srslte::proc_result_t<void>;
|
||||
struct connection_request_completed_t {
|
||||
bool outcome;
|
||||
};
|
||||
|
@ -268,6 +267,8 @@ private:
|
|||
rrc_connect_proc(nas* nas_ptr_) : nas_ptr(nas_ptr_) {}
|
||||
srslte::proc_outcome_t init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu);
|
||||
srslte::proc_outcome_t step();
|
||||
void then(const srslte::proc_result_t<void>& result);
|
||||
srslte::proc_outcome_t react(connection_request_completed_t event);
|
||||
static const char* name() { return "RRC Connect"; }
|
||||
|
||||
private:
|
||||
|
@ -281,7 +282,7 @@ private:
|
|||
struct plmn_search_complete_t {
|
||||
rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS];
|
||||
int nof_plmns;
|
||||
plmn_search_complete_t(rrc_interface_nas::found_plmn_t* plmns_, int nof_plmns_) : nof_plmns(nof_plmns_)
|
||||
plmn_search_complete_t(const rrc_interface_nas::found_plmn_t* plmns_, int nof_plmns_) : nof_plmns(nof_plmns_)
|
||||
{
|
||||
if (nof_plmns > 0) {
|
||||
std::copy(&plmns_[0], &plmns_[nof_plmns], found_plmns);
|
||||
|
@ -292,7 +293,9 @@ private:
|
|||
plmn_search_proc(nas* nas_ptr_) : nas_ptr(nas_ptr_) {}
|
||||
srslte::proc_outcome_t init();
|
||||
srslte::proc_outcome_t step();
|
||||
srslte::proc_outcome_t trigger_event(const plmn_search_complete_t& t);
|
||||
void then(const srslte::proc_result_t<void>& result);
|
||||
srslte::proc_outcome_t react(const plmn_search_complete_t& t);
|
||||
srslte::proc_outcome_t react(const rrc_connect_proc::rrc_connect_complete_ev& t);
|
||||
static const char* name() { return "PLMN Search"; }
|
||||
|
||||
private:
|
||||
|
@ -302,7 +305,6 @@ private:
|
|||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<plmn_search_proc> plmn_searcher;
|
||||
srslte::proc_t<rrc_connect_proc> rrc_connector;
|
||||
srslte::proc_t<srslte::query_proc_t<bool> > conn_req_proc;
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -316,7 +316,7 @@ bool rrc::plmn_search()
|
|||
rrc_log->error("Unable to initiate PLMN search\n");
|
||||
return false;
|
||||
}
|
||||
callback_list.defer_proc(plmn_searcher);
|
||||
callback_list.add_proc(plmn_searcher);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ bool rrc::connection_request(srslte::establishment_cause_t cause, srslte::unique
|
|||
rrc_log->error("Failed to initiate connection request procedure\n");
|
||||
return false;
|
||||
}
|
||||
callback_list.defer_proc(conn_req_proc);
|
||||
callback_list.add_proc(conn_req_proc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1189,7 +1189,7 @@ bool rrc::con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig)
|
|||
|
||||
void rrc::start_ho()
|
||||
{
|
||||
callback_list.defer_task([this]() {
|
||||
callback_list.add_task([this]() {
|
||||
if (state != RRC_STATE_CONNECTED) {
|
||||
rrc_log->info("HO interrupted, since RRC is no longer in connected state\n");
|
||||
return srslte::proc_outcome_t::success;
|
||||
|
@ -1208,7 +1208,7 @@ void rrc::start_go_idle()
|
|||
rrc_log->info("Failed to set RRC to IDLE\n");
|
||||
return;
|
||||
}
|
||||
callback_list.defer_proc(idle_setter);
|
||||
callback_list.add_proc(idle_setter);
|
||||
}
|
||||
|
||||
// Handle RRC Reconfiguration without MobilityInformation Section 5.3.5.3
|
||||
|
@ -1478,7 +1478,7 @@ void rrc::start_cell_reselection()
|
|||
return;
|
||||
}
|
||||
|
||||
if (cell_reselector.is_active()) {
|
||||
if (cell_reselector.is_busy()) {
|
||||
// it is already running
|
||||
return;
|
||||
}
|
||||
|
@ -1492,7 +1492,7 @@ void rrc::start_cell_reselection()
|
|||
void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret,
|
||||
const phy_interface_rrc_lte::phy_cell_t& found_cell)
|
||||
{
|
||||
cell_searcher.trigger_event(cell_search_proc::cell_search_event_t{cs_ret, found_cell});
|
||||
cell_searcher.trigger(cell_search_proc::cell_search_event_t{cs_ret, found_cell});
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -1725,7 +1725,7 @@ void rrc::write_pdu_pcch(unique_byte_buffer_t pdu)
|
|||
|
||||
void rrc::paging_completed(bool outcome)
|
||||
{
|
||||
pcch_processor.trigger_event(process_pcch_proc::paging_complete{outcome});
|
||||
pcch_processor.trigger(process_pcch_proc::paging_complete{outcome});
|
||||
}
|
||||
|
||||
void rrc::process_pcch(unique_byte_buffer_t pdu)
|
||||
|
@ -1760,7 +1760,7 @@ void rrc::process_pcch(unique_byte_buffer_t pdu)
|
|||
}
|
||||
|
||||
// we do not care about the outcome
|
||||
callback_list.defer_proc(pcch_processor);
|
||||
callback_list.add_proc(pcch_processor);
|
||||
}
|
||||
|
||||
void rrc::write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
|
||||
|
|
|
@ -35,7 +35,7 @@ using srslte::proc_outcome_t;
|
|||
* Cell Search Procedure
|
||||
*************************************/
|
||||
|
||||
rrc::cell_search_proc::cell_search_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {}
|
||||
rrc::cell_search_proc::cell_search_proc(rrc* parent_) : rrc_ptr(parent_) {}
|
||||
|
||||
/* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet */
|
||||
proc_outcome_t rrc::cell_search_proc::init()
|
||||
|
@ -43,7 +43,7 @@ proc_outcome_t rrc::cell_search_proc::init()
|
|||
Info("Starting...\n");
|
||||
state = state_t::phy_cell_search;
|
||||
rrc_ptr->stack->start_cell_search();
|
||||
return proc_outcome_t::repeat;
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
/* Implements the SI acquisition procedure. Configures MAC/PHY scheduling to retrieve SI messages.*/
|
||||
|
@ -53,19 +53,16 @@ proc_outcome_t rrc::cell_search_proc::step()
|
|||
// Waits for cell search to complete
|
||||
return proc_outcome_t::yield;
|
||||
} else if (state == state_t::si_acquire) {
|
||||
if (not rrc_ptr->si_acquirer.run()) {
|
||||
if (rrc_ptr->si_acquirer.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
// SI Acquire has completed
|
||||
srslte::proc_result_t<si_acquire_proc> ret = rrc_ptr->si_acquirer.pop();
|
||||
if (ret.is_error()) {
|
||||
if (si_acquire_fut.is_error()) {
|
||||
Error("Failed to trigger SI acquire for SIB0\n");
|
||||
return proc_outcome_t::error;
|
||||
} else {
|
||||
// if(parent->serving_cell->has_sib(0)) {
|
||||
// }
|
||||
}
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
}
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
|
@ -82,7 +79,7 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
|
|||
rrc_ptr->set_serving_cell(new_cell);
|
||||
|
||||
if (not rrc_ptr->phy->cell_is_camping()) {
|
||||
log_h->warning("Could not camp on found cell.\n");
|
||||
Warning("Could not camp on found cell.\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
|
@ -97,6 +94,7 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
|
|||
Error("SI Acquire is already running...\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
si_acquire_fut = rrc_ptr->si_acquirer.get_future();
|
||||
|
||||
// instruct MAC to look for SIB1
|
||||
Info("Cell has no SIB1. Obtaining SIB1...\n");
|
||||
|
@ -104,7 +102,7 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
|
|||
return proc_outcome_t::repeat;
|
||||
}
|
||||
|
||||
proc_outcome_t rrc::cell_search_proc::trigger_event(const cell_search_event_t& event)
|
||||
proc_outcome_t rrc::cell_search_proc::react(const cell_search_event_t& event)
|
||||
{
|
||||
if (state != state_t::phy_cell_search) {
|
||||
Error("Received unexpected cell search result\n");
|
||||
|
@ -279,6 +277,7 @@ proc_outcome_t rrc::serving_cell_config_proc::step()
|
|||
Error("SI Acquire is already running...\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
si_acquire_fut = rrc_ptr->si_acquirer.get_future();
|
||||
search_state = search_state_t::si_acquire;
|
||||
return proc_outcome_t::repeat;
|
||||
} else {
|
||||
|
@ -301,10 +300,11 @@ proc_outcome_t rrc::serving_cell_config_proc::step()
|
|||
return proc_outcome_t::success;
|
||||
}
|
||||
} else if (search_state == search_state_t::si_acquire) {
|
||||
if (rrc_ptr->si_acquirer.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
uint32_t required_sib = required_sibs[req_idx];
|
||||
if (not rrc_ptr->si_acquirer.run()) {
|
||||
srslte::proc_result_t<si_acquire_proc> ret = rrc_ptr->si_acquirer.pop();
|
||||
if (ret.is_error() or not rrc_ptr->serving_cell->has_sib(required_sib)) {
|
||||
if (si_acquire_fut.is_error() or not rrc_ptr->serving_cell->has_sib(required_sib)) {
|
||||
if (required_sib < 2) {
|
||||
log_h->warning("Serving Cell Configuration has failed\n");
|
||||
return proc_outcome_t::error;
|
||||
|
@ -315,7 +315,6 @@ proc_outcome_t rrc::serving_cell_config_proc::step()
|
|||
req_idx++;
|
||||
return proc_outcome_t::repeat;
|
||||
}
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
|
@ -323,7 +322,7 @@ proc_outcome_t rrc::serving_cell_config_proc::step()
|
|||
* Cell Selection Procedure
|
||||
*************************************/
|
||||
|
||||
rrc::cell_selection_proc::cell_selection_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {}
|
||||
rrc::cell_selection_proc::cell_selection_proc(rrc* parent_) : rrc_ptr(parent_) {}
|
||||
|
||||
/*
|
||||
* Cell selection procedure 36.304 5.2.3
|
||||
|
@ -361,13 +360,14 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection()
|
|||
// Try to select Cell
|
||||
rrc_ptr->set_serving_cell(rrc_ptr->neighbour_cells.at(neigh_index)->phy_cell);
|
||||
Info("Selected cell: %s\n", rrc_ptr->serving_cell->print().c_str());
|
||||
log_h->console("Selected cell: %s\n", rrc_ptr->serving_cell->print().c_str());
|
||||
rrc_ptr->rrc_log->console("Selected cell: %s\n", rrc_ptr->serving_cell->print().c_str());
|
||||
|
||||
/* BLOCKING CALL */
|
||||
if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) {
|
||||
if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) {
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
serv_cell_cfg_fut = rrc_ptr->serv_cell_cfg.get_future();
|
||||
state = search_state_t::cell_config;
|
||||
return proc_outcome_t::repeat;
|
||||
} else {
|
||||
|
@ -400,47 +400,43 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection()
|
|||
if (not rrc_ptr->cell_searcher.launch()) {
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
cell_search_fut = rrc_ptr->cell_searcher.get_future();
|
||||
state = search_state_t::cell_search;
|
||||
return proc_outcome_t::repeat;
|
||||
}
|
||||
|
||||
proc_outcome_t rrc::cell_selection_proc::step_cell_search()
|
||||
{
|
||||
|
||||
if (rrc_ptr->cell_searcher.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<cell_search_proc> ret = rrc_ptr->cell_searcher.pop();
|
||||
if (ret.is_error()) {
|
||||
if (cell_search_fut.is_error()) {
|
||||
cs_result = cs_result_t::no_cell;
|
||||
return proc_outcome_t::error;
|
||||
} else {
|
||||
cs_result = (ret.proc()->get_cs_ret().found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND)
|
||||
}
|
||||
cs_result = (cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND)
|
||||
? cs_result_t::changed_cell
|
||||
: cs_result_t::no_cell;
|
||||
Info("Cell Search of cell selection run successfully\n");
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
}
|
||||
|
||||
proc_outcome_t rrc::cell_selection_proc::step_cell_config()
|
||||
{
|
||||
if (rrc_ptr->serv_cell_cfg.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<serving_cell_config_proc> ret = rrc_ptr->serv_cell_cfg.pop();
|
||||
if (ret.is_success()) {
|
||||
if (serv_cell_cfg_fut.is_success()) {
|
||||
Info("All SIBs of serving cell obtained successfully\n");
|
||||
cs_result = cs_result_t::changed_cell;
|
||||
return proc_outcome_t::success;
|
||||
} else {
|
||||
}
|
||||
Error("While configuring serving cell\n");
|
||||
// resume cell selection
|
||||
state = search_state_t::cell_selection;
|
||||
++neigh_index;
|
||||
return proc_outcome_t::repeat;
|
||||
}
|
||||
}
|
||||
|
||||
proc_outcome_t rrc::cell_selection_proc::step()
|
||||
{
|
||||
|
@ -455,13 +451,13 @@ proc_outcome_t rrc::cell_selection_proc::step()
|
|||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
void rrc::cell_selection_proc::on_complete(bool is_success)
|
||||
void rrc::cell_selection_proc::then(const srslte::proc_result_t<cs_result_t>& proc_result) const
|
||||
{
|
||||
// Inform Connection Request Procedure
|
||||
Info("Completed with %s. Informing proc %s\n",
|
||||
is_success ? "success" : "failure",
|
||||
proc_result.is_success() ? "success" : "failure",
|
||||
rrc_ptr->conn_req_proc.get()->name());
|
||||
rrc_ptr->conn_req_proc.trigger_event(connection_request_proc::cell_selection_complete{is_success, cs_result});
|
||||
rrc_ptr->conn_req_proc.trigger(proc_result);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
|
@ -478,6 +474,7 @@ proc_outcome_t rrc::plmn_search_proc::init()
|
|||
Error("Failed due to fail to init cell search...\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
cell_search_fut = rrc_ptr->cell_searcher.get_future();
|
||||
return proc_outcome_t::repeat;
|
||||
}
|
||||
|
||||
|
@ -492,16 +489,14 @@ proc_outcome_t rrc::plmn_search_proc::step()
|
|||
// wait for new TTI
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<cell_search_proc> ret = rrc_ptr->cell_searcher.pop();
|
||||
phy_interface_rrc_lte::cell_search_ret_t cs_ret = ret.proc()->get_cs_ret();
|
||||
if (ret.is_error() or cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) {
|
||||
if (cell_search_fut.is_error() or cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) {
|
||||
// stop search
|
||||
nof_plmns = -1;
|
||||
Error("Failed due to failed cell search sub-procedure\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
if (cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) {
|
||||
if (cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) {
|
||||
if (rrc_ptr->serving_cell->has_sib1()) {
|
||||
// Save PLMN and TAC to NAS
|
||||
for (uint32_t i = 0; i < rrc_ptr->serving_cell->nof_plmns(); i++) {
|
||||
|
@ -518,7 +513,7 @@ proc_outcome_t rrc::plmn_search_proc::step()
|
|||
}
|
||||
}
|
||||
|
||||
if (cs_ret.last_freq == phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS) {
|
||||
if (cell_search_fut.value()->last_freq == phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS) {
|
||||
Info("completed PLMN search\n");
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
|
@ -532,10 +527,10 @@ proc_outcome_t rrc::plmn_search_proc::step()
|
|||
return proc_outcome_t::repeat;
|
||||
}
|
||||
|
||||
void rrc::plmn_search_proc::on_complete(bool is_success)
|
||||
void rrc::plmn_search_proc::then(const srslte::proc_result_t<void>& result) const
|
||||
{
|
||||
// on cleanup, call plmn_search_completed
|
||||
if (is_success) {
|
||||
if (result.is_success()) {
|
||||
Info("completed with success\n");
|
||||
rrc_ptr->nas->plmn_search_completed(found_plmns, nof_plmns);
|
||||
} else {
|
||||
|
@ -577,25 +572,15 @@ proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t
|
|||
cs_ret = cs_result_t::no_cell;
|
||||
|
||||
state = state_t::cell_selection;
|
||||
if (rrc_ptr->cell_selector.is_idle()) {
|
||||
// No one is running cell selection
|
||||
if (not rrc_ptr->cell_selector.launch()) {
|
||||
if (not rrc_ptr->cell_selector.is_active()) {
|
||||
// Launch failed but cell selection was not already running
|
||||
Error("Failed to initiate cell selection procedure...\n");
|
||||
return proc_outcome_t::error;
|
||||
} else if (not rrc_ptr->cell_selector.is_complete()) {
|
||||
// In case it was already running, just wait for an cell_selection_complete event trigger
|
||||
Info("Cell selection proc already on-going. Wait for its result\n");
|
||||
} else {
|
||||
// It already completed with success. FIXME: Find more elegant solution
|
||||
Info("A cell selection procedure has just finished successfully. I am reusing its result\n");
|
||||
cell_selection_complete e{};
|
||||
e.cs_result = rrc_ptr->cell_selector.get()->get_cs_result();
|
||||
e.is_success = e.cs_result == cs_result_t::same_cell or e.cs_result == cs_result_t::changed_cell;
|
||||
return trigger_event(e);
|
||||
}
|
||||
rrc_ptr->callback_list.add_proc(rrc_ptr->cell_selector);
|
||||
} else {
|
||||
// In case we were able to launch it, let the callback list handle it
|
||||
rrc_ptr->callback_list.defer_proc(rrc_ptr->cell_selector);
|
||||
Info("Cell selection proc already on-going. Wait for its result\n");
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
@ -609,9 +594,7 @@ proc_outcome_t rrc::connection_request_proc::step()
|
|||
if (rrc_ptr->serv_cell_cfg.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<serving_cell_config_proc> ret = rrc_ptr->serv_cell_cfg.pop();
|
||||
|
||||
if (ret.is_error()) {
|
||||
if (serv_cfg_fut.is_error()) {
|
||||
Error("Configuring serving cell\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
@ -643,13 +626,13 @@ proc_outcome_t rrc::connection_request_proc::step()
|
|||
return proc_outcome_t::success;
|
||||
} else if (rrc_ptr->timers->get(rrc_ptr->t300)->is_expired()) {
|
||||
// T300 is expired: 5.3.3.6
|
||||
Info("Timer T300 expired: ConnectionRequest timed out\n");
|
||||
Warning("Timer T300 expired: ConnectionRequest timed out\n");
|
||||
rrc_ptr->mac->reset();
|
||||
rrc_ptr->set_mac_default();
|
||||
rrc_ptr->rlc->reestablish();
|
||||
} else {
|
||||
// T300 is stopped but RRC not Connected is because received Reject: Section 5.3.3.8
|
||||
Info("Timer T300 stopped: Received ConnectionReject\n");
|
||||
Warning("Timer T300 stopped: Received ConnectionReject\n");
|
||||
rrc_ptr->mac->reset();
|
||||
rrc_ptr->set_mac_default();
|
||||
}
|
||||
|
@ -658,28 +641,27 @@ proc_outcome_t rrc::connection_request_proc::step()
|
|||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
void rrc::connection_request_proc::on_complete(bool is_success)
|
||||
void rrc::connection_request_proc::then(const srslte::proc_result_t<void>& result)
|
||||
{
|
||||
if (not is_success) {
|
||||
if (result.is_error()) {
|
||||
log_h->warning("Could not establish connection. Deallocating dedicatedInfoNAS PDU\n");
|
||||
this->dedicated_info_nas.reset();
|
||||
rrc_ptr->nas->connection_request_completed(false);
|
||||
} else {
|
||||
Info("Finished connection request procedure successfully.\n");
|
||||
rrc_ptr->nas->connection_request_completed(true);
|
||||
}
|
||||
rrc_ptr->nas->connection_request_completed(result.is_success());
|
||||
}
|
||||
|
||||
srslte::proc_outcome_t rrc::connection_request_proc::trigger_event(const cell_selection_complete& e)
|
||||
srslte::proc_outcome_t rrc::connection_request_proc::react(const cell_selection_proc::cell_selection_complete_ev& e)
|
||||
{
|
||||
if (state != state_t::cell_selection) {
|
||||
// ignore if we are not expecting an cell selection result
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
if (not e.is_success) {
|
||||
if (e.is_error()) {
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
cs_ret = e.cs_result;
|
||||
cs_ret = *e.value();
|
||||
// .. and SI acquisition
|
||||
if (rrc_ptr->phy->cell_is_camping()) {
|
||||
|
||||
|
@ -695,6 +677,7 @@ srslte::proc_outcome_t rrc::connection_request_proc::trigger_event(const cell_se
|
|||
Error("Attach request failed to configure serving cell...\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
serv_cfg_fut = rrc_ptr->serv_cell_cfg.get_future();
|
||||
state = state_t::config_serving_cell;
|
||||
return proc_outcome_t::repeat;
|
||||
} else {
|
||||
|
@ -744,11 +727,14 @@ proc_outcome_t rrc::process_pcch_proc::step()
|
|||
if (RRC_STATE_IDLE == rrc_ptr->state) {
|
||||
Info("S-TMSI match in paging message\n");
|
||||
log_h->console("S-TMSI match in paging message\n");
|
||||
rrc_ptr->nas->paging(&s_tmsi_paged);
|
||||
if (not rrc_ptr->nas->paging(&s_tmsi_paged)) {
|
||||
Error("Unable to start NAS paging proc\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
state = state_t::nas_paging;
|
||||
return proc_outcome_t::repeat;
|
||||
} else {
|
||||
log_h->warning("Received paging while in CONNECT\n");
|
||||
Warning("Received paging while in CONNECT\n");
|
||||
}
|
||||
} else {
|
||||
Info("Received paging for unknown identity\n");
|
||||
|
@ -764,6 +750,7 @@ proc_outcome_t rrc::process_pcch_proc::step()
|
|||
Error("Failed to initiate a serving cell configuration procedure\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
serv_cfg_fut = rrc_ptr->serv_cell_cfg.get_future();
|
||||
} else {
|
||||
Info("Completed successfully\n");
|
||||
return proc_outcome_t::success;
|
||||
|
@ -777,8 +764,7 @@ proc_outcome_t rrc::process_pcch_proc::step()
|
|||
if (rrc_ptr->serv_cell_cfg.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<serving_cell_config_proc> ret = rrc_ptr->serv_cell_cfg.pop();
|
||||
if (ret.is_success()) {
|
||||
if (serv_cfg_fut.is_success()) {
|
||||
Info("All SIBs of serving cell obtained successfully\n");
|
||||
return proc_outcome_t::success;
|
||||
} else {
|
||||
|
@ -789,8 +775,12 @@ proc_outcome_t rrc::process_pcch_proc::step()
|
|||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
proc_outcome_t rrc::process_pcch_proc::trigger_event(paging_complete e)
|
||||
proc_outcome_t rrc::process_pcch_proc::react(paging_complete e)
|
||||
{
|
||||
if (state != state_t::nas_paging) {
|
||||
Warning("Received an unexpected paging complete\n");
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
if (not e.outcome) {
|
||||
Info("NAS Paging has failed\n");
|
||||
return proc_outcome_t::error;
|
||||
|
@ -826,8 +816,7 @@ proc_outcome_t rrc::go_idle_proc::step()
|
|||
rrc_ptr->leave_connected();
|
||||
return proc_outcome_t::success;
|
||||
} else {
|
||||
rrc_ptr->rrc_log->debug(
|
||||
"Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_counter, rlc_flush_timeout);
|
||||
Debug("Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_counter, rlc_flush_timeout);
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
@ -846,6 +835,7 @@ proc_outcome_t rrc::cell_reselection_proc::init()
|
|||
Error("Failed to initiate a Cell Selection procedure...\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
cell_selection_fut = rrc_ptr->cell_selector.get_future();
|
||||
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
@ -855,13 +845,12 @@ proc_outcome_t rrc::cell_reselection_proc::step()
|
|||
if (rrc_ptr->cell_selector.run()) {
|
||||
return srslte::proc_outcome_t::yield;
|
||||
}
|
||||
srslte::proc_result_t<cell_selection_proc> ret = rrc_ptr->cell_selector.pop();
|
||||
if (ret.is_error()) {
|
||||
if (cell_selection_fut.is_error()) {
|
||||
Error("Cell Reselection - Error while selecting a cell\n");
|
||||
return srslte::proc_outcome_t::error;
|
||||
}
|
||||
|
||||
switch (ret.proc()->get_cs_result()) {
|
||||
switch (*cell_selection_fut.value()) {
|
||||
case cs_result_t::changed_cell:
|
||||
// New cell has been selected, start receiving PCCH
|
||||
rrc_ptr->mac->pcch_start_rx();
|
||||
|
|
|
@ -59,21 +59,34 @@ proc_outcome_t nas::plmn_search_proc::init()
|
|||
|
||||
proc_outcome_t nas::plmn_search_proc::step()
|
||||
{
|
||||
if (state == state_t::rrc_connect) {
|
||||
if (nas_ptr->rrc_connector.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
proc_result_t<rrc_connect_proc> ret = nas_ptr->rrc_connector.pop();
|
||||
if (ret.is_success()) {
|
||||
return proc_outcome_t::success;
|
||||
}
|
||||
nas_ptr->enter_emm_deregistered();
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
proc_outcome_t nas::plmn_search_proc::trigger_event(const plmn_search_complete_t& t)
|
||||
void nas::plmn_search_proc::then(const srslte::proc_result_t<void>& result)
|
||||
{
|
||||
ProcInfo("Completed with %s\n", result.is_success() ? "success" : "failure");
|
||||
|
||||
// start T3411
|
||||
nas_ptr->nas_log->debug("Starting T3411\n");
|
||||
nas_ptr->timers->get(nas_ptr->t3411)->reset();
|
||||
nas_ptr->timers->get(nas_ptr->t3411)->run();
|
||||
|
||||
if (result.is_error()) {
|
||||
nas_ptr->enter_emm_deregistered();
|
||||
}
|
||||
}
|
||||
|
||||
proc_outcome_t nas::plmn_search_proc::react(const rrc_connect_proc::rrc_connect_complete_ev& t)
|
||||
{
|
||||
if (state != state_t::rrc_connect) {
|
||||
// not expecting a rrc connection result
|
||||
ProcWarning("Received unexpected RRC Connection Result event\n");
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
return t.is_success() ? proc_outcome_t::success : proc_outcome_t::error;
|
||||
}
|
||||
|
||||
proc_outcome_t nas::plmn_search_proc::react(const plmn_search_complete_t& t)
|
||||
{
|
||||
if (state != state_t::plmn_search) {
|
||||
ProcWarning("PLMN Search Complete was received but PLMN Search is not running.\n");
|
||||
|
@ -114,12 +127,13 @@ proc_outcome_t nas::plmn_search_proc::trigger_event(const plmn_search_complete_t
|
|||
|
||||
nas_ptr->rrc->plmn_select(nas_ptr->current_plmn);
|
||||
|
||||
state = state_t::rrc_connect;
|
||||
if (not nas_ptr->rrc_connector.launch(srslte::establishment_cause_t::mo_data, nullptr)) {
|
||||
ProcError("Unable to initiate RRC connection.\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
nas_ptr->callbacks.add_proc(nas_ptr->rrc_connector);
|
||||
|
||||
state = state_t::rrc_connect;
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
|
@ -155,37 +169,26 @@ proc_outcome_t nas::rrc_connect_proc::init(srslte::establishment_cause_t cause_,
|
|||
|
||||
ProcInfo("Starting...\n");
|
||||
state = state_t::conn_req;
|
||||
if (not nas_ptr->start_connection_request(cause_, std::move(pdu))) {
|
||||
if (not nas_ptr->rrc->connection_request(cause_, std::move(pdu))) {
|
||||
ProcError("Failed to initiate a connection request procedure\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
proc_outcome_t nas::rrc_connect_proc::step()
|
||||
{
|
||||
if (state == state_t::conn_req) {
|
||||
if (nas_ptr->conn_req_proc.run()) {
|
||||
if (state != state_t::wait_attach) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
proc_result_t<query_proc_t<bool>> ret = nas_ptr->conn_req_proc.pop();
|
||||
if (ret.is_error()) {
|
||||
ProcError("Could not establish RRC connection\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
ProcInfo("Connection established correctly. Waiting for Attach\n");
|
||||
wait_timeout = 0;
|
||||
// Wait until attachment. If doing a service request is already attached
|
||||
state = state_t::wait_attach;
|
||||
return proc_outcome_t::repeat;
|
||||
}
|
||||
if (state == state_t::wait_attach) {
|
||||
wait_timeout++;
|
||||
// Wait until attachment. If doing a service request is already attached
|
||||
if (wait_timeout >= 5000 or nas_ptr->state == EMM_STATE_REGISTERED or not nas_ptr->running or
|
||||
not nas_ptr->rrc->is_connected()) {
|
||||
if (wait_timeout < 5000 and nas_ptr->state != EMM_STATE_REGISTERED and nas_ptr->running and
|
||||
nas_ptr->rrc->is_connected()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
if (nas_ptr->state == EMM_STATE_REGISTERED) {
|
||||
ProcInfo("EMM Registered correctly\n");
|
||||
ProcInfo("Success: EMM Registered correctly.\n");
|
||||
return proc_outcome_t::success;
|
||||
} else if (nas_ptr->state == EMM_STATE_DEREGISTERED) {
|
||||
ProcError("Timeout or received attach reject while trying to attach\n");
|
||||
|
@ -197,8 +200,25 @@ proc_outcome_t nas::rrc_connect_proc::step()
|
|||
}
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
|
||||
void nas::rrc_connect_proc::then(const srslte::proc_result_t<void>& result)
|
||||
{
|
||||
nas_ptr->plmn_searcher.trigger(result);
|
||||
}
|
||||
|
||||
proc_outcome_t nas::rrc_connect_proc::react(nas::rrc_connect_proc::connection_request_completed_t event)
|
||||
{
|
||||
if (state == state_t::conn_req and event.outcome) {
|
||||
ProcInfo("Connection established correctly. Waiting for Attach\n");
|
||||
wait_timeout = 0;
|
||||
// Wait until attachment. If doing a service request is already attached
|
||||
state = state_t::wait_attach;
|
||||
// wake up proc
|
||||
return proc_outcome_t::repeat;
|
||||
} else {
|
||||
ProcError("Could not establish RRC connection\n");
|
||||
return proc_outcome_t::error;
|
||||
}
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -318,7 +338,7 @@ void nas::timer_expired(uint32_t timeout_id)
|
|||
* The function returns true if the UE could attach correctly or false in case of error or timeout during attachment.
|
||||
*
|
||||
*/
|
||||
void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishment_cause_t cause_)
|
||||
void nas::start_attach_request(srslte::proc_result_t<void>* result, srslte::establishment_cause_t cause_)
|
||||
{
|
||||
nas_log->info("Attach Request\n");
|
||||
switch (state) {
|
||||
|
@ -341,29 +361,20 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme
|
|||
nas_log->info("No PLMN selected. Starting PLMN Search...\n");
|
||||
if (not plmn_searcher.launch()) {
|
||||
if (result != nullptr) {
|
||||
*result = proc_state_t::error;
|
||||
result->set_error();
|
||||
}
|
||||
return;
|
||||
}
|
||||
callbacks.defer_proc(plmn_searcher);
|
||||
plmn_searcher.then([this, result](bool is_success) {
|
||||
nas_log->info("Attach Request from PLMN Search %s\n", is_success ? "finished successfully" : "failed");
|
||||
plmn_searcher.then([this, result](const proc_result_t<void>& res) {
|
||||
nas_log->info("Attach Request from PLMN Search %s\n", res.is_success() ? "finished successfully" : "failed");
|
||||
if (result != nullptr) {
|
||||
*result = is_success ? proc_state_t::success : proc_state_t::error;
|
||||
}
|
||||
// start T3411
|
||||
nas_log->debug("Starting T3411\n");
|
||||
timers->get(t3411)->reset();
|
||||
timers->get(t3411)->run();
|
||||
|
||||
if (not is_success) {
|
||||
enter_emm_deregistered();
|
||||
*result = res;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
nas_log->error("PLMN selected in state %s\n", emm_state_text[state]);
|
||||
if (result != nullptr) {
|
||||
*result = proc_state_t::error;
|
||||
result->set_error();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -371,43 +382,42 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme
|
|||
if (rrc->is_connected()) {
|
||||
nas_log->info("NAS is already registered and RRC connected\n");
|
||||
if (result != nullptr) {
|
||||
*result = proc_state_t::success;
|
||||
result->set_val();
|
||||
}
|
||||
} else {
|
||||
nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n");
|
||||
if (not rrc_connector.launch(cause_, nullptr)) {
|
||||
nas_log->error("Cannot initiate concurrent rrc connection procedures\n");
|
||||
if (result != nullptr) {
|
||||
*result = proc_state_t::error;
|
||||
result->set_error();
|
||||
}
|
||||
return;
|
||||
}
|
||||
callbacks.defer_proc(rrc_connector);
|
||||
rrc_connector.then([this, result](bool is_success) {
|
||||
if (is_success) {
|
||||
rrc_connector.then([this, result](const proc_result_t<void>& res) {
|
||||
if (res.is_success()) {
|
||||
nas_log->info("NAS attached successfully\n");
|
||||
} else {
|
||||
nas_log->error("Could not attach from attach_request\n");
|
||||
}
|
||||
if (result != nullptr) {
|
||||
*result = is_success ? proc_state_t::success : proc_state_t::error;
|
||||
*result = res;
|
||||
}
|
||||
return proc_outcome_t::success;
|
||||
});
|
||||
callbacks.add_proc(rrc_connector);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
|
||||
if (result != nullptr) {
|
||||
*result = proc_state_t::error;
|
||||
result->set_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nas::plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
void nas::plmn_search_completed(const rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS],
|
||||
int nof_plmns)
|
||||
{
|
||||
plmn_searcher.trigger_event(plmn_search_proc::plmn_search_complete_t(found_plmns, nof_plmns));
|
||||
plmn_searcher.trigger(plmn_search_proc::plmn_search_complete_t(found_plmns, nof_plmns));
|
||||
}
|
||||
|
||||
bool nas::detach_request(const bool switch_off)
|
||||
|
@ -447,58 +457,41 @@ bool nas::is_attached()
|
|||
return state == EMM_STATE_REGISTERED;
|
||||
}
|
||||
|
||||
void nas::paging(s_tmsi_t* ue_identity)
|
||||
bool nas::paging(s_tmsi_t* ue_identity)
|
||||
{
|
||||
if (state == EMM_STATE_REGISTERED) {
|
||||
nas_log->info("Received paging: requesting RRC connection establishment\n");
|
||||
if (rrc_connector.is_active()) {
|
||||
nas_log->error("Cannot initiate concurrent RRC connection establishment procedures\n");
|
||||
return;
|
||||
}
|
||||
if (not rrc_connector.launch(srslte::establishment_cause_t::mt_access, nullptr)) {
|
||||
nas_log->error("Could not launch RRC Connect()\n");
|
||||
return;
|
||||
}
|
||||
// once completed, call paging complete
|
||||
callbacks.defer_task([this]() {
|
||||
if (rrc_connector.run()) {
|
||||
return proc_outcome_t::yield;
|
||||
}
|
||||
bool success = rrc_connector.pop().is_success();
|
||||
rrc->paging_completed(success);
|
||||
return proc_outcome_t::success;
|
||||
});
|
||||
} else {
|
||||
nas_log->warning("Received paging while in state %s\n", emm_state_text[state]);
|
||||
}
|
||||
}
|
||||
|
||||
void nas::set_barring(barring_t barring) {
|
||||
current_barring = barring;
|
||||
}
|
||||
|
||||
bool nas::start_connection_request(srslte::establishment_cause_t establish_cause,
|
||||
srslte::unique_byte_buffer_t ded_info_nas)
|
||||
{
|
||||
if (not conn_req_proc.launch()) {
|
||||
nas_log->error("Failed to initiate a connection request procedure\n");
|
||||
return false;
|
||||
}
|
||||
if (not rrc->connection_request(establish_cause, std::move(ded_info_nas))) {
|
||||
nas_log->error("Failed to initiate a connection request procedure\n");
|
||||
conn_req_proc.pop();
|
||||
// once completed, call paging complete
|
||||
rrc_connector.then([this](proc_result_t<void> outcome) {
|
||||
rrc->paging_completed(outcome.is_success());
|
||||
return proc_outcome_t::success;
|
||||
});
|
||||
callbacks.add_proc(rrc_connector);
|
||||
} else {
|
||||
nas_log->warning("Received paging while in state %s\n", emm_state_text[state]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nas::connection_request_completed(bool outcome)
|
||||
void nas::set_barring(barring_t barring)
|
||||
{
|
||||
conn_req_proc.trigger_event(outcome);
|
||||
return conn_req_proc.is_active();
|
||||
current_barring = barring;
|
||||
}
|
||||
|
||||
void nas::select_plmn() {
|
||||
// Signal from RRC that connection request proc completed
|
||||
bool nas::connection_request_completed(bool outcome)
|
||||
{
|
||||
rrc_connector.trigger(rrc_connect_proc::connection_request_completed_t{outcome});
|
||||
return true;
|
||||
}
|
||||
|
||||
void nas::select_plmn()
|
||||
{
|
||||
|
||||
plmn_is_selected = false;
|
||||
|
||||
|
@ -1786,7 +1779,7 @@ void nas::send_detach_request(bool switch_off)
|
|||
if (not rrc_connector.launch(establishment_cause_t::mo_sig, std::move(pdu))) {
|
||||
nas_log->error("Failed to initiate RRC Connection Request\n");
|
||||
}
|
||||
callbacks.defer_proc(rrc_connector);
|
||||
callbacks.add_proc(rrc_connector);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,10 +119,11 @@ public:
|
|||
printf("NAS generated SDU (len=%d):\n", sdu->N_bytes);
|
||||
last_sdu_len = sdu->N_bytes;
|
||||
srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes);
|
||||
is_connected_flag = true;
|
||||
nas_ptr->connection_request_completed(true);
|
||||
return true;
|
||||
}
|
||||
bool is_connected() {return false;}
|
||||
bool is_connected() { return is_connected_flag; }
|
||||
|
||||
uint16_t get_mcc() { return mcc; }
|
||||
uint16_t get_mnc() { return mnc; }
|
||||
|
@ -134,6 +135,7 @@ private:
|
|||
nas* nas_ptr;
|
||||
uint32_t last_sdu_len;
|
||||
found_plmn_t plmns;
|
||||
bool is_connected_flag = false;
|
||||
};
|
||||
|
||||
class stack_dummy : public stack_interface_gw, public thread
|
||||
|
@ -143,12 +145,12 @@ public:
|
|||
void init() { start(-1); }
|
||||
bool switch_on() final
|
||||
{
|
||||
proc_state_t proc_result = proc_state_t::on_going;
|
||||
proc_result_t<void> proc_result;
|
||||
nas->start_attach_request(&proc_result, srslte::establishment_cause_t::mo_data);
|
||||
while (proc_result == proc_state_t::on_going) {
|
||||
while (not proc_result.is_complete()) {
|
||||
usleep(1000);
|
||||
}
|
||||
return proc_result == proc_state_t::success;
|
||||
return proc_result.is_success();
|
||||
}
|
||||
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue