17c909ec83
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
271 lines
8.2 KiB
C
271 lines
8.2 KiB
C
//
|
|
// Copyright (c) 2015 Wind River Systems, Inc.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
#include "sm_notify_api.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <glib.h>
|
|
|
|
#include "sm_types.h"
|
|
#include "sm_debug.h"
|
|
#include "sm_timer.h"
|
|
#include "sm_selobj.h"
|
|
|
|
#define SM_NOTIFY_API_MSG_ADDRESS "/tmp/.sm_notify_api"
|
|
|
|
#define SM_NOTIFY_API_MSG_VERSION "1"
|
|
#define SM_NOTIFY_API_MSG_REVISION "1"
|
|
#define SM_NOTIFY_API_MSG_TYPE_SERVICE_EVENT "SERVICE_EVENT"
|
|
|
|
#define SM_NOTIFY_API_MSG_SERVICE_EVENT_SYNC_START "sync-start"
|
|
#define SM_NOTIFY_API_MSG_SERVICE_EVENT_SYNC_END "sync-end"
|
|
|
|
#define SM_NOTIFY_API_MSG_VERSION_FIELD 0
|
|
#define SM_NOTIFY_API_MSG_REVISION_FIELD 1
|
|
#define SM_NOTIFY_API_MSG_TYPE_FIELD 2
|
|
#define SM_NOTIFY_API_MSG_ORIGIN_FIELD 3
|
|
#define SM_NOTIFY_API_MSG_SERVICE_NAME_FIELD 4
|
|
#define SM_NOTIFY_API_MSG_SERVICE_EVENT_FIELD 5
|
|
|
|
#define SM_NOTIFY_API_MAX_MSG_SIZE 256
|
|
|
|
static int _sm_notify_api_socket = -1;
|
|
static char _rx_buffer[SM_NOTIFY_API_MAX_MSG_SIZE] __attribute__((aligned));
|
|
static SmNotifyApiCallbacksT _callbacks = {0};
|
|
|
|
// ****************************************************************************
|
|
// Notify API - Register Callbacks
|
|
// ===============================
|
|
SmErrorT sm_notify_api_register_callbacks( SmNotifyApiCallbacksT* callbacks )
|
|
{
|
|
memcpy( &_callbacks, callbacks, sizeof(SmNotifyApiCallbacksT) );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Notify API - Deregister Callbacks
|
|
// =================================
|
|
SmErrorT sm_notify_api_deregister_callbacks( SmNotifyApiCallbacksT* callbacks )
|
|
{
|
|
memset( &_callbacks, 0, sizeof(SmNotifyApiCallbacksT) );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Notify API - Service Event Value
|
|
// ================================
|
|
static SmNotifyServiceEventT sm_notify_api_service_event_value(
|
|
const char* event_str )
|
|
{
|
|
if( 0 == strcmp( SM_NOTIFY_API_MSG_SERVICE_EVENT_SYNC_START,
|
|
event_str ) )
|
|
{
|
|
return( SM_NOTIFY_SERVICE_EVENT_SYNC_START );
|
|
|
|
} else if( 0 == strcmp( SM_NOTIFY_API_MSG_SERVICE_EVENT_SYNC_END,
|
|
event_str ) )
|
|
{
|
|
return( SM_NOTIFY_SERVICE_EVENT_SYNC_END );
|
|
|
|
} else {
|
|
return( SM_NOTIFY_SERVICE_EVENT_UNKNOWN );
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Notify API - Dispatch
|
|
// =====================
|
|
static void sm_notify_api_dispatch( int selobj, int64_t user_data )
|
|
{
|
|
char* service_name;
|
|
gchar** params;
|
|
int bytes_read;
|
|
SmNotifyServiceEventT service_event;
|
|
|
|
int retry_count;
|
|
for( retry_count = 5; retry_count != 0; --retry_count )
|
|
{
|
|
memset( _rx_buffer, 0, sizeof(_rx_buffer) );
|
|
|
|
bytes_read = recv( selobj, &_rx_buffer, sizeof(_rx_buffer), 0 );
|
|
if( 0 < bytes_read )
|
|
{
|
|
break;
|
|
|
|
} else if( 0 == bytes_read ) {
|
|
// For connection oriented sockets, this indicates that the peer
|
|
// has performed an orderly shutdown.
|
|
return;
|
|
|
|
} else if(( 0 > bytes_read )&&( EINTR != errno )) {
|
|
DPRINTFE( "Failed to receive message, errno=%s.",
|
|
strerror( errno ) );
|
|
return;
|
|
}
|
|
|
|
DPRINTFD( "Interrupted while receiving message, retry=%d, errno=%s.",
|
|
retry_count, strerror( errno ) );
|
|
}
|
|
|
|
params = g_strsplit( _rx_buffer, ",", -1 );
|
|
if( params[SM_NOTIFY_API_MSG_VERSION_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing version field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
if( 0 != strcmp( SM_NOTIFY_API_MSG_VERSION,
|
|
params[SM_NOTIFY_API_MSG_VERSION_FIELD] ) )
|
|
{
|
|
DPRINTFE( "Unsupported version (%s) received, expected=%s.",
|
|
params[SM_NOTIFY_API_MSG_VERSION_FIELD],
|
|
SM_NOTIFY_API_MSG_VERSION );
|
|
goto ERROR;
|
|
}
|
|
|
|
if( params[SM_NOTIFY_API_MSG_REVISION_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing revision field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
if( params[SM_NOTIFY_API_MSG_TYPE_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing message-type field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
if( 0 == strcmp( SM_NOTIFY_API_MSG_TYPE_SERVICE_EVENT,
|
|
params[SM_NOTIFY_API_MSG_TYPE_FIELD] ) )
|
|
{
|
|
if( params[SM_NOTIFY_API_MSG_ORIGIN_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing origin field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
if( params[SM_NOTIFY_API_MSG_SERVICE_NAME_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing service-name field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
service_name = (char*) params[SM_NOTIFY_API_MSG_SERVICE_NAME_FIELD];
|
|
|
|
if( params[SM_NOTIFY_API_MSG_SERVICE_EVENT_FIELD] == NULL )
|
|
{
|
|
DPRINTFE( "Missing service-event field in received message." );
|
|
goto ERROR;
|
|
}
|
|
|
|
service_event = sm_notify_api_service_event_value( (char*)
|
|
params[SM_NOTIFY_API_MSG_SERVICE_EVENT_FIELD]);
|
|
|
|
if( NULL != _callbacks.service_event )
|
|
{
|
|
_callbacks.service_event( service_name, service_event );
|
|
}
|
|
|
|
} else {
|
|
DPRINTFE( "Unknown/unsupported message-type (%s) received.",
|
|
params[SM_NOTIFY_API_MSG_TYPE_FIELD] );
|
|
goto ERROR;
|
|
}
|
|
|
|
g_strfreev( params );
|
|
return;
|
|
|
|
ERROR:
|
|
g_strfreev( params );
|
|
return;
|
|
}
|
|
// ***************************************************************************
|
|
|
|
// ***************************************************************************
|
|
// Notify API - Initialize
|
|
// =======================
|
|
SmErrorT sm_notify_api_initialize( void )
|
|
{
|
|
int sock;
|
|
socklen_t len;
|
|
struct sockaddr_un src_addr;
|
|
int result;
|
|
SmErrorT error;
|
|
|
|
memset( &src_addr, 0, sizeof(src_addr) );
|
|
|
|
src_addr.sun_family = AF_UNIX;
|
|
snprintf( src_addr.sun_path, sizeof(src_addr.sun_path),
|
|
SM_NOTIFY_API_MSG_ADDRESS );
|
|
|
|
sock = socket( AF_LOCAL, SOCK_DGRAM, 0 );
|
|
if( 0 > sock )
|
|
{
|
|
DPRINTFE( "Failed to create socket for sm-notify-api, error=%s.",
|
|
strerror( errno ) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
unlink( src_addr.sun_path );
|
|
|
|
len = strlen(src_addr.sun_path) + sizeof(src_addr.sun_family);
|
|
|
|
result = bind( sock, (struct sockaddr *) &src_addr, len );
|
|
if( 0 > result )
|
|
{
|
|
DPRINTFE( "Failed to bind address (%s) to socket for sm-notify-api, "
|
|
"error=%s.", src_addr.sun_path, strerror( errno ) );
|
|
close( sock );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
_sm_notify_api_socket = sock;
|
|
|
|
error = sm_selobj_register( _sm_notify_api_socket,
|
|
sm_notify_api_dispatch, 0 );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register selection object, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ***************************************************************************
|
|
|
|
// ***************************************************************************
|
|
// Notify API - Finalize
|
|
// =====================
|
|
SmErrorT sm_notify_api_finalize( void )
|
|
{
|
|
SmErrorT error;
|
|
|
|
memset( &_callbacks, 0, sizeof(_callbacks) );
|
|
|
|
if( -1 < _sm_notify_api_socket )
|
|
{
|
|
error = sm_selobj_deregister( _sm_notify_api_socket );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister selection object, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ***************************************************************************
|