mirror of
https://github.com/Hizenberg469/MultiThreading_Part_A.git
synced 2026-04-19 18:12:24 +03:00
Threads
This commit is contained in:
1
Hello_World_Thread/cleaner.sh
Normal file
1
Hello_World_Thread/cleaner.sh
Normal file
@@ -0,0 +1 @@
|
||||
rm *~ .*
|
||||
3
Hello_World_Thread/compile.sh
Normal file
3
Hello_World_Thread/compile.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
gcc -g -c hello_world_thread.c -o hello_world_thread.o
|
||||
gcc -g hello_world_thread.o -o hello_world_thread.exe -lpthread
|
||||
rm *.o
|
||||
87
Hello_World_Thread/hello_world_thread.c
Normal file
87
Hello_World_Thread/hello_world_thread.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hello_world_thread.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 06/03/24 08:38:10 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h> /* For working with POSIX threads */
|
||||
#include <unistd.h> /* For pause() and sleep() */
|
||||
|
||||
|
||||
/*Note: pthread_exit(0) API can be used to terminate a thread
|
||||
* , be it child thread or parent thread */
|
||||
|
||||
|
||||
/* A thread callback fn must have following prototypes
|
||||
* void *(*thread_fn)(void *)
|
||||
* */
|
||||
static void *
|
||||
thread_fn_callback(void *arg){
|
||||
char *input = (char *)arg;
|
||||
while(1){
|
||||
printf("Input is : %s\n",input);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that this function is not
|
||||
* main thread, rather it just a function
|
||||
* which create a thread and return to main()
|
||||
* function, which is actually the main thread of this
|
||||
* process */
|
||||
void
|
||||
thread1_create(){
|
||||
|
||||
/* opaque object, don't bother about its internal
|
||||
* members */
|
||||
pthread_t pthread; /* Thread handler: This is like a variable which is used
|
||||
* handle the thread processed */
|
||||
|
||||
/* Take some argument to be passed to the thread fn,
|
||||
* Look after that you always pass the persistant memory
|
||||
* as an argument to the thread, do not pass caller's
|
||||
* local variables Or stack Memory */
|
||||
static char *thread_input1 = "I am thread 1, child thread of main thread";
|
||||
|
||||
/* Return 0 on success, otherwise returns error-code, all
|
||||
* pthread functions return -ve error-code on failure, they
|
||||
* do not set global 'errno' variable */
|
||||
int rc = pthread_create(&pthread,
|
||||
NULL,
|
||||
thread_fn_callback,
|
||||
(void *)thread_input1);
|
||||
|
||||
if( rc != 0 ){
|
||||
printf("Error occured, thread could not be created, errno = %d\n",rc);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc , char **argv){
|
||||
|
||||
thread1_create();
|
||||
printf("The execution of main function( or main thread ) is paused\n");
|
||||
//pause();
|
||||
/* Main thread, if complete its execution and return normally
|
||||
* by returning 0 then all the child thread of main thread terminates
|
||||
* but, if we use pthread_exit(0) to terminate main thread then the
|
||||
* child threads can continue to exit without any obstruction. */
|
||||
|
||||
pthread_exit(0);
|
||||
return 0;
|
||||
}
|
||||
BIN
Hello_World_Thread/hello_world_thread.exe
Normal file
BIN
Hello_World_Thread/hello_world_thread.exe
Normal file
Binary file not shown.
1
Joinable_Detached_thread/cleaner.sh
Normal file
1
Joinable_Detached_thread/cleaner.sh
Normal file
@@ -0,0 +1 @@
|
||||
rm *~ .*
|
||||
3
Joinable_Detached_thread/compile_joinable.sh
Normal file
3
Joinable_Detached_thread/compile_joinable.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
gcc -g -c joinable_example.c -o joinable_example.o
|
||||
gcc -g joinable_example.o -o joinable_example.exe -lpthread
|
||||
rm *.o
|
||||
111
Joinable_Detached_thread/joinable_example.c
Normal file
111
Joinable_Detached_thread/joinable_example.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: joinable_example.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 07/03/24 04:17:21 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h> /* For working with POSIX threads */
|
||||
#include <unistd.h> /* For pause() and sleep() */
|
||||
#include <errno.h> /* For using Global variable errno */
|
||||
|
||||
void *
|
||||
thread_fn_callback(void *arg) {
|
||||
|
||||
int th_id = *(int *)arg;
|
||||
|
||||
free(arg);
|
||||
|
||||
int rc = 0;
|
||||
|
||||
while(rc != th_id ){
|
||||
|
||||
printf("Thread %d doing some work\n", th_id);
|
||||
sleep(1);
|
||||
rc++;
|
||||
}
|
||||
|
||||
int *result = calloc(1,sizeof(int));
|
||||
|
||||
*result = th_id * th_id;
|
||||
|
||||
return (void *)result;
|
||||
}
|
||||
|
||||
void
|
||||
thread_create(pthread_t *pthread_handle, int th_id){
|
||||
|
||||
pthread_attr_t attr;
|
||||
|
||||
int *_th_id = calloc(1, sizeof(int));
|
||||
*_th_id = th_id;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
pthread_attr_setdetachstate(&attr,
|
||||
PTHREAD_CREATE_JOINABLE
|
||||
/* PTHREAD_CREATE_DETACHED */);
|
||||
|
||||
pthread_create(pthread_handle,
|
||||
&attr,
|
||||
thread_fn_callback,
|
||||
(void *)_th_id);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* These thread would find the square of the
|
||||
* argument passed onto it */
|
||||
pthread_t pthread2;
|
||||
pthread_t pthread3;
|
||||
|
||||
int
|
||||
main( int argc, char **argv ){
|
||||
|
||||
void *thread_result2 , *thread_result3;
|
||||
thread_create(&pthread2, 10);
|
||||
thread_create(&pthread3, 2);
|
||||
|
||||
printf("main fn blocked on pthread join for thread with "
|
||||
"th_id = 2\n");
|
||||
|
||||
pthread_join(pthread2, &thread_result2);
|
||||
|
||||
if( thread_result2 ){
|
||||
|
||||
printf("Return result from thread 2 = %d\n",
|
||||
*(int *)thread_result2);
|
||||
free(thread_result2);
|
||||
thread_result2 = NULL;
|
||||
}
|
||||
|
||||
printf("main fn blocked on pthread join for thread with "
|
||||
"th_id = 3\n");
|
||||
|
||||
pthread_join(pthread3, &thread_result3);
|
||||
|
||||
if( thread_result3 ){
|
||||
|
||||
printf("Return result from thread 3 = %d\n",
|
||||
*(int *)thread_result3);
|
||||
free(thread_result3);
|
||||
thread_result3 = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
Joinable_Detached_thread/joinable_example.exe
Normal file
BIN
Joinable_Detached_thread/joinable_example.exe
Normal file
Binary file not shown.
1
NFC/clearner.sh
Normal file
1
NFC/clearner.sh
Normal file
@@ -0,0 +1 @@
|
||||
rm *~ .*
|
||||
7
NFC/compile.sh
Normal file
7
NFC/compile.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
gcc -g -c glthread/glthread.c -o glthread/glthread.o
|
||||
gcc -g -c notif.c -o notif.o
|
||||
gcc -g -c rtm_publisher.c -o rtm_publisher.o
|
||||
gcc -g -c rt.c -o rt.o
|
||||
gcc -g -c threaded_subsciber.c -o threaded_subsciber.o
|
||||
gcc -g rtm_publisher.o threaded_subsciber.o rt.o notif.o glthread/glthread.o -o main.exe -lpthread
|
||||
rm *.o glthread/*.o
|
||||
BIN
NFC/glthread/.glthread.h.un~
Normal file
BIN
NFC/glthread/.glthread.h.un~
Normal file
Binary file not shown.
1
NFC/glthread/cleaner.sh
Normal file
1
NFC/glthread/cleaner.sh
Normal file
@@ -0,0 +1 @@
|
||||
rm *~ .*
|
||||
196
NFC/glthread/glthread.c
Normal file
196
NFC/glthread/glthread.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: glthread.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 09/03/24 07:31:52 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "glthread.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
init_glthread(glthread_t *glthread){
|
||||
|
||||
glthread->left = NULL;
|
||||
glthread->right = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
glthread_add_next(glthread_t *curr_glthread, glthread_t *new_glthread){
|
||||
|
||||
if(!curr_glthread->right){
|
||||
curr_glthread->right = new_glthread;
|
||||
new_glthread->left = curr_glthread;
|
||||
return;
|
||||
}
|
||||
|
||||
glthread_t *temp = curr_glthread->right;
|
||||
curr_glthread->right = new_glthread;
|
||||
new_glthread->left = curr_glthread;
|
||||
new_glthread->right = temp;
|
||||
temp->left = new_glthread;
|
||||
}
|
||||
|
||||
void
|
||||
glthread_add_before(glthread_t *curr_glthread, glthread_t *new_glthread){
|
||||
|
||||
if(!curr_glthread->left){
|
||||
new_glthread->left = NULL;
|
||||
new_glthread->right = curr_glthread;
|
||||
curr_glthread->left = new_glthread;
|
||||
return;
|
||||
}
|
||||
|
||||
glthread_t *temp = curr_glthread->left;
|
||||
temp->right = new_glthread;
|
||||
new_glthread->left = temp;
|
||||
new_glthread->right = curr_glthread;
|
||||
curr_glthread->left = new_glthread;
|
||||
}
|
||||
|
||||
void
|
||||
remove_glthread(glthread_t *curr_glthread){
|
||||
|
||||
if(!curr_glthread->left){
|
||||
if(curr_glthread->right){
|
||||
curr_glthread->right->left = NULL;
|
||||
curr_glthread->right = 0;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(!curr_glthread->right){
|
||||
curr_glthread->left->right = NULL;
|
||||
curr_glthread->left = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
curr_glthread->left->right = curr_glthread->right;
|
||||
curr_glthread->right->left = curr_glthread->left;
|
||||
curr_glthread->left = 0;
|
||||
curr_glthread->right = 0;
|
||||
}
|
||||
|
||||
void
|
||||
delete_glthread_list(glthread_t *glthread_head){
|
||||
|
||||
glthread_t *glthreadptr = NULL;
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(glthread_head, glthreadptr){
|
||||
remove_glthread(glthreadptr);
|
||||
} ITERATE_GLTHREAD_END(glthread_head, glthreadptr);
|
||||
}
|
||||
|
||||
void
|
||||
glthread_add_last(glthread_t *glthread_head, glthread_t *new_glthread){
|
||||
|
||||
glthread_t *glthreadptr = NULL,
|
||||
*prevglthreadptr = NULL;
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(glthread_head, glthreadptr){
|
||||
prevglthreadptr = glthreadptr;
|
||||
} ITERATE_GLTHREAD_END(glthread_head, glthreadptr);
|
||||
|
||||
if(prevglthreadptr)
|
||||
glthread_add_next(prevglthreadptr, new_glthread);
|
||||
else
|
||||
glthread_add_next(glthread_head, new_glthread);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
get_glthread_list_count(glthread_t *glthread_head){
|
||||
|
||||
unsigned int count = 0;
|
||||
glthread_t *glthreadptr = NULL;
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(glthread_head, glthreadptr){
|
||||
count++;
|
||||
} ITERATE_GLTHREAD_END(glthread_head, glthreadptr);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glthread_priority_insert(glthread_t *glthread_head,
|
||||
glthread_t *glthread,
|
||||
int (*comp_fn)(void *, void *),
|
||||
int offset){
|
||||
|
||||
|
||||
glthread_t *curr = NULL,
|
||||
*prev = NULL;
|
||||
|
||||
init_glthread(glthread);
|
||||
|
||||
if(IS_GLTHREAD_LIST_EMPTY(glthread_head)){
|
||||
glthread_add_next(glthread_head, glthread);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only one node*/
|
||||
if(glthread_head->right && !glthread_head->right->right){
|
||||
if(comp_fn(GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread, offset),
|
||||
GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread_head->right, offset)) == -1){
|
||||
glthread_add_next(glthread_head, glthread);
|
||||
}
|
||||
else{
|
||||
glthread_add_next(glthread_head->right, glthread);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(glthread_head, curr){
|
||||
|
||||
if(comp_fn(GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread, offset),
|
||||
GLTHREAD_GET_USER_DATA_FROM_OFFSET(curr, offset)) != -1){
|
||||
prev = curr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!prev)
|
||||
glthread_add_next(glthread_head, glthread);
|
||||
else
|
||||
glthread_add_next(prev, glthread);
|
||||
|
||||
return;
|
||||
|
||||
}ITERATE_GLTHREAD_END(glthread_head, curr);
|
||||
|
||||
/*Add in the end*/
|
||||
glthread_add_next(prev, glthread);
|
||||
}
|
||||
|
||||
glthread_t *
|
||||
dequeue_glthread_first(glthread_t *base_glthread){
|
||||
|
||||
glthread_t *temp;
|
||||
if(!base_glthread->right)
|
||||
return NULL;
|
||||
temp = base_glthread->right;
|
||||
remove_glthread(temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void *
|
||||
gl_thread_search(glthread_t *glthread_head,
|
||||
void *(*thread_to_struct_fn)(glthread_t *),
|
||||
void *key,
|
||||
int (*comparison_fn)(void *, void *)){
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
95
NFC/glthread/glthread.h
Normal file
95
NFC/glthread/glthread.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: glthread.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 09/03/24 07:30:40 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GLUETHREAD__
|
||||
#define __GLUETHREAD__
|
||||
|
||||
typedef struct _glthread{
|
||||
|
||||
struct _glthread *left;
|
||||
struct _glthread *right;
|
||||
} glthread_t;
|
||||
|
||||
void
|
||||
glthread_add_next(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
void
|
||||
glthread_add_before(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
void
|
||||
remove_glthread(glthread_t *glthread);
|
||||
|
||||
void
|
||||
init_glthread(glthread_t *glthread);
|
||||
|
||||
void
|
||||
glthread_add_last(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
#define IS_GLTHREAD_LIST_EMPTY(glthreadptr) \
|
||||
((glthreadptr)->right == 0 && (glthreadptr)->left == 0)
|
||||
|
||||
#define GLTHREAD_TO_STRUCT(fn_name, structure_name, field_name) \
|
||||
static inline structure_name * fn_name(glthread_t *glthreadptr){ \
|
||||
if(glthreadptr)\
|
||||
return (structure_name *)((char *)(glthreadptr) - (char *)&(((structure_name *)0)->field_name)); \
|
||||
else return NULL;\
|
||||
}
|
||||
|
||||
/* delete safe loop*/
|
||||
/*Normal continue and break can be used with this loop macro*/
|
||||
|
||||
#define BASE(glthreadptr) ((glthreadptr)->right)
|
||||
|
||||
#define ITERATE_GLTHREAD_BEGIN(glthreadptrstart, glthreadptr) \
|
||||
{ \
|
||||
glthread_t *_glthread_ptr = NULL; \
|
||||
glthreadptr = BASE(glthreadptrstart); \
|
||||
for(; glthreadptr!= NULL; glthreadptr = _glthread_ptr){ \
|
||||
_glthread_ptr = (glthreadptr)->right;
|
||||
|
||||
#define ITERATE_GLTHREAD_END(glthreadptrstart, glthreadptr) \
|
||||
}}
|
||||
|
||||
#define GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthreadptr, offset) \
|
||||
(void *)((char *)(glthreadptr) - offset)
|
||||
|
||||
void
|
||||
delete_glthread_list(glthread_t *base_glthread);
|
||||
|
||||
unsigned int
|
||||
get_glthread_list_count(glthread_t *base_glthread);
|
||||
|
||||
void
|
||||
glthread_priority_insert(glthread_t *base_glthread,
|
||||
glthread_t *glthread,
|
||||
int (*comp_fn)(void *, void *),
|
||||
int offset);
|
||||
|
||||
glthread_t *
|
||||
dequeue_glthread_first(glthread_t *base_glthread);
|
||||
|
||||
#if 0
|
||||
void *
|
||||
gl_thread_search(glthread_t *base_glthread,
|
||||
void *(*thread_to_struct_fn)(glthread_t *),
|
||||
void *key,
|
||||
int (*comparison_fn)(void *, void *));
|
||||
|
||||
#endif
|
||||
#endif /* __GLUETHREAD__ */
|
||||
95
NFC/glthread/glthread.h~
Normal file
95
NFC/glthread/glthread.h~
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: glthread.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 09/03/24 07:30:40 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GLUETHREAD__
|
||||
#define __GLUETHREAD__
|
||||
|
||||
typedef struct _glthread{
|
||||
|
||||
struct _glthread *left;
|
||||
struct _glthread *right;
|
||||
} glthread_t;
|
||||
|
||||
void
|
||||
glthread_add_next(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
void
|
||||
glthread_add_before(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
void
|
||||
remove_glthread(glthread_t *glthread);
|
||||
|
||||
void
|
||||
init_glthread(glthread_t *glthread);
|
||||
|
||||
void
|
||||
glthread_add_last(glthread_t *base_glthread, glthread_t *new_glthread);
|
||||
|
||||
#define IS_GLTHREAD_LIST_EMPTY(glthreadptr) \
|
||||
((glthreadptr)->right == 0 && (glthreadptr)->left == 0)
|
||||
|
||||
#define GLTHREAD_TO_STRUCT(fn_name, structure_name, field_name,glthreadptr) \
|
||||
static inline structure_name * fn_name(glthread_t *glthreadptr){ \
|
||||
if(glthreadptr)\
|
||||
return (structure_name *)((char *)(glthreadptr) - (char *)&(((structure_name *)0)->field_name)); \
|
||||
else return NULL;\
|
||||
}
|
||||
|
||||
/* delete safe loop*/
|
||||
/*Normal continue and break can be used with this loop macro*/
|
||||
|
||||
#define BASE(glthreadptr) ((glthreadptr)->right)
|
||||
|
||||
#define ITERATE_GLTHREAD_BEGIN(glthreadptrstart, glthreadptr) \
|
||||
{ \
|
||||
glthread_t *_glthread_ptr = NULL; \
|
||||
glthreadptr = BASE(glthreadptrstart); \
|
||||
for(; glthreadptr!= NULL; glthreadptr = _glthread_ptr){ \
|
||||
_glthread_ptr = (glthreadptr)->right;
|
||||
|
||||
#define ITERATE_GLTHREAD_END(glthreadptrstart, glthreadptr) \
|
||||
}}
|
||||
|
||||
#define GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthreadptr, offset) \
|
||||
(void *)((char *)(glthreadptr) - offset)
|
||||
|
||||
void
|
||||
delete_glthread_list(glthread_t *base_glthread);
|
||||
|
||||
unsigned int
|
||||
get_glthread_list_count(glthread_t *base_glthread);
|
||||
|
||||
void
|
||||
glthread_priority_insert(glthread_t *base_glthread,
|
||||
glthread_t *glthread,
|
||||
int (*comp_fn)(void *, void *),
|
||||
int offset);
|
||||
|
||||
glthread_t *
|
||||
dequeue_glthread_first(glthread_t *base_glthread);
|
||||
|
||||
#if 0
|
||||
void *
|
||||
gl_thread_search(glthread_t *base_glthread,
|
||||
void *(*thread_to_struct_fn)(glthread_t *),
|
||||
void *key,
|
||||
int (*comparison_fn)(void *, void *));
|
||||
|
||||
#endif
|
||||
#endif /* __GLUETHREAD__ */
|
||||
BIN
NFC/main.exe
Normal file
BIN
NFC/main.exe
Normal file
Binary file not shown.
92
NFC/notif.c
Normal file
92
NFC/notif.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: notif.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 12:00:51 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <assert.h>
|
||||
#include "notif.h"
|
||||
|
||||
notif_chain_t *
|
||||
nfc_create_new_notif_chain(char *notif_chain_name) {
|
||||
|
||||
notif_chain_t *nfc = calloc(1, sizeof(notif_chain_t));
|
||||
if(notif_chain_name) {
|
||||
strncpy(nfc->nfc_name, notif_chain_name,
|
||||
sizeof(nfc->nfc_name));
|
||||
}
|
||||
init_glthread(&nfc->notif_chain_head);
|
||||
return nfc;
|
||||
}
|
||||
|
||||
void
|
||||
nfc_register_notif_chain(notif_chain_t *nfc,
|
||||
notif_chain_elem_t *nfce){
|
||||
|
||||
notif_chain_elem_t *new_nfce = calloc(1, sizeof(notif_chain_elem_t));
|
||||
memcpy(new_nfce, nfce, sizeof(notif_chain_elem_t));
|
||||
init_glthread(&new_nfce->glue);
|
||||
glthread_add_next(&nfc->notif_chain_head, &new_nfce->glue);
|
||||
}
|
||||
|
||||
void
|
||||
nfc_delete_all_nfce(notif_chain_t *nfc){
|
||||
|
||||
glthread_t *curr;
|
||||
notif_chain_elem_t *nfce;
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(&nfc->notif_chain_head, curr){
|
||||
|
||||
nfce = glthread_glue_to_notif_chain_elem(curr);
|
||||
remove_glthread(&nfce->glue);
|
||||
free(nfce);
|
||||
} ITERATE_GLTHREAD_END(&nfc->notif_chain_head, curr);
|
||||
}
|
||||
|
||||
void
|
||||
nfc_invoke_notif_chain(notif_chain_t *nfc,
|
||||
void *arg, size_t arg_size,
|
||||
char *key, size_t key_size,
|
||||
nfc_op_t nfc_op_code){
|
||||
|
||||
glthread_t *curr;
|
||||
notif_chain_elem_t *nfce;
|
||||
|
||||
if(IS_GLTHREAD_LIST_EMPTY(&nfc->notif_chain_head)) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(key_size <= MAX_NOTIF_KEY_SIZE);
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(&nfc->notif_chain_head, curr){
|
||||
|
||||
nfce = glthread_glue_to_notif_chain_elem(curr);
|
||||
|
||||
if(!(key && key_size &&
|
||||
nfce->is_key_set && (key_size == nfce->key_size))){
|
||||
|
||||
nfce->app_cb(arg, arg_size, nfc_op_code, nfce->subs_id);
|
||||
}
|
||||
else {
|
||||
|
||||
if(memcmp(key, nfce->key, key_size) == 0) {
|
||||
|
||||
nfce->app_cb(arg, arg_size, nfc_op_code, nfce->subs_id);
|
||||
}
|
||||
}
|
||||
}ITERATE_GLTHREAD_END(&nfc->notif_chain_head, curr);
|
||||
}
|
||||
95
NFC/notif.h
Normal file
95
NFC/notif.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: notif.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 12:02:16 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef __NOTIF_CHAIN_
|
||||
#define __NOTIF_CHAIN_
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include "glthread/glthread.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#define MAX_NOTIF_KEY_SIZE 64
|
||||
|
||||
typedef enum{
|
||||
|
||||
NFC_UNKNOWN,
|
||||
NFC_SUB,
|
||||
NFC_ADD,
|
||||
NFC_MOD,
|
||||
NFC_DEL,
|
||||
} nfc_op_t;
|
||||
|
||||
static inline char *
|
||||
nfc_get_str_op_code(nfc_op_t nfc_op_code) {
|
||||
|
||||
static char op_code_str[16];
|
||||
|
||||
switch(nfc_op_code) {
|
||||
|
||||
case NFC_UNKNOWN:
|
||||
return "NFC_UNKNOWN";
|
||||
case NFC_SUB:
|
||||
return "NFC_SUB";
|
||||
case NFC_ADD:
|
||||
return "NFC_ADD";
|
||||
case NFC_MOD:
|
||||
return "NFC_MOD";
|
||||
case NFC_DEL:
|
||||
return "NFC_DEL";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef void (*nfc_app_cb)(void *, size_t, nfc_op_t, uint32_t);
|
||||
|
||||
typedef struct notif_chain_elem_{
|
||||
|
||||
char key[MAX_NOTIF_KEY_SIZE];
|
||||
size_t key_size;
|
||||
uint32_t subs_id;
|
||||
bool is_key_set;
|
||||
nfc_app_cb app_cb;
|
||||
glthread_t glue;
|
||||
} notif_chain_elem_t;
|
||||
GLTHREAD_TO_STRUCT(glthread_glue_to_notif_chain_elem,
|
||||
notif_chain_elem_t, glue);
|
||||
|
||||
typedef struct notif_chain_ {
|
||||
|
||||
char nfc_name[64];
|
||||
glthread_t notif_chain_head;
|
||||
} notif_chain_t;
|
||||
|
||||
notif_chain_t *
|
||||
nfc_create_new_notif_chain(char *notif_chain_name);
|
||||
|
||||
void
|
||||
nfc_delete_all_nfce(notif_chain_t *nfc);
|
||||
|
||||
void
|
||||
nfc_register_notif_chain(notif_chain_t *nfc,
|
||||
notif_chain_elem_t *nfce);
|
||||
|
||||
void
|
||||
nfc_invoke_notif_chain(notif_chain_t *nfc,
|
||||
void *arg, size_t arg_size,
|
||||
char *key, size_t key_size,
|
||||
nfc_op_t nfc_op_code);
|
||||
|
||||
#endif /* __NOTIF_CHAIN_ */
|
||||
217
NFC/rt.c
Normal file
217
NFC/rt.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: rt.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 12:55:35 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <assert.h>
|
||||
#include "rt.h"
|
||||
|
||||
void
|
||||
rt_init_rt_table(rt_table_t *rt_table){
|
||||
|
||||
rt_table->head = NULL;
|
||||
}
|
||||
|
||||
rt_entry_t *
|
||||
rt_add_or_update_rt_entry(rt_table_t *rt_table,
|
||||
char *dest,
|
||||
char mask,
|
||||
char *gw_ip,
|
||||
char *oif){
|
||||
|
||||
bool new_entry;
|
||||
rt_entry_t *head = NULL;
|
||||
rt_entry_t *rt_entry = NULL;
|
||||
|
||||
new_entry = false;
|
||||
|
||||
rt_entry = rt_look_up_rt_entry(rt_table, dest, mask);
|
||||
|
||||
if(!rt_entry) {
|
||||
|
||||
rt_entry = calloc(1, sizeof(rt_entry_t));
|
||||
|
||||
strncpy(rt_entry->rt_entry_keys.dest, dest,
|
||||
sizeof(rt_entry->rt_entry_keys.dest));
|
||||
rt_entry->rt_entry_keys.mask = mask;
|
||||
|
||||
rt_entry->nfc = nfc_create_new_notif_chain(0);
|
||||
new_entry = true;
|
||||
}
|
||||
|
||||
if(gw_ip)
|
||||
strncpy(rt_entry->gw_ip, gw_ip, sizeof(rt_entry->gw_ip));
|
||||
if(oif)
|
||||
strncpy(rt_entry->oif, oif, sizeof(rt_entry->oif));
|
||||
|
||||
if (new_entry) {
|
||||
head = rt_table->head;
|
||||
rt_table->head = rt_entry;
|
||||
rt_entry->prev = 0;
|
||||
rt_entry->next = head;
|
||||
if(head)
|
||||
head->prev = rt_entry;
|
||||
}
|
||||
|
||||
if (gw_ip || oif) {
|
||||
|
||||
/* Entry is being updated by the publisher, send
|
||||
* notification to all subscribers*/
|
||||
nfc_invoke_notif_chain(rt_entry->nfc,
|
||||
(char *)rt_entry, sizeof(rt_entry_t),
|
||||
0, 0, NFC_MOD);
|
||||
}
|
||||
|
||||
return rt_entry;
|
||||
}
|
||||
|
||||
bool
|
||||
rt_delete_rt_entry(rt_table_t *rt_table,
|
||||
char *dest, char mask){
|
||||
|
||||
rt_entry_t *rt_entry = NULL;
|
||||
|
||||
ITERTAE_RT_TABLE_BEGIN(rt_table, rt_entry){
|
||||
|
||||
if(strncmp(rt_entry->rt_entry_keys.dest,
|
||||
dest, sizeof(rt_entry->rt_entry_keys.dest)) == 0 &&
|
||||
rt_entry->rt_entry_keys.mask == mask){
|
||||
|
||||
rt_entry_remove(rt_table, rt_entry);
|
||||
|
||||
nfc_invoke_notif_chain(rt_entry->nfc,
|
||||
(char *)rt_entry, sizeof(rt_entry_t),
|
||||
0, 0, NFC_DEL);
|
||||
nfc_delete_all_nfce(rt_entry->nfc);
|
||||
free(rt_entry->nfc);
|
||||
rt_entry->nfc = NULL;
|
||||
free(rt_entry->nfc);
|
||||
|
||||
free(rt_entry);
|
||||
return true;
|
||||
}
|
||||
} ITERTAE_RT_TABLE_END(rt_table, curr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
rt_clear_rt_table(rt_table_t *rt_table){
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
rt_free_rt_table(rt_table_t *rt_table){
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
rt_dump_rt_table(rt_table_t *rt_table){
|
||||
|
||||
rt_entry_t *rt_entry = NULL;
|
||||
|
||||
ITERTAE_RT_TABLE_BEGIN(rt_table, rt_entry){
|
||||
|
||||
printf("%-20s %-4d %-20s %s\n",
|
||||
rt_entry->rt_entry_keys.dest,
|
||||
rt_entry->rt_entry_keys.mask,
|
||||
rt_entry->gw_ip,
|
||||
rt_entry->oif);
|
||||
printf("\tPrinting Subscribers : ");
|
||||
|
||||
glthread_t *curr;
|
||||
notif_chain_elem_t *nfce;
|
||||
|
||||
ITERATE_GLTHREAD_BEGIN(&rt_entry->nfc->notif_chain_head, curr){
|
||||
|
||||
nfce = glthread_glue_to_notif_chain_elem(curr);
|
||||
|
||||
printf("%u ", nfce->subs_id);
|
||||
|
||||
} ITERATE_GLTHREAD_END(&rt_entry->nfc->notif_chain_head, curr)
|
||||
printf("\n");
|
||||
} ITERTAE_RT_TABLE_END(rt_table, rt_entry);
|
||||
}
|
||||
|
||||
rt_entry_t *
|
||||
rt_look_up_rt_entry(rt_table_t *rt_table,
|
||||
char *dest, char mask) {
|
||||
|
||||
rt_entry_t *rt_entry = NULL;
|
||||
|
||||
ITERTAE_RT_TABLE_BEGIN(rt_table, rt_entry) {
|
||||
if ((strncmp(rt_entry->rt_entry_keys.dest,
|
||||
dest, sizeof(rt_entry->rt_entry_keys.dest)) == 0) &&
|
||||
rt_entry->rt_entry_keys.mask == mask) {
|
||||
|
||||
return rt_entry;
|
||||
}
|
||||
} ITERTAE_RT_TABLE_END(rt_table, rt_entry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rt_table_register_for_notification(
|
||||
rt_table_t *rt_table,
|
||||
rt_entry_keys_t *key,
|
||||
size_t key_size,
|
||||
nfc_app_cb app_cb,
|
||||
uint32_t subs_id) {
|
||||
|
||||
bool new_entry_created;
|
||||
rt_entry_t *rt_entry;
|
||||
notif_chain_elem_t nfce;
|
||||
|
||||
new_entry_created = false;
|
||||
|
||||
rt_entry = rt_look_up_rt_entry(rt_table, key->dest, key->mask);
|
||||
|
||||
if (!rt_entry) {
|
||||
/* rt_entry was not existing before, but we are
|
||||
* creating it because subscriber is interested in notif
|
||||
* for this entry. Create such an entry without data. Later
|
||||
* When publisher would actually cate this entry, all registered
|
||||
* subscriber should be notified
|
||||
* */
|
||||
rt_entry = rt_add_or_update_rt_entry(
|
||||
rt_table, key->dest, key->mask, 0, 0);
|
||||
new_entry_created = true;
|
||||
}
|
||||
|
||||
memset(&nfce, 0, sizeof(notif_chain_elem_t));
|
||||
|
||||
assert(key_size <= MAX_NOTIF_KEY_SIZE);
|
||||
|
||||
/* No need to keep keys as nfce;s are tied to
|
||||
* routing table entry which contain keys*/
|
||||
//memcpy(nfce.key, (char *)key, key_size);
|
||||
//nfce.key_size = key_size;
|
||||
nfce.app_cb = app_cb;
|
||||
nfce.subs_id = subs_id;
|
||||
nfc_register_notif_chain(rt_entry->nfc, &nfce);
|
||||
|
||||
/* Subscriber subscribes to already existing rt entry,
|
||||
* immediately send notif to Subscriber with opcode
|
||||
* NFC_ADD*/
|
||||
if (!new_entry_created) {
|
||||
app_cb(rt_entry, sizeof(rt_entry_t), NFC_ADD, subs_id);
|
||||
}
|
||||
}
|
||||
122
NFC/rt.h
Normal file
122
NFC/rt.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: rt.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 12:47:20 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef __RT__
|
||||
#define __RT__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "notif.h"
|
||||
|
||||
typedef struct rt_entry_keys_{
|
||||
|
||||
char dest[16];
|
||||
char mask;
|
||||
} rt_entry_keys_t;
|
||||
|
||||
typedef struct rt_entry_{
|
||||
|
||||
/* A Structure which represnets only the keys of the
|
||||
* Routing Table.*/
|
||||
rt_entry_keys_t rt_entry_keys;
|
||||
|
||||
char gw_ip[16];
|
||||
char oif[32];
|
||||
bool created;
|
||||
struct rt_entry_ *prev;
|
||||
struct rt_entry_ *next;
|
||||
notif_chain_t *nfc;
|
||||
} rt_entry_t;
|
||||
|
||||
typedef struct rt_table_{
|
||||
|
||||
rt_entry_t *head;
|
||||
} rt_table_t;
|
||||
|
||||
void
|
||||
rt_init_rt_table(rt_table_t *rt_table);
|
||||
|
||||
rt_entry_t *
|
||||
rt_add_or_update_rt_entry(rt_table_t *rt_table,
|
||||
char *dest_ip, char mask, char *gw_ip, char *oif);
|
||||
|
||||
bool
|
||||
rt_delete_rt_entry(rt_table_t *rt_table,
|
||||
char *dest_ip, char mask);
|
||||
|
||||
bool
|
||||
rt_update_rt_entry(rt_table_t *rt_table,
|
||||
char *dest_ip, char mask,
|
||||
char *new_gw_ip, char *new_oif);
|
||||
|
||||
rt_entry_t *
|
||||
rt_look_up_rt_entry(rt_table_t *rt_table,
|
||||
char *dest, char mask);
|
||||
|
||||
void
|
||||
rt_clear_rt_table(rt_table_t *rt_table);
|
||||
|
||||
void
|
||||
rt_free_rt_table(rt_table_t *rt_table);
|
||||
|
||||
void
|
||||
rt_dump_rt_table(rt_table_t *rt_table);
|
||||
|
||||
static inline void
|
||||
rt_entry_remove(rt_table_t *rt_table,
|
||||
rt_entry_t *rt_entry){
|
||||
|
||||
if(!rt_entry->prev){
|
||||
if(rt_entry->next){
|
||||
rt_entry->next->prev = 0;
|
||||
rt_table->head = rt_entry->next;
|
||||
rt_entry->next = 0;
|
||||
return;
|
||||
}
|
||||
rt_table->head = 0;
|
||||
return;
|
||||
}
|
||||
if(!rt_entry->next){
|
||||
rt_entry->prev->next = 0;
|
||||
rt_entry->prev = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
rt_entry->prev->next = rt_entry->next;
|
||||
rt_entry->next->prev = rt_entry->prev;
|
||||
rt_entry->prev = 0;
|
||||
rt_entry->next = 0;
|
||||
}
|
||||
|
||||
#define ITERTAE_RT_TABLE_BEGIN(rt_table_ptr, rt_entry_ptr) \
|
||||
{ \
|
||||
rt_entry_t *_next_rt_entry; \
|
||||
for((rt_entry_ptr) = (rt_table_ptr)->head; \
|
||||
(rt_entry_ptr); \
|
||||
(rt_entry_ptr) = _next_rt_entry) { \
|
||||
_next_rt_entry = (rt_entry_ptr)->next;
|
||||
|
||||
#define ITERTAE_RT_TABLE_END(rt_table_ptr, rt_entry_ptr) }}
|
||||
|
||||
void
|
||||
rt_table_register_for_notification(
|
||||
rt_table_t *rt_table,
|
||||
rt_entry_keys_t *key,
|
||||
size_t key_size,
|
||||
nfc_app_cb app_cb,
|
||||
uint32_t subs_id);
|
||||
|
||||
#endif /* __RT__ */
|
||||
128
NFC/rtm_publisher.c
Normal file
128
NFC/rtm_publisher.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: rtm_publisher.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 02:01:50 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "rt.h"
|
||||
|
||||
extern void
|
||||
create_subscriber_thread(uint32_t client_id);
|
||||
|
||||
rt_table_t publisher_rt_table;
|
||||
|
||||
rt_table_t *
|
||||
publisher_get_rt_table() {
|
||||
|
||||
return &publisher_rt_table;
|
||||
}
|
||||
|
||||
void
|
||||
main_menu() {
|
||||
|
||||
int choice;
|
||||
while(1){
|
||||
printf("Publisher Menu\n");
|
||||
printf("1. Add/Update rt table entry\n");
|
||||
printf("2. Delete rt table entry\n");
|
||||
printf("3. Dump rt table\n");
|
||||
printf("Enter Choice :");
|
||||
choice = 0;
|
||||
scanf("%d", &choice);
|
||||
switch(choice){
|
||||
case 1:
|
||||
{
|
||||
char dest[16];
|
||||
char mask;
|
||||
char oif[32];
|
||||
char gw[16];
|
||||
printf("Enter Destination :");
|
||||
scanf("%s", dest);
|
||||
printf("Mask : ");
|
||||
scanf("%d", &mask);
|
||||
printf("Enter oif name :");
|
||||
scanf("%s", oif);
|
||||
printf("Enter Gateway IP :");
|
||||
scanf("%s", gw);
|
||||
rt_add_or_update_rt_entry(publisher_get_rt_table(),
|
||||
dest, mask, gw, oif);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* Implement your self */
|
||||
break;
|
||||
case 3:
|
||||
rt_dump_rt_table(publisher_get_rt_table());
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
publisher_thread_fn(void *arg) {
|
||||
|
||||
/* Add some default entries in rt table */
|
||||
rt_add_or_update_rt_entry(
|
||||
publisher_get_rt_table(),
|
||||
"122.1.1.1", 32, "10.1.1.1", "eth1");
|
||||
|
||||
rt_add_or_update_rt_entry(
|
||||
publisher_get_rt_table(),
|
||||
"122.1.1.2", 32, "10.1.1.2", "eth1");
|
||||
|
||||
rt_add_or_update_rt_entry(
|
||||
publisher_get_rt_table(),
|
||||
"122.1.1.3", 32, "10.1.1.3", "eth1");
|
||||
|
||||
rt_dump_rt_table(publisher_get_rt_table());
|
||||
main_menu();
|
||||
}
|
||||
|
||||
void
|
||||
create_publisher_thread() {
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_t pub_thread;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
pthread_create(&pub_thread, &attr,
|
||||
publisher_thread_fn,
|
||||
(void *)0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
|
||||
rt_init_rt_table(&publisher_rt_table);
|
||||
/* Create Subscriber threads */
|
||||
create_subscriber_thread(1);
|
||||
sleep(1);
|
||||
|
||||
create_subscriber_thread(2);
|
||||
sleep(1);
|
||||
|
||||
create_subscriber_thread(3);
|
||||
sleep(1);
|
||||
/* Create publisher thread*/
|
||||
create_publisher_thread();
|
||||
printf("Publisher thread created\n");
|
||||
pthread_exit(0);
|
||||
return 0;
|
||||
}
|
||||
93
NFC/threaded_subsciber.c
Normal file
93
NFC/threaded_subsciber.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: threaded_subsciber.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 10/03/24 02:45:48 PM IST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: YOUR NAME (),
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h> /*for pid_t*/
|
||||
#include <unistd.h> /*for getpid()*/
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include "notif.h"
|
||||
#include "rt.h"
|
||||
|
||||
void
|
||||
create_subscriber_thread();
|
||||
|
||||
extern rt_table_t *
|
||||
publisher_get_rt_table();
|
||||
|
||||
static void
|
||||
test_cb(void *arg, size_t arg_size,
|
||||
nfc_op_t nfc_op_code,
|
||||
uint32_t client_id) {
|
||||
|
||||
rt_entry_t *rt_entry;
|
||||
printf("%s() client : %u, Notified with opcode %s\n",
|
||||
__FUNCTION__, client_id, nfc_get_str_op_code(nfc_op_code));
|
||||
|
||||
rt_entry = (rt_entry_t *) arg;
|
||||
|
||||
printf("%-20s %-4d %-20s %s\n",
|
||||
rt_entry->rt_entry_keys.dest,
|
||||
rt_entry->rt_entry_keys.mask,
|
||||
rt_entry->gw_ip,
|
||||
rt_entry->oif);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void *
|
||||
subscriber_thread_fn(void *arg){
|
||||
|
||||
rt_entry_keys_t rt_entry_keys;
|
||||
|
||||
/* register for Notif 122.1.1.1/32 */
|
||||
memset(&rt_entry_keys, 0, sizeof(rt_entry_keys_t));
|
||||
strncpy(rt_entry_keys.dest, "122.1.1.1", 16);
|
||||
rt_entry_keys.mask = 32;
|
||||
rt_table_register_for_notification(publisher_get_rt_table(), &rt_entry_keys, sizeof(rt_entry_keys_t), test_cb, *((uint32_t *)arg));
|
||||
|
||||
/* register for Notif 122.1.1.2/32 */
|
||||
memset(&rt_entry_keys, 0, sizeof(rt_entry_keys_t));
|
||||
strncpy(rt_entry_keys.dest, "122.1.1.5", 16);
|
||||
rt_entry_keys.mask = 32;
|
||||
rt_table_register_for_notification(publisher_get_rt_table(), &rt_entry_keys, sizeof(rt_entry_keys_t), test_cb, *((uint32_t *)arg));
|
||||
|
||||
/* register for Notif 122.1.1.3/32 */
|
||||
memset(&rt_entry_keys, 0, sizeof(rt_entry_keys_t));
|
||||
strncpy(rt_entry_keys.dest, "122.1.1.6", 16);
|
||||
rt_entry_keys.mask = 32;
|
||||
rt_table_register_for_notification(publisher_get_rt_table(), &rt_entry_keys, sizeof(rt_entry_keys_t), test_cb, *((uint32_t *)arg));
|
||||
|
||||
pause();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
create_subscriber_thread(uint32_t client_id){
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_t subs_thread;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
pthread_create(&subs_thread, &attr,
|
||||
subscriber_thread_fn,
|
||||
(void *)&client_id);
|
||||
printf("Subscriber %u created\n", client_id);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user