John Nagle <nagle@downside.com> wrote:
JN > On a related note, can anyone use name_attach, or do you
JN > have to be root, or what?
JN > John Nagle
JN > John Nagle wrote:
“name_attach” and “name_open” seem to be the standard way
to pass connection info around, but Krten’s book says the’re
deprecated. What’s the story?
I need to establish interprocess communication, but
it’s message-passing, not stream I/O, so a resource
manager is inappropriate. I’d like to do this without
anything running as root. What’s the right way to do this?
John Nagle
Team Overbot
You can use a very stripped down resource manager. It is definitely a
lot more work to set up on the server side then in QNX4 days. But once
you’ve registered a name it is pretty much the same.
Here is a sample server and client sample code that I used as a starting point.
=====================================
/*
#ifdef __USAGE
This is an example Resource Manager using MsgSend() & MsgReply().
It is copied from
http://www.qnx.com/developer/articles/index.html?article=jan2601
#endif
*/
/*
- ResMgr and Message Server Process
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/neutrino.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
resmgr_connect_funcs_t ConnectFuncs;
resmgr_io_funcs_t IoFuncs;
iofunc_attr_t IoFuncAttr;
typedef struct
{
uint16_t msg_no;
char msg_data[255];
} server_msg_t;
int other_callback ( resmgr_context_t ctp, void msg )
{
printf( “Server Got OTHER Message\n” );
printf( " ctp=%p, ctp->msg=%p, msg*=%p\n", ctp, ctp->msg, msg );
#ifdef DONT_COMPILE
server_msg_t *msg;
int num;
char msg_reply[255];
/* cast a pointer to the message data */
msg = (server_msg_t *)ctp->msg;
/* Print out some usefull information on the message */
printf( “Server Got Message:\n” );
printf( " type: %d\n" , type );
printf( " data: %s\n\n", msg->msg_data );
/* Build the reply message */
num = type - _IO_MAX;
snprintf( msg_reply, 254, “Server Got Message Code: _IO_MAX + %d”, num );
/* Send a reply to the waiting (blocked) client */
MsgReply( ctp->rcvid, EOK, msg_reply, strlen( msg_reply ) + 1 );
#endif
return 0;
}
int message_callback ( message_context_t *ctp, int type, unsigned flags, void *handle )
{
server_msg_t *msg;
int num;
char msg_reply[255];
/* cast a pointer to the message data */
msg = (server_msg_t *)ctp->msg;
/* Print out some usefull information on the message */
printf( “\n\nServer Got Message:\n” );
printf( " type: %d\n" , type );
printf( " data: %s\n\n", msg->msg_data );
/* Build the reply message */
num = type - _IO_MAX;
snprintf( msg_reply, 254, “Server Got Message Code: _IO_MAX + %d”, num );
/* Send a reply to the waiting (blocked) client */
MsgReply( ctp->rcvid, EOK, msg_reply, strlen( msg_reply ) + 1 );
return 0;
}
int main ( int argc, char **argv )
{
resmgr_attr_t resmgr_attr;
message_attr_t message_attr;
dispatch_t *dpp;
dispatch_context_t *ctp, *ctp_ret;
int resmgr_id, message_id;
/* Create the Dispatch Interface */
dpp = dispatch_create();
if( dpp == NULL )
{
fprintf( stderr, “dispatch_create() failed: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
memset( &resmgr_attr, 0, sizeof( resmgr_attr ) );
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
// next 2 lines added by Bill
resmgr_attr.other_func = other_callback;
resmgr_attr.flags |= RESMGR_FLAG_ATTACH_OTHERFUNC;
/* Setup the default I/O functions to handle open/read/write/… */
iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &ConnectFuncs,
_RESMGR_IO_NFUNCS, &IoFuncs );
/* Setup the attribute for the entry in the filesystem */
iofunc_attr_init( &IoFuncAttr, S_IFNAM | 0666, 0, 0 );
resmgr_id = resmgr_attach( dpp, &resmgr_attr, “/dev/serv”,
_FTYPE_ANY, 0, &ConnectFuncs, &IoFuncs, &IoFuncAttr );
if( resmgr_id == -1 )
{
fprintf( stderr, “resmgr_attach() failed: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
/* Setup our private message callback */
memset( &message_attr, 0, sizeof( message_attr ) );
message_attr.nparts_max = 1;
message_attr.msg_max_size = 4096;
/* Attach a callback (handler) for two message types */
// Note: Using this technique, if the server hasn’t registered the message type
// that was sent, it will not receive anything
// unless it also registers an resmgr_attr.other_func and sets
// resmsg_attr.flags |= RESMGR_FLAG_ATTACH_OTHERFUNC;
message_id = message_attach( dpp, &message_attr,
_IO_MAX + 1,_IO_MAX + 2, message_callback, NULL );
if( message_id == -1 )
{
fprintf( stderr, “message_attach() failed: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
/* Setup a context for the dispatch layer to use /
ctp = dispatch_context_alloc( dpp );
if( ctp == NULL )
{
fprintf( stderr, “dispatch_context_alloc() failed: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
/ The “Data Pump” - get and process messages */
while( 1 )
{
ctp_ret = dispatch_block( ctp );
if( ctp_ret )
{
printf( “main loop woke up\n” );
ctp = ctp_ret;
dispatch_handler( ctp );
}
else
{
fprintf( stderr, “dispatch_block() failed: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
#ifdef __USAGE
This is an example Resource Manager Client using
MsgSend() & MsgReply(). It is copied from
http://www.qnx.com/developer/articles/index.html?article=jan2601
#endif
/*
- Message Client Process
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/neutrino.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
typedef struct
{
uint16_t msg_no;
char msg_data[255];
} client_msg_t;
int main ( int argc, char **argv )
{
int fd;
int c;
client_msg_t msg;
int ret;
int num;
char msg_reply [255];
num = 1;
/* Process any command line arguments */
while( ( c = getopt( argc, argv, “n:” ) ) != -1 )
{
if( c == ‘n’ )
{
num = strtol( optarg, 0, 0 );
}
}
/* Open a connection to the server (fd == coid) */
fd = open( “/dev/serv”, O_RDWR );
if( fd == -1 )
{
fprintf( stderr, “Unable to open server connection: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
/* Clear the memory for the msg and the reply */
memset( &msg, 0, sizeof( msg ) );
memset( &msg_reply, 0, sizeof( msg_reply ) );
/* Setup the message data to send to the server */
msg.msg_no = _IO_MAX + num;
snprintf( msg.msg_data, 254, “client %d requesting reply.”, getpid() );
printf( “client: msg_no: _IO_MAX + %d\n”, num );
fflush( stdout );
sleep(10);
/* Send the data to the server and get a reply */
// Note: Using this technique, if the server hasn’t registered the message type
// that was sent, it will not receive anything
ret = MsgSend( fd, &msg, sizeof( msg ), msg_reply, 255 );
sleep(10);
if( ret == -1 )
{
fprintf( stderr, “Unable to MsgSend() to server: %s\n”, strerror( errno ) );
return EXIT_FAILURE;
}
/* Print out the reply data */
printf( “client: server replied: %s\n”, msg_reply );
close( fd );
return EXIT_SUCCESS;
}
–
Bill Caroselli – Q-TPS Consulting
1-(708) 308-4956 <== Note: New Number
qtps@earthlink.net