📄 udpipsck.cpp
字号:
/*
** Make the socket
*/
pData->iSocket = ::socket( AF_INET, SOCK_DGRAM, 0);
if ( pData->iSocket<0 )
{
CONFIG_ERR(pThis, "socket() failed" );
return PIAPI_ERROR;
};
/*
**
** Attempt to bind to port
**
*/
pData->iSize=sizeof( struct sockaddr_in );
pData->tAddr.sin_family = AF_INET;
if (PIUtil_stricmp( pData->pMainSocketData->pHost, VALUE_INADDR_ANY )
&& PIUtil_stricmp( pData->pMainSocketData->pHost, VALUE_INADDR_ZERO ))
{
/*
** Sequence for binding to a specific address
*/
struct hostent *phe = ::gethostbyname( pData->pMainSocketData->pHost );
if ( !phe )
{
CONFIG_ERR(pThis, "gethostbyname() failed" );
return PIAPI_ERROR;
};
/* --- setup local address structure -- */
memcpy( &(pData->tAddr.sin_addr.s_addr), phe->h_addr, phe->h_length );
}
else
{
/*
** Sequence for binding to any address
*/
pData->tAddr.sin_addr.s_addr=htonl(INADDR_ANY);
}
pData->tAddr.sin_port = htons( pData->pMainSocketData->iPort );
#if 0
// LATER
/*
** Allow host,port to be reused (or attempt to reuse existing host,port)
*/
if ( ::setsockopt( pData->iSocket, SOL_SOCKET, SO_REUSEADDR,
(const char *)&iOne, sizeof( iOne ) )!=0 )
{
CONFIG_ERR(pThis, "setsockopt() failed for SO_REUSEADDR" );
return PIAPI_ERROR;
};
#endif
if ( ::bind( pData->iSocket, (struct sockaddr *)&(pData->tAddr),
pData->iSize)<0)
{
const char *pError = "";
switch( errno )
{
case EACCES:
pError = szBindFailedAccess;
break;
case EINVAL:
#if POSIX
case EADDRINUSE:
#endif
pError = szBindFailedInUse;
break;
default:;
};
PILog_addMessage(
PIObject_getDB( pThis ),
PIObject_getConfigurationDB( pThis ), PILOG_ERROR,
"Failed to bind to port %d.%s", pData->pMainSocketData->iPort,
pError );
return PIAPI_ERROR;
};
/*
** Done
*/
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function: Internal_getHostEnt
Synopsis: private
Description:
returns a struct hostent *, given either an id address or hostname
as parameter.
\*____________________________________________________________________________*/
struct hostent *Internal_getHostEnt( const char *pHost )
{
int i;
int iIsAddr=1;
int iLen;
struct hostent *phe;
/*
** If the string consists only of decimal digits and '.'
** assume its an IP address
*/
if ( !pHost ) return 0;
iLen = strlen( pHost );
for(i=0; i<iLen; i++)
{
if ( !isdigit( pHost[i] ) && pHost[i]!='.' )
{
iIsAddr=0;
break;
};
};
/* --- get hostent * --- */
phe=0;
if ( iIsAddr )
{
struct in_addr tAddr;
u_long ul;
int iSize;
ul = inet_addr( pHost );
iSize = sizeof( struct in_addr );
memcpy( &tAddr, &ul, iSize );
phe = gethostbyaddr( (const char *)&tAddr, iSize, AF_INET);
}
else
{
phe = gethostbyname( pHost );
};
return phe;
}
/*____________________________________________________________________________*\
*
Function: Internal_connect
Synopsis:
Description:
Open a connection to a remote host
\*____________________________________________________________________________*/
static int Internal_connect( PIObject *pThis,
const char *pHostName, int iPort )
{
/* automatic variables */
UDPIPSocketData *pData=(UDPIPSocketData *)PIObject_getUserData( pThis );
struct hostent *phe;
assert( pData );
/*
** Make the socket
*/
pData->iSocket = ::socket( AF_INET, SOCK_DGRAM, 0);
if ( pData->iSocket==SOCKET_ERROR )
{
PIPlatform_setLastError( PIAPI_EXHAUSTED );
CONFIG_ERR(pThis, "socket() failed" );
return PIAPI_ERROR;
};
/*
** setup pData->tAddr with remote host information.
*/
phe=Internal_getHostEnt( pHostName );
if ( !phe )
{
PIPlatform_setLastError( PIAPI_ERROR );
return PIAPI_ERROR;
};
pData->iSize=sizeof( struct sockaddr_in );
pData->tAddr.sin_family = AF_INET;
memcpy( &(pData->tAddr.sin_addr), phe->h_addr, phe->h_length );
pData->tAddr.sin_port = htons( iPort );
/*
** bind
*/
/* or not to bind */
/*
** connect
*/
if ( connect( pData->iSocket, (struct sockaddr *)&(pData->tAddr),
pData->iSize )<0 )
{
PIPlatform_setLastError( PIAPI_ERROR );
return PIAPI_ERROR;
};
/* ---
**
**
** This is a new connection. Look at the flags and variable names
** to see what lookups should occur and where the data is put
**
**
--- */
/* --- should this object set the PeerIP address? --- */
int iFlags = pData->pMainSocketData->iFlags;
/* ---
Set PeerAddress variable, if applicable
--- */
/* ---
When the hostname is unavailable just have it turn up blank
# define TEXT_UNAVAILABLE "** Unavailable **"
--- */
# define TEXT_UNAVAILABLE ""
if ( iFlags & FLG_SETREMOTEADDRESS )
{
/* --- set remote Address ? --- */
DBInfo *pIPInfo = pData->pMainSocketData->pPeerAddressVariable;
if ( pIPInfo )
{
/* ---
inet_ntoa is not thread safe, protect access to it
--- */
PIPlatform_beforeUnsafeBlock();
/* --- convert the peer ip to a string if we have the ip --- */
const char *pPeerAddress = 0;
pPeerAddress = ::inet_ntoa( pData->tAddr.sin_addr );
PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
pIPInfo->pFKVariableName, (void *)pPeerAddress,
pIPInfo->iFlags | PIDBFLAG_FASTKEY );
PIPlatform_afterUnsafeBlock();
};
if ( iFlags & FLG_DNSREVERSELOOKUP )
{
/* --- set remote hostname ? --- */
DBInfo *pHostInfo = pData->pMainSocketData->pPeerHostVariable;
if ( pHostInfo )
{
/* ---
inet_ntoa is not thread safe, protect access to it
--- */
PIPlatform_beforeUnsafeBlock();
/* --- if we have the ip structure, lookup the hostname --- */
struct hostent *pEnt;
pEnt = ::gethostbyaddr(
(const char *)&(pData->tAddr.sin_addr),
sizeof(pData->tAddr.sin_addr), AF_INET );
PIDB_add( PIObject_getDB( pThis ), pHostInfo->iType,
pHostInfo->pFKVariableName,
(void *)( pEnt ? pEnt->h_name : TEXT_UNAVAILABLE ),
pHostInfo->iFlags | PIDBFLAG_FASTKEY );
PIPlatform_afterUnsafeBlock();
};
};
/* ---
set ServerPort variable
--- */
DBInfo *pPortInfo = pData->pMainSocketData->pServerPortVariable;
if ( pPortInfo ) {
char szPort[6];
char *pPort = szPort;
sprintf(pPort, "%lu", iPort);
PIDB_add( PIObject_getDB( pThis ), pPortInfo->iType, pPortInfo->pFKVariableName,
(void *)pPort, 0 );
};
};
/* ---
Set LocalAddress if applicable
--- */
if ( iFlags & FLG_SETLOCALADDRESS )
{
DBInfo *pIPInfo = pData->pMainSocketData->pLocalAddressVariable;
if ( pIPInfo )
{
struct sockaddr_in tLocalAddr;
int iLocalSize = sizeof( struct sockaddr_in );
for(;;)
{
/* --- get local socket information --- */
if ( ::getsockname( pData->iSocket,
(struct sockaddr *)&tLocalAddr,
&((uint)iLocalSize) )==-1 )
{
if ( errno==EINTR )
{
/* --- restart system call --- */
PIThread_userYield();
continue;
};
iLocalSize = 0; /* indicate an error */
};
break;
};
if ( iLocalSize>0 )
{
/* ---
inet_ntoa is not thread safe, protect access to it
--- */
PIPlatform_beforeUnsafeBlock();
const char *pLocalAddress = 0;
pLocalAddress = ::inet_ntoa( tLocalAddr.sin_addr );
PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
pIPInfo->pFKVariableName, (void *)pLocalAddress,
pIPInfo->iFlags | PIDBFLAG_FASTKEY );
PIPlatform_afterUnsafeBlock();
}
else
{
/* --- error --- */
STDERR << "getsockname() failed, errno#" << errno << endl;
PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
pIPInfo->pFKVariableName, (void *)"0.0.0.0",
pIPInfo->iFlags | PIDBFLAG_FASTKEY );
}; /* iLocalSize!=0 */
}; /* pIPInfo!=NULL */
}; /* iFlags & FLG_SETLOCALADDRRESS */
/* ---
Write send and receive timeout into the DB, to be overridden as
necessary
--- */
assert( pFKRecvTimeout );
assert( pFKSendTimeout );
PIDB_add( PIObject_getDB( pThis ), PIDBTYPE_OPAQUE, pFKRecvTimeout,
(void *)(pData->pMainSocketData->iRecvTimeout), PIDBFLAG_FASTKEY );
PIDB_add( PIObject_getDB( pThis ), PIDBTYPE_OPAQUE, pFKSendTimeout,
(void *)(pData->pMainSocketData->iSendTimeout), PIDBFLAG_FASTKEY );
/*
** Done
*/
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
int MainSocketData::Accept( UDPIPSocketData *pData, PIObject *pNewSocket )
{
/* --- automatic variables --- */
int iRet;
UDPIPSocketData *pChildData;
if ( !pNewSocket ) return PIAPI_ABORT;
/* --- get data object of child class --- */
pChildData=(UDPIPSocketData *)PIObject_getUserData( pNewSocket );
/*
** Accept a new connection
*/
iRet=-1;
/* --- note the new accepting IO object, so it can be deleted --- */
pAcceptingIOObject = pNewSocket;
for(;;)
{
/* --- test that accept is possible --- */
if ( PIPlatform_pollNetFD( pData->iSocket, PIPLATFORM_POLL_READ,
iAcceptTimeout ) <=0 )
{
break;
};
#if POSIX
/* ---
wait to acquire the POSIX lock to stop multiple
processes colliding on the accept
--- */
if ( iFAcceptLockFD!=-1 )
{
/* ---
Lock
--- */
if ( PIPlatform_advisaryLockFd( iFAcceptLockFD )!=PIAPI_COMPLETED )
{
/* --- an error occurred in lock --- */
PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
"UDPIPIO: Error obtaining lock (locking failed) errno: \
'%d'.\
Removing lockfile to force server shutdown.", errno );
/* ---
remove lockfile to shutdown entire server
see notes above.
--- */
::unlink( pFAcceptLockFile ); /* --- remove file --- */
return PIAPI_ABORT;
};
};
#endif
#if 0
/* --- accept the connection --- */
iNewS=::accept( pData->iSocket,
(struct sockaddr *)&(pChildData->tAddr),
&(pChildData->iSize) );
#endif
pChildData->iSocket = pData->iSocket;
iRet = ::recvfrom(
pData->iSocket,
pChildData->szReceived,
MAX_PACKET_SIZE,
0,
(struct sockaddr *)&(pChildData->tAddr),
&((uint)pChildData->iSize) );
if ( iFAcceptLockFD!=-1 )
{
/* ---
Release the lock
--- */
if ( PIPlatform_advisaryUnlockFd( iFAcceptLockFD )!=PIAPI_COMPLETED )
{
PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
"UDPIPIO: Error releasing lock, (unlock failed) errno:\
'%d'.", errno );
::unlink( pFAcceptLockFile ); /* --- remove file --- */
return PIAPI_ABORT;
};
};
/* ---
Some cases of error on accept are restartable, don't return an error
for those
--- */
if ( iRet==-1 )
{
#if POSIX
if ( errno==EINTR ) { /* just a signal */ continue; };
if ( errno==ECONNRESET ) { /* aborted connection */ continue; };
#endif
};
/* --- done --- */
break;
};
/* --- NULL out the pointer to pNewSocket --- */
pAcceptingIOObject = 0;
if ( iRet<0 )
{
return PIAPI_ERROR; /* non-critical error, callee may try again */
};
pChildData->iReceivedLen = iRet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -