2005-06-16 09:39:40 +04:00
/*
Unix SMB / CIFS implementation .
2005-10-24 13:34:12 +04:00
implements a non - blocking connect operation that is aware of the samba4
events system
2005-06-16 09:39:40 +04:00
Copyright ( C ) Andrew Tridgell 2005
2005-10-24 13:34:12 +04:00
Copyright ( C ) Volker Lendecke 2005
2005-06-16 09:39:40 +04:00
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-06-16 09:39:40 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-06-16 09:39:40 +04:00
*/
# include "includes.h"
# include "lib/socket/socket.h"
# include "lib/events/events.h"
2005-10-24 13:34:12 +04:00
# include "libcli/composite/composite.h"
struct connect_state {
struct socket_context * sock ;
2006-01-10 01:12:53 +03:00
const struct socket_address * my_address ;
const struct socket_address * server_address ;
2005-10-24 13:34:12 +04:00
uint32_t flags ;
} ;
2008-12-29 22:24:57 +03:00
static void socket_connect_handler ( struct tevent_context * ev ,
struct tevent_fd * fde ,
2009-02-02 10:21:17 +03:00
uint16_t flags , void * private_data ) ;
2005-10-24 13:34:12 +04:00
2005-11-21 10:23:36 +03:00
/*
call the real socket_connect ( ) call , and setup event handler
*/
2005-11-21 12:17:00 +03:00
static void socket_send_connect ( struct composite_context * result )
2005-11-21 10:23:36 +03:00
{
2008-12-29 22:24:57 +03:00
struct tevent_fd * fde ;
2005-11-21 12:17:00 +03:00
struct connect_state * state = talloc_get_type ( result - > private_data ,
struct connect_state ) ;
result - > status = socket_connect ( state - > sock ,
state - > my_address ,
state - > server_address ,
state - > flags ) ;
if ( NT_STATUS_IS_ERR ( result - > status ) & &
! NT_STATUS_EQUAL ( result - > status ,
2005-11-21 10:23:36 +03:00
NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2005-11-21 12:17:00 +03:00
composite_error ( result , result - > status ) ;
2005-11-21 10:23:36 +03:00
return ;
}
2010-05-25 23:28:35 +04:00
fde = tevent_add_fd ( result - > event_ctx , result ,
2005-11-21 12:17:00 +03:00
socket_get_fd ( state - > sock ) ,
2010-05-25 23:28:35 +04:00
TEVENT_FD_READ | TEVENT_FD_WRITE ,
2005-11-21 12:17:00 +03:00
socket_connect_handler , result ) ;
composite_nomem ( fde , result ) ;
2005-11-21 10:23:36 +03:00
}
/*
send a socket connect , potentially doing some name resolution first
*/
2005-10-24 13:34:12 +04:00
struct composite_context * socket_connect_send ( struct socket_context * sock ,
2006-01-10 01:12:53 +03:00
struct socket_address * my_address ,
struct socket_address * server_address ,
2005-10-24 13:34:12 +04:00
uint32_t flags ,
2008-12-29 22:24:57 +03:00
struct tevent_context * event_ctx )
2005-10-24 13:34:12 +04:00
{
2005-11-21 12:17:00 +03:00
struct composite_context * result ;
2005-10-24 13:34:12 +04:00
struct connect_state * state ;
2008-12-18 01:13:44 +03:00
result = composite_create ( sock , event_ctx ) ;
2005-11-21 10:23:36 +03:00
if ( result = = NULL ) return NULL ;
2005-10-24 13:34:12 +04:00
2005-11-21 10:23:36 +03:00
state = talloc_zero ( result , struct connect_state ) ;
2006-01-10 01:12:53 +03:00
if ( composite_nomem ( state , result ) ) return result ;
2005-10-24 13:34:12 +04:00
result - > private_data = state ;
state - > sock = talloc_reference ( state , sock ) ;
2006-01-10 01:12:53 +03:00
if ( composite_nomem ( state - > sock , result ) ) return result ;
2005-11-21 10:23:36 +03:00
if ( my_address ) {
2006-01-10 01:12:53 +03:00
void * ref = talloc_reference ( state , my_address ) ;
if ( composite_nomem ( ref , result ) ) {
return result ;
}
state - > my_address = my_address ;
2005-11-21 10:23:36 +03:00
}
2006-01-10 01:12:53 +03:00
{
void * ref = talloc_reference ( state , server_address ) ;
if ( composite_nomem ( ref , result ) ) {
return result ;
}
state - > server_address = server_address ;
}
2005-11-21 10:23:36 +03:00
2005-10-24 13:34:12 +04:00
state - > flags = flags ;
2005-08-28 06:37:14 +04:00
2007-10-05 22:03:01 +04:00
set_blocking ( socket_get_fd ( sock ) , false ) ;
2005-08-28 06:37:14 +04:00
2005-11-21 12:17:00 +03:00
socket_send_connect ( result ) ;
2005-06-16 09:39:40 +04:00
2005-10-24 13:34:12 +04:00
return result ;
}
2005-06-16 09:39:40 +04:00
/*
handle write events on connect completion
*/
2008-12-29 22:24:57 +03:00
static void socket_connect_handler ( struct tevent_context * ev ,
struct tevent_fd * fde ,
2009-02-02 10:21:17 +03:00
uint16_t flags , void * private_data )
2005-06-16 09:39:40 +04:00
{
2005-11-21 12:17:00 +03:00
struct composite_context * result =
2009-02-02 10:21:17 +03:00
talloc_get_type ( private_data , struct composite_context ) ;
2005-11-21 12:17:00 +03:00
struct connect_state * state = talloc_get_type ( result - > private_data ,
struct connect_state ) ;
2005-06-16 09:39:40 +04:00
2005-11-21 12:17:00 +03:00
result - > status = socket_connect_complete ( state - > sock , state - > flags ) ;
if ( ! composite_is_ok ( result ) ) return ;
2005-06-16 09:39:40 +04:00
2005-11-21 12:17:00 +03:00
composite_done ( result ) ;
2005-10-24 13:34:12 +04:00
}
2005-08-28 06:37:38 +04:00
2005-11-21 10:23:36 +03:00
/*
wait for a socket_connect_send ( ) to finish
*/
2005-11-21 12:17:00 +03:00
NTSTATUS socket_connect_recv ( struct composite_context * result )
2005-10-24 13:34:12 +04:00
{
2005-11-21 12:17:00 +03:00
NTSTATUS status = composite_wait ( result ) ;
talloc_free ( result ) ;
2005-06-16 09:39:40 +04:00
return status ;
}
2005-10-24 13:34:12 +04:00
2005-11-21 10:23:36 +03:00
/*
like socket_connect ( ) but takes an event context , doing a semi - async connect
*/
2005-10-24 13:34:12 +04:00
NTSTATUS socket_connect_ev ( struct socket_context * sock ,
2006-01-10 01:12:53 +03:00
struct socket_address * my_address ,
struct socket_address * server_address ,
2008-12-18 01:13:44 +03:00
uint32_t flags ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev )
2005-10-24 13:34:12 +04:00
{
struct composite_context * ctx ;
2006-01-10 01:12:53 +03:00
ctx = socket_connect_send ( sock , my_address ,
2008-12-18 01:13:44 +03:00
server_address , flags , ev ) ;
2005-10-24 13:34:12 +04:00
return socket_connect_recv ( ctx ) ;
}