2009-02-13 17:43:04 +03:00
/*
Unix SMB / CIFS implementation .
Infrastructure for async requests
Copyright ( C ) Volker Lendecke 2008
2009-02-13 17:37:35 +03:00
Copyright ( C ) Stefan Metzmacher 2009
2009-02-13 17:43:04 +03:00
2009-02-16 10:52:06 +03:00
* * NOTE ! The following LGPL license applies to the tevent
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2009-02-13 17:43:04 +03:00
2009-02-16 10:52:06 +03:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
2009-02-13 17:43:04 +03:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2009-02-16 10:52:06 +03:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
2009-02-13 17:43:04 +03:00
2009-02-16 10:52:06 +03:00
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2009-02-13 17:43:04 +03:00
*/
2009-02-13 17:37:35 +03:00
# include "replace.h"
# include "tevent.h"
# include "tevent_internal.h"
# include "tevent_util.h"
2009-02-13 17:43:04 +03:00
2009-02-25 16:29:31 +03:00
char * tevent_req_default_print ( struct tevent_req * req , TALLOC_CTX * mem_ctx )
2009-02-13 17:43:04 +03:00
{
2009-02-13 17:37:35 +03:00
return talloc_asprintf ( mem_ctx ,
" tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] "
" state[%s (%p)] timer[%p] " ,
2009-03-17 22:13:34 +03:00
req , req - > internal . create_location ,
2009-02-13 17:37:35 +03:00
req - > internal . state ,
( unsigned long long ) req - > internal . error ,
( unsigned long long ) req - > internal . error ,
2009-02-28 23:44:30 +03:00
talloc_get_name ( req - > data ) ,
req - > data ,
2009-02-13 17:37:35 +03:00
req - > internal . timer
) ;
2009-02-13 17:43:04 +03:00
}
2009-02-25 16:29:31 +03:00
char * tevent_req_print ( TALLOC_CTX * mem_ctx , struct tevent_req * req )
{
if ( ! req - > private_print ) {
return tevent_req_default_print ( req , mem_ctx ) ;
}
return req - > private_print ( req , mem_ctx ) ;
}
2013-09-27 05:41:29 +04:00
static int tevent_req_destructor ( struct tevent_req * req ) ;
2009-02-13 17:37:35 +03:00
struct tevent_req * _tevent_req_create ( TALLOC_CTX * mem_ctx ,
2009-02-28 23:44:30 +03:00
void * pdata ,
size_t data_size ,
2009-02-13 17:37:35 +03:00
const char * type ,
const char * location )
2009-02-13 17:43:04 +03:00
{
2009-02-13 17:37:35 +03:00
struct tevent_req * req ;
2009-02-28 23:44:30 +03:00
void * * ppdata = ( void * * ) pdata ;
void * data ;
2009-02-13 17:37:35 +03:00
2013-09-07 02:37:56 +04:00
req = talloc_pooled_object (
mem_ctx , struct tevent_req , 2 ,
sizeof ( struct tevent_immediate ) + data_size ) ;
2009-02-13 17:37:35 +03:00
if ( req = = NULL ) {
return NULL ;
}
2013-09-07 02:37:56 +04:00
ZERO_STRUCTP ( req ) ;
2009-02-13 17:37:35 +03:00
req - > internal . private_type = type ;
2009-03-17 22:13:34 +03:00
req - > internal . create_location = location ;
2009-02-13 17:37:35 +03:00
req - > internal . state = TEVENT_REQ_IN_PROGRESS ;
2009-03-17 12:18:34 +03:00
req - > internal . trigger = tevent_create_immediate ( req ) ;
if ( ! req - > internal . trigger ) {
talloc_free ( req ) ;
return NULL ;
}
2009-02-13 17:43:04 +03:00
2009-07-15 03:54:01 +04:00
data = talloc_zero_size ( req , data_size ) ;
2009-02-28 23:44:30 +03:00
if ( data = = NULL ) {
2009-02-13 17:37:35 +03:00
talloc_free ( req ) ;
2009-02-13 17:43:04 +03:00
return NULL ;
}
2009-02-28 23:44:30 +03:00
talloc_set_name_const ( data , type ) ;
2009-02-13 17:37:35 +03:00
2009-02-28 23:44:30 +03:00
req - > data = data ;
2009-02-13 17:37:35 +03:00
2013-09-27 05:41:29 +04:00
talloc_set_destructor ( req , tevent_req_destructor ) ;
2009-02-28 23:44:30 +03:00
* ppdata = data ;
2009-02-13 17:37:35 +03:00
return req ;
2009-02-13 17:43:04 +03:00
}
2013-09-27 05:41:29 +04:00
static int tevent_req_destructor ( struct tevent_req * req )
{
tevent_req_received ( req ) ;
return 0 ;
}
2009-06-04 19:26:23 +04:00
void _tevent_req_notify_callback ( struct tevent_req * req , const char * location )
2009-02-13 17:43:04 +03:00
{
2009-03-17 22:13:34 +03:00
req - > internal . finish_location = location ;
2011-07-08 17:54:51 +04:00
if ( req - > internal . defer_callback_ev ) {
( void ) tevent_req_post ( req , req - > internal . defer_callback_ev ) ;
req - > internal . defer_callback_ev = NULL ;
return ;
}
2009-02-13 17:43:04 +03:00
if ( req - > async . fn ! = NULL ) {
req - > async . fn ( req ) ;
}
}
2009-06-04 19:26:23 +04:00
static void tevent_req_finish ( struct tevent_req * req ,
enum tevent_req_state state ,
const char * location )
{
2011-09-17 21:53:55 +04:00
/*
* make sure we do not timeout after
* the request was already finished
*/
TALLOC_FREE ( req - > internal . timer ) ;
2009-06-04 19:26:23 +04:00
req - > internal . state = state ;
_tevent_req_notify_callback ( req , location ) ;
}
2009-03-17 22:13:34 +03:00
void _tevent_req_done ( struct tevent_req * req ,
const char * location )
2009-02-13 17:43:04 +03:00
{
2009-03-17 22:13:34 +03:00
tevent_req_finish ( req , TEVENT_REQ_DONE , location ) ;
2009-02-13 17:43:04 +03:00
}
2009-03-17 22:13:34 +03:00
bool _tevent_req_error ( struct tevent_req * req ,
uint64_t error ,
const char * location )
2009-02-13 17:43:04 +03:00
{
2009-02-13 17:37:35 +03:00
if ( error = = 0 ) {
return false ;
2009-02-13 17:43:04 +03:00
}
2009-02-13 17:37:35 +03:00
req - > internal . error = error ;
2009-03-17 22:13:34 +03:00
tevent_req_finish ( req , TEVENT_REQ_USER_ERROR , location ) ;
2009-02-13 17:37:35 +03:00
return true ;
2009-02-13 17:43:04 +03:00
}
2011-06-19 22:55:46 +04:00
void _tevent_req_oom ( struct tevent_req * req , const char * location )
{
tevent_req_finish ( req , TEVENT_REQ_NO_MEMORY , location ) ;
}
2009-03-17 22:13:34 +03:00
bool _tevent_req_nomem ( const void * p ,
struct tevent_req * req ,
const char * location )
2009-02-13 17:43:04 +03:00
{
if ( p ! = NULL ) {
return false ;
}
2011-06-19 22:55:46 +04:00
_tevent_req_oom ( req , location ) ;
2009-02-13 17:43:04 +03:00
return true ;
}
/**
2010-01-14 16:41:49 +03:00
* @ internal
*
* @ brief Immediate event callback .
*
* @ param [ in ] ev The event context to use .
*
* @ param [ in ] im The immediate event .
*
* @ param [ in ] priv The async request to be finished .
2009-02-13 17:37:35 +03:00
*/
static void tevent_req_trigger ( struct tevent_context * ev ,
2009-03-17 12:18:34 +03:00
struct tevent_immediate * im ,
2009-02-13 17:37:35 +03:00
void * private_data )
{
2013-12-05 11:47:27 +04:00
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2009-02-13 17:37:35 +03:00
2009-03-17 22:13:34 +03:00
tevent_req_finish ( req , req - > internal . state ,
req - > internal . finish_location ) ;
2009-02-13 17:37:35 +03:00
}
struct tevent_req * tevent_req_post ( struct tevent_req * req ,
struct tevent_context * ev )
2009-02-13 17:43:04 +03:00
{
2009-03-17 12:18:34 +03:00
tevent_schedule_immediate ( req - > internal . trigger ,
ev , tevent_req_trigger , req ) ;
2009-02-13 17:37:35 +03:00
return req ;
2009-02-13 17:43:04 +03:00
}
2011-07-08 17:54:51 +04:00
void tevent_req_defer_callback ( struct tevent_req * req ,
struct tevent_context * ev )
{
req - > internal . defer_callback_ev = ev ;
}
2009-02-13 17:37:35 +03:00
bool tevent_req_is_in_progress ( struct tevent_req * req )
2009-02-13 17:43:04 +03:00
{
2009-02-13 17:37:35 +03:00
if ( req - > internal . state = = TEVENT_REQ_IN_PROGRESS ) {
return true ;
}
2009-02-13 17:43:04 +03:00
2009-02-13 17:37:35 +03:00
return false ;
2009-02-13 17:43:04 +03:00
}
2009-03-10 15:54:57 +03:00
void tevent_req_received ( struct tevent_req * req )
{
2013-09-27 05:41:29 +04:00
talloc_set_destructor ( req , NULL ) ;
2009-03-10 15:54:57 +03:00
req - > private_print = NULL ;
2013-09-27 04:59:22 +04:00
req - > private_cancel = NULL ;
2009-03-10 15:54:57 +03:00
2009-03-17 12:17:50 +03:00
TALLOC_FREE ( req - > internal . trigger ) ;
TALLOC_FREE ( req - > internal . timer ) ;
2009-03-10 15:54:57 +03:00
req - > internal . state = TEVENT_REQ_RECEIVED ;
2013-09-27 05:41:29 +04:00
TALLOC_FREE ( req - > data ) ;
2009-03-10 15:54:57 +03:00
}
2009-02-25 15:53:19 +03:00
bool tevent_req_poll ( struct tevent_req * req ,
struct tevent_context * ev )
{
while ( tevent_req_is_in_progress ( req ) ) {
int ret ;
ret = tevent_loop_once ( ev ) ;
if ( ret ! = 0 ) {
return false ;
}
}
return true ;
}
2009-02-13 17:37:35 +03:00
bool tevent_req_is_error ( struct tevent_req * req , enum tevent_req_state * state ,
uint64_t * error )
2009-02-13 17:43:04 +03:00
{
2009-02-13 17:37:35 +03:00
if ( req - > internal . state = = TEVENT_REQ_DONE ) {
return false ;
2009-02-13 17:43:04 +03:00
}
2009-02-13 17:37:35 +03:00
if ( req - > internal . state = = TEVENT_REQ_USER_ERROR ) {
* error = req - > internal . error ;
2009-02-13 17:43:04 +03:00
}
2009-02-13 17:37:35 +03:00
* state = req - > internal . state ;
2009-02-13 17:43:04 +03:00
return true ;
}
2009-02-13 17:37:35 +03:00
static void tevent_req_timedout ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval now ,
void * private_data )
2009-02-13 17:43:04 +03:00
{
2013-12-05 11:47:27 +04:00
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2009-02-13 17:43:04 +03:00
2009-03-17 12:17:50 +03:00
TALLOC_FREE ( req - > internal . timer ) ;
2009-02-13 17:43:04 +03:00
2009-03-17 22:13:34 +03:00
tevent_req_finish ( req , TEVENT_REQ_TIMED_OUT , __FUNCTION__ ) ;
2009-02-13 17:43:04 +03:00
}
2009-02-17 12:15:18 +03:00
bool tevent_req_set_endtime ( struct tevent_req * req ,
2009-02-13 17:37:35 +03:00
struct tevent_context * ev ,
struct timeval endtime )
2009-02-13 17:43:04 +03:00
{
2009-03-17 12:17:50 +03:00
TALLOC_FREE ( req - > internal . timer ) ;
2009-02-13 17:43:04 +03:00
2009-02-13 17:37:35 +03:00
req - > internal . timer = tevent_add_timer ( ev , req , endtime ,
tevent_req_timedout ,
req ) ;
if ( tevent_req_nomem ( req - > internal . timer , req ) ) {
2009-02-13 17:43:04 +03:00
return false ;
}
return true ;
}
2009-02-28 23:44:30 +03:00
void tevent_req_set_callback ( struct tevent_req * req , tevent_req_fn fn , void * pvt )
{
req - > async . fn = fn ;
req - > async . private_data = pvt ;
}
void * _tevent_req_callback_data ( struct tevent_req * req )
{
return req - > async . private_data ;
}
void * _tevent_req_data ( struct tevent_req * req )
{
return req - > data ;
}
void tevent_req_set_print_fn ( struct tevent_req * req , tevent_req_print_fn fn )
{
req - > private_print = fn ;
}
2009-08-15 11:46:23 +04:00
void tevent_req_set_cancel_fn ( struct tevent_req * req , tevent_req_cancel_fn fn )
{
req - > private_cancel = fn ;
}
bool _tevent_req_cancel ( struct tevent_req * req , const char * location )
{
if ( req - > private_cancel = = NULL ) {
return false ;
}
return req - > private_cancel ( req ) ;
}