GROS CHANTIER

more_to_read
Philippe PITTOLI 2016-06-04 20:33:44 +02:00
parent ea882d37dc
commit 6df133c2c1
10 changed files with 436 additions and 148 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.a
*.so
*.swp

View File

@ -72,6 +72,23 @@ int service_close (const char *fifopath)
return 0;
}
struct process * srv_process_copy (const struct process *p)
{
if (p == NULL)
return NULL;
struct process * copy = malloc (sizeof(struct process));
memcpy (copy, p, sizeof (struct process));
return copy;
}
int srv_process_eq (const struct process *p1, const struct process *p2)
{
return (p1->pid == p2->pid && p1>version == p2->version
&& p1->index == p2->index);
}
int service_get_new_process (struct process *proc, const char * spath)
{
if (spath == NULL) {

View File

@ -36,6 +36,10 @@ struct service {
int service_path (char *buf, const char *sname);
struct process * srv_process_copy (struct process *p);
int srv_process_eq (const struct process *p1, const struct process *p2);
void gen_process_structure (struct process *p
, pid_t pid, unsigned int index, unsigned int version);
@ -53,6 +57,7 @@ int service_get_new_process (struct process *proc, const char * spath);
void service_get_new_processes (struct process ***, int *nproc, char *spath);
void service_free_processes (struct process **, int nproc);
void process_print (struct process *);
int process_create (struct process *, int index); // called by the application
int process_destroy (struct process *); // called by the application

BIN
lib/communication.o Normal file

Binary file not shown.

171
lib/queue.h Normal file
View File

@ -0,0 +1,171 @@
/* $OpenBSD: queue.h,v 1.43 2015/12/28 19:38:40 millert Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues and XOR simple queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* An XOR simple queue is used in the same way as a regular simple queue.
* The difference is that the head structure also includes a "cookie" that
* is XOR'd with the queue pointer (first, last or next) to generate the
* real pointer value.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
#endif
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods.
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#endif /* _SYS_QUEUE_H_ */

22
pubsub/Makefile Normal file
View File

@ -0,0 +1,22 @@
CC=gcc
CFLAGS=-Wall -g
LDFLAGS=
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
EXEC=$(basename $(wildcard *.c))
SOURCES=$(wildcard ../lib/*.c)
OBJECTS=$(SOURCES:.c=.o)
TESTS=$(addsuffix .test, $(EXEC))
all: $(SOURCES) $(EXEC)
$(EXEC): $(OBJECTS) $(CFILES)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
clean:
-rm $(OBJECTS)
mrproper: clean
rm $(EXEC)

View File

@ -1,48 +0,0 @@
#include <stdlib.h>
#include "list.h"
List*
list_new(size_t element_size)
{
List* l = malloc(sizeof(*l));
l->element_size = element_size;
l->head = NULL;
l->tail = NULL;
l->length = 0;
return l;
}
void*
list_append(List* l)
{
struct link* link = malloc(sizeof(*link) + l->element_size);
link->next = l->tail;
l->tail = link;
if (!l->head)
l->tail = link;
l->length++;
return (void*) link->value;
}
void
list_free(List* l)
{
struct link* next;
struct link* link;
for (link = l->head; link; link = next) {
next = link->next;
free(link);
}
free(l);
}

View File

@ -1,23 +0,0 @@
#ifndef LIST_H
#define LIST_H
struct link {
struct link* next;
char value[];
};
typedef struct {
struct link* head;
struct link* tail;
size_t element_size;
size_t length;
} List;
List* list_new(size_t);
void* list_append(List*);
void list_remove(List*, size_t);
void list_free(List*);
#endif

View File

@ -1,91 +1,191 @@
#include "../lib/communication.h"
#include <stdlib.h>
#include <communication.h>
#include "list.h"
typedef struct {
int test;
} Publisher;
typedef struct {
int test;
} Subscriber;
const char* service_name = "pubsub";
void
ohshit(int rvalue, const char* str) {
fprintf(stderr, "%s\n", str);
exit(rvalue);
fprintf(stderr, "%s\n", str);
exit(rvalue);
}
// init lists
void pubsubd_channels_init (struct channels *chans) { LIST_INIT(chans); }
void pubsubd_subscriber_init (struct app_list *al) { LIST_INIT(al); }
int
main(int argc, char* argv[])
pubsubd_channels_eq (const struct channel *c1, const struct channel *c2)
{
List* subscribers;
List* publishers;
int r;
char s_path[PATH_MAX];
int s_pipe;
return (strncmp (c1->chan, c2->chan, c1->chanlen) == 0);
}
struct channels * pubsubd_channels_copy (struct channels *c);
(void) argc;
(void) argv;
void
pubsubd_channels_add (struct channels *chans, struct channels *c)
{
if(!chans || !c)
return;
service_path(s_path, service_name);
printf("Listening on %s.\n", s_path);
if ((r = service_create(s_path)))
ohshit(1, "service_create error");
publishers = list_new(sizeof(Publisher));
subscribers = list_new(sizeof(Subscriber));
if (!publishers && !subscribers)
ohshit(1, "out of memory, already...");
/* ?!?!?!?!? */
mkfifo(s_path, S_IRUSR);
s_pipe = open(s_path, S_IRUSR);
for (;;) {
struct process* proc;
int proc_count, i;
service_get_new_processes(&proc, &proc_count, s_pipe);
printf("> %i proc\n", proc_count);
for (i = 0; i < proc_count; i++) {
size_t message_size = BUFSIZ;
char buffer[BUFSIZ];
process_print(proc + i);
if ((r = process_read(&proc[i], &buffer, &message_size))) {
ohshit(1, "process_read error");
}
printf(": %s\n", buffer);
}
service_free_processes(&proc, proc_count);
break;
}
close(s_pipe);
list_free(publishers);
list_free(subscribers);
service_close(s_path);
return 0;
struct process *n = pubsubd_channels_copy (c);
LIST_INSERT_HEAD(al, n, entries);
}
void
pubsubd_subscriber_del (struct app_list *al, struct process *p)
{
struct process *todel = srv_subscriber_get (al, p);
if(todel != NULL) {
LIST_REMOVE(todel, entries);
srv_process_free (mfree, todel);
mfree (todel);
todel = NULL;
}
}
void
pubsubd_subscriber_add (struct app_list *al, struct process *p)
{
if(!al || !p)
return;
struct process *n = srv_process_copy (p);
LIST_INSERT_HEAD(al, n, entries);
}
struct process *
pubsubd_subscriber_get (const struct app_list *al
, const struct process *p)
{
struct process *np, *res = NULL;
LIST_FOREACH(np, al, entries) {
if(srv_process_eq (np, p)) {
res = np;
}
}
return res;
}
void
pubsubd_subscriber_del (struct app_list *al, struct process *p)
{
struct process *todel = srv_subscriber_get (al, p);
if(todel != NULL) {
LIST_REMOVE(todel, entries);
srv_process_free (mfree, todel);
mfree (todel);
todel = NULL;
}
}
void pubsubd_msg_send (struct service *s, struct message * m, struct process *p)
{
}
void pubsubd_msg_recv (struct service *s, struct message * m, struct process *p)
{
}
void pubsub_msg_send (struct service *s, struct message * m)
{
}
void pubsub_msg_recv (struct service *s, struct message * m)
{
}
int
main(int argc, char* argv[])
{
// gets the service path, such as /tmp/<service>
char s_path[PATH_MAX];
service_path (s_path, service_name);
printf ("Listening on %s.\n", s_path);
// creates the service named pipe, that listens to client applications
if (service_create (s_path))
ohshit(1, "service_create error");
struct channels chans;
pubsubd_channels_init (&chans);
for (;;) {
struct process proc;
int proc_count, i;
service_get_new_process (&proc, s_path);
printf("> %i proc\n", proc_count);
for (i = 0; i < proc_count; i++) {
size_t message_size = BUFSIZ;
char buffer[BUFSIZ];
process_print(proc + i);
if (process_read (&proc[i], &buffer, &message_size))
ohshit(1, "process_read error");
printf(": %s\n", buffer);
}
service_free_processes(&proc, proc_count);
}
// the application will shut down, and remove the service named pipe
if (service_close (s_path))
ohshit(1, "service_close error");
return EXIT_SUCCESS;
}
/*
* main loop
*
* opens the application pipes,
* reads then writes the same message,
* then closes the pipes
*/
void main_loop (const char *spath)
{
int ret;
struct process proc;
int cnt = 10;
while (cnt--) {
// -1 : error, 0 = no new process, 1 = new process
ret = service_get_new_process (&proc, spath);
if (ret == -1) {
fprintf (stderr, "error service_get_new_process\n");
continue;
} else if (ret == 0) { // that should not happen
continue;
}
// printf ("before print\n");
process_print (&proc);
// printf ("after print\n");
// about the message
size_t msize = BUFSIZ;
char buf[BUFSIZ];
bzero(buf, BUFSIZ);
// printf ("before read\n");
if ((ret = service_read (&proc, &buf, &msize))) {
fprintf(stdout, "error service_read %d\n", ret);
continue;
}
// printf ("after read\n");
printf ("read, size %ld : %s\n", msize, buf);
// printf ("before proc write\n");
if ((ret = service_write (&proc, &buf, msize))) {
fprintf(stdout, "error service_write %d\n", ret);
continue;
}
// printf ("after proc write\n");
printf ("\033[32mStill \033[31m%d\033[32m applications to serve\n",cnt);
}
}

41
pubsub/pubsubd.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef __PUBSUBD_H__
#define __PUBSUBD_H__
#include "queue.h"
struct message {
unsigned char *chan;
size_t chanlen;
unsigned char *data;
size_t datalen;
unsigned char type; // message type : alert, notification, …
};
struct channel {
unsigned char *chan;
size_t chanlen;
};
struct channels {
struct channel *chan;
LIST_ENTRY(channels) entries;
};
int pubsubd_channels_eq (const struct channels *c1, const struct channels *c2);
struct app_list {
struct process *p;
LIST_ENTRY(app_list) entries;
};
void pubsubd_msg_send (struct service *, struct message *msg, struct process *p);
void pubsubd_msg_recv (struct service *, struct message *msg, struct process *p);
struct process * pubsubd_subscriber_get (const struct app_list *
, const struct process *);
void pubsubd_subscriber_del (struct app_list *al, struct process *p);
void pubsub_msg_send (struct service *, struct message *msg);
void pubsub_msg_recv (struct service *, struct message *msg);
#endif