apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Laurent Pointal <laurent.poin...@limsi.fr>
Subject Multicast + poll with APR
Date Tue, 23 Jan 2007 14:49:41 GMT
[ this is more an APR usage question, thanks to redirect me to another
more appropriate list if any ]


Platform: Windows (XP SP2), MS Visual C++ 2003 7.1.3088


I'm trying to setup multicast reception with polling sockets.

Q? Is this possible: multicast + DGRAM (UDP) + polling ?


If no, what would be the better way to process (I tried to avoid having
N threads suspended each on its own socket... and to avoid having active
wait with a loop testing N sockets with immediate return for each) ?


If yes, here is my current usage and problem with APR and polling:

apr_pool_create	
apr_pcalloc
	=> create a memory pool associated to the socket
		for my management, allocate memory in the
		pool
apr_parse_addr_port
	=> resolve DNS things if any
apr_sockaddr_info_get
	=> fill'in apr_sockaddr_t structure from address string
		(using family APR_UNSPEC and flags APR_IPV4_ADDR_OK)
apr_socket_create
	=> make the socket
		(using type SOCK_DGRAM and protocol APR_PROTO_UDP
		and same sock_addr family as sockaddr_info)
apr_socket_opt_set
	=> set socket blocking (APR_SO_NONBLOCK, 0) [see note 1]
apr_socket_timeout_set
	=> set infinite timeout (-1) [see note 1]
apr_socket_opt_set
	=> allow address reuse (APR_SO_REUSEADDR, 1)
apr_socket_bind
	=> bind socket to sock_addr

*** I have a failure here, using address 239.192.10.10:12345       ***
*** Error APR 730049                                               ***
*** [in english ~= requested address is not valid in its context]  ***
*** I tried blocking/non-blocking socket options, same result      ***

For multicast, I have the following operations:
	apr_mcast_hops
		=> setup mcast routing zone
	apr_mcast_loopback
		=> allow loopback on mcast
	apr_mcast_join
		=> join mcast group

apr_pollset_add
	=> add socket to poll for APR_POLLIN


The listing is at the end of this email (note 2).


Thanks for any help/idea.

L.Pointal.




[note 1] I read for portable blocking in
http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4

[note 2] Partial source (I removed status tests and logs generation for
readability):

...........................;

/** A specific socket management structure. */
struct _bvnet_socket_management_t
    {
    /** Internal check code.
    _BVNET_INTERNAL_MAGIC
    */
    u_long internal_magic ;
    /** Memory pool for this socket related operations. */
    apr_pool_t* mempool ;
    /** Host and port used to bind socket. */
    char* hostnameport ;
    /** Multicast use on this socket. */
    int ttlmcast ;
    /** Address for binding. */
	char* addr ;
	/** Port for binding. */
    apr_port_t port ;
    /** Socket address binding informations. */
    apr_sockaddr_t* sock_addr ;
    /** Socket reference. */
    apr_socket_t* sock ;
    /** Socket poll file descriptor. */
    apr_pollfd_t pfd ;
    } ;
typedef struct _bvnet_socket_management_t _bvnet_socket_management_t ;


/** The global application listening structure.
*/
struct _bvnet_listening_t
    {
    /** Memory pool for listening structures. */
    apr_pool_t* mempool ;
    /** Socket management to use when listener work in a separate
	thread. */
    _bvnet_socket_management_t* listener_ctrl_sm ;
    /** Currently receiving messages.
    This is a hash on message identifier giving message reception
	 structures.
    */
    apr_hash_t* running_messages_hash ;
    /** Messages which have been completly received.
    Here we just keep a time stamp for each received message.
    From time to time, a function must process this map and remove all
    entries where time stamps
    */
    apr_hash_t* received_messages_hash ;
    /** Pool of sockets to listen to. */
    apr_pollset_t* listening_sockets_poll ;
    /** Descriptors for these sockets. */
    apr_pollfd_t* sockets_table ;
    /** Number of descriptors. */
    int sockets_table_count ;
    } ;

typedef struct _bvnet_listening_t _bvnet_listening_t ;

/** Data for all listenings.
*/
_bvnet_listening_t my_listenings ;


................


//=========================================================================
apr_status_t
_bvnet_make_listen_to(const char* hostnameport, int makewritable, int
ttlmcast, _bvnet_socket_management_t** return_sm)
{
apr_status_t status ;
apr_pool_t* mempool = NULL ;
_bvnet_socket_management_t* sm = NULL ;
char* scope_id ;

*return_sm = NULL ;

// Make a poll for the socket.
status = apr_pool_create(&mempool,my_listenings.mempool) ;

// Allocate room in the poll for socket management (set it to zeroes).
sm =  apr_pcalloc(mempool,sizeof(_bvnet_socket_management_t)) ;
sm->internal_magic = _BVNET_INTERNAL_MAGIC ;
sm->ttlmcast = ttlmcast ;
sm->mempool = mempool ;

// We keep a copy of original hostname and port - may be nice for logs.
sm->hostnameport = apr_pstrdup (sm->mempool,hostnameport) ;

// Extract port from hosname and port.
status = apr_parse_addr_port (
        &sm->addr, //  	char **   	 addr,
      	&scope_id, // char **  	scope_id,
      	&sm->port, // apr_port_t *  	port,
      	sm->hostnameport, // const char *   	 str,
      	sm->mempool// apr_pool_t *  	p	
      	) ;


// Create socket address to bind to.
status = apr_sockaddr_info_get(
      	&sm->sock_addr, //apr_sockaddr_t **   	 sa,
      	sm->addr,       //const char *  	hostname,
      	// family: Let the system decide which address family to use,
       	//in place of APR_INET[6].
      	APR_UNSPEC,     //apr_int32_t  	family,
      	sm->port,           //apr_port_t  	port,
      	// flags: Use IPV4 if available, and fallback to IPV6
      	// only if cant find IPV4.
      	APR_IPV4_ADDR_OK,              //apr_int32_t  	flags,
      	sm->mempool // apr_pool_t *  	p	
      	) ;

// Create socket.
status = apr_socket_create(  	
        &sm->sock, //apr_socket_t **   	 new_sock,
      	sm->sock_addr->family,     //int  	family,
      	SOCK_DGRAM,     //int  	type,
      	APR_PROTO_UDP,  //int   	 protocol,
      	sm->mempool //apr_pool_t *  	cont	
      	) ;

// Set socket options.
// !!! See portability issue in INOUE Seiichiro tutorial !!!
// !!! (section 13.4 - real network programming)         !!!
// !!! Options selected to have indefinitely blocking.   !!!
// !!! => modified to become non-blocking (blocking commented out)
status = apr_socket_opt_set(sm->sock,APR_SO_NONBLOCK, 0) ;  // blocking

apr_socket_timeout_set(sm->sock, -1) ;             // blocking forever

apr_socket_opt_set(sm->sock,APR_SO_REUSEADDR, 1) ; // can reuse address

// Now, can bind socket to address, and set it listening.
status = apr_socket_bind(sm->sock, sm->sock_addr) ;

// Not found many documentation about APR and its multicast functions
// (there is the ref doc, but no more general guidelines and example
// like in Inoue tutorial).
if (sm->ttlmcast != BVNET_TTL_NO_MCAST)
    {
    // Set maximum TTL - this set the maximum zone that
    // multicast packets
    // can reach (host, service, enterprise...).
    status = apr_mcast_hops(sm->sock, //apr_socket_t * sock,
		sm->ttlmcast //apr_byte_t  	ttl	
	    )  ;

    // ? Is the loopback notion only process relative or complete
    // host relative.
    // Because we may want no loopback on different parts of
    // same process (considering better alternatives), but want
    // loopback between different
    // process on the same host.
    // In doubt, set it to true (want loopback). At least, this is an
    // existing solution for in-process communications.
    status = apr_mcast_loopback(
      	sm->sock, //apr_socket_t *   	 sock,
      	1 //apr_byte_t  	opt	
      	) ; 	
	
    // Join the multicast group to listen on it.
    status = apr_mcast_join(
      	sm->sock, // apr_socket_t *   	 sock,
      	sm->sock_addr, // apr_sockaddr_t *  	join,
      	NULL, // apr_sockaddr_t *  	iface,
      	NULL // apr_sockaddr_t *  	source	
      	) ;
    }
	
// Install the socket in the poll.
sm->pfd.p = sm->mempool ;  //apr_pool_t * 	p
sm->pfd.desc_type = APR_POLL_SOCKET ; //apr_datatype_e 	desc_type
sm->pfd.reqevents = APR_POLLIN ; //apr_int16_t 	reqevents
sm->pfd.rtnevents = 0 ; //apr_int16_t 	rtnevents
sm->pfd.desc.s = sm->sock ; //apr_descriptor 	desc
sm->pfd.client_data = sm ; //void * 	client_data

status = apr_pollset_add(my_listenings.listening_sockets_poll,&sm->pfd) ;

*return_sm = sm ;
return APR_SUCCESS ;
}







-- 
Laurent POINTAL
CNRS-LIMSI dépt. CHM, groupes AMI et PS
Courriel: laurent.pointal@limsi.fr    (prof)
          laurent.pointal@laposte.net (perso)
Ouebe: http://www.limsi.fr/Individu/pointal/
Tél. 01 69 85 81 06 (prof)
Fax. 01 69 85 80 88



Mime
View raw message