Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Commits on Source (10)
Showing with 447 additions and 369 deletions
......@@ -2,7 +2,7 @@ project(cellframe-sdk C)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_C_STANDARD 11)
set(CELLFRAME_SDK_NATIVE_VERSION "2.6-33")
set(CELLFRAME_SDK_NATIVE_VERSION "2.6-34")
add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
set(DAPSDK_MODULES "")
......
......@@ -77,7 +77,7 @@
#define DAP_ENC_KS_KEY_ID_SIZE 33
#endif
static void s_stage_status_after(dap_client_pvt_t * a_client_internal);
static bool s_stage_status_after(dap_client_pvt_t * a_client_internal);
// ENC stage callbacks
static void s_enc_init_response(dap_client_t *, void *, size_t);
......@@ -188,7 +188,7 @@ static void s_stream_connected(dap_client_pvt_t * a_client_pvt)
* @brief s_client_internal_stage_status_proc
* @param a_client
*/
static void s_stage_status_after(dap_client_pvt_t * a_client_pvt)
static bool s_stage_status_after(dap_client_pvt_t * a_client_pvt)
{
dap_worker_t * l_worker= a_client_pvt->worker;
assert(l_worker);
......@@ -213,7 +213,7 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt)
}
a_client_pvt->stage_status = STAGE_STATUS_DONE;
s_stage_status_after(a_client_pvt);
return;
return false;
}
switch (l_stage) {
case STAGE_ENC_INIT: {
......@@ -474,10 +474,9 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt)
// Trying the step again
a_client_pvt->stage_status = STAGE_STATUS_IN_PROGRESS;
log_it(L_INFO, "Connection attempt %d in 0.3 seconds", a_client_pvt->stage_errors);
// small delay before next request
dap_timerfd_start_on_worker( l_worker, 300, (dap_timerfd_callback_t)s_stage_status_after,
a_client_pvt, false );
dap_timerfd_start_on_worker(l_worker, 300, (dap_timerfd_callback_t)s_stage_status_after,
a_client_pvt);
}
else{
log_it(L_INFO, "Too many connection attempts. Tries are over.");
......@@ -514,7 +513,7 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt)
if(a_client_pvt->stage_status_callback)
a_client_pvt->stage_status_callback(a_client_pvt->client, NULL);
return false;
}
/**
......
......@@ -59,9 +59,9 @@ int dap_timerfd_init()
* @param a_callback
* @return new allocated dap_timerfd_t structure or NULL if error
*/
dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg, bool a_repeated)
dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg)
{
return dap_timerfd_start_on_worker(dap_events_worker_get_auto(), a_timeout_ms, a_callback, a_callback_arg, a_repeated);
return dap_timerfd_start_on_worker(dap_events_worker_get_auto(), a_timeout_ms, a_callback, a_callback_arg);
}
#ifdef DAP_OS_WINDOWS
......@@ -84,7 +84,7 @@ void __stdcall TimerAPCb(void* arg, DWORD low, DWORD high) { // Timer high valu
* @param a_callback_arg
* @return
*/
dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg, bool a_repeated)
dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg)
{
dap_timerfd_t *l_timerfd = DAP_NEW(dap_timerfd_t);
......@@ -149,7 +149,6 @@ dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_t
l_timerfd->events_socket = l_events_socket;
l_timerfd->callback = a_callback;
l_timerfd->callback_arg = a_callback_arg;
l_timerfd->repeated = a_repeated;
#ifdef DAP_OS_WINDOWS
l_timerfd->th = l_th;
l_timerfd->pipe_in = l_pipe[1];
......@@ -168,9 +167,9 @@ dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_t
static void s_es_callback_timer(struct dap_events_socket *a_event_sock)
{
dap_timerfd_t *l_timerfd = a_event_sock->_inheritor;
if(l_timerfd->callback)
l_timerfd->callback(l_timerfd->callback_arg);
if (l_timerfd->repeated) {
// run user's callback
if(l_timerfd->callback && l_timerfd->callback(l_timerfd->callback_arg)) {
//printf("\nread() returned %d, %d\n", l_ptiu64, l_read_ret);
#if defined DAP_OS_UNIX
struct itimerspec l_ts;
// repeat never
......@@ -192,6 +191,7 @@ static void s_es_callback_timer(struct dap_events_socket *a_event_sock)
#endif
dap_events_socket_set_readable_unsafe(a_event_sock, true);
} else {
close(l_timerfd->tfd);
#if defined DAP_OS_WINDOWS
CloseHandle(l_timerfd->th);
#endif
......
......@@ -43,7 +43,7 @@
static time_t s_connection_timeout = 20000; // 60; // seconds
static void s_socket_all_check_activity( void * a_arg);
static bool s_socket_all_check_activity( void * a_arg);
static void s_queue_add_es_callback( dap_events_socket_t * a_es, void * a_arg);
static void s_queue_delete_es_callback( dap_events_socket_t * a_es, void * a_arg);
static void s_queue_es_reassign_callback( dap_events_socket_t * a_es, void * a_arg);
......@@ -114,7 +114,7 @@ void *dap_worker_thread(void *arg)
l_worker->event_exit = dap_events_socket_create_type_event_unsafe(l_worker, s_event_exit_callback );
l_worker->timer_check_activity = dap_timerfd_start_on_worker( l_worker, s_connection_timeout * 1000 / 2,
s_socket_all_check_activity, l_worker, true );
s_socket_all_check_activity, l_worker);
pthread_setspecific(l_worker->events->pth_key_worker, l_worker);
pthread_cond_broadcast(&l_worker->started_cond);
......@@ -663,7 +663,7 @@ static void s_queue_es_io_callback( dap_events_socket_t * a_es, void * a_arg)
* @brief s_socket_all_check_activity
* @param a_arg
*/
static void s_socket_all_check_activity( void * a_arg)
static bool s_socket_all_check_activity( void * a_arg)
{
dap_worker_t *l_worker = (dap_worker_t*) a_arg;
assert(l_worker);
......@@ -685,6 +685,7 @@ static void s_socket_all_check_activity( void * a_arg)
}
}
}
return true;
}
/**
......
......@@ -38,7 +38,7 @@
#include "dap_common.h"
#include "dap_events_socket.h"
typedef void (*dap_timerfd_callback_t)(void* ); // Callback for timer
typedef bool (*dap_timerfd_callback_t)(void* ); // Callback for timer. If return true, it will be called after next timeout
typedef struct dap_timerfd {
uint64_t timeout_ms;
......@@ -46,7 +46,6 @@ typedef struct dap_timerfd {
dap_events_socket_t *events_socket;
dap_timerfd_callback_t callback;
void *callback_arg;
bool repeated;
#ifdef DAP_OS_WINDOWS
HANDLE th;
int pipe_in;
......@@ -54,7 +53,7 @@ typedef struct dap_timerfd {
} dap_timerfd_t;
int dap_timerfd_init();
dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *callback_arg, bool a_repeated);
dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg, bool a_repeated);
dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *callback_arg);
dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg);
void dap_timerfd_delete(dap_timerfd_t *l_timerfd);
......@@ -162,8 +162,8 @@ bool dap_stream_ch_check_unsafe(dap_stream_worker_t * a_worker,dap_stream_ch_t *
*/
size_t dap_stream_ch_pkt_write_unsafe(dap_stream_ch_t * a_ch, uint8_t a_type, const void * a_data, size_t a_data_size)
{
if (!a_data_size || !a_ch || !a_data) {
log_it(L_WARNING, "NULL ptr or zero data size to write out in channel");
if (!a_ch) {
log_it(L_WARNING, "Channel is NULL ptr");
return 0;
}
//log_it(L_DEBUG,"Output: Has %u bytes of %c type for %c channel id",data_size, (char)type, (char) ch->proc->id );
......@@ -200,7 +200,7 @@ size_t dap_stream_ch_pkt_write_unsafe(dap_stream_ch_t * a_ch, uint8_t a_type, c
size_t l_ret=dap_stream_pkt_write_unsafe(a_ch->stream,l_buf_selected,a_data_size+sizeof(l_hdr));
a_ch->stat.bytes_write+=a_data_size;
a_ch->ready_to_write=true;
dap_stream_ch_set_ready_to_write_unsafe(a_ch, true);
if(l_buf_allocated)
DAP_DELETE(l_buf_allocated);
......
......@@ -75,13 +75,12 @@ static void s_http_client_delete(dap_http_client_t * a_esocket, void * a_arg);
static dap_stream_t *s_stream_keepalive_list = NULL;
static pthread_mutex_t s_mutex_keepalive_list;
static void s_keepalive_cb( void );
static bool s_keepalive_cb( void );
static bool s_dump_packet_headers = false;
bool dap_stream_get_dump_packet_headers(){ return s_dump_packet_headers; }
static struct timespec keepalive_loop_sleep = { 0, STREAM_KEEPALIVE_TIMEOUT * 1000 * 1000 };
static bool s_detect_loose_packet(dap_stream_t * a_stream);
dap_enc_key_type_t s_stream_get_preferred_encryption_type = DAP_ENC_KEY_TYPE_IAES;
......@@ -119,7 +118,7 @@ int dap_stream_init(dap_config_t * a_config)
s_dap_stream_load_preferred_encryption_type(a_config);
s_dump_packet_headers = dap_config_get_item_bool_default(g_config,"general","debug_dump_stream_headers",false);
pthread_mutex_init( &s_mutex_keepalive_list, NULL );
dap_timerfd_start(STREAM_KEEPALIVE_TIMEOUT * 1000, (dap_timerfd_callback_t)s_keepalive_cb, NULL, true);
dap_timerfd_start(STREAM_KEEPALIVE_TIMEOUT * 1000, (dap_timerfd_callback_t)s_keepalive_cb, NULL);
log_it(L_NOTICE,"Init streaming module");
return 0;
......@@ -786,7 +785,7 @@ static bool s_detect_loose_packet(dap_stream_t * a_stream)
}
static void s_keepalive_cb( void )
static bool s_keepalive_cb( void )
{
dap_stream_t *l_stream, *tmp;
pthread_mutex_lock( &s_mutex_keepalive_list );
......@@ -797,5 +796,6 @@ static void s_keepalive_cb( void )
dap_events_socket_write_mt(l_stream->stream_worker->worker, l_stream->esocket, &l_pkt, sizeof(l_pkt));
}
pthread_mutex_unlock( &s_mutex_keepalive_list );
return true;
}
......@@ -635,13 +635,13 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,dap_cha
l_srv = DAP_NEW_Z(dap_chain_net_srv_t);
l_srv->uid.uint64 = a_uid.uint64;
l_srv->callback_requested = a_callback_request;
l_srv->callback_receipt_first_success = a_callback_response_success;
l_srv->callback_response_success = a_callback_response_success;
l_srv->callback_response_error = a_callback_response_error;
l_srv->callback_receipt_next_success = a_callback_receipt_next_success;
pthread_mutex_init(&l_srv->banlist_mutex, NULL);
l_sdata = DAP_NEW_Z(service_list_t);
memcpy(&l_sdata->uid, &l_uid, sizeof(l_uid));
l_sdata->srv = l_srv;//DAP_NEW(dap_chain_net_srv_t);
//memcpy(l_sdata->srv, l_srv, sizeof(dap_chain_net_srv_t));
l_sdata->srv = l_srv;
HASH_ADD(hh, s_srv_list, uid, sizeof(l_srv->uid), l_sdata);
}else{
log_it(L_ERROR, "Already present service with 0x%016llX ", a_uid.uint64);
......@@ -701,8 +701,10 @@ void dap_chain_net_srv_del(dap_chain_net_srv_t * a_srv)
pthread_mutex_lock(&s_srv_list_mutex);
HASH_FIND(hh, s_srv_list, a_srv, sizeof(dap_chain_net_srv_uid_t), l_sdata);
if(l_sdata) {
DAP_DELETE(l_sdata);
HASH_DEL(s_srv_list, l_sdata);
pthread_mutex_destroy(&a_srv->banlist_mutex);
DAP_DELETE(a_srv);
DAP_DELETE(l_sdata);
}
pthread_mutex_unlock(&s_srv_list_mutex);
}
......@@ -763,8 +765,10 @@ void dap_chain_net_srv_del_all(void)
pthread_mutex_lock(&s_srv_list_mutex);
HASH_ITER(hh, s_srv_list , l_sdata, l_sdata_tmp)
{
DAP_DELETE(l_sdata);
HASH_DEL(s_srv_list, l_sdata);
pthread_mutex_destroy(&l_sdata->srv->banlist_mutex);
DAP_DELETE(l_sdata->srv);
DAP_DELETE(l_sdata);
}
pthread_mutex_unlock(&s_srv_list_mutex);
}
......
......@@ -36,18 +36,30 @@ typedef int (*dap_chain_net_srv_callback_data_t)(dap_chain_net_srv_t *, uint32_t
typedef int (*dap_chain_net_srv_callback_sign_request_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_t *, dap_chain_datum_tx_receipt_t **, size_t );
typedef void (*dap_chain_net_srv_callback_ch_t)(dap_chain_net_srv_t *, dap_stream_ch_t *);
typedef struct dap_chain_net_srv_banlist_item {
dap_chain_hash_fast_t client_pkey_hash;
pthread_mutex_t *ht_mutex;
struct dap_chain_net_srv_banlist_item **ht_head;
UT_hash_handle hh;
} dap_chain_net_srv_banlist_item_t;
typedef struct dap_chain_net_srv
{
dap_chain_net_srv_uid_t uid; // Unique ID for service.
dap_chain_net_srv_abstract_t srv_common;
dap_chain_net_srv_price_t *pricelist;
uint32_t grace_period;
pthread_mutex_t banlist_mutex;
dap_chain_net_srv_banlist_item_t *ban_list;
dap_chain_callback_trafic_t callback_trafic;
// Request for usage
dap_chain_net_srv_callback_data_t callback_requested;
// Receipt first sign successfull
dap_chain_net_srv_callback_data_t callback_receipt_first_success;
dap_chain_net_srv_callback_data_t callback_response_success;
// Response error
dap_chain_net_srv_callback_data_t callback_response_error;
......
......@@ -33,11 +33,7 @@
#include "dap_chain_ledger.h"
#include "dap_chain_net.h"
#include "dap_chain_wallet.h"
//Units of service
//#include "dap_chain_net_srv_stream_session.h"
//Service direction
......@@ -48,8 +44,6 @@ typedef enum dap_chain_net_srv_order_direction{
} dap_chain_net_srv_order_direction_t;
typedef struct dap_chain_net_srv_abstract
{
uint8_t class; //Class of service (once or permanent)
......@@ -89,7 +83,6 @@ typedef struct dap_chain_net_srv_price
struct dap_chain_net_srv_price * prev;
} dap_chain_net_srv_price_t;
// Ch pkt types
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST 0x01
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST 0x10
......@@ -117,6 +110,7 @@ typedef struct dap_chain_net_srv_price
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND 0x00000500
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN 0x00000501
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_WRONG_PKEY_HASH 0x00000502
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH 0x00000503
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND 0x00000600
#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNKNOWN 0xffffffff
......@@ -186,6 +180,15 @@ typedef struct dap_stream_ch_chain_net_srv_pkt_test{
uint8_t data[];
} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_test_t;
typedef struct dap_chain_net_srv_usage dap_chain_net_srv_usage_t;
typedef struct dap_chain_net_srv_grace {
dap_stream_worker_t *stream_worker;
dap_stream_ch_t *ch;
dap_chain_net_srv_usage_t *usage;
dap_stream_ch_chain_net_srv_pkt_request_t *request;
size_t request_size;
} dap_chain_net_srv_grace_t;
DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chain_net_srv_price_unit_uid_t a_uid )
{
......
......@@ -37,6 +37,7 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic
#include "dap_chain_wallet.h"
typedef struct dap_chain_net_srv dap_chain_net_srv_t;
typedef struct dap_chain_net_srv_usage{
uint32_t id; // Usage id
pthread_rwlock_t rwlock;
......@@ -53,14 +54,14 @@ typedef struct dap_chain_net_srv_usage{
dap_chain_net_srv_client_t * client;
dap_chain_datum_tx_t * tx_cond;
dap_chain_hash_fast_t tx_cond_hash;
dap_chain_hash_fast_t client_pkey_hash;
char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
bool is_active;
bool is_free;
bool is_grace;
UT_hash_handle hh; //
} dap_chain_net_srv_usage_t;
typedef void (*dap_response_success_callback_t) (dap_stream_ch_chain_net_srv_pkt_success_t*, void*);
typedef struct dap_net_stats{
uintmax_t bytes_sent;
uintmax_t bytes_recv;
......@@ -74,10 +75,10 @@ typedef struct dap_net_stats{
} dap_net_stats_t;
typedef struct dap_chain_net_srv_stream_session {
time_t ts_activated;
dap_stream_session_t * parent;
dap_chain_net_srv_usage_t * usages;
dap_chain_net_srv_usage_t * usage_active;
uintmax_t limits_bytes; // Bytes left
time_t limits_ts; // Timestamp until its activte
dap_chain_net_srv_price_unit_uid_t limits_units_type;
......@@ -85,12 +86,8 @@ typedef struct dap_chain_net_srv_stream_session {
// Some common stats
volatile dap_net_stats_t stats;
time_t ts_activated;
dap_sign_t* user_sign; // User's signature for auth if reconnect
dap_response_success_callback_t response_success_callback;
void *response_success_callback_data;
} dap_chain_net_srv_stream_session_t;
#define DAP_CHAIN_NET_SRV_STREAM_SESSION(a) ((dap_chain_net_srv_stream_session_t *) (a)->_inheritor )
......
......@@ -670,14 +670,13 @@ int s_vpn_service_create(dap_config_t * g_config){
l_srv->_inhertor = l_srv_vpn;
l_srv_vpn->parent = l_srv;
uint16_t l_pricelist_count = 0;
// Read if we need to dump all pkt operations
s_debug_more= dap_config_get_item_bool_default(g_config,"srv_vpn", "debug_more",false);
l_srv->grace_period = dap_config_get_item_uint32_default(g_config, "srv_vpn", "grace_period", 60);
//! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data
//! it also must NOT be freed within this module !
uint16_t l_pricelist_count = 0;
char **l_pricelist = dap_config_get_array_str(g_config, "srv_vpn", "pricelist", &l_pricelist_count); // must not be freed!
for (uint16_t i = 0; i < l_pricelist_count; i++) {
dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
......@@ -1269,14 +1268,16 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_ch_vpn->usage_id);
if ( ! l_usage){
log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothin on this channel");
log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothing on this channel");
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
return;
}
if ( ! l_usage->is_active ){
log_it(L_INFO, "Usage inactivation: switch off packet input channel");
log_it(L_INFO, "Usage inactivation: switch off packet input & output channels");
if (l_usage->client)
dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 );
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
return;
......@@ -1413,26 +1414,26 @@ static void s_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg)
dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_ch_vpn->usage_id);
if ( ! l_usage){
log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothin on this channel");
log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothing on this channel");
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
return;
}
if ( ! l_usage->is_active ){
log_it(L_INFO, "Usage inactivation: switch off packet output channel");
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
log_it(L_INFO, "Usage inactivation: switch off packet input & output channels");
if (l_usage->client)
dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 );
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
return;
}
if ( (! l_usage->is_free) && (! l_usage->receipt) ){
log_it(L_WARNING, "No active receipt, switching off");
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
if (l_usage->client)
dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 );
dap_stream_ch_set_ready_to_write_unsafe(a_ch,false);
dap_stream_ch_set_ready_to_read_unsafe(a_ch,false);
return;
}
// Check for empty buffer out here to prevent warnings in worker
......