original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
# Makefile - top level makefile for target/src/dsi to build runtime libraries
#
# modification history
# --------------------
# 01c,11oct04,p_r changed description comment to remove "wrn" (SPR#102446)
# 01b,11jun04,ymz removed clean flag.
# 01a,03dec03,als Created from target/src/wrn/Makefile
#
# DESCRIPTION
# This file contains the makefile rules to detect subdirectories that contain
# sources for building the vx library and builds them.
#
#*/
TGT_DIR=$(WIND_BASE)/target
include $(TGT_DIR)/h/make/rules.library
@@ -0,0 +1,22 @@
# Makefile - makefile for dsi/backend
#
# modification history
# --------------------
# 01b,27oct04,bwa added flag to enable Windview instrumentation (SPR# 103042).
# 01a,04oct04,p_r written (SPR#102446)
#
# DESCRIPTION
# This file contains the makefile rules for building the backend library
#
TGT_DIR = $(WIND_BASE)/target
DOC_FILES= dsiSockLib.c
LIB_BASE_NAME = dsi
EXTRA_DEFINE+=-DINCLUDE_WVNETD
OBJS= dsiSockLib.o dsiUtilLib.o
include $(TGT_DIR)/h/make/rules.library
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,186 @@
/* dsiUtilLib.c - utilities for the DSI stack */
/*
* Copyright (c) 2004-2005, 2007, 2011, 2013 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01h,16sep13,f_f fix static overrun (WIND00435182)
01g,07jun11,shi LP64 conversion
01f,04jul07,ebh changes to allow DSI to run in SMP systems
01e,04may07,ebh modify dsiTsleep to return EINTR (Defect #91328)
01d,21feb05,ebh update manually (zippy merge was not running)
01c,28jan05,dlk Fix compiler warning.
01c,04jan05,bwa doc fix (SPR #103021).
01b,11oct04,p_r fixed pathname for dsi header (SPR #102446)
01a,17aug04,dlk written.
*/
/*
DESCRIPTION
This is an internal library that provides general utilities for the DSI
stack.
In particular, it provides the mutual exclusion routines dsiLock() and
dsiUnlock(), which replace splnet() and splx() for the DSI/AF_LOCAL/COMP
stack. It also provides the dsiTsleep() routine, which replaces tsleep()
and ksleep().
NOMANUAL
*/
/* VxWorks system includes */
#include <vxWorks.h>
#include <taskLib.h>
#include <semLib.h>
#include <private/semLibP.h>
#include <errno.h>
#include <dsi/backend/dsiUtilLib.h>
typedef struct _DSI_LOCK_INFO
{
TASK_ID lockTask;
SEMAPHORE sem;
BOOL initialized;
} DSI_LOCK_INFO;
/* globals */
int dsiLockMutexOptions = (SEM_Q_PRIORITY |
SEM_DELETE_SAFE |
SEM_INVERSION_SAFE);
/* locals */
LOCAL DSI_LOCK_INFO dsiLockInfo;
/**************************************************************************
*
* dsiLockInit - initialize AF_LOCAL/COMP/DSI mutual exclusion.
*
* This routine must be called as part of DSI initialization.
*
* RETURNS: OK or ERROR.
*
* NOMANUAL
*/
STATUS dsiLockInit (void)
{
STATUS status;
if (dsiLockInfo.initialized)
return OK;
dsiLockInfo.lockTask = 0;
status = semMInit (&dsiLockInfo.sem, dsiLockMutexOptions);
if (status == OK)
dsiLockInfo.initialized = TRUE;
return status;
}
/**************************************************************************
*
* dsiLock - obtain AF_LOCAL/COMP/DSI mutual exclusion.
*
* This routine is the equivalent of splnet() for the DSI stack.
*
* RETURNS: 1 if the caller owned the DSI lock before the call; 0 if the
* caller did not.
*
* NOMANUAL
*/
int dsiLock (void)
{
if (dsiLockInfo.lockTask == (TASK_ID)taskIdCurrent)
return 1;
(void)semTake (&dsiLockInfo.sem, WAIT_FOREVER);
dsiLockInfo.lockTask = (TASK_ID)taskIdCurrent;
return 0;
}
/**************************************************************************
*
* dsiUnlock - release AF_LOCAL/COMP/DSI mutual exclusion.
*
* This routine is the equivalent of splx() for the DSI stack.
* It gets passed the return value from the corresponding call to
* dsiLock(); it releases mutual exlusion when the argument <key> is zero.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void dsiUnlock
(
int key
)
{
if (key == 0)
{
dsiLockInfo.lockTask = 0;
semGive (&dsiLockInfo.sem);
}
}
/**************************************************************************
*
* dsiTsleep - sleep with a timeout
*
* This routine is the equivalent of tsleep() for DSI.
* It should only be called when holding DSI lock.
*
* NOMANUAL
*/
STATUS dsiTsleep
(
SEM_ID semId,
int timeo_val
)
{
STATUS status;
/* Note, we must be holding the DSI lock */
if (timeo_val != NO_WAIT)
{
/* give up DSI big lock */
dsiLockInfo.lockTask = 0;
semGive (&dsiLockInfo.sem);
/* wait for event */
status = semTake (semId, timeo_val);
/* get DSI big lock */
(void)semTake (&dsiLockInfo.sem, WAIT_FOREVER);
dsiLockInfo.lockTask = (TASK_ID) taskIdCurrent;
}
else
{
/* Do not wait, so don't give up DSI big lock */
status = semTake (semId, timeo_val);
}
/* assume timeout or interruption rather than corruption ! */
return(status == OK ? OK : (errno == EINTR) ? EINTR : EWOULDBLOCK);
}
@@ -0,0 +1,26 @@
# Makefile - makefile for dsi/sockapp
#
# modification history
# --------------------
# 01g,31mar05,ebh added dsalMonitor.o for distributed SAL
# 01f,11oct04,p_r removed reference to "wrn" in comment (part of SPR#102446)
# 01e,01sep04,ymz added snsCommon.c renamed salClientBase.c to salCommon.c
# 01d,25may04,ymz update due to files merging.
# 01c,17feb04,pch remove PPC32 hack, no longer needed
# 01b,03dec03,als simplified DOC_FILES list
# 01a,26nov03,als written
#
# DESCRIPTION
# This file contains the makefile rules for building the sockapp library
#
TGT_DIR = $(WIND_BASE)/target
DOC_FILES= salClient.c salServer.c snsLib.c snsShow.c
LIB_BASE_NAME = dsi
OBJS= salCommon.o salClient.o salSns.o salServer.o snsCommon.o \
snsLib.o snsShow.o snsRtpHook.o dsalMonitor.o
include $(TGT_DIR)/h/make/rules.library
@@ -0,0 +1,795 @@
/* dsalMonitor.c - Distributed SAL Monitor task */
/*
* Copyright (c) 2005-2007, 2011-2013 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01l,27jun13,shi eliminate Coverity warnings.(WIND00423922)
01k,07may13,shi eliminate Coverity warnings.(WIND00416493)
01j,12jul12,shi clean up warnings (WIND00357529)
01i,24jun11,shi LP64 conversion
01h,17oct07,ebh Review comments included
01g,15oct07,ebh modify DSAL sequence to allow for standalone->network mode
transition in TIPC
01f,20jun07,ebh modify outdated comments
01e,15mar06,mze need a delay loop when connecting to the topology server
01d,05jan06,mze update to use new TIPC subcription method
01c,10may05,ebh update to use a single instance value
01b,25apr05,ebh adjusted structures and names
01a,22mar05,ebh created
*/
/*
DESCRIPTION
This code provides a monitor service needed by the distributed
SAL (Socket Application Library) layer. It monitors the network
for new or disappearing SNS servers and flags this information
for processing.
The only responsibility of the dsalMonitor routine is to inform
the SNS server of topology events. The snsServer takes care of
everything else.
Note that the dsalMonitor relies on the TIPC protocol to monitor
all the distributed SNS servers in the network. This method
will obviously fail if TIPC is not part of the system.
The SNS server will query all new SNS servers for all named
sockets that would be visible from this node. Disappearing SNS
servers result in a purge of all information pertaining to that
server from the locally maintained name database.
INTERNAL
Messaging
The SNS server is single-threaded. It can interact
with any number of clients using COMP transport protocol connections
or TIPC protocol connectionless channels (currently only connection
oriented channels).
*/
/* includes */
#include <vxWorks.h>
#include <ctype.h>
#include <dllLib.h>
#include <stdio.h>
#include <errnoLib.h>
#include <hostLib.h>
#include <sockLib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <taskLib.h>
#include <rtpLibCommon.h>
#include <dsi/private/salClientP.h>
#include <dsi/private/salServerP.h>
#include <dsi/private/snsLibP.h>
#include <tipc/tipc.h>
#include <ioLib.h>
/* defines */
#define DPRINT /* swap order of these two lines to enable/disable */
#undef DPRINT /* swap order of these two lines to enable/disable */
#ifdef DPRINT
# define dprintf printf
#else
# define dprintf if (0) printf
#endif
/*******************************************************************************
*
* getSock - local routine getSock
*
* This routine gets a TIPC socket at a time when TIPC is just starting up
* as a result the call to socket may fail. The code will allow for 5 failures
* before it will give up and return ERROR
*
* RETURNS: OK or ERROR
*
* ERRNO:
* \is
* \i "S_salLib_SERVER_SOCKET_ERROR"
* A server socket has failed unexpectedly.
* \ie
*
* \NOMANUAL
*/
LOCAL STATUS getSock
(
int *topsockfd /* topology socket descriptor */
)
{
int sleepCount; /* length of time to sleep */
for (sleepCount = 1, *topsockfd = -1;
(*topsockfd < 0 && sleepCount < 5);
sleepCount++)
{
*topsockfd = socket (AF_TIPC, SOCK_SEQPACKET, 0);
if (*topsockfd >= 0)
{
dprintf("dsalMonitor: set up communication socket %d.\n",
*topsockfd);
break;
}
dprintf("dsalMonitor: Could not set up communication socket, "
"sleeping %d.\nDone.\n",sleepCount);
sleep(sleepCount);
}
if (*topsockfd < 0)
{
dprintf("dsalMonitor: Could not set up communication socket.\nDone.\n");
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* dsalMonitor - Distributed SNS server monitor task
*
* This routine sets up a TIPC socket that monitors topology events in the
* system that deal with distributed SNS server events.
*
* All distributed SNS servers publish their existance in the TIPC world using
* the {type, instance} configured in the CDF files. Each node uses the same
* {type, instance} values.
*
* When a new distributed SNS server is detected, this information is sent to
* the local SNS server via a TIPC message (the local SNS server then adds
* the new server to its list of servers).
*
* When a known distributed SNS server disappears, a message is sent to the
* local SNS server stating that the node is no longer accessible (the local
* SNS server then deletes all socket information in its database pertaining
* to that node).
*
* Order of operations in this routine:
* - detect TIPC being up: use getSock() to repeatedly try to create TIPC socket
* - detect network mode: use subscription to {0, 1-max} to detect other nodes
* - tell our DSAL server we are in network mode
* - enter full monitor state: monitor for external DSAL servers joining/leaving
*
* RETURNS: OK or ERROR
*
* ERRNO:
* \is
* \i "S_salLib_SERVER_SOCKET_ERROR"
* A server socket has failed unexpectedly.
* \i "S_salLib_INTERNAL_ERROR"
* The server's internal data structure has become corrupted.
* \ie
*
* \NOMANUAL
*/
STATUS dsalMonitor (
const unsigned int dsalSnsServerType, /* SNS Server TIPC type */
const unsigned int dsalSnsServerInstance/* SNS Server TIPC instance */
)
{
struct tipc_subscr subscr; /* blocking subscription for dsal */
int dsockfd = -1; /* socket descriptor */
int topsockfd; /* topology socket descriptor */
struct tipc_event event; /* event structure */
DSAL_SNS_MSG msg; /* SNS message */
int msgSize; /* size of the message */
struct sockaddr_tipc addr; /* our TIPC address */
struct sockaddr_tipc dsalTipcAddr; /* topology server address */
int addrSize; /* size of socket structure */
int sleepCount; /* length of time to sleep */
int rc; /* return code for the connect */
dprintf("dsalMonitor: entry (type=%d, instance=%d).\n",
dsalSnsServerType, dsalSnsServerInstance);
/* ensure we have a type and instance to monitor */
if (dsalSnsServerType == 0 || dsalSnsServerInstance == 0)
{
dprintf("dsalMonitor: DSAL type,instance pair not valid.\nDone.\n");
return ERROR;
}
/* create a connection to topology server to ensure TIPC is up */
memset((char*)(&dsalTipcAddr),0,sizeof(dsalTipcAddr));
dsalTipcAddr.family = AF_TIPC;
dsalTipcAddr.addrtype = TIPC_ADDR_NAME;
dsalTipcAddr.addr.name.name.type = TIPC_TOP_SRV;
dsalTipcAddr.addr.name.name.instance = TIPC_TOP_SRV;
dsalTipcAddr.addr.name.domain = 0;
while (1)
{
/* create the socket to communicate with the topology server */
if (getSock(&topsockfd)!= OK)
return ERROR;
/* Connect to topology server - use backoff scheme to connect */
for (sleepCount = 1,rc = -1;(sleepCount<5 && rc <0) ;sleepCount++)
{
rc = connect (topsockfd, (struct sockaddr *)&dsalTipcAddr,
sizeof (dsalTipcAddr));
if (rc >= 0)
{
dprintf("dsalMonitor: connected to topology Server.\n");
break;
}
close(topsockfd); /* must close socket to try this again */
dprintf("dsalMonitor: could not connect to topology Server , sleeping %d.\n",sleepCount);
sleep(sleepCount);
if (getSock(&topsockfd)!= OK)
return ERROR;
}
if (rc < 0)
{
perror("connect to topology server failed \n");
dprintf("dsalMonitor: could not connect to topology Server.\nDone. "
"Socket was %d\n",topsockfd);
goto err_dsal;
}
/* wait for TIPC to go into network mode */
subscr.seq.type = 0;
subscr.seq.lower = 1; /* <0.0.0> is not network mode */
subscr.seq.upper = (unsigned int)-1;
subscr.timeout = WAIT_FOREVER; /* ms */
subscr.filter = TIPC_SUB_SERVICE;
subscr.usr_handle[0] = 0; /* use 0 here to distinguish later */
/* subscribe to topology events */
if (send(topsockfd, (char *) &subscr, sizeof(subscr), 0) != sizeof(subscr))
{
dprintf("dsalMonitor:1 failure to set up a subscription.\n");
goto err_dsal;
}
/* wait until we detect a network subscription */
dprintf("dsalMonitor: waiting for Network subscription event.\n");
if (recv(topsockfd, (char *)&event, sizeof(event), 0) != sizeof(event))
{
/* note that we will lose connectivity when going to network mode,
* but maybe something else entirely happened, so we can't assume
* that we are actually in network mode. So we will have to loop
* back and try again.
*/
dprintf("dsalMonitor: failure to perform block get event.\n");
close(topsockfd); /* close to cancel subscription */
}
else
{
/* we had an event */
dprintf("dsalMonitor: wait for Net UP Event = %d.\n", event.event);
dprintf("dsalMonitor: found_lower = %d, found_upper = %d, handle=%ld.\n",
event.found_lower,event.found_upper, (long)event.s.usr_handle);
dprintf("dsalMonitor: port.ref = %d, port.node = %d.\n",
event.port.ref,event.port.node);
close(topsockfd); /* close to cancel subscription */
break; /* we are done here, exit loop */
}
} /* while loop for NETwork mode detection */
/* continue to detect our own distributed SNS server */
if (getSock(&topsockfd)!= OK)
return ERROR;
rc = connect (topsockfd, (struct sockaddr *)&dsalTipcAddr,
sizeof (dsalTipcAddr));
if (rc < 0)
{
dprintf("dsalMonitor: cannot connect to topology Server (rc=%d, errno=%d).\n", rc, errno);
goto err_dsal;
}
/* Determine own TIPC address - we must have an address in network mode */
addrSize = sizeof(dsalTipcAddr);
if (getsockname(topsockfd, (struct sockaddr *)&dsalTipcAddr, &addrSize) != OK)
{
dprintf("dsalMonitor: could not determine own address.\nDone.\n");
goto err_dsal;
}
/* exit if we are running single node */
if (dsalTipcAddr.addr.id.node == 0)
{
/* we should never be single node mode after detecting network above */
dprintf("dsalMonitor: Should not be here. Running in single node mode. Shutting down.\n");
goto err_dsal;
}
/* Display our own address information */
dprintf("dsalMonitor: TIPC address = <%d.%d.%d>.\n",
tipc_zone (dsalTipcAddr.addr.id.node),
tipc_cluster (dsalTipcAddr.addr.id.node),
tipc_node (dsalTipcAddr.addr.id.node));
/* create the socket to send data to the SNS server */
dsockfd = socket (AF_TIPC, SOCK_RDM, 0);
if (dsockfd < 0)
{
dprintf("dsalMonitor: Could not set up communication socket.\nDone.\n");
goto err_dsal;
}
/* watch for our own node to come up before continuing */
/* monitor the type for our local server */
subscr.seq.type = dsalSnsServerType;
subscr.seq.lower = dsalSnsServerInstance;
subscr.seq.upper = dsalSnsServerInstance;
subscr.timeout = 2000; /* ms */
subscr.filter = TIPC_SUB_PORTS;
subscr.usr_handle[0] = 1;
/* subscribe to topology events */
if (send(topsockfd, (char *) &subscr, sizeof(subscr), 0) != sizeof(subscr))
{
dprintf("dsalMonitor:1 failure to set up a subscription.\n");
goto err_dsal;
}
/* prepare the address structure */
addr.family = AF_TIPC;
addr.addrtype = TIPC_ADDR_ID;
addr.addr.id.node = dsalTipcAddr.addr.id.node;
/* addr.addr.id.ref = _determined below_; */
/* wait until the SNS server on our node comes up */
while (1)
{
/* wait for an event */
if (recv(topsockfd, (char *)&event, sizeof(event), 0) != sizeof(event))
{
dprintf("dsalMonitor: failure to perform block get event.\n");
goto err_dsal;
}
/* we had an event */
dprintf("dsalMonitor: Wait SNS server Event = %d.\n", event.event);
dprintf("dsalMonitor: found_lower = %d, found_upper = %d, handle=%ld.\n",
event.found_lower,event.found_upper, (long)event.s.usr_handle);
dprintf("dsalMonitor: port.ref = %d, port.node = %d.\n",
event.port.ref,event.port.node);
if (event.event == TIPC_PUBLISHED)
{
dprintf("dsalMonitor: event was TIPC_PUBLISHED\n");
if (event.port.node == addr.addr.id.node ||
event.port.node == 0 /* leftover standalone publication */)
{
/* the SNS server on our node is up!! */
addr.addr.id.ref = event.port.ref;
/* send a note to say that network mode in TIPC is achieved */
/* create a message */
msg.cmd = htonl(DSAL_CMD_SNS_NETWORK);
msg.nodeId = htonl(event.port.node);
msg.ref = htonl(event.port.ref);
msgSize = sizeof(msg);
dprintf("dsalMonitor: Msg created (%d bytes) our NODE is now up!\n",msgSize);
/* send the message to the local SNS server */
if (sendto(dsockfd, (char *)&msg, msgSize, 0,
(struct sockaddr *) &addr, sizeof(addr)) != msgSize)
{
dprintf("dsalMonitor: Could not send message to server\n");
goto err_dsal;
}
break; /* no more waiting */
}
}
if (event.event == TIPC_SUBSCR_TIMEOUT)
{
dprintf("event was TIPC_TIMEOUT - did not find local SNS server\n");
goto err_dsal;
}
} /* loop to wait for our distributed SNS server */
/* we do not bother to unsubscribe just look for a usr_handle[0] set to 2 */
/* There really should not be that many events as the system runs unless
* this is a very dynamic system. Even then, it will be a few extra
* events.
*/
/* subscr.seq.type = dsalSnsServerType; */
/* subscr.seq.lower = dsalSnsServerInstance; */
/* subscr.seq.upper = dsalSnsServerInstance; */
subscr.timeout = TIPC_WAIT_FOREVER;
/* subscr.filter = TIPC_SUB_PORTS; */
subscr.usr_handle[0] = 2;
/* subscribe to topology events */
if (send(topsockfd, (char *) &subscr, sizeof(subscr), 0) != sizeof(subscr))
{
dprintf("dsalMonitor:2 failure to set up a subscription.\n");
goto err_dsal;
}
dprintf("dsalServer: entering loop to monitor for changes in servers\n");
FOREVER
{
/* wait for an event */
if (recv(topsockfd, (char *)&event, sizeof(event), 0) != sizeof(event))
{
/* things may be messed up if we get in here - exit */
dprintf("dsalMonitor: failed to read topology event.\n");
goto err_dsal;
}
/* ignore events from earlier subscription */
if (event.s.usr_handle[0] != 2)
{
dprintf("dsalMonitor: Ignoring event (%d, nodeId=0x%x) with handle=%d.\n",
event.event, event.port.node, event.s.usr_handle[0]);
continue;
}
/* we had an event */
dprintf("dsalMonitor: Event = %d.\n", event.event);
dprintf("dsalMonitor: found_lower = %d, found_upper = %d, handle=%ld.\n",
event.found_lower,event.found_upper, (long)event.s.usr_handle);
dprintf("dsalMonitor: port.ref = %d, port.node = %d.\n",
event.port.ref,event.port.node);
/* concerned about TIPC_PUBLISHED and TIPC_WITHDRAWN events only */
if (event.event != TIPC_PUBLISHED && event.event != TIPC_WITHDRAWN)
continue;
dprintf("dsalMonitor: Event %s.\n", event.event == TIPC_PUBLISHED ?
"TIPC_PUBLISHED" : "TIPC_WITHDRAWN");
/* check if this is our own node */
if ((event.port.node == dsalTipcAddr.addr.id.node))
{
dprintf("dsalMonitor: Found our own node. Skipping it.\n");
continue;
}
dprintf("dsalMonitor: Node status changed - will send msg.\n");
/* send a node PUBLISHED / WITHDRAWN message to the local SNS server */
/* create a message */
msg.cmd = (event.event == TIPC_PUBLISHED)
? htonl(DSAL_CMD_SNS_PUBLISHED)
: htonl(DSAL_CMD_SNS_WITHDRAWN);
msg.nodeId = htonl(event.port.node);
msg.ref = htonl(event.port.ref);
msgSize = sizeof(msg);
dprintf("dsalMonitor: Msg created (%d bytes).\n",msgSize);
/* WORKAROUND for Nodes requiring a new route to be established by
* TIPC. In TIPC, when a new node is discovered, it is possible that
* information will get updated in the name table (including any
* publications from that node) before the routing table has had a
* chance to update.
* For any node that requires a route (any node outside our cluster)
* we introduce a slight delay here before telling our SNS server
* about a NEW node. While inefficient, we at least do not slow down
* any active communications using message channels.
*/
if (event.event == TIPC_PUBLISHED)
{
/* see if the new node is in a different cluster */
if ((tipc_cluster(event.port.node)
!= tipc_cluster(dsalTipcAddr.addr.id.node)) ||
(tipc_zone(event.port.node)
!= tipc_zone(dsalTipcAddr.addr.id.node)))
{
dprintf("dsalMonitor: Delay before telling SNS server about node=0x%x\n", event.port.node);
taskDelay(10); /* delay to give TIPC a chance to run */
}
}
/* send the message to the local SNS server */
if (sendto(dsockfd, (char *)&msg, msgSize, 0,
(struct sockaddr *) &addr, sizeof(addr)) != msgSize)
{
dprintf("dsalMonitor: Could not send message to server\n");
goto err_dsal;
}
} /* end of FOREVER */
err_dsal:
/* shut down all sockets */
close(topsockfd);
if (dsockfd >= 0)
close(dsockfd);
/* note that there is no way to exit this routine if things are good */
return ERROR;
}
#if 0 /* EXAMPLE code follows */
/* ****************************************************** */
/* EXAMPLE echo server code */
/* salServer.c - socket application server library */
/*
* salEchoServer - runs an echo server on a node
*
* Usage:
* salEchoServer [ socket_family [, socket_type] ]
* where:
* socket_family defaults to AF_TIPC if not specified
* socket_type defaults to SOCK_SEQPACKET if not specified
*
* This routine sets up a named server called "echo" at the
* cluster scope. If not specified, the server will use AF_TIPC
* and SOCK_SEQPACKET. Both the socket family and socket type can
* be specified as parameters.
*/
#include "vxWorks.h"
#include "sockLib.h"
#include "dsi/salServer.h"
/* defines */
#define MAX_ECHO_SIZE 72 /* max message size */
#define MAX_REQ_COUNT 5 /* max number of client requests */
/* forward declarations */
LOCAL SAL_RTN_STATUS salEchoServerRead (int sockfd, void * pData);
/* This routine creates and runs the server for the echo service */
/* Note that if ai_family is not specified, the code will use AF_TIPC */
STATUS salEchoServer (
int ai_family, /* protocol family to use */
int sock_type /* socket type to use */
)
{
SAL_SERVER_ID serverId; /* server structure */
STATUS result; /* return value */
int count; /* counter */
/* create server socket & register service with SNS */
if (ai_family == 0)
ai_family = AF_TIPC;
if (sock_type == 0)
sock_type = SOCK_SEQPACKET;
if ((serverId = salCreate ("echo@cluster",ai_family, sock_type, 0,
NULL, 0)) == NULL)
{
return ERROR;
}
/* configure read routine for server */
salServerRtnSet (serverId, SAL_RTN_READ, salEchoServerRead);
/* request counter initialized */
count = 0;
/* activate the server (never returns unless a fatal error occurs */
/* or the application processing routine requests a termination) */
result = salRun (serverId, &count);
/* close server socket & deregister service from SNS */
salDelete (serverId);
return result;
}
/* This is the read routine for the echo server. */
LOCAL SAL_RTN_STATUS salEchoServerRead
(
int sockfd, /* active socket to read */
void * pData /* user data */
)
{
char message[MAX_ECHO_SIZE]; /* buffer for message */
int msgSize; /* size of message */
int * pCounter; /* request counter */
/* get message from specified client */
msgSize = recv (sockfd, message, sizeof (message), MSG_DONTWAIT);
if (msgSize <= 0)
{
/* client connection has been closed by client or has failed */
return SAL_SOCK_CLOSE;
}
/* send message back to client */
message[msgSize] = '\0'; /* null terminate string for printing */
printf("SALECHOSERVER: Rcvd %d bytes. ('%s').\n",
msgSize, message);
if (send (sockfd, message, msgSize, MSG_DONTWAIT) < 0)
{
/* client connection has failed */
close (sockfd);
return SAL_SOCK_IGNORE;
}
pCounter = pData;
if (*pCounter++ >= MAX_REQ_COUNT)
return SAL_RUN_TERMINATE;
/* indicate that client connection is still OK */
return SAL_SOCK_KEEP;
}
/* salClient.c - socket application client library */
/*
* salEchoClient - runs an echo client on a node
*
* Usage:
* salEchoClient "string"
*
* This routine sets up a connection to "echo@cluser" if it exists.
* The "string" is sent to the listening server. The echo is checked
* against the sent data for verification.
*/
/* This routine creates and runs a client of the echo service. */
#include "vxWorks.h"
#include "dsi/salClient.h"
#define MAX_ECHO_SIZE 72
STATUS salEchoClient
(
char * message /* message buffer */
)
{
char reply[MAX_ECHO_SIZE]; /* reply buffer */
int replySize; /* size of reply */
int sockfd; /* socket file descriptor */
int msgSize; /* size of the message passed */
msgSize = strlen(message);
/* set up client connection to ECHO server */
if ((sockfd = salOpen ("echo@cluster")) < 0)
{
return ERROR;
}
/* send message to ECHO server and get reply */
replySize = salCall (sockfd, message, msgSize,
reply, sizeof (reply));
/* tear down client connection to ECHO server */
if (close (sockfd) <0)
return ERROR;
/* check that reply matches message */
if (replySize > 0)
{
reply[replySize] = '\0'; /* null terminate string for printing */
printf("SALECHOCLIENT: Sent %d bytes. Received %d bytes ('%s').\n",
msgSize, replySize, reply);
}
else
{
printf("SALECHOCLIENT: Sent %d bytes. Error on return (%d bytes received).\n",
msgSize, replySize);
}
if ((replySize != msgSize) || (memcmp (message, reply, msgSize) != 0))
{
return ERROR;
}
return OK;
}
/* salTest.c - socket application client library */
/*
* salTest - runs a simple test with SAL
*
* Usage:
* salTest n
* where:
* n is the test number
*
* This routine runs a test based on the simple code. It is designed to
* allow the user to create separate simple test functions. This code
* exists only to allow someone to test out something specific in a quick
* manner.
*/
/* This routine creates and runs a client of the echo service. */
#include "vxWorks.h"
#include "dsi/salClient.h"
#define MAX_ECHO_SIZE 72
STATUS salTest
(
int testNum /* test number */
)
{
char reply[MAX_ECHO_SIZE]; /* reply buffer */
int replySize; /* size of reply */
int sockfd; /* socket file descriptor */
int msgSize; /* size of the message passed */
SAL_SERVER_ID servId; /* server structure */
if (testNum == 0)
{
printf("salTest: usage\n");
printf(" salTest(testNum)\n\n");
printf(" where testNum values are:\n");
printf(" 0 = usage\n");
printf(" 1 = salCreate/pause/salDelete\n");
printf(" 2 = ???\n");
return OK;
}
if (testNum == 1)
{
printf("salTest: salCreate/pause/salDelete\n");
printf(" salCreate('mynode@cluster',30,5)\n");
servId = salCreate ("mynode@cluster", 30, 5, 0, NULL, 0);
printf(" servId = %.d\n",servId);
printf("Delay started (600 ticks)...\n");
taskDelay(600); /* 600 ticks ~= 10 seconds */
printf("... delay completed.\n");
printf(" salDelete...\n");
salDelete(servId);
printf(" ... done.\n");
return OK;
}
return OK;
}
#endif
@@ -0,0 +1,765 @@
/* salClient.c - socket application client library */
/*
* Copyright (c) 2003-2005,2007-2008, 2010-2011 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01x,22jul11,shi LP64 conversion
01x,14jan10,pad System Viewer's instrumentation is available in the kernel
only.
01w,12may08,jpb Modifications for source build. Renamed
WV_INSTRUMENTATION to _WRS_CONFIG_SV_INSTRUMENTATION.
01v,04jan07,mze changed calls to freeaddrinfo to snsfreeaddrinfo
01u,16may05,ebh Change ECHO to PING where needed
01t,07mar05,ebh added distributed (AF_TIPC) support (original by fr)
01s,22feb05,ebh update manually (zippy merge was not running)
01r,10jan05,dgp update configuration references
01q,15dec04,aeg added inclusion of unistd.h (SPR #105335).
01p,13oct04,kk updated kernelBaseLib.h to private/kernelBaseLibP.h
01o,13sep04,kk renamed rtpBaseLib.h to kernelBaseLib.h
01n,01sep04,ymz modified documentation.
01m,28may04,ymz removed internal definition of getpid.
01l,20may04,ymz coding convention changes.
01k,19may04,p_r documentation update
01j,18may04,kk replaced rtpIdSelf() with MY_CTX_ID()
01i,26apr04,ymz windview instrumentation.
01h,08apr04,ymz code review changes.
01g,06apr04,ymz fixed bug in salNameFind
01f,30mar04,ymz renamed salSockFind to salSocketFind.
added salNameFind routine.
01e,20feb04,ymz code review changes
01d,08jan04,als enable getpid() support for RTPs (SPR#92745); add examples
01c,08dec03,als revised workaround for determining RTP ID
01b,03dec03,als clean up (comments, errnos, etc.)
01a,26nov03,als created
*/
/*
DESCRIPTION
This portion of the Socket Application Library (SAL) provides the
infrastructure for implementing a socket-based client application.
The routines provided by SAL allow client applications to communicate
easily with socket-based server applications that are registered
with the Socket Name Service (SNS).
Some routines can also be used to communicate with unregistered
server applications.
SAL routines assume connection oriented message based communications.
Although it could provide support for all protocols with the above
features, the current implementation is supporting only local (single node)
inter process communication using the COMP (Connection Oriented Message
Passing) protocol and distributed (multi-node) inter process communication
using the TIPC (Transparent Inter-Process Communication) protocol.
\sh SAL Client
The SAL client API allows a client application to communicate with
a specified server application by using socket descriptors.
A client application can utilize SAL routines to communicate
with different server applications in succession, or create
multiple SAL clients that are each linked to a different server.
A client application typically calls salOpen() to configure a socket descriptor
associated with a named server application. salOpen() simplifies
the procedures needed to initialize the socket and its connection to
the server. The server can be easily identified by a name, represented by
a character string.
The client application can then communicate with the server
by passing the socket descriptor to standard socket API routines,
such as send() and recv().
Alternatively, the client application can perform a send() and recv()
as a single operation using salCall().
When the client application no longer needs to communicate with a server
it calls close() to close the socket to the server.
A client application can utilize salSocketFind() to
exercise more control over the establishment of communication
with a server, as an alternative to using salOpen(). salSocketFind() can
be used to determine the socket addresses related to a
server, and then create a socket to communicate with the server. The client
can therefore choose the server socket address or addresses that better suits
its needs.
A client can also use salNameFind() to identify one or more services based on a
search pattern. Therefore, the client does not need to know the exact name of
a service and, in case multiple names are found, it can choose which ones to
use.
Because normal socket descriptors are used, the client application also has
access to all of the standard socket API.
EXAMPLE
The following code illustrates how to create a client
that utilizes an "ping" service
which simply returns each incoming message to the sender.
The maximum size of a message is limited to MAX_PING_SIZE bytes.
This service uses the connection-based COMP socket protocol.
\cs
/@ This routine creates and runs a client of the ping service. @/
#include "vxWorks.h"
#include "dsi/salClient.h"
#define MAX_PING_SIZE 72
STATUS pingClient
(
char * message, /@ message buffer @/
int msgSize /@ size of message @/
)
{
char reply[MAX_PING_SIZE]; /@ reply buffer @/
int replySize; /@ size of reply @/
int sockfd; /@ socket file descriptor @/
/@ set up client connection to PING server @/
if ((sockfd = salOpen ("ping")) < 0)
{
return ERROR;
}
/@ send message to PING server and get reply @/
replySize = salCall (sockfd, message, msgSize,
reply, sizeof (reply));
/@ tear down client connection to PING server @/
if (close (sockfd) <0)
return ERROR;
/@ check that reply matches message @/
if ((replySize != msgSize) || (memcmp (message, reply, msgSize) != 0))
{
return ERROR;
}
return OK;
}
\ce
CONFIGURATION
To use the SAL client library, configure VxWorks with the INCLUDE_SAL_CLIENT
component.
INCLUDE FILES: salClient.h
SEE ALSO: 'salServer', snsLib
APPEND salCommon.c
*/
/* includes */
#include "vxWorks.h"
#include "errnoLib.h"
#include "hostLib.h"
#include "rtpLib.h"
#include "stdlib.h"
#include "string.h"
#ifdef _WRS_KERNEL
#include "private/kernelBaseLibP.h"
#else
#include "syscall.h"
#endif /* _WRS_KERNEL */
#include "taskLib.h"
#include "sockLib.h"
#include "dsi/private/salClientP.h"
#include "dsi/private/snsLibP.h"
#ifndef _WRS_KERNEL
#include "unistd.h" /* getpid */
#endif /* _WRS_KERNEL */
#ifdef _WRS_KERNEL
#ifdef _WRS_CONFIG_SV_INSTRUMENTATION
#include "private/eventP.h"
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
#endif /* _WRS_KERNEL */
/* forward declarations */
STATUS salSocketSearch
(
const char * name, /* service name in URL format */
int sockFamily, /* desired socket address family */
int sockType, /* desired socket type */
int sockProtocol, /* desired socket protocol */
struct addrinfo ** ppSockInfoList, /* list of socket entries */
snsServDesc * service /* ptr to service descriptor */
);
/*******************************************************************************
*
* salOpen - establish communication with a named socket-based server
*
* This routine establishes a connection to the server application
* corresponding to the SNS service name <name>. If the specified
* service exists salOpen() tries to connect to each of the server's sockets
* in turn, until it is successful or all sockets have been tried;
* it returns the resulting socket descriptor.
*
* <name> is represented in the following URL format:
*
* '[SNS:]service_name[@scope]'
*
* If <name> contains wildcard characters, the routine will use
* the first matching service.
*
* Refer to snsLib for more information on the format and the use
* of wildcards.
*
* This routine uses the default socket options for the client socket it creates;
* if special options are required by the client before completing the connection,
* use salSocketFind() to establish communication with the server.
*
* User should close the returned socket using close().
*
* RETURNS:
* >=0: the descriptor of the newly connected socket;
* -1 : cannot establish communication.
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish connection to the SNS server task.
* \i S_salLib_SNS_DID_NOT_REPLY
* Did not receive a reply from the SNS server task.
* \i S_salLib_SNS_PROTOCOL_ERROR
* Received an invalid reply from the SNS server task.
* \i S_salLib_SERVICE_NOT_FOUND
* The specified service is not registered with SNS.
* \i S_salLib_INVALID_SERVICE_DESCRIPTOR
* The specified service was deregistered from SNS before all socket addresses
* could be examined.
* \i S_salLib_CLIENT_SOCKET_ERROR
* Unable to connect to any of the specified server socket addresses.
* \ie
*
* SEE ALSO: close(), salSocketFind(), snsLib
*/
int salOpen
(
const char * name /* service name in URL format */
)
{
struct addrinfo * pSockInfoList; /* info about server's sockets */
snsServDesc service; /* service descriptor */
int sockfd; /* client socket to the server */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered, client '%s'", name);
/* validate parameters */
if ( (name == NULL) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"invalid parameters, NULL server Id 0x%x", name);
errnoSet (S_salLib_INVALID_ARGUMENT);
return ERROR;
}
/* search from scratch */
service = NULL;
/* continue making connection attempts to services until a successful
connection is made or the service list has been traversed */
FOREVER
{
pSockInfoList = NULL;
/* locate service & get info about server's sockets */
if (salSocketSearch (name, AF_UNSPEC, 0, 0, &pSockInfoList,
&service) == ERROR)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "failed, client '%s'", name);
return ERROR;
}
/* open connection to server */
sockfd = salAttach (pSockInfoList, NULL, 0);
#if defined(_WRS_CONFIG_SV_INSTRUMENTATION) && defined(_WRS_KERNEL)
EVT_OBJ_SAL_STR_2 (EVENT_SALOPEN, name, sockfd);
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
/* release storage for info about server's sockets */
snsfreeaddrinfo (pSockInfoList);
/* break if connection to server is successful */
if (sockfd >= 0) break;
}
/* indicate success or failure */
SAL_DEBUG (SAL_DEBUG_CONTROL, "returned, sockfd 0x%0x", sockfd);
return sockfd;
}
/*******************************************************************************
*
* salSocketFind - find sockets for a named socket-based server
*
* This routine looks for sockets related to a server application
* registered with SNS, which matches the specified search criteria.
* Each socket entry associated with the SNS service name <name>
* is examined to see if it is compatible with the restrictions imposed by
* <sockFamily>, <sockType>, and <sockProtocol>.
* The search succeeds if at least one matching socket entry is found.
*
* <name> is represented in the following URL format:
*
* '[SNS:]service_name[@scope]'
*
* Please refer to snsLib for more information on the format.
*
* If <name> contains wildcard characters, the function will only
* find the first matching service and retrieve its socket information.
*
* To obtain the complete list of service matching the given pattern, use the
* salNameFind() routine.
*
* If <sockInfoList> is not NULL then a list of the matching socket entries
* is created, and <sockInfoList> is set to the start of the list.
* However if <sockInfoList> is NULL, or the service specified by <name>
* does not exist, then no list of socket entries is created
* and <sockInfoList> is left unchanged.
*
* WARNING
* The storage for the socket list created by this routine must be released by
* calling snsfreeaddrinfo() when the list is no longer required.
*
* RETURNS: OK or ERROR
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish connection to the SNS server task.
* \i S_salLib_SNS_DID_NOT_REPLY
* Did not receive a reply from the SNS server task.
* \i S_salLib_SNS_PROTOCOL_ERROR
* Received an invalid reply from the SNS server task.
* \i S_salLib_SERVICE_NOT_FOUND
* The specified service is not registered with SNS.
* \i S_salLib_INVALID_SERVICE_DESCRIPTOR
* The specified service was deregistered from SNS before all socket entries
* could be examined.
* \i S_salLib_NO_SOCKET_FOUND
* The specified service has no sockets that match the desired criteria.
* \ie
*
* SEE ALSO: salNameFind(), snsLib
*/
STATUS salSocketFind
(
const char * name, /* service name in URL format */
int sockFamily, /* desired socket address family */
int sockType, /* desired socket type */
int sockProtocol, /* desired socket protocol */
struct addrinfo ** ppSockInfoList /* list of socket entries */
)
{
snsServDesc service = NULL;
/* start search from beginning of SNS list */
return salSocketSearch (name, sockFamily, sockType, sockProtocol,
ppSockInfoList, &service);
}
/*******************************************************************************
*
* salSocketSearch - continue to find sockets for a named socket based server
*
* This routine looks for sockets related to a server application, but the
* search entry point is specified by the service descriptor which acts as an
* index into the list of services. If <service> is NULL, then the search
* starts at the beginning of the SNS list.
*
* NOMANUAL
*/
STATUS salSocketSearch
(
const char * name, /* service name in URL format */
int sockFamily, /* desired socket address family */
int sockType, /* desired socket type */
int sockProtocol, /* desired socket protocol */
struct addrinfo ** ppSockInfoList, /* list of socket entries */
snsServDesc * service /* ptr to service descriptor */
)
{
int snsClient; /* SNS client sockfd */
SNS_FINDSERV_MSG msg; /* find service msg buffer */
SNS_GET_NAMESOCK_REPLY_MSG reply; /* get socket reply buffer */
int replySize; /* size of reply */
int findErrno; /* error number for routine */
struct addrinfo dummySocket; /* (fake) first socket in list */
struct addrinfo * lastSocket; /* ptr to last socket in list */
int socketCount; /* # of sockets processed */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered", 0);
/* validate parameters */
if ( (name == NULL) || (name[0] == '\0') ||
(strlen (name) > SAL_SERV_NAME_MAXSIZE-1) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid parameters", 0);
errnoSet (S_salLib_INVALID_ARGUMENT);
return ERROR;
}
/* establish client to SNS server */
if ((snsClient = salSnsClientCreate ()) <0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "cannot contact SNS server", 0);
return ERROR;
}
/* create find service message */
msg.cmd = SNS_CMD_FINDSERV;
msg.findSocket = TRUE;
msg.rtpId = (long)getpid ();
strcpy (msg.name, name);
/* search from specified service descriptor */
msg.service = *service;
/* send find service message to SNS server and get reply */
SAL_DEBUG (SAL_DEBUG_ALL, "searching for '%s'", name);
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/*
* set list of sockets to empty
* NOTE: we use a dummy first entry (which is not returned to caller)
* to avoid writing special code to handle insertion into an empty list
*/
dummySocket.ai_next = NULL;
lastSocket = &dummySocket;
/* build list of sockets for service, in the order they are returned */
for (socketCount = 1; ; socketCount++)
{
SNS_GETSOCK_MSG msg; /* get socket info msg buffer */
/* fail if reply is invalid */
findErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (findErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid reply, errno=%0x", findErrno);
break;
}
/* fail if service not known to SNS */
if (reply.service == NULL)
{
SAL_DEBUG (SAL_DEBUG_ALL, "service not known to SNS", 0);
findErrno = reply.getSockErrno;
break;
}
/* compare socket info against hints to see if is acceptable */
if ( ((sockFamily == AF_UNSPEC) ||
(sockFamily == reply.servSockInfo.ai_family)) &&
((sockType == 0) ||
(sockType == reply.servSockInfo.ai_socktype)) &&
((sockProtocol == 0) ||
(sockProtocol == reply.servSockInfo.ai_protocol))
)
{
SAL_DEBUG (SAL_DEBUG_ALL, "socket %d matches hints", socketCount);
/*
* Quit if caller isn't interested in knowing about the sockets
* (one acceptable socket is all that is needed)
*/
if (ppSockInfoList == NULL)
{
SAL_DEBUG (SAL_DEBUG_ALL, "socket list not required", 0);
break;
}
/*
* Allocate space for socket info & append to list.
* (note that the "sockaddr_xxx" structure containing the actual
* socket address is appended to the "addrinfo" struct rather than
* being malloc'd separately -- this is in keeping with the approach
* taken by the getaddrinfo() and freeaddrinfo() routines,
* but we use malloc and snsfreeaddrinfo routines instead)
*/
lastSocket->ai_next = malloc (sizeof (struct addrinfo) +
reply.servSockInfo.ai_addrlen);
lastSocket = lastSocket->ai_next;
if (lastSocket == NULL)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "out of memory", 0);
findErrno = errnoGet (); /* preserve errno from malloc */
break;
}
/* fill in socket info fields */
lastSocket->ai_flags = 0;
lastSocket->ai_family = reply.servSockInfo.ai_family;
lastSocket->ai_socktype = reply.servSockInfo.ai_socktype;
lastSocket->ai_protocol = reply.servSockInfo.ai_protocol;
lastSocket->ai_addrlen = reply.servSockInfo.ai_addrlen;
lastSocket->ai_canonname = NULL;
lastSocket->ai_addr = (struct sockaddr *)(lastSocket + 1);
lastSocket->ai_next = NULL;
/* fill in socket address fields */
memcpy (lastSocket->ai_addr, &reply.servSockAddr,
lastSocket->ai_addrlen);
}
else
{
/* ignore socket that doesn't match hints criteria */
SAL_DEBUG (SAL_DEBUG_ALL,
"socket %d doesn't match hints", socketCount);
}
/* bail out if SNS server has no more socket info to give */
if (reply.done)
{
SAL_DEBUG (SAL_DEBUG_ALL, "all sockets have been examined", 0);
if (dummySocket.ai_next == NULL)
{
/* didn't find any acceptable sockets */
findErrno = S_salLib_NO_SOCKET_FOUND;
}
break;
}
/* create get socket info message */
msg.cmd = SNS_CMD_GETSOCK;
msg.rtpId = (long)getpid ();
msg.service = reply.service;
msg.numSockets = socketCount;
/* send get socket message to SNS server and get reply */
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
}
/* terminate client to SNS server */
salSnsClientDelete (snsClient);
/* indicate results to caller */
if (findErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "failed, errno=%0x", findErrno);
/* free up socket list if find operation failed */
snsfreeaddrinfo (dummySocket.ai_next);
errnoSet (findErrno);
return ERROR;
}
else
{
SAL_DEBUG (SAL_DEBUG_SUCCESS, "succeeded", 0);
/*
* pass back pointer to list of sockets (which may be empty)
* if caller asked us to create such a list
*/
if (ppSockInfoList != NULL)
*ppSockInfoList = dummySocket.ai_next;
/* update service descriptor */
*service = reply.service;
return OK;
}
}
/*******************************************************************************
*
* salNameFind - find services with the specified name
*
* This function returns services with names that match the specified
* <pattern>.
*
* Applications provide the buffer for storing the returned names. The function
* returns the number of names found. The function also returns a cookie for
* follow up searching.
*
* <pattern> is represented in the following URL format:
*
* '[SNS:]service_name[@scope]'
*
* If <pattern> contains wildcard characters, the routine will search for all
* services that match the pattern.
*
* Refer to snsLib for more information on the format and the use
* of wildcards.
*
* The function returns a number of services no greater than <num>.
* If more matches are found the function can be called again to retrieve the
* remaining values. The behavior of the function is determined by
* the <ppCookie> field.
*
* In order to guarantee all data can be retrieved (possibly through
* subsequent calls) when the function is called for the first time,
* the <ppCookie> field needs to be
* non-NULL and the value *<ppCookie> needs to be set to NULL.
* If the returned value *<ppCookie> is still NULL, this means all the services
* matching the <pattern> have been retrieved. XXX - Yiming to verify
* If the returned value *<ppCookie> is not NULL, this means that more matches
* might be available.
* In this case, the client application can call salNameFind() again using the
* returned <ppCookie> to retrieve further entries.
*
* Hence, in order to start a new search, either <ppCookie> is NULL (in which
* case the function can not be called again to retrieve more values) or
* *<ppCookie> is NULL.
*
* RETURNS:
* >=0: number of services found,
* -1: error.
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* Invalid argument.
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish communications with the SNS server task.
* \ie
*
* SEE ALSO: salSocketFind(), snsLib
*/
int salNameFind
(
const char * pattern, /* services name pattern */
char servName[][SAL_SERV_NAME_MAXSIZE],
/* buffer to hold the returned name */
int num, /* number of element in the servNames */
void ** ppCookie /* cookie get/return last matching address */
)
{
int snsClient; /* socket to SNS server */
int replySize; /* SNS server reply msg size */
int numFound; /* number of matching found */
int nameFindErrno; /* errNo for the command */
SNS_FINDSERV_MSG msg; /* message to the SNS server */
SNS_GET_NAMESOCK_REPLY_MSG reply; /* SNS server reply */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered", 0);
if (NULL == pattern || '\0' == pattern[0] ||
strlen (pattern) > SAL_SERV_NAME_MAXSIZE-1 ||
NULL == servName || num<=0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid parameters", 0);
errnoSet (S_salLib_INVALID_ARGUMENT);
return -1;
}
if ((snsClient = salSnsClientCreate ()) < 0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "Cannot connect to SNS server", 0);
return -1;
}
msg.cmd = SNS_CMD_FINDSERV;
msg.findSocket = FALSE;
msg.rtpId = (long)getpid();
strcpy (msg.name, pattern);
/* if user passin NULL cookie reference, search from scratch */
if (NULL == ppCookie)
msg.service = NULL;
else
msg.service = (snsServDesc) *ppCookie;
nameFindErrno = 0;
numFound = 0;
while (numFound < num)
{
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
nameFindErrno =
salSnsClientReplyCheck (replySize, sizeof (reply));
if (nameFindErrno == 0)
nameFindErrno = reply.getSockErrno;
if (nameFindErrno != 0)
break;
if (NULL == reply.service)
{
/* not find anything in this loop, no need to continue */
break;
}
strcpy (servName[numFound], reply.serName);
++numFound;
/* Check if necessary to continue */
if (reply.done)
break;
msg.service = reply.service;
}
salSnsClientDelete (snsClient);
if (nameFindErrno != 0)
{
errnoSet (nameFindErrno);
return -1;
}
if (ppCookie != NULL)
*ppCookie = (reply.done)? NULL:reply.service;
return numFound;
}
@@ -0,0 +1,446 @@
/* salCommon.c - socket application common library */
/*
* Copyright (c) 2003-2008, 2010, 2012 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01n,12jul12,shi clean up warnings (WIND00357529)
01m,14jan10,pad System Viewer's instrumentation is available in the kernel
only.
01l,12may08,jpb Modifications for source build. Renamed
WV_INSTRUMENTATION to _WRS_CONFIG_SV_INSTRUMENTATION.
01k,18apr05,ebh connectionless sockets are considered always connected
01j,16feb05,ebh rename sockopt struct to salSockopt (it conflicts with
target/h/wrn/coreip/net/socketvar.h)
01i,01sep04,ymz renamed from salClientBase.c to salCommon.c (SPR 98185).
01h,25may04,ymz merged salClientSns.c
01g,20may04,ymz coding convention changes.
01f,19may04,p_r documentation update
01e,26apr04,ymz windview instrumentation.
01d,08apr04,ymz iteration 5 code review changes
01c,20feb04,ymz code review changes, added salCall timeout support
01b,03dec03,als clean up (comments, errnos, etc.)
01a,26nov03,als created
*/
/*
DESCRIPTION
This module contains the fundamental routines used by a SAL application,
and utility routines used by the SAL client and server libraries.
The routines assist a SAL client to look up the Socket Name Service (SNS),
and assist a SAL server to register register service with SNS.
These routines have been separated from the main SAL client and server library
so that both the client and the server components can use this common code,
without having to include each other's component.
INCLUDE FILES: salClient.h
NOMANUAL
*/
/* includes */
#include "vxWorks.h"
#include "errnoLib.h"
#include "ioLib.h"
#include "semLib.h"
#include "sockLib.h"
#include "string.h"
#include "sys/socket.h"
#include "sys/un.h"
#include "unistd.h"
#include "dsi/private/salClientP.h"
#include "dsi/private/snsLibP.h"
#include "stdio.h" /* if using DPRINT */
#ifdef _WRS_KERNEL
#ifdef _WRS_CONFIG_SV_INSTRUMENTATION
#include "private/eventP.h"
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
#endif /* _WRS_KERNEL */
/* defines */
#define DPRINT /* swap order of these two lines to enable/disable */
#undef DPRINT /* swap order of these two lines to enable/disable */
#ifdef DPRINT /* local file debug statements when DPRINT defined */
# define dprintf printf
#else
# define dprintf if (0) printf
#endif /* DPRINT */
/*******************************************************************************
*
* salAttach - establish communication with a socket-based server
*
* This routine establishes a connection with the server application
* using the sockets specified by <pSockInfoList>.
* It tries to connect to each of the server's sockets in turn,
* until it is successful or all sockets have been tried.
*
* User should close the attached socket using close().
*
* The <options> parameter points to an array of <numOptions> socket option
* values that are applied to the client socket before a connection is attempted.
* If no options are required, <numOptions> should be set to zero.
*
* If the socket is of a connectionless type, then this routine always
* returns success. This allows the socket to be set up and be considered
* "connected".
*
* RETURNS: >=0 opened socket file descriptor, -1 otherwise
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \i S_salLib_CLIENT_SOCKET_ERROR
* Unable to connect to server using any of the specified socket addresses.
* \ie
*
* SEE ALSO: close().
*
* NOMANUAL
*/
int salAttach
(
struct addrinfo * pSockInfoList, /* list of server sockets */
struct salSockopt * pSockOptions, /* array of socket options */
int numOptions /* number of socket options */
)
{
int newSockfd; /* new client socket */
int currOpt; /* socket option counter */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered, salAttach numOptions=%d.", numOptions);
/* validate parameters */
if ( (pSockInfoList == NULL) || (numOptions < 0) ||
((numOptions > 0) && (pSockOptions == NULL)))
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid parameters, numOptions 0x%x",
numOptions);
errnoSet (S_salLib_INVALID_ARGUMENT);
return -1;
}
/* create connection to one of the specified server sockets */
newSockfd = -1;
for (; pSockInfoList != NULL; pSockInfoList = pSockInfoList->ai_next)
{
/* create a client socket of the same type as the server uses */
dprintf("salAttach: attempt sockfamily=%d.\n",pSockInfoList->ai_family);
dprintf(" socktype=%d.\n",pSockInfoList->ai_socktype);
dprintf(" protocol=%d.\n",pSockInfoList->ai_protocol);
newSockfd = socket (pSockInfoList->ai_family,
pSockInfoList->ai_socktype,
pSockInfoList->ai_protocol);
SAL_DEBUG (SAL_DEBUG_ALL, "socket(...) returned fd=%d\n", newSockfd);
if (newSockfd == ERROR)
{
/* try next server socket */
continue;
}
/* set the socket options (if any) */
for (currOpt = 0; currOpt < numOptions; currOpt++)
{
if (setsockopt (newSockfd, pSockOptions[currOpt].so_level,
pSockOptions[currOpt].so_name,
pSockOptions[currOpt].so_value,
pSockOptions[currOpt].so_length) != OK)
break;
}
if (currOpt != numOptions)
{
SAL_DEBUG (SAL_DEBUG_ALL,
"setsockopt(...) failed on option %d", currOpt);
/* get rid of the newly created client socket */
close (newSockfd);
newSockfd = -1;
/* try next server socket */
continue;
}
/* connect to the server socket - if connection oriented */
if ((pSockInfoList->ai_socktype == SOCK_SEQPACKET) ||
(pSockInfoList->ai_socktype == SOCK_STREAM))
{
if (connect (newSockfd, pSockInfoList->ai_addr,
pSockInfoList->ai_addr->sa_len) < 0)
{
SAL_DEBUG (SAL_DEBUG_ALL,
"connect(...) failed, socket 0x%x", newSockfd);
/* get rid of the newly created client socket */
close (newSockfd);
newSockfd = -1;
/* try next server socket */
continue;
}
}
else
{
dprintf("salAttach: connection-less socket.\n");
}
/* have successfully created a client socket, so exit loop */
break;
}
/* creation fails if unable to create a client socket */
if (newSockfd < 0)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "unable to create a client socket", 0);
errnoSet (S_salLib_CLIENT_SOCKET_ERROR);
return -1;
}
SAL_DEBUG (SAL_DEBUG_SUCCESS, "salAttach returned, sockfd 0x%0x",
newSockfd);
return newSockfd;
}
/*******************************************************************************
*
* salCall - invoke a socket-based server
*
* This routine sends a message to the server associated with the socket
* descriptor <sockfd> and waits for a reply. The message consists of the
* <sendLen> bytes pointed at by <pSendBuf>. The reply is placed in the
* <recvLen> bytes pointed at by <pRecvBuf>. If fewer than <recvLen> bytes
* are received the unused portion of <pRecvBuf> is not altered; if more
* than <recvLen> bytes are received the unused portion of the reply may be
* kept or discarded depending on the socket protocol being used.
*
* If the socket descriptor is used by multiple clients, mutual exclusion
* needs to be provided before this routines is called. This is to avoid the
* case when a reply is intercepted by a higher priority task sharing the
* same <sockfd>.
*
* RETURNS:
* # of bytes placed in reply buffer, for connection based transport,
* 0 bytes may returned when the called end closes the connection;
* ERROR otherwise.
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \ie
*/
int salCall
(
int sockfd, /* client socket fd */
void * pSendBuf, /* message buffer */
int sendLen, /* size of message buffer */
void * pRecvBuf, /* reply buffer */
int recvLen /* size of reply buffer */
)
{
int replySize; /* actual size of reply */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered with sockfd 0x%x", sockfd);
/* validate parameters */
if ( (sockfd < 0) || (pSendBuf == NULL) || (pRecvBuf == NULL) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"invalid parameters, socket 0x%0x", sockfd);
errnoSet (S_salLib_INVALID_ARGUMENT);
return ERROR;
}
#if defined(_WRS_CONFIG_SV_INSTRUMENTATION) && defined(_WRS_KERNEL)
EVT_OBJ_SAL_3 (EVENT_SALCALL_SENDREQ, sendLen, pSendBuf, sockfd);
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
/* send message to server */
SAL_DEBUG (SAL_DEBUG_ALL, "sending %d bytes", sendLen);
if (send (sockfd, pSendBuf, sendLen, 0) == ERROR)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "send to fd=%d failed", sockfd);
return ERROR;
}
/* get reply from server */
replySize = (int)recv (sockfd, pRecvBuf, recvLen, 0);
SAL_DEBUG (SAL_DEBUG_ALL, "received %d bytes", replySize);
#if defined(_WRS_CONFIG_SV_INSTRUMENTATION) && defined(_WRS_KERNEL)
EVT_OBJ_SAL_3 (EVENT_SALCALL_REPLY, replySize, pRecvBuf, sockfd);
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
if (replySize == ERROR)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "recv from fd=%d failed", sockfd);
return ERROR;
}
/* indicate success */
SAL_DEBUG (SAL_DEBUG_CONTROL, "returned, replySize=%d", replySize);
return replySize;
}
/*******************************************************************************
*
* salSnsClientCreate - create an SNS client
*
* This routine establishes communication to the SNS server.
*
* RETURNS: socket fd if >=0; -1 if error.
*
* ERRNO:
* \is
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish communications with the SNS server task.
* \ie
*
* NOMANUAL
*/
int salSnsClientCreate (void)
{
static struct addrinfo snsServerInfo; /* socket info for SNS server */
static struct sockaddr_un snsServerAddr; /* socket address of SNS server */
static BOOL addrCreated = FALSE; /* is server address created? */
int sockfd; /* returned socket fd */
/* create info about the well-known socket for the SNS server */
if (!addrCreated)
{
snsServerAddr.sun_len = sizeof (snsServerAddr);
snsServerAddr.sun_family = AF_LOCAL;
strcpy (snsServerAddr.sun_path, SNS_SERVER_PATH);
snsServerInfo.ai_flags = 0;
snsServerInfo.ai_family = AF_LOCAL;
snsServerInfo.ai_socktype = SOCK_SEQPACKET;
snsServerInfo.ai_protocol = 0;
snsServerInfo.ai_addrlen = snsServerAddr.sun_len;
snsServerInfo.ai_canonname = NULL;
snsServerInfo.ai_addr = (struct sockaddr *)&snsServerAddr;
snsServerInfo.ai_next = NULL;
addrCreated = TRUE;
}
/* try to create a client that connects to the SNS server */
sockfd = salAttach (&snsServerInfo, NULL, 0);
/* indicate results to caller */
if (sockfd < 0)
{
errnoSet (S_salLib_SNS_UNAVAILABLE);
}
return sockfd;
}
/*******************************************************************************
*
* salSnsClientDelete - delete an SNS client
*
* This routine terminates communication with the SNS server.
*
* RETURNS: OK or ERROR.
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \ie
*
* NOMANUAL
*/
STATUS salSnsClientDelete
(
int sockfd /* SNS client socket fd */
)
{
return close (sockfd);
}
/*******************************************************************************
*
* salSnsClientReplyCheck - validate the size of a reply from the SNS server
*
* This routine validates the size of a reply received from the SNS server
* by comparing it to the expected reply size.
*
* RETURNS: S_salLib_SNS_DID_NOT_REPLY if size is negative;
* S_salLib_SNS_PROTOCOL_ERROR if size does not match expected size;
* 0 if size is correct.
*
* NOMANUAL
*/
int salSnsClientReplyCheck
(
int actualSize, /* message actual size */
int expectedSize /* message expected size */
)
{
int checkErrno; /* error code to return */
/* validate size of reply */
if (actualSize < 0)
{
checkErrno = S_salLib_SNS_DID_NOT_REPLY;
}
else if (actualSize != expectedSize)
{
checkErrno = S_salLib_SNS_PROTOCOL_ERROR;
}
else
{
checkErrno = 0;
}
/* indicate results of check */
return checkErrno;
}
File diff suppressed because it is too large Load Diff
+490
View File
@@ -0,0 +1,490 @@
/* salSns.c - socket application serice naming library */
/*
* Copyright (c) 2003-2005, 2011 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01u,22jul11,shi LP64 conversion
01t,25apr05,ebh add 'scope' field to removal structure for distributed SAL
01s,09apr05,ebh added distributed (AF_TIPC) support (original by fr)
01r,22feb05,ebh update manually (zippy merge was not running)
01q,11jan05,dgp convert mangen markup to apigen markup
01p,15dec04,aeg added inclusion of unistd.h (SPR #105335).
01o,13oct04,kk updated kernelBaseLib.h to private/kernelBaseLibP.h
01n,10aug04,kk renamed rtpBaseLib.h to kernelBaseLib.h
01m,10jun04,ymz made salRegsister and salDeregister private API.
01l,27may04,ymz modified comment due to file name change.
01k,21may04,ymz coding convention changes.
01j,19may04,p_r documentation update
01i,18may04,kk replaced rtpIdSelf() with MY_CTX_ID().
01h,14apr04,ymz code review changes.
01g,30mar04,ymz added salRemove support
01f,02mar04,ymz code review changes
01e,23feb04,ymz modified documentation.
01d,08jan04,als enable getpid() support for RTPs (SPR#92745)
01c,08dec03,als revised workaround for determining RTP ID
01b,03dec03,als clean up (comments, errnos, etc.)
01a,26nov03,als created
*/
/*
DESCRIPTION
This module contains routines that allow a SAL server to interact
with the Socket Name Service.
These routines have been separated from the main SAL server library
to allow an application that creates its own sockets
to register a service with the SNS server task
without forcing it to include unnecessary SAL code to create sockets.
INCLUDE FILES: snsLibP.h
\NOMANUAL
*/
/* includes */
#include "vxWorks.h"
#include "errnoLib.h"
#ifdef _WRS_KERNEL
#include "private/kernelBaseLibP.h"
#else
#include "syscall.h"
#include "unistd.h" /* getpid */
#endif /* _WRS_KERNEL */
#include "rtpLib.h"
#include "string.h"
#include "sockLib.h"
#include "taskLib.h"
#include "dsi/private/salClientP.h"
#include "dsi/private/salServerP.h"
#include "dsi/private/snsLibP.h"
#include "tipc/tipc.h"
/* define */
#define DPRINT /* swap order of these two lines to enable/disable */
#undef DPRINT /* swap order of these two lines to enable/disable */
#ifdef DPRINT
# define dprintf printf
#else
# define dprintf if (0) printf
#endif
/*******************************************************************************
*
* salRegister - register a service with SNS
*
* This routine registers the service name <name> with SNS. <name> is represented
* in the following URL format:
*
* '[SNS:]service_name[@scope]'
*
* Refer to snsLib for more information on the format.
*
* The <sockInfoList> parameter points to a list of one or more socket entries
* to be associated with the specified service.
*
* Server applications should typically call salCreate(),
* however this routine is available to applications that wish
* to create their server sockets themselves.
*
* RETURNS: service descriptor for service, or NULL if registration failed
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish communications with the SNS server task.
* \i S_salLib_SNS_DID_NOT_REPLY
* Did not receive a reply from the SNS server task.
* \i S_salLib_SNS_PROTOCOL_ERROR
* Received an invalid reply from the SNS server task.
* \i S_salLib_SNS_OUT_OF_MEMORY
* The SNS server task has insufficient memory to register the service.
* \i S_salLib_SERVICE_ALREADY_EXISTS
* The specified service is already registered with SNS.
* \ie
*
* SEE ALSO: salDeregister(), salCreate (), snsLib
*
* \NOMANUAL
*/
snsServDesc salRegister
(
const char * name, /* service name */
struct addrinfo * pSockInfoList /* list of socket entries */
)
{
int snsClient; /* SNS client socket */
SNS_REGISTER_MSG msg; /* registration msg buffer */
SNS_REGISTER_REPLY_MSG reply; /* registration reply buffer */
int replySize; /* size of reply */
int regErrno; /* error number for routine */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered", 0);
/* validate parameters */
if ( (name == NULL) || (name[0] == '\0') ||
(strlen (name) > sizeof(msg.name)-1) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid service id", 0);
errnoSet (S_salLib_INVALID_ARGUMENT);
return NULL;
}
if ( (pSockInfoList == NULL) || (pSockInfoList->ai_addr == NULL) ||
(pSockInfoList->ai_addrlen > sizeof (msg.sockAddr)) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid socket list", 0);
errnoSet (S_salLib_INVALID_ARGUMENT);
return NULL;
}
/* establish client to SNS server */
if ((snsClient = salSnsClientCreate ()) <0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "cannot contact SNS server", 0);
return NULL;
}
/* create registration message, including info for first socket */
msg.cmd = SNS_CMD_REGISTER;
msg.rtpId = (long)getpid ();
msg.scope = SNS_SCOPE_NONE; /* don't override the scope */
strcpy (msg.name, name);
msg.sockInfo = *pSockInfoList;
memcpy (&msg.sockAddr, pSockInfoList->ai_addr, pSockInfoList->ai_addrlen);
pSockInfoList = pSockInfoList->ai_next;
msg.done = (pSockInfoList == NULL);
/* send registration message and get reply */
SAL_DEBUG (SAL_DEBUG_ALL, "registering '%s'", name);
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/* continue registration until all sockets have been registered */
FOREVER
{
SNS_REGCONT_MSG msg; /* continue reg msg buffer */
/* quit if reply is invalid */
regErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (regErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid reply, errno=%0x", regErrno);
break;
}
/* quit if socket not successfully registered */
if (reply.service == NULL)
{
SAL_DEBUG (SAL_DEBUG_ALL, "SNS socket registration failed", 0);
regErrno = reply.regErrno;
break;
}
SAL_DEBUG (SAL_DEBUG_ALL, "SNS socket registration succeeded", 0);
/* return the scope */
/* quit if all sockets have been registered */
if (pSockInfoList == NULL)
{
SAL_DEBUG (SAL_DEBUG_ALL, "all sockets now registered", 0);
break;
}
/* quit if the next socket to be registered is invalid */
if ( (pSockInfoList->ai_addr == NULL) ||
(pSockInfoList->ai_addrlen > sizeof (msg.sockAddr)) )
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid socket list", 0);
/* deregister the partially registered service */
salDeregister (reply.service);
regErrno = S_salLib_INVALID_ARGUMENT;
break;
}
/* create registration continuation message */
msg.cmd = SNS_CMD_REGCONT;
msg.rtpId = (long)getpid ();
msg.service = reply.service;
msg.sockInfo = *pSockInfoList;
memcpy (&msg.sockAddr, pSockInfoList->ai_addr,
pSockInfoList->ai_addrlen);
pSockInfoList = pSockInfoList->ai_next;
msg.done = (pSockInfoList == NULL);
/* send registration continuation message and get reply */
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
}
/* terminate client to SNS server */
salSnsClientDelete (snsClient);
/* indicate results to caller */
if (regErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "failed, errno=0x%0x\n", regErrno);
errnoSet (regErrno);
return NULL;
}
else
{
SAL_DEBUG (SAL_DEBUG_SUCCESS,
"succeeded, service=0x%0x", reply.service);
return reply.service;
}
}
/*******************************************************************************
*
* salDeregister - deregister a service with SNS
*
* This routine deregisters the service specified by <servDesc> from SNS.
*
* Server applications should typically call salDelete(),
* however this routine is available to applications that wish
* to close their server sockets themselves.
*
* RETURNS: OK or ERROR
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* An invalid argument was passed to this routine.
* \i S_salLib_SNS_UNAVAILABLE
* Unable to establish connection to the SNS server task.
* \i S_salLib_SNS_DID_NOT_REPLY
* Did not receive a reply from the SNS server task.
* \i S_salLib_SNS_PROTOCOL_ERROR
* Received an invalid reply from the SNS server task.
* \i S_salLib_INVALID_SERVICE_DESCRIPTOR
* Service descriptor is not registered with SNS, or has a different owner.
* \ie
*
* SEE ALSO: salRegister(), salDelete(), salRemove()
*
* \NOMANUAL
*/
STATUS salDeregister
(
snsServDesc servDesc /* service descriptor */
)
{
int snsClient; /* SNS client socket */
SNS_DEREGISTER_MSG msg; /* deregistration msg buffer */
SNS_DEREGISTER_REPLY_MSG reply; /* deregistration reply buffer */
int replySize; /* size of reply */
int deregErrno; /* error number for routine */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered, servDesc=0x%0x", servDesc);
/* validate parameters */
if (servDesc == NULL)
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"invalid parameters, servDesc=0x%0x", servDesc);
errnoSet (S_salLib_INVALID_ARGUMENT);
return ERROR;
}
/* establish client to SNS server */
if ((snsClient = salSnsClientCreate ()) <0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"cannot contact SNS server, servDesc=0x%0x", servDesc);
return ERROR;
}
/* create deregistration message */
msg.cmd = SNS_CMD_DEREGISTER;
msg.rtpId = (long)getpid ();
msg.service = servDesc;
/* send deregistration message and get reply */
SAL_DEBUG (SAL_DEBUG_ALL, "deregistering servDesc=0x%0x", servDesc);
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/* see if reply is invalid or service is not known to SNS */
deregErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (deregErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid reply, errno=%0x", deregErrno);
}
else
{
deregErrno = reply.deregErrno;
}
/* terminate client to SNS server */
salSnsClientDelete (snsClient);
/* indicate results to caller */
if (deregErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "failed, errno=%0x", deregErrno);
errnoSet (deregErrno);
return ERROR;
}
else
{
SAL_DEBUG (SAL_DEBUG_SUCCESS, "succeeded, servDesc=0x%0x", servDesc);
return OK;
}
}
/*******************************************************************************
*
* salRemove - Remove service from SNS by name
*
* This function removes a service identified by <name> from SNS.
* Unlike salDelete(), which requires the caller and service owner to be in
* the same memory space, this function can delete any service as long as
* the service is visible to the caller. Therefore, a service with scope
* 'node' can be deleted by any task on the same node, and a service
* with scope 'private' can only be deleted by tasks in the same memory space.
* Further, services of scope 'cluster' (or larger) can only be
* deleted by the node that created them.
*
* <name> is represented in the following URL format:
*
* '[SNS:]service_name[@scope]'
*
* Refer to snsLib for more information on the format.
*
* <name> must uniquely identify a service:
* \is
* \i 'service_name'
* should not contain any wildcard character
* \i scope
* must refer a specific level (i.e. the "upto_" prefix can not be used)
* \ie
*
* NOTE
* This routine removes only the service name from SNS. It does not remove the
* service, nor does it close any of the sockets associated to it. These
* features are provided by salDelete().
*
* RETURNS: OK if the service is removed, ERROR otherwise.
*
* ERRNO:
* \is
* \i S_salLib_INVALID_ARGUMENT
* The service name is invalid
* \i S_salLib_SERVICE_NOT_FOUND
* The specified service is not found.
* \ie
*
* SEE ALSO: salDelete(), salCreate(), snsLib
*/
STATUS salRemove
(
const char * name /* service name */
)
{
SNS_REMOVE_MSG msg; /* message sent to the SNS server */
SNS_REMOVE_REPLY_MSG reply; /* reply from the SNS server */
int snsClient; /* SNS client socket */
int removeErrno; /* error number for routine */
int replySize; /* SNS server replied size */
SAL_DEBUG (SAL_DEBUG_CONTROL, "entered, servname=%s", name);
if (NULL == name || '\0' == name[0] ||
(strlen (name) > sizeof(msg.name)-1))
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"invalid parameters, name=0x%0x", name);
errnoSet (S_salLib_INVALID_ARGUMENT);
return ERROR;
}
/* establish client to SNS server */
if ((snsClient = salSnsClientCreate ()) <0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE,
"cannot contact SNS server, snsClient=0x%0x", snsClient);
return ERROR;
}
msg.cmd = SNS_CMD_REMOVE;
msg.rtpId = (long)getpid();
msg.scope = SNS_SCOPE_NONE;
strcpy (msg.name, name);
/* send remove message and get reply */
SAL_DEBUG (SAL_DEBUG_ALL, "removing service=%s", name);
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/* see if reply is invalid or service is not known to SNS */
removeErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (removeErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_SEVERE, "invalid reply, errno=0x%x", removeErrno);
}
else
{
removeErrno = reply.removeErrno;
}
/* terminate client to SNS server */
salSnsClientDelete (snsClient);
/* indicate results to caller */
if (removeErrno != 0)
{
SAL_DEBUG (SAL_DEBUG_ERROR, "failed, errno=0x%x", removeErrno);
errnoSet (removeErrno);
return ERROR;
}
else
{
SAL_DEBUG (SAL_DEBUG_SUCCESS, "succeeded, name=%s", name);
return OK;
}
}
@@ -0,0 +1,87 @@
/* snsCommon.c - Socket Name Service common library */
/*
* Copyright (c) 2004-2005 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
#include "copyright_wrs.h"
/*
modification history
--------------------
01a,31mar05,ebh added new entries for snsShow to display truncated scope text
01a,22aug04,ymz created (extracted from snsLib.c). SPR 98183
*/
/*
DESCRIPTION
This library contains the Socket Name Service (SNS) common variable
and routine used by snsLib.c and snsShow.c. Therefore, both snsLib
and snsShow components can use the common data and routine but still
decoupled from each other in the project build.
INCLUDE FILES" snsLibP.h
NOMANUAL
*/
/* includes */
#include "vxWorks.h"
#include "dsi/private/snsLibP.h"
/* defines */
/* globals */
/* table used in converting text form of scope to numeric form */
const struct sns_scope_info snsScopeTbl[SNS_NUM_SCOPES] =
{
{ SNS_SCOPE_PRIVATE, SNS_SCOPE_PRIVATE_STR, SNS_SCOPE_UPTO_PRIVATE_STR, SNS_SCOPE_SHOW_PRIVATE_STR},
{ SNS_SCOPE_NODE, SNS_SCOPE_NODE_STR, SNS_SCOPE_UPTO_NODE_STR, SNS_SCOPE_SHOW_NODE_STR},
{ SNS_SCOPE_CLUSTER, SNS_SCOPE_CLUSTER_STR, SNS_SCOPE_UPTO_CLUSTER_STR, SNS_SCOPE_SHOW_CLUSTER_STR},
{ SNS_SCOPE_SYSTEM, SNS_SCOPE_SYSTEM_STR, SNS_SCOPE_UPTO_SYSTEM_STR, SNS_SCOPE_SHOW_SYSTEM_STR}
};
/*******************************************************************************
*
* snsPatMatch - matching a wildcard pattern with a name string
*
* This function matches a pattern with a name string, the function only interpret
* '*'s and/or '?'s as metacharacter for wildcard matching. This function
* does not intepret other classic regular expression such as '.', brackets ,
* backslash escape, nested grouping etc.
*
* Note, '*' denotes any number of characters, including zero,
* '?' denote any single character matching.
*
* RETURNS: 1 if matched, 0 otherwise.
*
* NOMANUAL
*/
int snsPatMatch
(
const char * pat, /* pattern */
const char * str /* string to be matched */
)
{
/*
* The following code should be further optimized to reduce the
* number of recursive calls.
*/
switch (*pat)
{
case '\0': return !*str;
case '*' : return (snsPatMatch (pat+1, str)) ||
(*str && snsPatMatch (pat, str+1));
case '?' : return *str && snsPatMatch (pat+1, str+1);
default : return *pat == *str && snsPatMatch (pat+1, str+1);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,185 @@
/* snsRtpHook.c - Socket Name Service hook for RTP deletion */
/*
* Copyright (c) 2004-2007, 2009, 2011, 2013 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01g,16sep13,f_f fix static overrun (WIND00435182)
01f,19jul11,shi LP64 conversion
01e,03dec09,cww Moved rtp funcbind pointers
01d,20jun07,ebh remove unnecessary variable taskId in snsRtpHookInit
01c,08mar06,ebh correct typo as per code review
01b,12jan05,bwa added check for presence of RTP hooks (SPR105673).
01a,02sep04,ymz created (moved from snsLib.c)
*/
/*
DESCRIPTION
This file contains routines to invoke socket name service (SNS) to
cleanup service records when the RTP where the service resides is deleted.
During the SNS initialization, SNS adds a routine to the RTP delete hook.
The initialization process preallocates a socket used by SNS to receive RTP
delete events.
When a RTP is deleted, the SNS hook is invoked. The routine sends an
asynchronous message to the SNS server asking for cleanup.
The routines in this file runs in the kernel, no matter whether the SNS
server is running in the kernel or in a RTP.
\NOMANUAL
*/
/* includes */
#include <vxWorks.h>
#include <rtpLibCommon.h>
#include <stdio.h>
#include <taskLib.h>
#include <sockLib.h>
#include <private/rtpLibP.h>
#include <dsi/private/salClientP.h>
#include <dsi/private/snsLibP.h>
/* locals */
LOCAL int snsCleanUpSockFd; /* socket to sns server to request cleanup */
/* forward declarations */
LOCAL void snsCleanupRtnInit (void);
LOCAL void snsCleanupHook (const RTP_ID rtpId, const int exitCode);
/*******************************************************************************
*
* snsRtpHookInit - initialize the cleanup mechanism
*
* This function initializes the cleanup mechanism. A task is spawned so the
* vxWorks system initialization process does not get delayed.
*
* RETURNS: OK if initialization completes, ERROR otherwise.
*
* \NOMANUAL
*/
STATUS snsRtpHookInit
(
int pri /* task priority */
)
{
if (_func_rtpDeleteHookAdd == NULL)
{
printf ("Can't initialize SNS cleanup subsystem.\n"
"RTP hooks not present in the system.\n");
return (ERROR);
}
if((taskSpawn ("tSnsCleanupInit",
pri, /* priority */
0, /* task options */
20000, /* stack space */
(FUNCPTR) snsCleanupRtnInit,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) == TASK_ID_ERROR)
{
printf(" Cannot spawn SNS cleanup init task...\n");
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* snsCleanupRtnInit - initializes SNS cleanup hook
*
* This routine initializes SNS cleanup mechanism by setting up RTP
* deletion hook and attaching a connection to the SNS server.
*
* RETURNS: OK if the initialization is successful, ERROR otherwise.
*
* \NOMANUAL
*/
LOCAL void snsCleanupRtnInit (void)
{
int i; /* number of attempts attaching to SNS server */
if ( _func_rtpHandleIdGet == NULL)
{
printf(" SNS cleanup init failed...\n");
return;
}
for (i=0; i<SNS_INIT_RETRY; i++)
{
/* wait if sns server is not started yet */
if ((snsCleanUpSockFd = salSnsClientCreate ()) <0)
taskDelay (SNS_INIT_TIMEOUT*10);
else
{
if (_func_rtpDeleteHookAdd (snsCleanupHook, FALSE) != OK)
{
salSnsClientDelete (snsCleanUpSockFd);
snsCleanUpSockFd = -1;
printf(" Cannot install SNS cleanup hook...\n");
return;
}
/* snsCleanUpSockFd remains opened, no close mechanism
* see comments in snsCleanupHook routine
*/
return;
}
}
printf(" SNS cleanup init failed...\n");
return;
}
/*******************************************************************************
*
* snsCleanupHook - notify SNS server a rtp is being deleted.
*
* This routine notifies SNS server that a RTP is being deleted.
*
* RETURNS: N/A.
*
* \NOMANUAL
*/
LOCAL void snsCleanupHook
(
const RTP_ID rtpId, /* rtp being deleted */
const int exitCode
)
{
SNS_SERV_CLEANUP_MSG msg;
msg.cmd = SNS_CMD_CLEANUP;
msg.rtpId = (long) _func_rtpHandleIdGet (rtpId);
(void) send (snsCleanUpSockFd, (void *) &msg, sizeof (SNS_SERV_CLEANUP_MSG),
MSG_DONTWAIT);
/* we do not check if send is fails, just keep sending
* the alternative is to close the socket and remove delete hook,
* but it is not safe to delete the hook within the hook routine (the
* next hook in the hook array may get skipped to call),
* so we take the policy of doing nothing.
*/
return;
}
@@ -0,0 +1,488 @@
/* snsShow.c - Socket Name Service show routines */
/*
* Copyright (c) 2003-2007, 2012 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01r,12jul12,shi clean up warnings (WIND00357529)
01q,15oct07,ebh handle late change in TIPC address with snsShow()
01p,20jun07,ebh close socket created when getting TIPC address in snsShow()
01o,06jan06,mze change to getSockName from ioctl call
01n,18mar05,ebh add support for distributed SAL
01m,10jan05,dgp update configuration references, migrate to apigen markup
01l,09sep04,ymz improve snsShow output layout (SPR # 101643).
01k,01sep04,ymz modified to use routines in snsCommon.c (SPR 98183).
01j,10jun04,ymz modified documentation.
01i,27may04,ymz removed pSnsShowConvRtn.
01h,24may04,ymz coding convention changes.
01g,19may04,p_r documentation update
01f,14apr04,ymz code review changes.
01e,30mar04,ymz modified to support wildcard pattern.
01d,02mar04,ymz code review changes
01c,02feb04,ymz added message printing even if SNS has no servic record.
Decoupled with TCP/IP stack.
01b,03dec03,als clean up (comments, errnos, etc.)
01a,26nov03,als created
*/
/*
DESCRIPTION
This library provides routines to show information about the services
registered with Socket Name Service (SNS), including the name and scope
of the service and the socket address(es) of the server application
that provides the service.
An SNS server task must be operational, otherwise no information
can be obtained about SNS.
CONFIGURATION
To use the SNS show facility, configure VxWorks with the INCLUDE_SNS_SHOW
component.
INCLUDE FILES: snsLib.h
SEE ALSO: snsLib
*/
/* includes */
#include <vxWorks.h>
#include <errnoLib.h>
#include <stdio.h>
#include <string.h>
#include "dsi/private/salClientP.h"
#include "dsi/private/snsLibP.h"
#include <sockLib.h>
#include <tipc/tipc.h>
/* defines */
#define SNS_SHOW_NAME_LEN 27 /* length of name field */
#define SNS_SHOW_SCOPE_LEN 6 /* length of scope field */
#define SNS_SHOW_FAMILY_LEN 7 /* length of family field */
#define SNS_SHOW_TYPE_LEN 8 /* length of type field */
#define SNS_SHOW_PROTO_LEN 4 /* length of protocol field */
#define SNS_SHOW_ADDR_LEN 26 /* length of address field */
#define SNS_INVALID_TIPC_ADDR (tipc_addr(1,1,0)) /* invalid address */
/* locals */
uint ownTipcAddr = SNS_INVALID_TIPC_ADDR; /* the TIPC address of this node */
/* forward declarations */
LOCAL int snsShowServ (SNS_NEXTSERV_REPLY_MSG * pServInfo, int sockfd);
/*******************************************************************************
*
* snsShow - show information about services in the SNS directory
*
* This routine displays information about the services registered with SNS.
* <servName> is represented in URL format:
*
* '[SNS:]service_name[@scope]'
*
* where the parts in brackets, [ ], are optional.
*
* 'SNS:' represent the URL service, i.e. the Socket Name Service. It is the
* only value accepted and can be omitted.
* '@<scope>' represents the visibility of the service name within the system.
* It can take several values, depending from the context and the application
* needs.
*
* If the the scope is not specified, "@node" is assumed.
*
* The URL representation is case insensitive.
*
* All services whose name begins with the string specified by 'service_name'
* are listed. 'service_name' may contain wildcard characters '*' or '?' for
* name pattern matching, where '*' denotes matching as many characters as
* possible, including zero number of character, '?' denotes matching any single
* character.
*
* If <servName> is NULL, or points to a null string,
* then all services in the SNS directory are listed.
*
* The information displayed for each service listed includes:
* \ml
* \m -
* the service name
* \m -
* the service scope
* \m -
* socket address family associated with the service
* \m -
* socket type associated with the service
* \m -
* socket protocol number associated with the service: 0 represents the
* dummy value, since the socket address family and type are known.
* \m -
* socket address associated with the service
* \me
*
* Examples,
*
* \ts
* NAME............. | SCOPE | FAMILY | .TYPE.. | PROTO | .... ADDR
* ------------------+-------+----------+------------+-------+-----------------
* webAdmin | node | LOCAL | SEQPKT | 0 | /comp/socket/0x4
* eventBlog | priv | LOCAL | SEQPKT | 0 | /comp/socket/0x8
* clusterTimeServer | clust | TIPC | SEQPKT | 0 * | <1.1.5>,1086717964
* \te
*
* RETURNS: N/A.
*
* SEE ALSO: snsLib
*/
void snsShow
(
const char * servName /* service name prefix */
)
{
int snsClient; /* SNS client socket */
SNS_NEXTSERV_MSG msg; /* next service msg buffer */
SNS_NEXTSERV_REPLY_MSG reply; /* next service reply buffer */
int replySize; /* size of reply */
int showErrno; /* error number for command */
int nameLen; /* length of service name prefix */
UINT total; /* total entries found */
int sockfd; /* socket to get tipc address */
struct sockaddr_tipc dsalTipcAddr; /* our TIPC address */
int addrSize; /* address size */
/* establish client to SNS server */
if ((snsClient = salSnsClientCreate ()) <0)
{
printf ("ERROR 0x%08x\n", errnoGet ());
return;
}
/* compute length of service name prefix */
if (servName != NULL)
nameLen = (int)strlen (servName);
else
nameLen = 0;
total = 0;
/* print header */
printf (" NAME SCOPE FAMILY TYPE PROTO ADDR\n");
printf ("-------------------------- ----- ------ ------- ----- --------------------------\n");
/*
* The first time through, try to determine the current TIPC address
* and use it for subsequent calls to this Show command. The
* variable "ownTipcAddr" is initialized to an invalid value on
* startup
*/
if (ownTipcAddr == SNS_INVALID_TIPC_ADDR || ownTipcAddr == 0)
{
ownTipcAddr = 0;
sockfd = socket (AF_TIPC, SOCK_DGRAM, 0);
if (sockfd >= 0)
{
/* Determine own address information */
addrSize = sizeof(dsalTipcAddr);
if (getsockname(sockfd, (struct sockaddr *)&dsalTipcAddr, &addrSize) == OK)
{
/* FIXME: there is no support for a reconfiguration of TIPC */
ownTipcAddr = dsalTipcAddr.addr.id.node;
}
close(sockfd);
}
}
/* loop through all SNS services */
msg.cmd = SNS_CMD_NEXTSERV;
msg.service = NULL;
FOREVER
{
/* send next service message and get reply */
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/* fail if reply is invalid */
showErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (showErrno != 0)
{
break;
}
/*
* fail if next service could not be located
* (i.e. current service has been deregistered)
*/
showErrno = reply.nextServErrno;
if (showErrno != 0)
{
break;
}
/* exit loop if all services have been returned */
if (reply.service == NULL)
{
break;
}
/* see if service name matches prefix specified for show command */
if ( (servName == NULL) ||
(snsPatMatch (servName, reply.servName) == 1) )
{
/* display info about the service; exit loop if an error occurs */
showErrno = snsShowServ (&reply, snsClient);
if (showErrno != 0)
{
break;
}
++total;
}
else
{
/* don't bother printing anything for this service */
}
/* advance to next service in SNS database */
msg.service = reply.service;
}
/* get rid of client to SNS server */
salSnsClientDelete (snsClient);
/* indicate results to user */
if (showErrno != 0)
{
errnoSet (showErrno);
printf ("ERROR 0x%08x\n", showErrno);
}
else
{
if (0 == total)
printf ("\n*** No service found ***\n\n");
}
return;
}
/*******************************************************************************
*
* snsShowServ - show information about a given SNS service
*
* This routine displays information about a service registered with SNS,
* including:
* \ms
* \m -
* service name
* \m -
* service scope (private, local, cluster, or global)
* \m -
* service owner (kernel or RTP id)
* \m -
* service availability (indicates partial registration)
* \m -
* socket addresses associated with service
* \me
*
* RETURNS:
* \is
* \i S_salLib_SNS_DID_NOT_REPLY
* if SNS server task failed to reply,
* \i S_salLib_SNS_PROTOCOL_ERROR
* if SNS server task sent invalid reply,
* \i S_salLib_INVALID_SERVICE_DESCRIPTOR
* if service became deregistered during the display process,
* \i 0
* if service information was displayed successfully
* \ie
*
* \NOMANUAL
*/
LOCAL int snsShowServ
(
SNS_NEXTSERV_REPLY_MSG * pServInfo, /* ptr to next service reply */
int snsClient /* SNS client socket */
)
{
SNS_GETSOCK_MSG msg; /* get socket info msg buffer */
SNS_GET_NAMESOCK_REPLY_MSG reply; /* get socket info reply buffer */
int replySize; /* size of reply */
int showErrno; /* error number for command */
int scopeIdx; /* array index for service scope */
/* do not display yet fully registered service */
if (pServInfo->servAvail != TRUE)
return 0;
/* translate service scope into string form */
for (scopeIdx = 0; scopeIdx < SNS_NUM_SCOPES; scopeIdx++)
{
if (pServInfo->servScope == snsScopeTbl[scopeIdx].value)
{
break;
}
}
if (scopeIdx == SNS_NUM_SCOPES)
{
/* got an invalid scope value from SNS -- should never happen */
return S_salLib_SNS_PROTOCOL_ERROR;
}
/* if the name is too long, print out entirely and push rest to newline */
if (strlen (pServInfo->servName)>SNS_SHOW_NAME_LEN-1)
{
printf ("%-s\n", pServInfo->servName);
printf ("%-*s%-*s", SNS_SHOW_NAME_LEN, " ----",
SNS_SHOW_SCOPE_LEN, snsScopeTbl[scopeIdx].displayScope);
}
else
{
/* print name and scope first */
printf ("%-*s%-*s", SNS_SHOW_NAME_LEN, pServInfo->servName,
SNS_SHOW_SCOPE_LEN, snsScopeTbl[scopeIdx].displayScope);
}
/* loop through all sockets associated with service */
msg.cmd = SNS_CMD_GETSOCK;
msg.rtpId = pServInfo->servOwner;
msg.service = pServInfo->service;
msg.numSockets = 0;
FOREVER
{
/* if more than one socket info to show, only display socket
* info, print spaces for alignment.
*/
if (msg.numSockets !=0)
printf ("%-*s", SNS_SHOW_NAME_LEN + SNS_SHOW_SCOPE_LEN, " ");
/* ask SNS server about specified socket and get reply */
replySize = salCall (snsClient, &msg, sizeof (msg),
&reply, sizeof (reply));
/* fail if reply is invalid */
showErrno = salSnsClientReplyCheck (replySize, sizeof (reply));
if (showErrno != 0)
{
break;
}
/*
* fail if SNS cannot locate current service
* (i.e. current service has been deregistered)
*/
if (reply.service == NULL)
{
showErrno = reply.getSockErrno;
break;
}
/* print info about socket */
switch (reply.servSockInfo.ai_family)
{
case AF_LOCAL:
printf ("%-*s", SNS_SHOW_FAMILY_LEN, "LOCAL");
break;
case AF_TIPC:
printf ("%-*s", SNS_SHOW_FAMILY_LEN, "TIPC");
break;
default:
printf ("%-*s", SNS_SHOW_FAMILY_LEN, "UNKNWN");
break;
}
switch (reply.servSockInfo.ai_socktype)
{
case SOCK_SEQPACKET:
printf ("%-*s", SNS_SHOW_TYPE_LEN, "SEQPKT");
break;
case SOCK_RDM:
printf ("%-*s", SNS_SHOW_TYPE_LEN, "RDM");
break;
case SOCK_DGRAM:
printf ("%-*s", SNS_SHOW_TYPE_LEN, "DGRAM");
break;
case SOCK_STREAM:
printf ("%-*s", SNS_SHOW_TYPE_LEN, "STREAM");
break;
default:
printf ("%-*s", SNS_SHOW_TYPE_LEN, "UNKNWN");
}
printf ("%-*d ", SNS_SHOW_PROTO_LEN-1, reply.servSockInfo.ai_protocol);
switch (reply.servSockInfo.ai_family)
{
case AF_LOCAL:
printf (" %s",
((struct sockaddr_un *)&reply.servSockAddr)->sun_path);
break;
case AF_TIPC:
{
uint addr; /* nodeId of owner of this name */
addr = ((struct sockaddr_tipc *)&reply.servSockAddr)->addr.id.node;
printf("%c", (addr == ownTipcAddr) ? ' ' : '*');
printf (" <%d.%d.%d>,%u",
tipc_zone(addr),
tipc_cluster(addr),
tipc_node(addr),
((struct sockaddr_tipc *)&reply.servSockAddr)->addr.id.ref);
}
break;
default:
break;
}
printf ("\n");
/* end loop if no more socket info to get for current service */
if (reply.done)
break;
/* move on to next socket */
msg.numSockets++;
}
/* indicate results to caller */
return showErrno;
}
+38
View File
@@ -0,0 +1,38 @@
# Makefile - makefile for un
#
# modification history
# --------------------
# 01i,21aug07,ebh Remove extraneous define of _KERNEL (WIND00102055)
# 01h,11oct04,p_r removed coreip reference from comment (SPR#102446)
# 01g,26aug04,ann added changes to select this directory only for 6.0 and
# beyond
# 01f,24may04,ann merged from /main/vdt/base6_itn5-int/1.
# 01e,30apr04,rp check for sh endianness no longer required
# 01d,17feb04,pch remove PPC32 hack, no longer needed
# 01c,05dec03,xli add EXTRA_DEFINE
# 01b,02dec03,bwa changed the make rules
# 01a,09oct03,bwa written
#
# DESCRIPTION
# This file contains the makefile rules for building the un (AF_LOCAL
# domain) library
#
TGT_DIR = $(WIND_BASE)/target
LIB_BASE_NAME = dsi
override EXTRA_DEFINE+=-DZ_PREFIX -D_WRS_VXWORKS_5_5
# Choose what we build for VxWorks 5.x
IS_BASE6 := $(wildcard $(TGT_DIR)/share/h/syscallApi.def)
ifneq ($(IS_BASE6),)
OBJS = unLib.o unShow.o
else
OBJS =
endif
DOC_FILES = unShow.c
include $(TGT_DIR)/h/make/rules.library
@@ -0,0 +1,47 @@
# Makefile - makefile for un/comp
#
# Copyright (c) 2003-2007 Wind River Systems, Inc.
#
# The right to copy, distribute, modify or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
#
# modification history
# --------------------
# 01k,21aug07,ebh Remove extraneous define of _KERNEL (WIND00102055)
# 01j,24aug06,kch Exclude netstat_uncomp.c from compilation for now.
# 01i,11oct04,p_r removed coreip reference from comment (SPR#102446)
# 01h,26aug04,ann added changes to select this directory only for 6.0 and
# beyond
# 01g,02jun04,ann merged from /main/vdt/base6_itn5-int/2.
# 01f,24may04,ann merged from /main/vdt/base6_itn5-int/1.
# 01e,30apr04,rp check for sh endianness no longer required
# 01d,17feb04,pch remove PPC32 hack, no longer needed
# 01c,05dec03,xli add EXTRA_DEFINE
# 01b,02dec03,bwa changed the make rules
# 01a,09oct03,bwa written
#
# DESCRIPTION
# This file contains the makefile rules for building the AF_LOCAL/COMP library
#
TGT_DIR = $(WIND_BASE)/target
LIB_BASE_NAME = dsi
override EXTRA_DEFINE+=-DZ_PREFIX -D_WRS_VXWORKS_5_5 -DINCLUDE_WVNETD $(ARCH_FLAGS)
# Choose what we build for VxWorks 5.x
IS_BASE6 := $(wildcard $(TGT_DIR)/share/h/syscallApi.def)
ifneq ($(IS_BASE6),)
OBJS = unCompLib.o uncomp_usrreq.o uncompShow.o
else
OBJS =
endif
DOC_FILES =
include $(TGT_DIR)/h/make/rules.library
@@ -0,0 +1,277 @@
/* netstat_uncomp.c - netstat() support for AF_LOCAL/COMP */
/*
* Copyright (c) 2004-2005, 2011 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01l,28jun11,shi LP64 conversion
01h,16feb05,aeg changed PRINTF to printf (SPR #106381).
01j,21feb05,ebh update manually (zippy merge was not running)
01i,16feb05,aeg changed PRINTF to printf (SPR #106381).
01h,21jan05,vvv osdep.h cleanup
01g,03jan05,bwa doc fix (SPR #102346).
01f,02nov04,bwa BUG FIX: NULL-pointer dereference (SPR #103461).
01e,11oct04,p_r fixed pathname for dsi header (SPR #102446)
01d,17aug04,dlk Replace splnet()/splx() with dsiLock()/dsiUnlock().
01c,27may04,bwa fixed 'netun' includes (SPR #97714).
01b,03mar04,bwa changed netinet directory references to netun
01a,27jan04,bwa written
*/
/*
DESCRIPTION
This module is the netstat() routine support for the AF_LOCAL/COMP protocol.
The netstat_uncompInit() routine links the AF_LOCAL/COMP netstat support into
the VxWorks system. This is performed automatically if INCLUDE_NETSTAT_UN_COMP
is defined.
NOMANUAL
*/
#include "vxWorks.h"
#include <netconf.h>
#include <stdio.h>
#include <netinet/in.h>
#include <net/socketvar.h>
#include <net/domain.h>
#include <net/protosw.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <dsi/un/uncomp_var.h>
#include <dsi/un/uncomp_fsm.h>
#include <dsi/backend/dsiUtilLib.h>
#include <net/utils/netstat.h>
/* externs */
extern DL_LIST uncompSocketList;
extern char * uncomp_stateGet (uint16_t state, char * pBuffer);
/* forward declarations */
LOCAL void netstat_uncompStats (u_long off, char * name, int af_netstat);
LOCAL void netstat_uncompCblocks (u_long off, char * name, int af_netstat);
/*******************************************************************************
*
* netstatUncompInit - initialize AF_LOCAL/COMP support for netstat()
*
* RETURNS: N/A
*
* NOMANUAL
*/
void netstatUncompInit (void)
{
struct protox *pTp;
/* find slot in netstat()'s table of printing routines */
if ((pTp = name2protox ("comp")) == NULL)
return;
/* hook stats and control block printing routines in COMP's entry */
pTp->pr_stats = NULL;
pTp->pr_cblocks = netstat_uncompCblocks;
}
/*******************************************************************************
*
* netstat_uncompCblocks - routine to print AF_LOCAL/COMP control block
*
* This routine is called from netstat()'s table of printing routines.
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void netstat_uncompCblocks
(
u_long off,
char * name,
int af_netstat
)
{
UNCOMPCB * pUnComp;
int level = dsiLock ();
if ((pUnComp = (UNCOMPCB *) DLL_FIRST (&uncompSocketList)) == NULL)
{
dsiUnlock (level);
return;
}
/* ignore invalid flags passed to netstat for AF_LOCAL/COMP */
if (Rflag || l1flag || bflag || d1flag || gflag || iflag || mflag ||
tflag || Wflag || n1flag)
{
dsiUnlock (level);
return;
}
/* only flags valid for 'netstat -f unix': a, A, and L */
/*
* to be of any use, 'L' flag must be paired with 'a' flag, since
* 'L' prints listening queues, and 'a' prints server sockets, which
* are the only ones to have listening queues
*/
if (Lflag && a1flag)
{
BOOL isfirst = TRUE; /* will print header ? */
/* exhaust the AF_LOCAL/COMP socket list */
do {
/* only print listening sockets */
if (pUnComp->selfState == UNCOMPS_LISTENING)
{
/* print header */
if (isfirst)
{
printf ("\nAF_LOCAL/COMP sockets (servers only)\n\n");
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf (" PCBs ");
#else
printf (" PCBs ");
#endif
printf (" addr qlen qlimit\n");
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf ("--------------------");
#else
printf ("------------");
#endif
printf ("--------------------\n");
isfirst = FALSE; /* won't print header again */
}
/*
* print stats about sockets; in order:
* if 'A' flag is on, CB address;
* socket's address (name);
* # of unaccepted connections;
* max # of unaccepted connections.
*/
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf ("%16p ", (void *)pUnComp);
#else
printf ("0x%8.8x ", (int)pUnComp);
#endif
printf ("0x%4.4x ", pUnComp->selfName);
printf ("%4d ", pUnComp->pSelfSocket->so_qlen);
printf ("%5d", pUnComp->pSelfSocket->so_qlimit);
printf ("\n");
}
} while ((pUnComp = (UNCOMPCB *) DLL_NEXT (pUnComp)) != NULL);
}
else if (!Lflag) /* anything but listening statistics */
{
UNCOMPCB * pUnCompPeer;
BOOL isfirst = TRUE;
char state[20];
/* exhaust AF_LOCAL/COMP socket list */
do {
/* if 'a' is not on, step over listening sockets */
if ((pUnComp->selfState == UNCOMPS_LISTENING) && !a1flag)
continue;
/* print header */
if (isfirst)
{
printf ("\n");
if (a1flag)
printf ("all ");
printf ("AF_LOCAL/COMP sockets");
if (a1flag)
printf (" (including servers)");
printf ("\n");
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf (" ");
#else
printf (" ");
#endif
printf (" data\n");
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf (" PCBs ");
#else
printf (" PCBs ");
#endif
printf ("address peer addr state queued\n");
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf ("--------------------");
#else
printf ("------------");
#endif
printf ("-------------------------------------\n");
isfirst = FALSE; /* won't print header again */
}
/*
* print socket stats, in order:
* if 'A' flag is on, CB address;
* socket's address (name);
* socket's peer's address (name);
* socket's state;
* amount of data queued (in bytes).
*/
if (Aflag)
#ifdef _WRS_CONFIG_LP64
printf ("%16p ", (void *)pUnComp);
#else
printf ("0x%8.8x ", (int)pUnComp);
#endif
printf (" 0x%4.4x ", pUnComp->selfName);
if (pUnComp->pPeerSocket != NULL)
{
pUnCompPeer = SO_TO_UNCOMPCB(pUnComp->pPeerSocket);
printf (" 0x%4.4x ", pUnCompPeer->selfName);
}
else
printf (" N/A ");
uncomp_stateGet (pUnComp->selfState, state);
printf ("%-10.10s ", state);
printf ("%6d", pUnComp->pSelfSocket->so_rcv.sb_cc);
printf ("\n");
} while ((pUnComp = (UNCOMPCB *) DLL_NEXT (pUnComp)) != NULL);
}
dsiUnlock (level);
}
@@ -0,0 +1,154 @@
/* unCompLib.c - initialization of the AF_LOCAL/COMP protocol switch entry */
/* Copyright 2003-2006 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01n,06sep06,kch cleanup coreip stack header files.
01m,21feb05,ebh update manually (zippy merge was not running)
01l,21jan05,vvv osdep.h cleanup
01l,04jan05,bwa removed 'Inst' part of init routine names (SPR #103232).
01k,11oct04,p_r fixed pathname for dsi header (SPR #102446)
01j,17aug04,dlk Replace splnet()/splx() with dsiLock()/dsiUnlock().
01i,27may04,bwa fixed kernel.h/netun include (SPR #97714)
01h,24apr04,p_r fixed headers pathnames
01g,18mar04,bwa changed 'netinet' directory references to 'netun'
01f,19feb04,bwa updated following code review
01e,05dec03,xli change the include path
01d,03dec03,bwa removed test code
01c,26nov03,bwa changed S_unCompLib errnos to S_unLib
01b,25nov03,bwa turned off debugging routines
01a,03nov03,bwa written
*/
/*
DESCRIPTION
This is an internal library that initializes the entry in the protocol switch
for the COMP protocol in the AF_LOCAL domain.
The COMP protocol is the Connection-Oriented Message Passing protocol. In
essence, it is a protocol that require connection between the end sockets and
that treats each packet as a whole message, that are delivered in the order
they are sent.
INTERNAL:
WINDVIEW INSTRUMENTATION
Level 1:
Level 2:
Level 3:
N/A
INCLUDE FILES: unCompLib.h
NOMANUAL
*/
/* VxWorks system includes */
#include <vxWorks.h>
#include <dllLib.h>
#include <errnoLib.h>
#include <string.h>
/* networking includes */
#include <sys/socket.h>
#include <net/domain.h>
#include <net/protosw.h>
#include <net/mbuf.h>
#include <net/systm.h>
#include <dsi/backend/dsiUtilLib.h>
#include <sys/un.h>
#include <dsi/un/uncomp.h>
#include <dsi/un/uncomp_var.h>
#include <dsi/un/unLib.h>
#include <dsi/un/unCompLib.h>
#include <sockLib.h>
/* globals */
DL_LIST uncompSocketList; /* list of AF_LOCAL/COMP sockets */
/* externs */
extern struct domain undomain; /* AF_LOCAL domain */
extern struct protosw unsw[UN_PROTO_MAX]; /* AF_LOCAL protocol switch */
extern struct pr_usrreqs uncomp_usrreqs; /* COMP protocol switch entry */
extern int _unProtoSwIndex; /* 1st available slot in sw */
/* locals */
LOCAL BOOL unCompInitialized = FALSE;
/*******************************************************************************
*
* unCompInit - AF_LOCAL/COMP protocol switch entry initialization
*
* RETURNS: OK or ERROR
*
* ERRNO: S_unLib_COMP_ALREADY_INITIALIZED
* S_unLib_PROTOCOL_SWITCH_FULL
*
* NOMANUAL
*/
STATUS unCompInit (void * pInitValues)
{
struct protosw *pProtoSwitch;
int level;
if (unCompInitialized)
{
errnoSet (S_unLib_COMP_ALREADY_INITIALIZED);
return (ERROR);
}
dsiLockInit ();
level = dsiLock ();
if (_unProtoSwIndex >= sizeof(unsw)/sizeof(unsw[0]))
{
dsiUnlock (level);
errnoSet (S_unLib_PROTOCOL_SWITCH_FULL);
return (ERROR);
}
pProtoSwitch = &unsw [_unProtoSwIndex];
_unProtoSwIndex++;
dsiUnlock (level);
if (pProtoSwitch->pr_domain != NULL)
return (OK); /* already initialized */
pProtoSwitch->pr_type = SOCK_SEQPACKET;
pProtoSwitch->pr_domain = &undomain;
pProtoSwitch->pr_protocol = 0;
pProtoSwitch->pr_flags = PR_CONNREQUIRED | PR_ATOMIC | PR_WANTRCVD;
pProtoSwitch->pr_input = NULL;
pProtoSwitch->pr_output = NULL;
pProtoSwitch->pr_ctlinput = NULL;
pProtoSwitch->pr_ctloutput = NULL;
pProtoSwitch->pr_ousrreq = NULL;
pProtoSwitch->pr_init = NULL;
pProtoSwitch->pr_fasttimo = NULL;
pProtoSwitch->pr_slowtimo = NULL;
pProtoSwitch->pr_drain = NULL;
pProtoSwitch->pr_usrreqs = &uncomp_usrreqs;
dllInit (&uncompSocketList);
unCompInitialized = TRUE;
return (OK);
}
@@ -0,0 +1,199 @@
/* uncompShow.c - information display routines for AF_LOCAL/COMP */
/*
* Copyright (c) 2004-2007 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01l,22jun07,ebh changes to allow COMP to run in SMP systems.
01k,06sep06,kch cleanup coreip stack header files.
01j,16feb05,aeg changed PRINTF to printf (SPR #106381).
01i,21feb05,ebh update manually (zippy merge was not running)
01h,16feb05,aeg changed PRINTF to printf (SPR #106381).
01g,21jan05,vvv osdep.h cleanup
01f,03jan05,bwa doc fix (SPR #102346).
01e,11oct04,p_r fixed pathname for dsi header (SPR #102446)
01d,17aug04,dlk Replace splnet()/splx() with dsiLock()/dsiUnlock().
01c,27may04,bwa fixed 'netun' includes (SPR #97714); fixed bug uncompShow() not
releasing the splnet semaphore when list is empty.
01b,03mar04,bwa changed netinet directory references to netun;
updated uncompShow() display with more relevant information
01a,22jan04,bwa written
*/
/*
DESCRIPTION
This library provides routines to display information for all sockets
and statistics for the AF_LOCAL/COMP protocol.
The uncompShowInit() routine links the AF_LOCAL/COMP show facility into the
VxWorks system. This is performed automatically if INCLUDE_UN_COMP_SHOW is
defined.
NOMANUAL
*/
#include "vxWorks.h"
#include <stdio.h>
#include <netinet/in.h>
#include <dsi/socketvar.h>
#include <net/domain.h>
#include <net/protosw.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <dsi/un/uncomp_var.h>
#include <dsi/un/uncomp_fsm.h>
#include <dsi/backend/dsiUtilLib.h>
/* externs */
extern DL_LIST uncompSocketList;
extern VOIDFUNCPTR _pUncompShow;
extern char * uncomp_stateGet (uint16_t state, char * pBuffer);
/* forward declarations */
LOCAL void uncompPrint (UNCOMPCB * pUnComp);
LOCAL void uncompShow (void);
/******************************************************************************
*
* uncompShowInit - initialize AF_LOCAL/COMP show routines
*
* This routine links the AF_LOCAL show facility into the VxWorks system.
* The library is included automatically if INCLUDE_UN_COMP_SHOW is defined.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void uncompShowInit (void)
{
_pUncompShow = uncompShow;
}
/*******************************************************************************
*
* uncompPrint - prints information on one AF_LOCAL/COMP socket
*
* See unstatShow() in unShow library for sample output and description of
* format.
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void uncompPrint (UNCOMPCB * pUnComp)
{
char state[20]; /* socket state */
struct socket *pSo = pUnComp->pSelfSocket; /* socket */
printf ("%3d", pSo->so_fd); /* socket # (relative to RTP) */
printf (" %4.4X/", pUnComp->selfName); /* socket address (name) */
/* peer socket's address (name) or N/A if not connected */
if (pUnComp->pPeerSocket != NULL)
printf ("%4.4X",(SO_TO_UNCOMPCB(pUnComp->pPeerSocket))->selfName);
else
printf ("NONE");
/* socket's state */
uncomp_stateGet (pUnComp->selfState, state);
printf (" %-10.10s", state);
/* amount of data received */
if (pUnComp->selfState == UNCOMPS_LISTENING)
printf (" %5s", "N/A");
else
printf (" %5d", pSo->so_rcv.sb_cc);
/* high watermark */
if (pUnComp->selfState == UNCOMPS_LISTENING)
printf (" %5s", "N/A");
else
printf (" %5d", pUnComp->hiwatermark);
if (pUnComp->selfState == UNCOMPS_LISTENING)
printf (" %5s", "N/A");
else
printf (" %5d", pUnComp->dropped);
/* unaccepted connections, or N/A if not a listening socket */
if (pUnComp->selfState == UNCOMPS_LISTENING)
printf (" %3d", pSo->so_qlen);
else
printf (" %7s", "N/A");
/* max unaccepted connections if a listening socket */
if (pUnComp->selfState == UNCOMPS_LISTENING)
printf ("/%3d", pSo->so_qlimit);
printf ("\n");
}
/*******************************************************************************
*
* uncompShow - display all AF_LOCAL/COMP sockets
*
* This routine displays a list of all active AF_LOCAL/COMP protocol socket in a
* format similar to the UNIX `netstat -f unix' command.
*
* See unstatShow() in unShow library for sample output and description of
* format.
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void uncompShow (void)
{
DL_NODE * pUnComp;
int level = dsiLock ();
if ((pUnComp = DLL_FIRST (&uncompSocketList)) == NULL)
{
dsiUnlock (level);
return;
}
/* print header */
printf
(
"\nAF_LOCAL/COMP protocol sockets \n"
" pending \n"
" address bytes high packets connections\n"
"so# (self/peer) State of data watermark dropped (cur/max) \n"
"--------------------------------------------------------------------\n"
);
/* exhaust list of AF_LOCAL/COMP sockets */
do {
uncompPrint ((UNCOMPCB *)pUnComp);
} while ((pUnComp = (DL_NODE *) DLL_NEXT (pUnComp)) != NULL);
dsiUnlock (level);
printf ("\n");
}
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
/* unLib.c - installation of the AF_LOCAL domain */
/* Copyright 2003-2006 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01k,06sep06,kch cleanup coreip stack header files.
01j,21feb05,ebh update manually (zippy merge was not running)
01i,21jan05,vvv osdep.h cleanup
01i,04jan05,bwa removed 'Inst' part of init routine names (SPR #103232).
01h,11oct04,p_r fixed pathname for dsi header (SPR #102446)
01g,23sep04,bwa now using dsiDomainAdd() instead of addDomain().
01f,27may04,bwa fixed 'netun' includes (SPR #97714).
01e,18mar04,bwa changed netinet directory references to netun.
01d,19feb04,bwa updated following code review
01c,04dec03,xli change the include path
01b,04dec03,bwa removed debugging info
01a,03nov03,bwa written
*/
/*
DESCRIPTION
This is an internal library that installs the AF_LOCAL domain in the list of
domains and initializes it.
INCLUDE FILES: unLib.h
NOMANUAL
*/
/* VxWorks system includes */
#include <vxWorks.h>
#include <errnoLib.h>
#include <string.h>
/* networking includes */
#include <sys/socket.h>
#include <net/domain.h>
#include <net/protosw.h>
#include <net/mbuf.h>
#include <sys/un.h>
#include <dsi/un/unLib.h>
#include <dsi/backend/dsiSockLib.h>
/* globals */
struct domain undomain; /* AF_LOCAL domain */
struct protosw unsw[UN_PROTO_MAX]; /* AF_LOCAL protocol switch */
int _unProtoSwIndex; /* next available entry in switch */
/* locals */
LOCAL BOOL unLibInitialized = FALSE; /* prevents multiple inits */
/*******************************************************************************
*
* unInit - AF_LOCAL domain initialization
*
* RETURNS: OK or ERROR
*
* ERRNO: S_unLib_ALREADY_INITIALIZED
*
* NOMANUAL
*/
STATUS unInit (void * pInitValues)
{
/* bail out if already initialized */
if (unLibInitialized)
{
errnoSet (S_unLib_ALREADY_INITIALIZED);
return (ERROR);
}
/* record family, name and register AF_LOCAL protocol switch */
undomain.dom_family = AF_LOCAL;
undomain.dom_name = "AF_LOCAL";
undomain.dom_init = NULL;
undomain.dom_externalize = NULL;
undomain.dom_dispose = NULL;
undomain.dom_protosw = unsw;
undomain.dom_protoswNPROTOSW =
&unsw[sizeof(unsw)/sizeof(unsw[0])];
undomain.dom_next = NULL;
undomain.dom_rtattach = NULL;
undomain.dom_rtoffset = 0;
undomain.dom_maxrtkey = 0;
/* ZERO AF_LOCAL protocol switch */
bzero ((char *)unsw, sizeof (unsw));
/* add AF_LOCAL domain to list of domains */
dsiDomainAdd (&undomain);
/* first AF_LOCAL protocol switch entry will be at index 0 */
_unProtoSwIndex = 0;
/* AF_LOCAL domain is now installed */
unLibInitialized = TRUE;
return (OK);
}
+132
View File
@@ -0,0 +1,132 @@
/* unShow.c - information display routines for AF_LOCAL */
/*
* Copyright (c) 2004-2005 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
#include "copyright_wrs.h"
/*
modification history
--------------------
01e,16feb05,aeg changed PRINTF to printf (SPR #106381).
01d,21jan05,vvv osdep.h cleanup
01c,10jun04,bwa corrected man page display (SPR98129).
01b,03mar04,bwa updated unstatShow() display with more relevant information.
01a,22jan04,bwa written.
*/
/*
DESCRIPTION
This library provides routines to display information for all sockets
and statistics for the AF_LOCAL address family.
The unShowInit() routine links the AF_LOCAL show facility into the VxWorks
system. This is performed automatically if INCLUDE_UN_SHOW is defined.
Components need to be added per-protocol as well, eg. INCLUDE_UN_COMP_SHOW
for the COMP protocol unstatShow() support.
INTERNAL
Some routines within this module are preempted by parallel versions
built in to the Tornado shell source code in the $WIND_BASE/host/src/windsh
directory. Changes to these routines must be duplicated within the shell to
maintain consistent output. The versions in this module can still be
accessed by prepending an "@" sign to the routine name.
*/
/* includes */
#include "vxWorks.h"
#include <stdio.h>
/* globals */
VOIDFUNCPTR _pUncompShow = NULL; /* ptr to AF_LOCAL/COMP show routine */
/******************************************************************************
*
* unShowInit - initialize AF_LOCAL show routines
*
* This routine links the AF_LOCAL show facility into the VxWorks system.
* The library is included automatically if INCLUDE_UN_SHOW is defined.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void unShowInit (void)
{
}
/*******************************************************************************
*
* unstatShow - display all AF_LOCAL sockets
*
* This routine displays a list of all AF_LOCAL family sockets in a format
* similar to the UNIX `netstat -f unix' command.
*
* Sample output:
*
* \cs
* AF_LOCAL/COMP protocol sockets
* pending
* address bytes high packets connections
* so# (self/peer) State of data watermark dropped (cur/max)
* --------------------------------------------------------------------
* 7 0001/NONE LISTENING 0 N/A N/A 1/ 20
* 9 0001/0002 EXCHANGING 30012 65535 10 N/A
* 8 0002/0001 EXCHANGING 20014 20014 0 N/A
* 10 0003/NONE LISTENING 0 N/A N/A 5/ 5
* 12 0003/0004 DONE_RECV 0 65535 132 N/A
* 11 0004/0003 DONE_SEND 16 16 0 N/A
* 4 0405/NONE LISTENING 0 N/A N/A 0/ 5
* 5 0000/NONE CLOSED 0 0 0 N/A
* 6 0000/NONE CLOSED 0 0 0 N/A
*
* \ce
* \is
* \i so#
* Socket identifier, relative to owner's RTP.
* \i address
* Socket's and peer's addresses (/comp/socket/0xWXYZ).
* 'peer' is only valid in the following state: 'EXCHANGING', 'DONE_RECV',
* 'DONE_SEND'. 'NONE' is printed otherwise.
* \i state
* \ms
* \m 'CLOSED': starting and ending state: no data can flow
* \m 'LISTENING': socket is a listening one, cannot be used to transfer data
* \m 'EXCHANGING': data can be sent in either direction
* \m 'DONE_SEND': socket can only receive, shutdown(write) has been called on it
* \m 'DONE_RECV': socket can only send, shutdown(write) has been done on peer
* \me
* \i bytes of data
* Amount of data that is pending on the socket, waiting to be received.
* \i high watermark
* Largest amount of pending data at one given time.
* \i dropped packets
* Number of packets dropped due to lack of space in the receiver's buffer space.
* \i pending connections
* Current and maximum number of unaccepted connections on a listening socket,
* i.e.: (number of connect() calls) - (number of accept() calls). 'N/A' is
* printed if not in the LISTENING state.
* \ie
*
* RETURNS: N/A
*/
void unstatShow (void)
{
printf ("\nSockets for AF_LOCAL address family\n");
if (_pUncompShow != NULL)
_pUncompShow();
else
printf ("\nNo protocol show routines installed\n");
}