📄 en_sock.c
字号:
/****************************************************************************
*****************************************************************************
**
** File Name
** ---------
**
** EN_SOCK.C
**
*****************************************************************************
*****************************************************************************
**
** Description
** -----------
**
** Ethernet Socket interface.
**
*****************************************************************************
*****************************************************************************
**
** Source Change Indices
** ---------------------
**
** Porting: <none>0----<major> Customization: <none>0----<major>
**
*****************************************************************************
*****************************************************************************
** **
** ETHERNET/IP EXAMPLE CODE **
** COPYRIGHT (c) 2000-2005 ODVA (Open DeviceNet Vendor Association) **
** & ControlNet International Ltd. **
** **
** All rights reserved, except as specifically licensed in writing. **
** Use of the Ethernet/IP Example Protocol Software is subject to **
** ODVA's and ControlNet International's Terms of Use Agreement. **
** The following work constitutes example program code and is intended **
** merely to illustrate useful programming techniques. The user is **
** responsible for applying the code correctly. The code is provided **
** AS IS without warranty and is in no way guaranteed to be error-free. **
** **
*****************************************************************************
*****************************************************************************
*/
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "ab.h"
#ifdef CD_EN_OBJECTS
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "cd.h"
#include "en.h"
#include "en_sock.h"
#include "id.h" /* Identity Object public interfaces */
#include "EcInterface.h"
#define CHECKPOINT(x)
/*#define CHECKPOINT(x) \
{\
char __tmpbuf[1024];\
sprintf(__tmpbuf,"[CheckPoint]: %s\n",x);\
OutputDebugString(__tmpbuf);\
}
*/
/****************************************************************************
**
** Public data
**
*****************************************************************************
*/
UINT32 lECE_connects = 0; /* Current number of TCP connections */
UINT32 lECE_connects_in = 0; /* Current number of incoming TCP connections */
UINT32 lECE_connects_out = 0; /* Current number of outgoing TCP connections */
UINT32 lTotal_lECE_connects = 0; /* Current number of TCP connections */
UINT32 lTotalProcessed = 0; /* Total Incoming messages processed */
INT32 lEncapServerPort = 0xaf12;
/****************************************************************************
**
** Private data
**
*****************************************************************************
*/
ECE sClass1Ece;
static ECE sUDPEce;
/*
** Open multicast client connections. Keep at least one for every
** possible connection. In actuality it will probably be much less
*/
static MulticastTblType sMulticastTbl[EN_CD_NUM_CLASS_1];
extern ENCAP_OBJ_TARGET list_target_data;
/****************************************************************************
**
** Private services
**
*****************************************************************************
*/
/*---------------------------------------------------------------------------
** en_cd_JoinMulticast( )
**---------------------------------------------------------------------------
*/
UINT32 en_cd_JoinMulticast( struct sockaddr_in *psMc_addr )
{
INT32 nAvailable;
struct ip_mreq sMreq;
INT32 nConnections;
struct sockaddr_in sTmp_addr;
if ( htons( CLASS1_UDP_PORT ) != psMc_addr->sin_port )
{
/*jjw non default port not yet supported */
return OE_ERROR;
}
sTmp_addr.sin_addr.s_addr = ntohl( psMc_addr->sin_addr.s_addr );
if ( IN_MULTICAST( sTmp_addr.sin_addr.s_addr ) )
{
for ( nConnections = 0;
nConnections < sizeof sMulticastTbl / sizeof sMulticastTbl[0];
nConnections++ )
{
/*
** Run through the list of existing connections, if the multicast
** address matches with the one we are going to join, up the
** connection count in our record and don't join again
*/
if ( ( sMulticastTbl[nConnections].iMcastAddr == sTmp_addr.sin_addr.s_addr ) &&
( sMulticastTbl[nConnections].iConnections > 0 ) )
{
sMulticastTbl[nConnections].iConnections += 1;
return OK;
}
else if ( sMulticastTbl[nConnections].iConnections == 0 )
{
nAvailable = nConnections;
}
} /* End for */
/*
** No pre-existing connections for this address, need to add a new one
*/
sMreq.imr_interface.s_addr = htonl( INADDR_ANY );
/*
** fill in the argument structure to join the multicast group
** initialize the multicast address to join
*/
sMreq.imr_multiaddr.s_addr = htonl( sTmp_addr.sin_addr.s_addr );
/*
** First check to see if this socket is initialized. We may have exceeded the
** IP_MAX_MEMBERSHIPS limit and not had the option of opening another
** socket.
*/
if ( sMulticastTbl[ nAvailable ].iSocket == 0 )
return OE_ERROR;
if ( setsockopt( sMulticastTbl[ nAvailable ].iSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
( char * ) &sMreq, sizeof( sMreq ) ) == OE_ERROR )
{
return OE_SOCKET_ERRNO;
} /* end if setsockopt */
/*
** keep track of the multicast groups, and the count of clients listening.
*/
sMulticastTbl[nAvailable].iConnections = 1;
sMulticastTbl[nAvailable].iMcastAddr = sTmp_addr.sin_addr.s_addr;
return OK;
} /* end if ( IN_MULTICAST( tmp_addr.sin_addr.s_addr ) ) */
return OE_ERROR;
} /* end en_cd_JoinMulticast */
/*---------------------------------------------------------------------------
** en_cd_DropMulticast( )
**---------------------------------------------------------------------------
*/
UINT32 en_cd_DropMulticast( struct sockaddr_in *psMc_addr )
{
struct ip_mreq sMreq;
INT32 nConnections;
struct sockaddr_in sTmp_addr;
sTmp_addr.sin_addr.s_addr = ntohl( psMc_addr->sin_addr.s_addr );
if ( IN_MULTICAST( sTmp_addr.sin_addr.s_addr ) )
{
for ( nConnections = 0;
nConnections < sizeof sMulticastTbl / sizeof sMulticastTbl[0];
nConnections++ )
{
/*
** Run through the list of existing connections, if the multicast
** address matches with the one we are going to join, lower the
** connection count in our record
*/
if ( ( sMulticastTbl[nConnections].iMcastAddr == sTmp_addr.sin_addr.s_addr ) &&
( sMulticastTbl[nConnections].iConnections > 0 ) )
{
/*
** Check to make sure no one else is listening to this address. If
** they are just return and don't leave the multicast group
*/
if ( sMulticastTbl[nConnections].iConnections > 1 )
{
sMulticastTbl[nConnections].iConnections -= 1; /* lower count */
return OK;
} /* end if connections > 0 */
/*
** We found the multicast address and no
** one else is listening
*/
break;
} /* end if same multicast connection */
} /* End for */
/*
** Check to make sure we really joined this multicast group. If we
** didn't this is a definate programming error
*/
if ( nConnections == sizeof sMulticastTbl / sizeof sMulticastTbl[0] )
{
GS_LogEvent( EN_NO_MULTICAST,
0,
0,
FATAL );
}
sMreq.imr_multiaddr.s_addr = htonl( sTmp_addr.sin_addr.s_addr );
/*
** Wind River requires the interface address in order to drop
** membership in a multicast connection. INADDR_ANY will return an
** error
*/
sMreq.imr_interface.s_addr = htonl( list_target_data.sS.s_sock.lSin_addr );
if ( setsockopt( sMulticastTbl[ nConnections ].iSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
( char * ) &sMreq, sizeof( sMreq ) ) == OE_ERROR )
{
return OE_SOCKET_ERRNO;
} /* end if setsockopt */
sMulticastTbl[nConnections].iConnections = 0; /* No more listeners */
sMulticastTbl[nConnections].iMcastAddr = 0; /* No more listeners */
return OK;
} /* end if ( IN_MULTICAST( * sTmp_addr.sin_addr.s_addr ) ) */
/*jjw do we really want to return OK if specified address is not Multicast ??*/
return OK;
} /* end en_cd_DropMulticast */
/*---------------------------------------------------------------------------
** en_cd_Class1RecvTask( )
**---------------------------------------------------------------------------
*/
TASKRETURN en_cd_Class1RecvTask( TASKPARAM )
{
INT32 lBytesReceived;
struct sockaddr_in sClientAddr;
CPFHDR *psMsg;
PKTBUF *psPacketBuf;
INT32 lSockFd;
struct sockaddr_in sSrvrAddr;
UINT32 lSockAddrSize;
UINT32 lFlagTrue = ~0;
UINT32 iConnIndex;
#if defined( IP_MAX_MEMBERSHIPS )
UINT32 iStatus;
UINT32 iMulticastSockets;
UINT32 iIndex;
#endif
lSockAddrSize = sizeof( struct sockaddr_in );
UC_SetMem( ( char * ) &sSrvrAddr, 0, sizeof( sSrvrAddr ) );
#ifndef _WIN32
sSrvrAddr.sin_len = ( UINT8 ) lSockAddrSize;
#endif
sSrvrAddr.sin_family = AF_INET;
sSrvrAddr.sin_addr.s_addr = htonl( INADDR_ANY );
sSrvrAddr.sin_port = htons( CLASS1_UDP_PORT );
/*
** zero out the client multicast connection table
*/
UC_SetMem( sMulticastTbl, 0, sizeof sMulticastTbl );
UC_SetMem( &sClass1Ece, 0, sizeof sClass1Ece );
#if defined( IP_MAX_MEMBERSHIPS )
/*
** The operating system limits the number of multicast connections
** per socket (BSD limits to 20). Therefore we need to open more sockets to handle
** the maximum number of Class 1 multicast connections we get . Currently
** this additional functionality is only enabled for the enhanced motorola
** fec drivers. Adding to NT and other operating systems would mean spawning
** multiple receive tasks, each maintaining their own segment of the sMulticastTbl.
*/
iMulticastSockets = ( EN_CD_NUM_CLASS_1 + IP_MAX_MEMBERSHIPS - 1 ) / IP_MAX_MEMBERSHIPS;
for ( iIndex = 0; iIndex < iMulticastSockets; iIndex++ )
{
/*
** Need a socket to do anything, fatal if can't get one....
*/
if ( ( lSockFd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == OE_ERROR )
{
GS_LogEvent( EN_SOCKET_ERR,
OE_SOCKET_ERRNO,
0,
FATAL );
GS_DeleteTask( 0 );
}
iStatus = setsockopt( lSockFd, SOL_SOCKET, SO_REUSEPORT, ( char * ) &lFlagTrue,
sizeof( lFlagTrue ) );
/*
** Bind the server to PORT, which the client knows
*/
if ( bind( lSockFd, ( struct sockaddr * ) & sSrvrAddr, sizeof( sSrvrAddr ) ) == OE_ERROR )
{
/*
** If we can't bind, no one can conect, fatal out
*/
GS_LogEvent( EN_BIND_ERR,
OE_SOCKET_ERRNO,
0,
FATAL );
GS_DeleteTask( 0 );
}
/*
** Now note the socket in the multicast connections table
*/
for ( iConnIndex = iIndex * IP_MAX_MEMBERSHIPS;
iConnIndex < ( iIndex + 1 ) * IP_MAX_MEMBERSHIPS;
iConnIndex++ )
{
sMulticastTbl[ iConnIndex ].iSocket = lSockFd;
} /* End for connections in sMulticastTbl */
} /* End for iMulticastSockets */
#else
/*
** Operating system does not limit the number of multicast connections per
** socket, so get a socket, then set all of the socket table entries to the socket.
*/
/*
** Need a socket to do anything, fatal if can't get one....
*/
if ( ( lSockFd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == OE_ERROR )
{
GS_LogEvent( EN_SOCKET_ERR,
OE_SOCKET_ERRNO,
0,
FATAL );
GS_DeleteTask( 0 );
}
if ( bind( lSockFd, ( struct sockaddr * ) & sSrvrAddr, sizeof( sSrvrAddr ) ) == OE_ERROR )
{
/*
** If we can't bind, no one can conect, fatal out
*/
GS_LogEvent( EN_BIND_ERR,
OE_SOCKET_ERRNO,
0,
FATAL );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -