867 lines
24 KiB
C
867 lines
24 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_channel.c,v $ $Revision: 1.6.2.6 $
|
|
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_channel.c,v $
|
|
* $Author: zan $ $Date: 2013-08-02 07:52:29 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Erik Dahlberg <erik.dahlberg@windriver.com>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* A message channel framework */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include "ipike_config.h"
|
|
|
|
#ifdef IPIKE_USE_EVENT_LOG
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#include "ipike_h.h"
|
|
#include "ipike_channel.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPIKE_CHANNEL_ADDRESS_MAX_LEN 32
|
|
#define IPIKE_CHANNEL_USE_TCP
|
|
|
|
#define for_each_channel_in_server(_chan, _server) \
|
|
for (_chan = (Ipike_channel *) ipcom_list_first(&_server->channel_list);\
|
|
_chan != IP_NULL; \
|
|
_chan = (Ipike_channel *) ipcom_list_next(&_chan->list) )
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
typedef enum Ipike_channel_state_enum
|
|
{
|
|
IPIKE_CHANNEL_STATE_CLOSED = 0,
|
|
IPIKE_CHANNEL_STATE_LISTEN = 1,
|
|
IPIKE_CHANNEL_STATE_OPEN = 2,
|
|
} Ipike_channel_state;
|
|
|
|
struct Ipike_channel_struct
|
|
{
|
|
Ipcom_list list;
|
|
Ip_fd fd;
|
|
Ipike_channel_state state;
|
|
Ipcom_mutex mutex;
|
|
};
|
|
|
|
struct Ipike_channel_server_struct
|
|
{
|
|
Ipcom_list channel_list;
|
|
Ipike_channel_server_cb on_open_cb;
|
|
Ipike_channel_server_cb on_close_cb;
|
|
Ipike_channel_server_receive_cb on_receive_cb;
|
|
};
|
|
|
|
enum Ipike_channel_msg_type_enum
|
|
{
|
|
IPIKE_CHANNEL_REGISTER = 0,
|
|
IPIKE_CHANNEL_UNREGISTER = 1,
|
|
IPIKE_CHANNEL_MESSAGE = 2,
|
|
};
|
|
|
|
|
|
#define MSG_HDR(_msg) ((Ipike_channel_msg_header *)_msg - 1);
|
|
|
|
|
|
struct Ipike_channel_addr_struct
|
|
{
|
|
union Ip_sockaddr_union addr;
|
|
};
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_set_state
|
|
*===========================================================================
|
|
*/
|
|
IP_INLINE void
|
|
ipike_channel_set_state(
|
|
Ipike_channel * channel,
|
|
Ipike_channel_state state)
|
|
{
|
|
channel->state = state;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_is_open
|
|
*===========================================================================
|
|
*/
|
|
IP_INLINE Ip_bool
|
|
ipike_channel_is_open(
|
|
const Ipike_channel * channel)
|
|
{
|
|
return (channel->state == IPIKE_CHANNEL_STATE_OPEN);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_lock
|
|
*===========================================================================
|
|
*/
|
|
IP_INLINE void
|
|
ipike_channel_lock(
|
|
const Ipike_channel * channel)
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "locking channel %p", channel);
|
|
ipcom_mutex_lock(channel->mutex);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_unlock
|
|
*===========================================================================
|
|
*/
|
|
IP_INLINE void
|
|
ipike_channel_unlock(
|
|
const Ipike_channel * channel)
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "Unlocking channel %p", channel);
|
|
ipcom_mutex_unlock(channel->mutex);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_destroy
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC void
|
|
ipike_channel_destroy(
|
|
Ipike_channel * channel)
|
|
{
|
|
ip_assert(channel != IP_NULL);
|
|
|
|
IPCOM_LOG1(DEBUG2, "Destroying channel %p", channel);
|
|
ipike_channel_close(channel);
|
|
(void)ipcom_mutex_delete(&channel->mutex);
|
|
ipcom_free(channel);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_destroy
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_channel_server_destroy(
|
|
Ipike_channel_server * cserver)
|
|
{
|
|
Ipike_channel * channel;
|
|
|
|
ip_assert(cserver != IP_NULL);
|
|
|
|
IPCOM_LOG1(DEBUG2, "Destroying channel server %p", cserver);
|
|
|
|
for ( channel = (Ipike_channel *) ipcom_list_first(&cserver->channel_list);
|
|
channel != IP_NULL;
|
|
channel = (Ipike_channel *) ipcom_list_first(&cserver->channel_list))
|
|
{
|
|
ipcom_list_remove(&channel->list);
|
|
ipike_channel_destroy(channel);
|
|
}
|
|
|
|
ipcom_free(cserver);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_create
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_channel *
|
|
ipike_channel_create()
|
|
{
|
|
Ipike_channel *channel;
|
|
|
|
channel = ipcom_malloc(sizeof(Ipike_channel));
|
|
|
|
if ( IP_NULL == channel )
|
|
return IP_NULL;
|
|
|
|
ipcom_memset(channel, 0, sizeof(Ipike_channel));
|
|
|
|
channel->fd = IP_INVALID_SOCKET;
|
|
|
|
ipike_channel_set_state(channel, IPIKE_CHANNEL_STATE_CLOSED);
|
|
|
|
/* Create channel mutex */
|
|
if ( ipcom_mutex_create(&channel->mutex) != IPCOM_SUCCESS )
|
|
{
|
|
ipcom_free(channel);
|
|
return IP_NULL;
|
|
}
|
|
|
|
return channel;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_accept_new_channel
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_channel_status
|
|
ipike_channel_server_accept_new_channel(
|
|
Ipike_channel_server * cserver,
|
|
Ipike_channel * channel)
|
|
{
|
|
Ipike_channel * new_channel;
|
|
Ip_fd fd;
|
|
|
|
ip_assert(channel->state == IPIKE_CHANNEL_STATE_LISTEN);
|
|
|
|
IPCOM_LOG0(DEBUG2, "ipike_channel_server_accept_new_channel() :: "\
|
|
"received new connection attempt");
|
|
|
|
fd = ipcom_accept(channel->fd, IP_NULL, 0 );
|
|
|
|
if ( fd < 0 )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_channel_server_accept_new_channel() :: "\
|
|
"failed to accept new connection (%s)",
|
|
ipcom_strerror(ipcom_errno));
|
|
|
|
return IPIKE_CHANNEL_ERROR;
|
|
}
|
|
|
|
/* Create a new channel */
|
|
new_channel = ipike_channel_create();
|
|
|
|
if ( new_channel == NULL )
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_CHANNEL_ERROR;
|
|
}
|
|
|
|
/* Set channel state and add it to the channel list */
|
|
new_channel->fd = fd;
|
|
ipike_channel_set_state(new_channel, IPIKE_CHANNEL_STATE_OPEN);
|
|
ipcom_list_insert_last(&cserver->channel_list, &new_channel->list);
|
|
|
|
/* Notify user with the new channel */
|
|
if ( cserver->on_open_cb )
|
|
cserver->on_open_cb(new_channel);
|
|
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_server_accept_new_channel() :: "\
|
|
"new channel established");
|
|
|
|
return IPIKE_CHANNEL_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_addr_create
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel_addr *
|
|
ipike_channel_addr_create(
|
|
const char * caddr_str)
|
|
{
|
|
Ipike_channel_addr * caddr;
|
|
char tmp[IPIKE_CHANNEL_ADDRESS_MAX_LEN];
|
|
char * ip_str;
|
|
char * port_str;
|
|
Ip_u16 port;
|
|
|
|
caddr = ipcom_malloc(sizeof(Ipike_channel_addr));
|
|
|
|
if ( caddr == IP_NULL )
|
|
return IP_NULL;
|
|
|
|
ipcom_memset(caddr, 0, sizeof(Ipike_channel_addr));
|
|
|
|
ipcom_memset(tmp, 0, sizeof(tmp));
|
|
ipcom_strncpy(tmp, caddr_str, sizeof(tmp) - 1);
|
|
|
|
port_str = ipcom_strchr(tmp, '@');
|
|
|
|
if ( port_str == IP_NULL )
|
|
{
|
|
ipcom_free(caddr);
|
|
return IP_NULL;
|
|
}
|
|
ip_str = tmp;
|
|
*port_str = '\0';
|
|
port_str++;
|
|
|
|
port = (Ip_u16)ipcom_atoi(port_str);
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if ( 1 == ipcom_inet_pton(IP_AF_INET,
|
|
ip_str,
|
|
&caddr->addr.sin.sin_addr))
|
|
{
|
|
caddr->addr.sa.sa_family = IP_AF_INET;
|
|
caddr->addr.sin.sin_port = ip_htons(port);
|
|
IPCOM_SA_LEN_SET(&caddr->addr.sa, sizeof(struct Ip_sockaddr_in));
|
|
return caddr;
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if ( 1 == ipcom_inet_pton(IP_AF_INET6,
|
|
ip_str,
|
|
&caddr->addr.sin6.sin6_addr) )
|
|
{
|
|
caddr->addr.sa.sa_family = IP_AF_INET6;
|
|
caddr->addr.sin6.sin6_port = ip_htons(port);
|
|
IPCOM_SA_LEN_SET(&caddr->addr.sa, sizeof(struct Ip_sockaddr_in6));
|
|
return caddr;
|
|
}
|
|
#endif
|
|
|
|
return caddr;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_addr_destroy
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_channel_addr_destroy(
|
|
Ipike_channel_addr * caddr)
|
|
{
|
|
ipcom_free(caddr);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_msg_create
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel_msg *
|
|
ipike_channel_msg_create(Ip_u16 len)
|
|
{
|
|
Ipike_channel_msg * msg;
|
|
Ip_size_t msg_len;
|
|
|
|
msg_len = sizeof(Ipike_channel_msg) + len;
|
|
msg = ipcom_malloc(msg_len);
|
|
|
|
if ( msg == IP_NULL )
|
|
return IP_NULL;
|
|
|
|
ipcom_memset(msg, 0, msg_len);
|
|
|
|
msg->type = IPIKE_CHANNEL_MESSAGE;
|
|
msg->len = (Ip_u16)msg_len;
|
|
|
|
return msg;
|
|
}
|
|
/*
|
|
*===========================================================================
|
|
* ike_channel_msg_destroy(
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_channel_msg_destroy(
|
|
Ipike_channel_msg *msg)
|
|
{
|
|
ip_assert(msg);
|
|
ipcom_free(msg);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_add_fds
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL int
|
|
ipike_channel_server_add_fds(
|
|
Ipike_channel_server * cserver,
|
|
Ip_fd_set * read_fds,
|
|
Ip_fd_set * write_fds)
|
|
{
|
|
Ipike_channel * channel;
|
|
int max = -1;
|
|
|
|
IPCOM_UNUSED_ARG(write_fds);
|
|
|
|
for_each_channel_in_server(channel, cserver)
|
|
{
|
|
switch (channel->state)
|
|
{
|
|
case IPIKE_CHANNEL_STATE_LISTEN:
|
|
case IPIKE_CHANNEL_STATE_OPEN:
|
|
IP_FD_SET(channel->fd, read_fds);
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "ipike_channel_server_add_fds() :: "\
|
|
"invalid fd state (%u)",
|
|
channel->state);
|
|
|
|
break;
|
|
}
|
|
max = IP_MAX(channel->fd, max);
|
|
}
|
|
|
|
return max;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_broadcast_msg
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_channel_server_broadcast_msg(
|
|
Ipike_channel_server * channel_server,
|
|
Ipike_channel_msg * msg)
|
|
{
|
|
Ipike_channel *channel;
|
|
|
|
/* Broadcast message on all open channels */
|
|
for_each_channel_in_server(channel, channel_server)
|
|
{
|
|
if ( ipike_channel_is_open(channel) )
|
|
{
|
|
ipike_channel_send_msg(channel, msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_create
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel_server *
|
|
ipike_channel_server_create(
|
|
Ipike_channel_addr * caddr,
|
|
Ipike_channel_server_cb on_open_cb,
|
|
Ipike_channel_server_cb on_close_cb,
|
|
Ipike_channel_server_receive_cb on_receive_cb)
|
|
{
|
|
Ipike_channel_server * cserver;
|
|
Ipike_channel * channel;
|
|
|
|
cserver = ipcom_malloc(sizeof(Ipike_channel_server));
|
|
|
|
if ( IP_NULL == cserver )
|
|
return IP_NULL;
|
|
|
|
ipcom_memset(cserver, 0, sizeof(Ipike_channel_server));
|
|
|
|
ipcom_list_init(&cserver->channel_list);
|
|
|
|
/* Set user callbacks */
|
|
cserver->on_open_cb = on_open_cb;
|
|
cserver->on_close_cb = on_close_cb;
|
|
cserver->on_receive_cb = on_receive_cb;
|
|
|
|
channel = ipike_channel_create();
|
|
|
|
if ( channel == IP_NULL )
|
|
goto errout;
|
|
|
|
ipcom_list_insert_last(&cserver->channel_list, &channel->list);
|
|
|
|
/* Open socket */
|
|
#if defined(IPCOM_USE_INET)
|
|
channel->fd = ipcom_socket(IP_AF_INET, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
#elif defined(IPCOM_USE_INET6)
|
|
channel->fd = ipcom_socket(IP_AF_INET6, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
#endif
|
|
|
|
if ( channel->fd < 0 )
|
|
goto errout;
|
|
|
|
/* Bind channel server */
|
|
if ( ipcom_bind(channel->fd,
|
|
(struct Ip_sockaddr *) &caddr->addr,
|
|
IPCOM_SA_LEN_GET(&caddr->addr)) < 0 )
|
|
goto errout;
|
|
|
|
/* Start listen for new connections */
|
|
if (ipcom_listen(channel->fd, 1) != 0)
|
|
{
|
|
IPCOM_LOG1(WARNING, "ipike_event_channel_bind() :: failed to set socket to"\
|
|
" listen state (%s)",
|
|
ipcom_strerror(ipcom_errno));
|
|
goto errout;
|
|
}
|
|
|
|
/* The channel is listen state */
|
|
ipike_channel_set_state(channel, IPIKE_CHANNEL_STATE_LISTEN);
|
|
|
|
return cserver;
|
|
|
|
errout:
|
|
if ( cserver )
|
|
ipike_channel_server_destroy(cserver);
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_open
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel *
|
|
ipike_channel_open(
|
|
Ipike_channel_addr * caddr)
|
|
{
|
|
Ipike_channel * channel;
|
|
|
|
/* Create channel */
|
|
channel = ipike_channel_create();
|
|
|
|
if ( channel == IP_NULL )
|
|
goto errout;
|
|
|
|
/* Open socket */
|
|
#if defined(IPCOM_USE_INET)
|
|
channel->fd = ipcom_socket(IP_AF_INET, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
#elif defined(IPCOM_USE_INET6)
|
|
channel->fd = ipcom_socket(IP_AF_INET6, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
#endif
|
|
|
|
if ( channel->fd < 0 )
|
|
goto errout;
|
|
|
|
/* Connect to IKE Daemon */
|
|
if ( ipcom_connect(channel->fd,
|
|
(struct Ip_sockaddr *) &caddr->addr,
|
|
IPCOM_SA_LEN_GET(&caddr->addr)) < 0 )
|
|
goto errout;
|
|
|
|
/* The channel is established */
|
|
ipike_channel_set_state(channel, IPIKE_CHANNEL_STATE_OPEN);
|
|
|
|
return channel;
|
|
|
|
errout:
|
|
if (channel)
|
|
ipike_channel_destroy(channel);
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_close
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_channel_close(
|
|
Ipike_channel * channel)
|
|
{
|
|
ipike_channel_lock(channel);
|
|
/* Close channel socket */
|
|
if ( channel->fd != IP_INVALID_SOCKET )
|
|
{
|
|
(void)ipcom_socketclose(channel->fd);
|
|
channel->fd = IP_INVALID_SOCKET;
|
|
}
|
|
|
|
ipike_channel_set_state(channel, IPIKE_CHANNEL_STATE_CLOSED);
|
|
ipike_channel_unlock(channel);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_receive_msg
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel_status
|
|
ipike_channel_receive_msg(
|
|
Ipike_channel * channel,
|
|
Ipike_channel_msg ** msg)
|
|
{
|
|
Ipike_channel_msg hdr;
|
|
Ipike_channel_msg * msg_out = IP_NULL;
|
|
Ipike_channel_status err = IPIKE_CHANNEL_ERROR;
|
|
Ip_ssize_t ret = 0;
|
|
Ip_size_t len;
|
|
Ip_fd fd;
|
|
|
|
ipike_channel_lock(channel);
|
|
fd = channel->fd;
|
|
ipike_channel_unlock(channel);
|
|
|
|
/* Read header information */
|
|
ret = ipcom_recv(fd, &hdr, sizeof(hdr), 0);
|
|
|
|
/* Receive error */
|
|
if ( ret < 0 )
|
|
{
|
|
IPCOM_LOG2(DEBUG, "ipike_channel_receive_msg() :: "\
|
|
"failed to receive (%ld) (%s)",
|
|
ret,
|
|
ipcom_strerror(ipcom_errno));
|
|
goto errout;
|
|
}
|
|
|
|
/* Socket closed */
|
|
if ( ret == 0 )
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_receive_msg() :: channel closed");
|
|
err = IPIKE_CHANNEL_CLOSED;
|
|
goto errout;
|
|
}
|
|
|
|
/* Expect the same size as specified in header */
|
|
if ( (Ip_ssize_t) ret != sizeof(hdr) )
|
|
{
|
|
IPCOM_LOG2(DEBUG, "ipike_channel_receive_msg() :: "\
|
|
"bad message, got %ld , expected %ld",
|
|
hdr.len, sizeof(hdr));
|
|
goto errout;
|
|
}
|
|
|
|
IPCOM_LOG1(DEBUG2, "ipike_channel_receive_msg() :: "\
|
|
"received message header of length %d\n", hdr.len);
|
|
|
|
/* If no message buffer was provided, create one dynamically */
|
|
if ( *msg == IP_NULL )
|
|
{
|
|
/* Allocate message space */
|
|
/* packet is sent by target itself, it is not vulnerable to attack */
|
|
/* coverity[tainted_data] : INTENTIONAL */
|
|
msg_out = ipike_channel_msg_create(hdr.len);
|
|
|
|
if ( msg_out == IP_NULL )
|
|
{
|
|
IP_PANIC();
|
|
goto errout;
|
|
}
|
|
|
|
*msg = msg_out;
|
|
}
|
|
else
|
|
{
|
|
/* Make sure the provided buffer has enough space for this message */
|
|
if ( (*msg)->len < hdr.len )
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_receive_msg() :: "
|
|
"not enough memory in provided message");
|
|
goto errout;
|
|
}
|
|
}
|
|
|
|
/* Set message length to the size of the received message */
|
|
(*msg)->len = hdr.len;
|
|
|
|
/* Read the rest of the message */
|
|
len = (*msg)->len - sizeof(Ipike_channel_msg);
|
|
ret = ipcom_recv(fd, (*msg) + 1, len , 0);
|
|
|
|
if ( ret == 0 )
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_receive_msg() :: channel closed");
|
|
err = IPIKE_CHANNEL_CLOSED;
|
|
goto errout;
|
|
}
|
|
|
|
|
|
if ( ret != (Ip_ssize_t) len )
|
|
{
|
|
IPCOM_LOG2(DEBUG, "ipike_channel_receive_msg() :: "\
|
|
"failed to receive message (%ld) (%s)",
|
|
ret,
|
|
ipcom_strerror(ipcom_errno));
|
|
goto errout;
|
|
}
|
|
|
|
IPCOM_LOG1(DEBUG, "ipike_channel_receive_msg() :: "\
|
|
"Successfully received message (%d)",
|
|
hdr.len);
|
|
|
|
|
|
return IPIKE_CHANNEL_OK;
|
|
|
|
errout:
|
|
if ( msg_out )
|
|
ipike_channel_msg_destroy(msg_out);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_send_msg
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_channel_status
|
|
ipike_channel_send_msg(
|
|
Ipike_channel * channel,
|
|
Ipike_channel_msg * msg)
|
|
{
|
|
ip_assert(channel);
|
|
ip_assert(msg);
|
|
|
|
/* We need an open channel */
|
|
if ( !ipike_channel_is_open(channel) )
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_send_msg() :: "\
|
|
"channel is not open");
|
|
return IPIKE_CHANNEL_CLOSED;
|
|
}
|
|
|
|
/* Send message */
|
|
if ( ipcom_send(channel->fd, (void *) msg, msg->len, 0) != msg->len )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_channel_send_msg() :: "\
|
|
"failed to send message (%s)",
|
|
ipcom_strerror(ipcom_errno));
|
|
|
|
return IPIKE_CHANNEL_ERROR;
|
|
}
|
|
|
|
/* Message has been sent */
|
|
return IPIKE_CHANNEL_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_channel_server_process
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL int
|
|
ipike_channel_server_process(
|
|
Ipike_channel_server * cserver,
|
|
Ip_fd_set * read_fds,
|
|
Ip_fd_set * write_fds)
|
|
{
|
|
Ipike_channel * channel;
|
|
Ipike_channel * next;
|
|
|
|
int num_processed = 0;
|
|
|
|
IPCOM_UNUSED_ARG(write_fds);
|
|
|
|
/* Get first channel */
|
|
channel = (Ipike_channel * )ipcom_list_first(&cserver->channel_list);
|
|
if (channel==IP_NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
/* This is the master channel where new connection can arrive on */
|
|
if ( IP_FD_ISSET(channel->fd, read_fds) )
|
|
{
|
|
/* Accept new channel connection */
|
|
(void)ipike_channel_server_accept_new_channel(cserver, channel);
|
|
num_processed++;
|
|
}
|
|
|
|
/* Continue to check if there are messages on other channels */
|
|
channel = (Ipike_channel *) ipcom_list_next(&channel->list);
|
|
|
|
while ( channel )
|
|
{
|
|
/* Receive data */
|
|
Ipike_channel_msg * msg = IP_NULL;
|
|
|
|
/* Store next pointer so we can remote the channel object if is needed */
|
|
next = (Ipike_channel *) ipcom_list_next(&channel->list);
|
|
|
|
if ( IP_FD_ISSET(channel->fd, read_fds) )
|
|
{
|
|
/* Receive message */
|
|
if ( ipike_channel_receive_msg(channel, &msg) != IPIKE_CHANNEL_OK )
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_channel_server_process():: "\
|
|
"closing channel");
|
|
|
|
ipcom_list_remove(&channel->list);
|
|
|
|
/* Notify user that channel is closed */
|
|
if ( cserver->on_close_cb )
|
|
cserver->on_close_cb(channel);
|
|
/* Destroy the channel on errors */
|
|
ipike_channel_destroy(channel);
|
|
}
|
|
else
|
|
{
|
|
/* Send message to user receive callback */
|
|
if (cserver->on_receive_cb)
|
|
cserver->on_receive_cb(channel, msg);
|
|
|
|
/* Destroy message */
|
|
ipike_channel_msg_destroy(msg);
|
|
}
|
|
num_processed++;
|
|
}
|
|
channel = next;
|
|
}
|
|
|
|
return num_processed;
|
|
}
|
|
#else
|
|
|
|
int ipike_channel_empty_file = 0;
|
|
|
|
#endif /* IPIKE_USE_EVENT_LOG */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|