liberipc/src/eripc.c File Reference

#include "eripc.h"
#include "eripcprivate.h"
#include "eripcports.h"
#include "eripcclient.h"
#include "eripclog.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

Go to the source code of this file.

Functions

int erIpcGetVersion ()
int erIpcInitServer (int channelIdx, int *sockfd, int local)
int erIpcStartServer (int channelIdx, erMessageCB callback, char *szBuffer, int *nBuf, void *data)
int erIpcOpenServerChannel (int channelIdx, erServerChannel_t *channel)
int erIpcGetServerFd (erServerChannel_t channel)
int erIpcGetMessage (erServerChannel_t channel, char *szBuffer, int *nBuf)
int erIpcStartClient (int channelIdx, erClientChannel_t *channel)


Function Documentation

int erIpcGetMessage ( erServerChannel_t  channel,
char *  szBuffer,
int *  nBuf 
)

Get a message from the channel, will block when no message is available

Cf. erIpcOpenServerChannel

Parameters:
channel Communication channel
szBuffer Buffer that will be used by callback
nBuf size of szBuffer
Returns:
The file descriptor associated with the channel

Definition at line 184 of file eripc.c.

00185 {
00186     char    szClientIP[INET_ADDRSTRLEN + 1];
00187     struct sockaddr_in clientAdr;
00188     socklen_t len;
00189     int     sockfd;
00190     erInternalServerChannel_t *serverChannel;
00191     int     nBufsize;
00192     int n;
00193 
00194     nBufsize = *nBuf;
00195     serverChannel = (erInternalServerChannel_t *) channel;
00196     sockfd = serverChannel->sockfd;
00197 
00198     // Blocking call.
00199     len = sizeof(clientAdr);
00200     n = recvfrom(sockfd, szBuffer, nBufsize, 0, (struct sockaddr *) &clientAdr, &len);
00201     szBuffer[n] = '\0';
00202     // Who's sending this message?
00203     // clientAdr.sin_addr.s_addr // 32-bit IPv4 address, network byte ordered.
00204     if (inet_ntop(AF_INET, &clientAdr.sin_addr, szClientIP, sizeof(szClientIP)))
00205     {
00206         ERIPC_LOGPRINTF("Message %s received from %s", szBuffer, szClientIP);
00207     }
00208     *nBuf = n;
00209     return 0;
00210 }

int erIpcGetServerFd ( erServerChannel_t  channel  ) 

Fetch the filedescriptor associated with the channel

Cf. erIpcOpenServerChannel

Parameters:
channel Communication channel
Returns:
The file descriptor associated with the channel

Definition at line 176 of file eripc.c.

00177 {
00178     erInternalServerChannel_t *serverChannel;
00179 
00180     serverChannel = (erInternalServerChannel_t *) channel;
00181     return serverChannel->sockfd;
00182 }

int erIpcGetVersion (  ) 

Definition at line 39 of file eripc.c.

00040 {
00041     return ER_IPC_VERSION;
00042 }

int erIpcInitServer ( int  channelIdx,
int *  sockfd,
int  local 
)

Initializes the server. Only use this function when you don't want a dedicated thread for IPC handling.

Parameters:
channelIdx Communication channel identifier
sockfd The socket filedescriptor
local Set to 1 if only local addresses need to be served
Returns:
A value of 0 signals success

Definition at line 48 of file eripc.c.

00049 {
00050     int     error;
00051     int     port;
00052     struct sockaddr_in serverAdr;
00053     int on = 1;
00054 
00055     // test code
00056     ERIPC_WARNPRINTF("Version: %d\n", erIpcGetVersion());
00057 
00058 
00059     *sockfd = socket(AF_INET, SOCK_DGRAM, 0);
00060     error = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on));
00061     if (error)
00062     {
00063         perror("Unable to set socket options to SO_REUSEADDR");
00064     }
00065 
00066     port = erIpcGetServerPort(channelIdx);
00067     if (port == ER_IPC_PORT_ILLEGAL)
00068     {
00069         ERIPC_ERRORPRINTF("Could not allocate channel %d", channelIdx);
00070         return -1;
00071     }
00072 
00073     bzero(&serverAdr, sizeof(serverAdr));
00074     serverAdr.sin_family = AF_INET;
00075     // NOTE :
00076     //   Setting the address to INADDR_LOOPBACK will only allow processes running
00077     // on the same host to send messages to the displayMgrServer
00078     //   Setting the address to INADDR_ANY will allow a process on any host to 
00079     // send messages to the displayMgrServer
00080     if (local == 1)
00081     {
00082         serverAdr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00083     }
00084     else
00085     {
00086         serverAdr.sin_addr.s_addr = htonl(INADDR_ANY);
00087     }
00088     serverAdr.sin_port = htons(port);
00089 
00090     error = bind(*sockfd, (struct sockaddr *) &serverAdr, sizeof(serverAdr));
00091     if (error)
00092     {
00093         perror("Error invoking bind");
00094         return -1;
00095     }
00096     else
00097     {
00098         char    szServerIP[INET_ADDRSTRLEN + 1];
00099 
00100         inet_ntop(AF_INET, &serverAdr.sin_addr, szServerIP, sizeof(szServerIP));
00101         ERIPC_WARNPRINTF("Bound successfully to %s:%d.", szServerIP, port);
00102     }
00103     return 0;
00104 }

Here is the call graph for this function:

int erIpcOpenServerChannel ( int  channelIdx,
erServerChannel_t channel 
)

Create the server side of the IPC communication channel.

After calling this function. Use erIpcGetServerFd() to fetch the filedescriptor associated with this channel. Monitor the filedescriptor for data. When data is available use erIpcGetMessage to fetch the data.

Parameters:
channelIdx Communication channel identifier
channel Opaque datastructure that contains info on communication channel
Returns:
A value of -1 signals failure

Definition at line 147 of file eripc.c.

00148 {
00149     erInternalServerChannel_t *serverChannel;
00150     int     sockfd;
00151     int     nErr;
00152     int     fLocal = 1;
00153 
00154     nErr = erIpcInitServer(channelIdx, &sockfd, fLocal);
00155     if (nErr != 0)
00156     {
00157         ERIPC_ERRORPRINTF("Failed to initialize IPC server");
00158         return -1;
00159     }
00160 
00161     serverChannel = (erInternalServerChannel_t *) malloc(sizeof(erInternalServerChannel_t));
00162 
00163     if (serverChannel != NULL)
00164     {
00165         *channel = (erServerChannel_t) serverChannel;
00166     }
00167     else
00168     {
00169         ERIPC_ERRORPRINTF("Out of memory.");
00170         return -1;
00171     }
00172     serverChannel->sockfd = sockfd;
00173     return 0;
00174 }

Here is the call graph for this function:

int erIpcStartClient ( int  channelIdx,
erClientChannel_t channel 
)

Start the client side of the IPC communication channel

Parameters:
channelIdx Communication channel identifier
channel Opaque datastructure that contains info on communication channel
Returns:
A value of 0 signals success

Definition at line 213 of file eripc.c.

00214 {
00215     erInternalClientChannel_t *clientChannel;
00216     int     port;
00217     int     ret;
00218     struct in_addr destinationAdr;
00219 
00220     // Note. The following variable can be turned into an argument later
00221     //   INADDR_LOOPBACK : "127.0.0.1"
00222     //   INADDR_ANY      : "0.0.0.0"
00223     char    szDestination[] = "127.0.0.1";
00224     int     sockfd;
00225     struct sockaddr_in serverAdr;
00226 
00227     clientChannel = (erInternalClientChannel_t *) malloc(sizeof(erInternalClientChannel_t));
00228 
00229     if (clientChannel != NULL)
00230     {
00231         *channel = (erClientChannel_t) clientChannel;
00232     }
00233     else
00234     {
00235         ERIPC_ERRORPRINTF("Out of memory.");
00236         return -1;
00237     }
00238     clientChannel->sockfd = -1;
00239 
00240     if ((ret = inet_pton(AF_INET, szDestination, &destinationAdr)) == 1)
00241     {
00242         ERIPC_LOGPRINTF("Sending messages to %s", szDestination);
00243     }
00244     else if (ret == 0)
00245     {
00246         ERIPC_WARNPRINTF("%s not a presentation IP address (not in dotted decimal format)", szDestination);
00247         return -1;
00248     }
00249     else
00250     {
00251         ERIPC_WARNPRINTF("Failed to convert to a numeric IP address");
00252         return -2;
00253     }
00254 
00255     port = erIpcGetServerPort(channelIdx);
00256     if (port == ER_IPC_PORT_ILLEGAL)
00257     {
00258         ERIPC_ERRORPRINTF("Could not allocate channel %d", channelIdx);
00259         return -1;
00260     }
00261 
00262 
00263     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
00264     bzero(&serverAdr, sizeof(serverAdr));
00265     serverAdr.sin_family = AF_INET;
00266     serverAdr.sin_addr.s_addr = destinationAdr.s_addr;
00267     serverAdr.sin_port = htons(port);
00268 
00269     clientChannel->sockfd = sockfd;
00270     clientChannel->serverAdr = serverAdr;
00271 
00272     return 0;
00273 }

int erIpcStartServer ( int  channelIdx,
erMessageCB  callback,
char *  szBuffer,
int *  nBuf,
void *  data 
)

Start the server side of the IPC communication channel. Under normal circumstances this function will not return. It invokes a callback when a message is received. It requires its own thread and is the easiest way to establish the server side. Note: Use erIpcOpenServerChannel(), erIpcGetServerFd() and * erIpcGetMessage() if you don't want to create a server specific thread.

Parameters:
channelIdx Communication channel identifier
callback Will be called when a message is received
szBuffer Buffer that will be used by callback
nBuf size of szBuffer
data pointer to opaque datastructure.
Returns:
A value of -1 signals failure

Definition at line 108 of file eripc.c.

00109 {
00110     int     sockfd;
00111     struct sockaddr_in clientAdr;
00112     socklen_t len;
00113     int     n;
00114     int     nErr;
00115     int     fLocal = 1;
00116     erMessageCB messageCallback = NULL;
00117     int     nBufsize;
00118 
00119     nErr = erIpcInitServer(channelIdx, &sockfd, fLocal);
00120     if (nErr != 0)
00121     {
00122         ERIPC_ERRORPRINTF("Failed to start IPC server");
00123         return -1;
00124     }
00125 
00126     nBufsize = *nBuf;
00127     messageCallback = callback;
00128     while (1)
00129     {
00130         char    szClientIP[INET_ADDRSTRLEN + 1];
00131 
00132         // Blocking call.
00133         len = sizeof(clientAdr);
00134         n = recvfrom(sockfd, szBuffer, nBufsize, 0, (struct sockaddr *) &clientAdr, &len);
00135         szBuffer[n] = '\0';
00136         // Who's sending this message?
00137         // clientAdr.sin_addr.s_addr // 32-bit IPv4 address, network byte ordered.
00138         if (inet_ntop(AF_INET, &clientAdr.sin_addr, szClientIP, sizeof(szClientIP)))
00139         {
00140             ERIPC_LOGPRINTF("Message %s received from %s", szBuffer, szClientIP);
00141         }
00142         *nBuf = n;
00143         messageCallback(szBuffer, nBuf, data);
00144     }
00145 }

Here is the call graph for this function:


Generated on Sun Dec 14 17:11:40 2008 by  doxygen 1.5.6