original files of m241
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user