/* * Copyright (c) 2012-2019 Belledonne Communications SARL. * * This file is part of belle-sip. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BELLE_SIP_MAINLOOP_H #define BELLE_SIP_MAINLOOP_H #include "defs.h" #include "utils.h" #include "types.h" #define BELLE_SIP_EVENT_READ 1 #define BELLE_SIP_EVENT_WRITE (1<<1) #define BELLE_SIP_EVENT_ERROR (1<<2) #define BELLE_SIP_EVENT_TIMEOUT (1<<3) typedef struct belle_sip_source belle_sip_source_t; BELLESIP_EXPORT int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask); BELLESIP_EXPORT belle_sip_socket_t belle_sip_source_get_socket(const belle_sip_source_t* source); /** * Callback function prototype for main loop notifications. * Return value is important: * BELLE_SIP_STOP => source is removed from main loop. * BELLE_SIP_CONTINUE => source is kept, timeout is restarted if any according to last expiry time * BELLE_SIP_CONTINUE_WITHOUT_CATCHUP => source is kept, timeout is restarted if any according to current time **/ typedef int (*belle_sip_source_func_t)(void *user_data, unsigned int events); /* * Call back fonction invoked when source is removed from main loop */ typedef void (*belle_sip_source_remove_callback_t)(belle_sip_source_t *); typedef void (*belle_sip_callback_t)(void *user_data); typedef struct belle_sip_main_loop belle_sip_main_loop_t; #define BELLE_SIP_CONTINUE_WITHOUT_CATCHUP 2 #define BELLE_SIP_CONTINUE 1 #define BELLE_SIP_STOP 0 BELLE_SIP_BEGIN_DECLS BELLESIP_EXPORT void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source); BELLESIP_EXPORT void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source); /** * Creates a mainloop. **/ BELLESIP_EXPORT belle_sip_main_loop_t *belle_sip_main_loop_new(void); /** * Adds a timeout into the main loop * @param ml * @param func a callback function to be called to notify timeout expiration * @param data a pointer to be passed to the callback * @param timeout_value_ms duration of the timeout. * @returns timeout id **/ BELLESIP_EXPORT unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms); /** * Adds a timeout into the main loop * The caller of this function is responsible for freeing (with belle_sip_object_unref()) the returned belle_sip_source_t object when it is no longer * needed. * @param ml * @param func a callback function to be called to notify timeout expiration * @param data a pointer to be passed to the callback * @param timeout_value_ms duration of the timeout. * @param timer_name name of the timer, can be null * @returns timeout belle_sip_source_t with ref count = 1 **/ BELLESIP_EXPORT belle_sip_source_t* belle_sip_main_loop_create_timeout(belle_sip_main_loop_t *ml , belle_sip_source_func_t func , void *data , unsigned int timeout_value_ms ,const char* timer_name); /** * Adds a timeout into the main loop * The caller of this function is responsible for freeing (with belle_sip_object_unref()) the returned belle_sip_source_t object when it is no longer * needed. * @param ml * @param func a callback function to be called to notify timeout expiration * @param data a pointer to be passed to the callback * @param timeout_value_ms duration of the timeout. * @param timer_name name of the timer, can be null * @param function called when source is removed, can be null * @returns timeout belle_sip_source_t with ref count = 1 **/ BELLESIP_EXPORT belle_sip_source_t* belle_sip_main_loop_create_timeout_with_remove_cb (belle_sip_main_loop_t *ml , belle_sip_source_func_t func , void *data , unsigned int timeout_value_ms , const char* timer_name , belle_sip_source_remove_callback_t remove_func); /** * Schedule an arbitrary task at next main loop iteration. * @note thread-safe **/ BELLESIP_EXPORT void belle_sip_main_loop_do_later(belle_sip_main_loop_t *ml, belle_sip_callback_t func, void *data); /** * Same as #belle_sip_main_loop_do_later() but allow to give a name to the task. * @param[in] timer_name The name of the task. If NULL, the task will be named as though * #belle_sip_main_loop_do_later() was called. * @note thread-safe **/ BELLESIP_EXPORT void belle_sip_main_loop_do_later_with_name( belle_sip_main_loop_t *ml, belle_sip_callback_t func, void *data, const char *timer_name ); /** * Creates a timeout source, similarly to belle_sip_main_loop_add_timeout(). * However in this case the timeout must be entered manually using belle_sip_main_loop_add_source(). * Its pointer can be used to remove it from the source (that is cancelling it). **/ BELLESIP_EXPORT belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms); /** * Set the timeout duration. * @param[in] s The source to modify. * @param[in] value_ms The new timeout duration in milliseconds. Only values in [0;INT_MAX] are valid to define a new * duration. Higher values will cause the timer to be disabled. * @deprecated Since 2020-05-20 (SDK 4.4). Use belle_sip_source_set_timeout_int64() instead. */ BELLESIP_DEPRECATED BELLESIP_EXPORT void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms); /** * Set the timeout duration. * @param[in] s The source to modify. * @param[in] value_ms Positive values willbe taken as the new duration to set. Negative values will cause the timer * to be disabled. */ BELLESIP_EXPORT void belle_sip_source_set_timeout_int64(belle_sip_source_t *s, int64_t value_ms); /** * Cancel a source. Will be removed at next iterate. It is not freed. **/ BELLESIP_EXPORT void belle_sip_source_cancel(belle_sip_source_t * src); BELLESIP_DEPRECATED BELLESIP_EXPORT unsigned int belle_sip_source_get_timeout(const belle_sip_source_t *s); BELLESIP_EXPORT int64_t belle_sip_source_get_timeout_int64(const belle_sip_source_t *s); BELLESIP_EXPORT belle_sip_source_t * belle_sip_socket_source_new(belle_sip_source_func_t func, void *data, belle_sip_socket_t fd, unsigned int events, unsigned int timeout_value_ms); /* * register a callback invoked once source is removed from mainloop */ BELLESIP_EXPORT void belle_sip_source_set_remove_cb(belle_sip_source_t *s, belle_sip_source_remove_callback_t func); BELLESIP_EXPORT unsigned long belle_sip_source_get_id(const belle_sip_source_t *s); BELLESIP_EXPORT void * belle_sip_source_get_user_data(const belle_sip_source_t *s); BELLESIP_EXPORT void belle_sip_source_set_user_data(belle_sip_source_t *s, void *user_data); BELLESIP_EXPORT belle_sip_source_t *belle_sip_main_loop_find_source(belle_sip_main_loop_t *ml, unsigned long id); /** * Executes the main loop forever (or until belle_sip_main_loop_quit() is called) **/ BELLESIP_EXPORT void belle_sip_main_loop_run(belle_sip_main_loop_t *ml); /** * Executes the main loop for the time specified in milliseconds. **/ BELLESIP_EXPORT void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds); /** * Break out the main loop. **/ BELLESIP_EXPORT int belle_sip_main_loop_quit(belle_sip_main_loop_t *ml); /** * Cancel (removes) a source. It is not freed. **/ BELLESIP_EXPORT void belle_sip_main_loop_cancel_source(belle_sip_main_loop_t *ml, unsigned long id); BELLE_SIP_END_DECLS #if (defined(WIN32) && defined(__cplusplus)) || __cplusplus >= 201103L /*Only Visual Studio 2018 properly defines __cplusplus according to c++ level. */ #include #include /** * A generic deleter for belle_sip_object_t objects that limits itself to decrementing the * reference counter. This class is to be used by std::unique_ptr and std::shared_ptr maybe. */ template struct BelleSipObjectDeleter { constexpr BelleSipObjectDeleter() noexcept = default; void operator()(T *ptr) const noexcept {belle_sip_object_unref(ptr);} }; using BelleSipSourcePtr = std::unique_ptr>; using belle_sip_source_cpp_func_t = std::function; using BelleSipDoLaterFunc = std::function; /** * The purpose of this function is to simplify c++ timer integration. * ex: * std::string helloworld("Hello world): * belle_sip_source_cpp_func_t *func = new belle_sip_source_cpp_func_t([helloworld](unsigned int events) { * std::cout << helloworld << std::endl; * return BELLE_SIP_STOP; * }); * // create timer * belle_sip_source_t *timer = belle_sip_main_loop_create_cpp_timeout( mainloop * , func * , 1000 * ,"timer for c++"); * [...] * // Unref the timer when you doesn't need it anymore * belle_sip_object_unref(timer); * * @warning Not thread-sfae * @deprecated Since 2020-04-17. */ BELLESIP_DEPRECATED BELLESIP_EXPORT belle_sip_source_t *belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml , belle_sip_source_cpp_func_t *func , unsigned int timeout_value_ms , const char* timer_name); /* * This variant does the same except that: * - it does not require to pass the std::function as a pointer allocated with new() * - the std::function shall return true/false instead of BELLE_SIP_CONTINUE/BELLE_SIP_STOP. */ BELLESIP_EXPORT belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout_2(belle_sip_main_loop_t *ml, const std::function &func, unsigned int timeout_value_ms, const std::string &timer_name); /** * The purpose of this function is to simplify c++ timer integration. * Unlike the deprecated overload of this function, there is no need to * allocate anything with new and to unref the timer. * * ex: * std::string helloworld{"Hello world}; * auto func = [helloworld](unsigned int events) { * std::cout << helloworld << std::endl; * return BELLE_SIP_STOP; * }); * * // create the timer * auto timer = belle_sip_main_loop_create_cpp_timeout( mainloop * , func * , 1000 * ,"timer for c++"); * */ BELLESIP_EXPORT BelleSipSourcePtr belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml , const belle_sip_source_cpp_func_t &func , unsigned int timeout_value_ms , const char* timer_name); /** * C++ wrapper for #belle_sip_main_loop_do_later(). * @note thread-safe */ BELLESIP_EXPORT void belle_sip_main_loop_cpp_do_later(belle_sip_main_loop_t *ml, const BelleSipDoLaterFunc &func); /** * Overload of the previous function that allow to give a name to the task. * @note thread-safe */ BELLESIP_EXPORT void belle_sip_main_loop_cpp_do_later( belle_sip_main_loop_t *ml, const BelleSipDoLaterFunc &func, const char *task_name ); #endif // C++ declarations #endif // #ifndef BELLE_SIP_MAINLOOP_H