great cleaning

pull/9/head
Ondřej Hruška 7 years ago
parent 87d1841fc8
commit 4ad1f09f73
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 88
      TinyFrame.c
  2. 39
      TinyFrame.h
  3. 52
      demo/demo.c
  4. 4
      demo/demo.h
  5. 8
      demo/hello/master.c
  6. 14
      demo/hello/slave.c
  7. 10
      demo/test/test.c
  8. 2
      demo/utils.c
  9. 13
      demo/utils.h

@ -23,7 +23,7 @@ enum TFState {
typedef struct _IdListener_struct_ {
TF_ID id;
TF_LISTENER fn;
TF_Listener fn;
TF_TICKS timeout; // nr of ticks remaining to disable this listener
TF_TICKS timeout_max; // the original timeout is stored here
void *userdata;
@ -31,11 +31,11 @@ typedef struct _IdListener_struct_ {
typedef struct _TypeListener_struct_ {
TF_TYPE type;
TF_LISTENER fn;
TF_Listener fn;
} TypeListener;
typedef struct _GenericListener_struct_ {
TF_LISTENER fn;
TF_Listener fn;
} GenericListener;
/**
@ -43,7 +43,7 @@ typedef struct _GenericListener_struct_ {
*/
static struct TinyFrameStruct {
/* Own state */
TF_PEER peer_bit; //!< Own peer bit (unqiue to avoid msg ID clash)
TF_Peer peer_bit; //!< Own peer bit (unqiue to avoid msg ID clash)
TF_ID next_id; //!< Next frame / frame chain ID
/* Parser state */
@ -201,7 +201,7 @@ static struct TinyFrameStruct {
//endregion
void _TF_FN TF_Init(TF_PEER peer_bit)
void _TF_FN TF_Init(TF_Peer peer_bit)
{
// Zero it out
memset(&tf, 0, sizeof(struct TinyFrameStruct));
@ -211,6 +211,11 @@ void _TF_FN TF_Init(TF_PEER peer_bit)
//region Listeners
static void _TF_FN renew_id_listener(IdListener *lst)
{
lst->timeout = lst->timeout_max;
}
/**
* Notify callback about ID listener demise & clean it
*
@ -218,12 +223,16 @@ void _TF_FN TF_Init(TF_PEER peer_bit)
*/
static void _TF_FN cleanup_id_listener(TF_COUNT i, IdListener *lst)
{
TF_MSG msg;
TF_Msg msg;
if (lst->fn == NULL) return;
msg.userdata = lst->userdata;
msg.data = NULL; // this is a signal that the listener should clean up
lst->fn(&msg);
// Make user clean up their data - only if not NULL
if (lst->userdata != NULL) {
msg.userdata = lst->userdata;
msg.data = NULL; // this is a signal that the listener should clean up
lst->fn(&msg); // return value is ignored here - use TF_STAY or TF_CLOSE
}
lst->fn = NULL; // Discard listener
if (i == tf.count_id_lst - 1) {
@ -257,7 +266,7 @@ static inline void _TF_FN cleanup_generic_listener(TF_COUNT i, GenericListener *
}
}
bool _TF_FN TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout)
bool _TF_FN TF_AddIdListener(TF_Msg *msg, TF_Listener cb, TF_TICKS timeout)
{
TF_COUNT i;
IdListener *lst;
@ -278,7 +287,7 @@ bool _TF_FN TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout)
return false;
}
bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb)
bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_Listener cb)
{
TF_COUNT i;
TypeListener *lst;
@ -297,7 +306,7 @@ bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb)
return false;
}
bool _TF_FN TF_AddGenericListener(TF_LISTENER cb)
bool _TF_FN TF_AddGenericListener(TF_Listener cb)
{
TF_COUNT i;
GenericListener *lst;
@ -345,7 +354,7 @@ bool _TF_FN TF_RemoveTypeListener(TF_TYPE type)
return false;
}
bool _TF_FN TF_RemoveGenericListener(TF_LISTENER cb)
bool _TF_FN TF_RemoveGenericListener(TF_Listener cb)
{
TF_COUNT i;
GenericListener *lst;
@ -367,9 +376,10 @@ static void _TF_FN TF_HandleReceivedMessage(void)
IdListener *ilst;
TypeListener *tlst;
GenericListener *glst;
TF_Result res;
// Prepare message object
TF_MSG msg;
TF_Msg msg;
msg.frame_id = tf.id;
msg.is_response = false;
msg.type = tf.type;
@ -388,10 +398,19 @@ static void _TF_FN TF_HandleReceivedMessage(void)
for (i = 0; i < tf.count_id_lst; i++) {
ilst = &tf.id_listeners[i];
if (ilst->fn && ilst->id == msg.frame_id) {
msg.renew = false;
msg.userdata = ilst->userdata; // pass userdata pointer to the callback
if (ilst->fn(&msg)) return;
res = ilst->fn(&msg);
ilst->userdata = msg.userdata; // put it back (may have changed the pointer or set to NULL)
if (res != TF_NEXT) {
if (res == TF_CLOSE) {
cleanup_id_listener(i, ilst);
}
else if (res == TF_RENEW) {
renew_id_listener(ilst);
}
return;
}
}
}
msg.userdata = NULL;
@ -401,7 +420,14 @@ static void _TF_FN TF_HandleReceivedMessage(void)
for (i = 0; i < tf.count_type_lst; i++) {
tlst = &tf.type_listeners[i];
if (tlst->fn && tlst->type == msg.type) {
if (tlst->fn(&msg)) return;
res = tlst->fn(&msg);
if (res != TF_NEXT) {
if (res == TF_CLOSE) {
cleanup_type_listener(i, tlst);
}
return;
}
}
}
@ -409,7 +435,14 @@ static void _TF_FN TF_HandleReceivedMessage(void)
for (i = 0; i < tf.count_generic_lst; i++) {
glst = &tf.generic_listeners[i];
if (glst->fn) {
if (glst->fn(&msg)) return;
res = glst->fn(&msg);
if (res != TF_NEXT) {
if (res == TF_CLOSE) {
cleanup_generic_listener(i, glst);
}
return;
}
}
}
}
@ -671,7 +704,7 @@ static inline size_t _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
}
// send without listener
bool _TF_FN TF_Send(TF_MSG *msg)
bool _TF_FN TF_Send(TF_Msg *msg)
{
return TF_Query(msg, NULL, 0);
}
@ -679,7 +712,7 @@ bool _TF_FN TF_Send(TF_MSG *msg)
// send without listener and struct
bool _TF_FN TF_SendSimple(TF_TYPE type, const uint8_t *data, TF_LEN len)
{
TF_MSG msg;
TF_Msg msg;
TF_ClearMsg(&msg);
msg.type = type;
msg.data = data;
@ -688,9 +721,9 @@ bool _TF_FN TF_SendSimple(TF_TYPE type, const uint8_t *data, TF_LEN len)
}
// send without listener and struct
bool _TF_FN TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_LISTENER listener, TF_TICKS timeout)
bool _TF_FN TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Listener listener, TF_TICKS timeout)
{
TF_MSG msg;
TF_Msg msg;
TF_ClearMsg(&msg);
msg.type = type;
msg.data = data;
@ -699,7 +732,7 @@ bool _TF_FN TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_LIS
}
// send with listener
bool _TF_FN TF_Query(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout)
bool _TF_FN TF_Query(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout)
{
size_t len;
len = TF_Compose(tf.sendbuf,
@ -719,13 +752,10 @@ bool _TF_FN TF_Query(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout)
}
// Like TF_Send, but with explicit frame ID
bool _TF_FN TF_Respond(TF_MSG *msg)
bool _TF_FN TF_Respond(TF_Msg *msg)
{
msg->is_response = true;
bool suc = TF_Send(msg);
if (suc && msg->renew) TF_RenewIdListener(msg->frame_id);
return suc;
return TF_Send(msg);
}
bool _TF_FN TF_RenewIdListener(TF_ID id)
@ -736,7 +766,7 @@ bool _TF_FN TF_RenewIdListener(TF_ID id)
lst = &tf.id_listeners[i];
// test if live & matching
if (lst->fn != NULL && lst->id == id) {
lst->timeout = lst->timeout_max;
renew_id_listener(lst);
return true;
}
}

@ -87,8 +87,15 @@
/** Peer bit enum (used for init) */
typedef enum {
TF_SLAVE = 0,
TF_MASTER = 1
} TF_PEER;
TF_MASTER,
} TF_Peer;
typedef enum {
TF_NEXT = 0, //!< Not handled, let other listeners handle it
TF_STAY = 1, //!< Handled, stay
TF_RENEW = 2, //!< Handled, stay, renew - useful only with listener timeout
TF_CLOSE = 3, //!< Handled, remove self
} TF_Result;
/** Data structure for sending / receiving messages */
typedef struct _TF_MSG_STRUCT_ {
@ -98,13 +105,12 @@ typedef struct _TF_MSG_STRUCT_ {
const uint8_t *data; //!< buffer of received data or data to send. NULL = listener timed out, free userdata!
TF_LEN len; //!< length of the buffer
void *userdata; //!< here's a place for custom data; this data will be stored with the listener
bool renew; //!< Renew the ID listener - if using timeout
} TF_MSG;
} TF_Msg;
/**
* Clear message struct
*/
static inline void TF_ClearMsg(TF_MSG *msg)
static inline void TF_ClearMsg(TF_Msg *msg)
{
msg->frame_id = 0;
msg->is_response = false;
@ -112,7 +118,6 @@ static inline void TF_ClearMsg(TF_MSG *msg)
msg->data = NULL;
msg->len = 0;
msg->userdata = NULL;
msg->renew = false;
}
/**
@ -122,9 +127,9 @@ static inline void TF_ClearMsg(TF_MSG *msg)
* @param type - type field from the message
* @param data - byte buffer with the application data
* @param len - number of bytes in the buffer
* @return true if the frame was consumed
* @return listener result
*/
typedef bool (*TF_LISTENER)(TF_MSG *msg);
typedef TF_Result (*TF_Listener)(TF_Msg *msg);
/**
* Initialize the TinyFrame engine.
@ -132,7 +137,7 @@ typedef bool (*TF_LISTENER)(TF_MSG *msg);
*
* @param peer_bit - peer bit to use for self
*/
void TF_Init(TF_PEER peer_bit);
void TF_Init(TF_Peer peer_bit);
/**
* Reset the frame parser state machine.
@ -148,7 +153,7 @@ void TF_ResetParser(void);
* @param timeout - timeout in ticks to auto-remove the listener (0 = keep forever)
* @return slot index (for removing), or TF_ERROR (-1)
*/
bool TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout);
bool TF_AddIdListener(TF_Msg *msg, TF_Listener cb, TF_TICKS timeout);
/**
* Remove a listener by the message ID it's registered for
@ -164,7 +169,7 @@ bool TF_RemoveIdListener(TF_ID frame_id);
* @param cb - callback
* @return slot index (for removing), or TF_ERROR (-1)
*/
bool TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb);
bool TF_AddTypeListener(TF_TYPE frame_type, TF_Listener cb);
/**
* Remove a listener by type.
@ -179,14 +184,14 @@ bool TF_RemoveTypeListener(TF_TYPE type);
* @param cb - callback
* @return slot index (for removing), or TF_ERROR (-1)
*/
bool TF_AddGenericListener(TF_LISTENER cb);
bool TF_AddGenericListener(TF_Listener cb);
/**
* Remove a generic listener by function pointer
*
* @param cb - callback function to remove
*/
bool TF_RemoveGenericListener(TF_LISTENER cb);
bool TF_RemoveGenericListener(TF_Listener cb);
/**
* Send a frame, no listener
@ -194,7 +199,7 @@ bool TF_RemoveGenericListener(TF_LISTENER cb);
* @param msg - message struct. ID is stored in the frame_id field
* @return success
*/
bool TF_Send(TF_MSG *msg);
bool TF_Send(TF_Msg *msg);
/**
* Like TF_Send, but without the struct
@ -204,7 +209,7 @@ bool TF_SendSimple(TF_TYPE type, const uint8_t *data, TF_LEN len);
/**
* Like TF_Query, but without the struct
*/
bool TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_LISTENER listener, TF_TICKS timeout);
bool TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Listener listener, TF_TICKS timeout);
/**
* Send a frame, and optionally attach an ID listener.
@ -214,7 +219,7 @@ bool TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_LISTENER l
* @param timeout - listener expiry time in ticks
* @return success
*/
bool TF_Query(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout);
bool TF_Query(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout);
/**
* Send a response to a received message.
@ -222,7 +227,7 @@ bool TF_Query(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout);
* @param msg - message struct. ID is read from frame_id. set ->renew to reset listener timeout
* @return success
*/
bool TF_Respond(TF_MSG *msg);
bool TF_Respond(TF_Msg *msg);
/**
* Renew ID listener timeout

@ -2,10 +2,9 @@
// Created by MightyPork on 2017/10/15.
//
// http://www.thegeekstuff.com/2011/12/c-socket-programming/?utm_source=feedburner
#include "demo.h"
// those magic defines are needed so we can use clone()
#define _GNU_SOURCE
#define __USE_GNU
#include <sched.h>
@ -20,15 +19,24 @@
volatile int sockfd = -1;
volatile bool conn_disband = false;
/**
* Close socket
*/
void demo_disconn(void)
{
conn_disband = true;
if (sockfd >= 0) close(sockfd);
}
/**
* Demo WriteImpl - send stuff to our peer
*
* @param buff
* @param len
*/
void TF_WriteImpl(const uint8_t *buff, size_t len)
{
printf("\033[32m--- TX %ld bytes ---\033[0m\n", len);
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
dumpFrame(buff, len);
usleep(1000);
@ -39,6 +47,13 @@ void TF_WriteImpl(const uint8_t *buff, size_t len)
}
}
/**
* Client bg thread
*
* @param unused
* @return unused
*/
static int demo_client(void* unused)
{
(void)unused;
@ -81,6 +96,12 @@ static int demo_client(void* unused)
return 0;
}
/**
* Server bg thread
*
* @param unused
* @return unused
*/
static int demo_server(void* unused)
{
(void)unused;
@ -136,20 +157,36 @@ static int demo_server(void* unused)
return 0;
}
void signal_handler(int sig)
/**
* Trap - clean up
*
* @param sig - signal that caused this
*/
static void signal_handler(int sig)
{
(void)sig;
printf("Shutting down...");
demo_disconn();
exit(sig);
exit(sig); // pass the signal through - this is nonstandard behavior but useful for debugging
}
/**
* Sleaping Beauty's fave function
*/
void demo_sleep(void)
{
while(1) usleep(10);
}
void demo_init(TF_PEER peer)
/**
* Start the background thread
*
* Slave is started first and doesn't normally init transactions - but it could
*
* @param peer what peer we are
*/
void demo_init(TF_Peer peer)
{
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
@ -163,6 +200,9 @@ void demo_init(TF_PEER peer)
}
printf("Starting %s...\n", peer == TF_MASTER ? "MASTER" : "SLAVE");
// CLONE_VM --- share heap
// CLONE_FILES --- share stdout and stderr
if (peer == TF_MASTER) {
retc = clone(&demo_client, (char *)stack+8192, CLONE_VM|CLONE_FILES, 0);
} else {

@ -15,9 +15,9 @@
void demo_sleep(void);
/** Init server - DOES NOT init TinyFrame! */
void demo_init(TF_PEER peer);
void demo_init(TF_Peer peer);
/** Disconnect client from the server - claled by a server-side callback */
/** Disconnect client from the server - can be called by a server-side callback */
void demo_disconn(void);
#endif //TF_DEMO_H

@ -5,18 +5,18 @@
#include <stdio.h>
#include "../demo.h"
bool testIdListener(TF_MSG *msg)
TF_Result testIdListener(TF_Msg *msg)
{
printf("testIdListener()\n");
dumpFrameInfo(msg);
return true;
return TF_CLOSE;
}
bool testGenericListener(TF_MSG *msg)
TF_Result testGenericListener(TF_Msg *msg)
{
printf("testGenericListener()\n");
dumpFrameInfo(msg);
return true;
return TF_STAY;
}
int main(void)

@ -6,14 +6,14 @@
#include "../demo.h"
#include <memory.h>
bool helloListener(TF_MSG *msg)
TF_Result helloListener(TF_Msg *msg)
{
printf("helloListener()\n");
dumpFrameInfo(msg);
return true;
return TF_STAY;
}
bool replyListener(TF_MSG *msg)
TF_Result replyListener(TF_Msg *msg)
{
printf("replyListener()\n");
dumpFrameInfo(msg);
@ -21,8 +21,14 @@ bool replyListener(TF_MSG *msg)
msg->len = (TF_LEN) strlen((const char *) msg->data);
TF_Respond(msg);
// unsolicted reply - will not be handled
msg->data = (const uint8_t *) "SPAM";
msg->len = 5;
TF_Respond(msg);
// unrelated message
TF_SendSimple(77, (const uint8_t *) "NAZDAR", 7);
return true;
return TF_STAY;
}
int main(void)

@ -19,22 +19,22 @@ void TF_WriteImpl(const uint8_t *buff, size_t len)
}
/** An example listener function */
bool myListener(TF_MSG *msg)
TF_Result myListener(TF_Msg *msg)
{
dumpFrameInfo(msg);
return true;
return TF_STAY;
}
bool testIdListener(TF_MSG *msg)
TF_Result testIdListener(TF_Msg *msg)
{
printf("OK - ID Listener triggered for msg!\n");
dumpFrameInfo(msg);
return true;
return TF_CLOSE;
}
void main(void)
{
TF_MSG msg;
TF_Msg msg;
const char *longstr = "Lorem ipsum dolor sit amet.";
// Set up the TinyFrame library

@ -21,7 +21,7 @@ void dumpFrame(const uint8_t *buff, size_t len)
printf("--- end of frame ---\n\n");
}
void dumpFrameInfo(TF_MSG *msg)
void dumpFrameInfo(TF_Msg *msg)
{
printf("\033[33mFrame info\n"
" type: %02Xh\n"

@ -8,8 +8,19 @@
#include <stdio.h>
#include "../TinyFrame.h"
/** pointer to unsigned char */
typedef unsigned char* pu8;
/**
* Dump a binary frame as hex, dec and ASCII
*/
void dumpFrame(const uint8_t *buff, size_t len);
void dumpFrameInfo(TF_MSG *msg);
/**
* Dump message metadata (not the content)
*
* @param msg
*/
void dumpFrameInfo(TF_Msg *msg);
#endif //TF_UTILS_H

Loading…
Cancel
Save