Files
m241Neelima/vxworks-6.9/target/src/dsi/sockapp/salCommon.c
T
2026-07-30 11:19:44 +05:30

447 lines
13 KiB
C

/* 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;
}