libipc split into its own, separate repository.
parent
ab3d9dd344
commit
878432e7eb
|
@ -0,0 +1,326 @@
|
|||
PACKAGE = 'ipc'
|
||||
VERSION = '0.1.0'
|
||||
|
||||
PREFIX := /usr/local
|
||||
BINDIR := $(PREFIX)/bin
|
||||
LIBDIR := $(PREFIX)/lib
|
||||
SHAREDIR := $(PREFIX)/share
|
||||
INCLUDEDIR := $(PREFIX)/include
|
||||
MANDIR := $(SHAREDIR)/man
|
||||
|
||||
CC := cc
|
||||
AR := ar
|
||||
RANLIB := ranlib
|
||||
CFLAGS :=
|
||||
LDFLAGS :=
|
||||
|
||||
Q := @
|
||||
|
||||
all: libipc src/ipc.h man/libipc.7
|
||||
@:
|
||||
|
||||
libipc: libipc.so libipc.a
|
||||
@:
|
||||
libipc.install: libipc.so.install libipc.a.install
|
||||
|
||||
libipc.clean: libipc.so.clean libipc.a.clean
|
||||
|
||||
libipc.uninstall: libipc.so.uninstall libipc.a.uninstall
|
||||
|
||||
src/ipc.h.install: src/ipc.h
|
||||
@echo '[01;31m IN > [01;37m$(INCLUDEDIR)/ipc.h[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(INCLUDEDIR)'
|
||||
$(Q)install -m0644 src/ipc.h $(DESTDIR)$(INCLUDEDIR)/ipc.h
|
||||
|
||||
src/ipc.h.clean: src/ipc.h
|
||||
$(Q):
|
||||
|
||||
src/ipc.h.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(INCLUDEDIR)/ipc.h[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(INCLUDEDIR)/ipc.h'
|
||||
|
||||
man/libipc.7: man/libipc.7.md
|
||||
@echo '[01;32m MAN > [01;37mman/libipc.7[00m'
|
||||
$(Q)pandoc -s --from markdown --to man 'man/libipc.7.md' -o 'man/libipc.7'
|
||||
|
||||
|
||||
man/libipc.7.install: man/libipc.7
|
||||
@echo '[01;31m IN > [01;37m$(MANDIR)/man7/libipc.7[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(MANDIR)/man7'
|
||||
$(Q)install -m0644 man/libipc.7 $(DESTDIR)$(MANDIR)/man7/libipc.7
|
||||
|
||||
man/libipc.7.clean:
|
||||
@echo '[01;37m RM > [01;37mman/libipc.7[00m'
|
||||
$(Q)rm -f man/libipc.7
|
||||
|
||||
man/libipc.7.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(MANDIR)/man7/libipc.7[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(MANDIR)/man7/libipc.7'
|
||||
|
||||
libipc.so: src/client.o src/communication.o src/logger.o src/message.o src/usocket.o src/utils.o
|
||||
@echo '[01;32m LD > [01;37mlibipc.so[00m'
|
||||
$(Q)$(CC) -o libipc.so -shared $(LDFLAGS) src/client.o src/communication.o src/logger.o src/message.o src/usocket.o src/utils.o
|
||||
|
||||
libipc.so.install: libipc.so
|
||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.so.0.1.0[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
|
||||
$(Q)install -m0755 libipc.so $(DESTDIR)$(LIBDIR)/libipc.so.0.1.0
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so.0.1[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.1.0' '$(DESTDIR)/$(LIBDIR)/libipc.so.0.1'
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so.0[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.1.0' '$(DESTDIR)/$(LIBDIR)/libipc.so.0'
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.1.0' '$(DESTDIR)/$(LIBDIR)/libipc.so'
|
||||
|
||||
libipc.so.clean:
|
||||
@echo '[01;37m RM > [01;37mlibipc.so[00m'
|
||||
$(Q)rm -f libipc.so
|
||||
|
||||
libipc.so.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0.1.0[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0.1.0'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0.1[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0.1'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so'
|
||||
|
||||
libipc.a: src/client.o src/communication.o src/logger.o src/message.o src/usocket.o src/utils.o
|
||||
@echo '[01;32m LD > [01;37mlibipc.a[00m'
|
||||
$(Q)$(AR) rc 'libipc.a' src/client.o src/communication.o src/logger.o src/message.o src/usocket.o src/utils.o
|
||||
|
||||
libipc.a.install: libipc.a
|
||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.a[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
|
||||
$(Q)install -m0755 libipc.a $(DESTDIR)$(LIBDIR)/libipc.a
|
||||
|
||||
libipc.a.clean:
|
||||
@echo '[01;37m RM > [01;37mlibipc.a[00m'
|
||||
$(Q)rm -f libipc.a
|
||||
|
||||
libipc.a.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.a[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.a'
|
||||
|
||||
src/client.o: src/client.c src/client.h
|
||||
@echo '[01;34m CC > [01;37msrc/client.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/client.c -fPIC -o src/client.o
|
||||
|
||||
src/client.o.install:
|
||||
|
||||
src/client.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/client.o[00m'
|
||||
$(Q)rm -f src/client.o
|
||||
|
||||
src/client.o.uninstall:
|
||||
|
||||
src/communication.o: src/communication.c src/communication.h src/utils.h src/error.h src/event.h
|
||||
@echo '[01;34m CC > [01;37msrc/communication.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/communication.c -fPIC -o src/communication.o
|
||||
|
||||
src/communication.o.install:
|
||||
|
||||
src/communication.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/communication.o[00m'
|
||||
$(Q)rm -f src/communication.o
|
||||
|
||||
src/communication.o.uninstall:
|
||||
|
||||
src/logger.o: src/logger.c src/logger.h
|
||||
@echo '[01;34m CC > [01;37msrc/logger.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/logger.c -fPIC -o src/logger.o
|
||||
|
||||
src/logger.o.install:
|
||||
|
||||
src/logger.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/logger.o[00m'
|
||||
$(Q)rm -f src/logger.o
|
||||
|
||||
src/logger.o.uninstall:
|
||||
|
||||
src/message.o: src/message.c src/message.h src/error.h src/usocket.h
|
||||
@echo '[01;34m CC > [01;37msrc/message.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/message.c -fPIC -o src/message.o
|
||||
|
||||
src/message.o.install:
|
||||
|
||||
src/message.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/message.o[00m'
|
||||
$(Q)rm -f src/message.o
|
||||
|
||||
src/message.o.uninstall:
|
||||
|
||||
src/usocket.o: src/usocket.c src/usocket.h src/utils.h src/error.h
|
||||
@echo '[01;34m CC > [01;37msrc/usocket.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/usocket.c -fPIC -o src/usocket.o
|
||||
|
||||
src/usocket.o.install:
|
||||
|
||||
src/usocket.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/usocket.o[00m'
|
||||
$(Q)rm -f src/usocket.o
|
||||
|
||||
src/usocket.o.uninstall:
|
||||
|
||||
src/utils.o: src/utils.c src/utils.h
|
||||
@echo '[01;34m CC > [01;37msrc/utils.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c src/utils.c -fPIC -o src/utils.o
|
||||
|
||||
src/utils.o.install:
|
||||
|
||||
src/utils.o.clean:
|
||||
@echo '[01;37m RM > [01;37msrc/utils.o[00m'
|
||||
$(Q)rm -f src/utils.o
|
||||
|
||||
src/utils.o.uninstall:
|
||||
|
||||
$(DESTDIR)$(PREFIX):
|
||||
@echo '[01;35m DIR > [01;37m$(PREFIX)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(PREFIX)
|
||||
$(DESTDIR)$(BINDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(BINDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(BINDIR)
|
||||
$(DESTDIR)$(LIBDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(LIBDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(LIBDIR)
|
||||
$(DESTDIR)$(SHAREDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(SHAREDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(SHAREDIR)
|
||||
$(DESTDIR)$(INCLUDEDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(INCLUDEDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(INCLUDEDIR)
|
||||
$(DESTDIR)$(MANDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(MANDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(MANDIR)
|
||||
install: subdirs.install libipc.install src/ipc.h.install man/libipc.7.install libipc.so.install libipc.a.install src/client.o.install src/communication.o.install src/logger.o.install src/message.o.install src/usocket.o.install src/utils.o.install src/client.o.install src/communication.o.install src/logger.o.install src/message.o.install src/usocket.o.install src/utils.o.install
|
||||
@:
|
||||
|
||||
subdirs.install:
|
||||
|
||||
uninstall: subdirs.uninstall libipc.uninstall src/ipc.h.uninstall man/libipc.7.uninstall libipc.so.uninstall libipc.a.uninstall src/client.o.uninstall src/communication.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall src/client.o.uninstall src/communication.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall
|
||||
@:
|
||||
|
||||
subdirs.uninstall:
|
||||
|
||||
test: all subdirs subdirs.test
|
||||
@:
|
||||
|
||||
subdirs.test:
|
||||
|
||||
clean: libipc.clean src/ipc.h.clean man/libipc.7.clean libipc.so.clean libipc.a.clean src/client.o.clean src/communication.o.clean src/logger.o.clean src/message.o.clean src/usocket.o.clean src/utils.o.clean src/client.o.clean src/communication.o.clean src/logger.o.clean src/message.o.clean src/usocket.o.clean src/utils.o.clean
|
||||
|
||||
distclean: clean
|
||||
|
||||
dist: dist-gz dist-xz dist-bz2
|
||||
$(Q)rm -- $(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir:
|
||||
$(Q)rm -rf -- $(PACKAGE)-$(VERSION)
|
||||
$(Q)ln -s -- . $(PACKAGE)-$(VERSION)
|
||||
|
||||
dist-gz: $(PACKAGE)-$(VERSION).tar.gz
|
||||
$(PACKAGE)-$(VERSION).tar.gz: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.gz[00m'
|
||||
$(Q)tar czf $(PACKAGE)-$(VERSION).tar.gz \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/src/error.h \
|
||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/src/event.h \
|
||||
$(PACKAGE)-$(VERSION)/man/libipc.7.md \
|
||||
$(PACKAGE)-$(VERSION)/src/client.c \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/src/client.h \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/src/message.h \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.h
|
||||
|
||||
dist-xz: $(PACKAGE)-$(VERSION).tar.xz
|
||||
$(PACKAGE)-$(VERSION).tar.xz: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.xz[00m'
|
||||
$(Q)tar cJf $(PACKAGE)-$(VERSION).tar.xz \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/src/error.h \
|
||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/src/event.h \
|
||||
$(PACKAGE)-$(VERSION)/man/libipc.7.md \
|
||||
$(PACKAGE)-$(VERSION)/src/client.c \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/src/client.h \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/src/message.h \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.h
|
||||
|
||||
dist-bz2: $(PACKAGE)-$(VERSION).tar.bz2
|
||||
$(PACKAGE)-$(VERSION).tar.bz2: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.bz2[00m'
|
||||
$(Q)tar cjf $(PACKAGE)-$(VERSION).tar.bz2 \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/src/error.h \
|
||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/src/event.h \
|
||||
$(PACKAGE)-$(VERSION)/man/libipc.7.md \
|
||||
$(PACKAGE)-$(VERSION)/src/client.c \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/src/client.h \
|
||||
$(PACKAGE)-$(VERSION)/src/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/src/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/src/message.h \
|
||||
$(PACKAGE)-$(VERSION)/src/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/src/utils.h
|
||||
|
||||
help:
|
||||
@echo '[01;37m :: ipc-0.1.0[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mGeneric targets:[00m'
|
||||
@echo '[00m - [01;32mhelp [37m Prints this help message.[00m'
|
||||
@echo '[00m - [01;32mall [37m Builds all targets.[00m'
|
||||
@echo '[00m - [01;32mdist [37m Creates tarballs of the files of the project.[00m'
|
||||
@echo '[00m - [01;32minstall [37m Installs the project.[00m'
|
||||
@echo '[00m - [01;32mclean [37m Removes compiled files.[00m'
|
||||
@echo '[00m - [01;32muninstall [37m Deinstalls the project.[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mCLI-modifiable variables:[00m'
|
||||
@echo ' - [01;34mCC [37m ${CC}[00m'
|
||||
@echo ' - [01;34mCFLAGS [37m ${CFLAGS}[00m'
|
||||
@echo ' - [01;34mLDFLAGS [37m ${LDFLAGS}[00m'
|
||||
@echo ' - [01;34mDESTDIR [37m ${DESTDIR}[00m'
|
||||
@echo ' - [01;34mPREFIX [37m ${PREFIX}[00m'
|
||||
@echo ' - [01;34mBINDIR [37m ${BINDIR}[00m'
|
||||
@echo ' - [01;34mLIBDIR [37m ${LIBDIR}[00m'
|
||||
@echo ' - [01;34mSHAREDIR [37m ${SHAREDIR}[00m'
|
||||
@echo ' - [01;34mINCLUDEDIR [37m ${INCLUDEDIR}[00m'
|
||||
@echo ' - [01;34mMANDIR [37m ${MANDIR}[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mProject targets: [00m'
|
||||
@echo ' - [01;33mlibipc [37m library[00m'
|
||||
@echo ' - [01;33msrc/ipc.h [37m header[00m'
|
||||
@echo ' - [01;33mman/libipc.7 [37m man[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mMakefile options:[00m'
|
||||
@echo ' - gnu: false'
|
||||
@echo ' - colors: true'
|
||||
@echo ''
|
||||
@echo '[01;37mRebuild the Makefile with:[00m'
|
||||
@echo ' zsh ./build.zsh -c'
|
||||
.PHONY: all subdirs clean distclean dist install uninstall help
|
||||
|
157
README.md
157
README.md
|
@ -1,158 +1,7 @@
|
|||
# Problem
|
||||
|
||||
End-user applications are huge, with tons of libraries used and are a pain in the ass to maintain.
|
||||
Libraries are huge, with a lot of things happening, with changes that break everything on a regular basis, with almost each time very few people working on it.
|
||||
Libraries are written for every project, most of the code can be re-used because it is not fundamentally bounded to a single project.
|
||||
# libipc
|
||||
|
||||
Start a new project is not an easy task neither.
|
||||
libipc - Simple, easy-to-use IPC library
|
||||
|
||||
- What language to use?
|
||||
- I am doing something already coded somewhere?
|
||||
- Is this library working on every platform?
|
||||
- Are the libraries I need (and the good version) available for my platform, do I need to install SomeBullshitOS or ProtoContenerizator3000 to code?
|
||||
See the introductory [man page](man/libipc.7.md).
|
||||
|
||||
# How to change that?
|
||||
|
||||
**Network protocols**
|
||||
|
||||
Network protocols are awesome: very few changes, well documented, programming language agnostics.
|
||||
|
||||
Don't (just) write libraries, write applications !
|
||||
|
||||
Your need a functionality in your application, why do you have to code it ?
|
||||
Just ask a service !
|
||||
|
||||
**Example**
|
||||
|
||||
You want to download a file, you will always have the same input: a string corresponding to the file to get, such as _ftp://example.com/file.txt_.
|
||||
You don't have to worry about the protocol to use in your own application, the burden is on the dedicated *downloading* service.
|
||||
|
||||
# Benefits
|
||||
|
||||
**Awesome abstractions**.
|
||||
|
||||
You will be able to do things without any code.
|
||||
|
||||
* applications don't have to know if the services they use is on the network or on your own computer
|
||||
* applications don't need to change anything to handle new protocols, no recompilation
|
||||
* applications can be statically compiled, the memory footprint should be extremely low (yes, even for a browser)
|
||||
|
||||
Let's write *abstractions* together, and less application-specific code !
|
||||
|
||||
**Simple applications**.
|
||||
|
||||
You only need to code the specific parts of your own application.
|
||||
The only thing your application should have to take care is its functionality, and to communicate to services providing abstractions.
|
||||
|
||||
**Consistency**.
|
||||
|
||||
Everything will be developed in the same repository: same [coding standards][codingstyle], changes will be tested on every provided applications…
|
||||
|
||||
**Code review**.
|
||||
|
||||
We should always try to provide new abstractions, reducing the code needed in both services and end-user applications.
|
||||
To that end, code review is a must.
|
||||
|
||||
**No need to rewrite everything**.
|
||||
|
||||
You have great libraries?
|
||||
Don't redevelop them!
|
||||
We can use already existing libraries to provide new functionalities to our programs: we just have to write a service and to define new messages to request it, period.
|
||||
|
||||
**Language independent**.
|
||||
|
||||
You have an awesome library to do X, but it's written in an obscure language.
|
||||
Who cares?
|
||||
Write a simple service that can be requested following our protocol, everybody will be able to use your library without painful-to-maintain bindings!
|
||||
We may even assist you doing that by providing templates for your language, or check the other services!
|
||||
|
||||
**The end of "oh, I would like to dev something but this requires too much painful-to-install dependencies"**.
|
||||
|
||||
You only need the communication library and the service running (not even on your own computer) without any other dependencies.
|
||||
That's it, you're good to go!
|
||||
|
||||
# Not adapted to everything
|
||||
|
||||
If you need incredible performances for your application, maybe this won't fit.
|
||||
There is no silver bullet or one-fit-all solution.
|
||||
Still, we think performances won't be much of a problem for most of the everyday life applications and if there are performances hits we still have plenty of room for optimisations!
|
||||
|
||||
# Application and services
|
||||
|
||||
- Services: daemons providing a feature (windowing, audio, network, input, pubsub, …)
|
||||
- Applications: end-user applications (browser, mail user agent, instant messaging app, …)
|
||||
|
||||
#### Examples
|
||||
|
||||
A browser that can download everything, via every existing protocol.
|
||||
No any specific code in the browser itself and no configuration.
|
||||
|
||||
You want to play a game on your raspberry pi, but it is not powerful enough, run your application on your laptop but take the inputs from the rpi (or anywhere on the network) !
|
||||
No specific code needed.
|
||||
|
||||
# TODO
|
||||
|
||||
Figures, a lot of them, to explain everything.
|
||||
|
||||
# Connection init (draft)
|
||||
|
||||
## How things happen
|
||||
|
||||
1. Service creates a unix socket /tmp/service-index-version.sock
|
||||
1. Application connects to /tmp/service-index-version.sock
|
||||
|
||||
__legend__:
|
||||
- service: service name
|
||||
- index: process index (to launch a service several times)
|
||||
- version: service version
|
||||
|
||||
# Networking point of view (what should go in the sockets)
|
||||
|
||||
#### Connection
|
||||
1. Application connects to /tmp/service-index-version.sock
|
||||
1. Service acknowledges (empty message)
|
||||
|
||||
#### Disconnection
|
||||
1. Application sends a message "CLOSE" to the server
|
||||
|
||||
#### Data
|
||||
1. Application or server sends a message "DATA", no acknowledgement
|
||||
|
||||
# Message formats
|
||||
|
||||
In order to communicate between the application and the service, we use the Type-Length-Value format.
|
||||
This will be used with some conventions.
|
||||
|
||||
The type will be a simple byte :
|
||||
|
||||
* <0 - 15> : control, meta data
|
||||
* <16 - 127> : later use
|
||||
* <128 - 255> : application specific (windowing system, audio system, …)
|
||||
|
||||
index | abbreviation | semantic
|
||||
0 | close | to close the communication between the application and the service
|
||||
1 | connection | to connect to the service
|
||||
2 | error | to send an error message
|
||||
3 | ack | to send an acknowledgment
|
||||
4 | message | to send data
|
||||
|
||||
# Service Status
|
||||
|
||||
Go to the relevant directory for details.
|
||||
|
||||
- pongd: stable
|
||||
- tcpd: experimental
|
||||
- pubsub: experimental
|
||||
|
||||
# Inspiration
|
||||
|
||||
This project is inspired by a number of great projects:
|
||||
|
||||
- [OpenBSD][openbsd] and UNIX in general for most of the concepts
|
||||
- Plan9 for the great abstractions and simplicity
|
||||
- [suckless][suckless] for the [coding style][codingstyle] and [cat-v][catv] for the philosophy
|
||||
|
||||
[codingstyle]: http://suckless.org/coding_style
|
||||
[suckless]: http://suckless.org
|
||||
[catv]: http://cat-v.org
|
||||
[openbsd]: https://openbsd.org
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../lib/*.c ../../core/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
|
@ -1,34 +0,0 @@
|
|||
#include "../../core/client.h"
|
||||
#include <string.h> /* memset */
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret;
|
||||
struct ipc_clients clients;
|
||||
memset(&clients, 0, sizeof(struct ipc_clients));
|
||||
|
||||
struct ipc_client client_tab[5];
|
||||
memset(&client_tab, 0, sizeof(struct ipc_client) * 5);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
client_tab[i].proc_fd = i;
|
||||
ret = ipc_client_add(&clients, &client_tab[i]);
|
||||
if (ret == -1) {
|
||||
printf("erreur realloc\n");
|
||||
}
|
||||
}
|
||||
|
||||
ipc_clients_print(&clients);
|
||||
|
||||
ret = ipc_client_del(&clients, &client_tab[2]);
|
||||
if(ret < 0) {
|
||||
printf("erreur %d\n", ret );
|
||||
}
|
||||
ipc_clients_print(&clients);
|
||||
|
||||
ipc_clients_free (&clients);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "../../core/usocket.h"
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
fprintf (stderr, "%s: file %s line %d %s\n", fun, __FILE__, __LINE__, msg);
|
||||
|
||||
#define UPATH "/tmp/ipc/usock-path.sock"
|
||||
#define MSG "coucou"
|
||||
|
||||
int main (int argc, char * argv[])
|
||||
{
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
int fd = 0;
|
||||
size_t msize = BUFSIZ;
|
||||
char *buf = NULL;
|
||||
|
||||
struct timeval t1;
|
||||
struct timeval t2;
|
||||
|
||||
if ( (buf = malloc (BUFSIZ)) == NULL) {
|
||||
handle_err ("main", "malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
if (usock_connect (&fd, UPATH) < 0) {
|
||||
handle_err("main", "usock_listen < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
gettimeofday (&t1, NULL);
|
||||
if (usock_send (fd, MSG, strlen(MSG)) < 0) {
|
||||
handle_err("main", "usock_send < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_recv (fd, &buf, &msize) < 0) {
|
||||
handle_err("main", "usock_recv < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
gettimeofday (&t2, NULL);
|
||||
|
||||
printf ("it took %ld µs to send then recv a message\n"
|
||||
, t2.tv_usec - t1.tv_usec);
|
||||
|
||||
if (usock_close (fd) < 0) {
|
||||
handle_err("main", "usock_close < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (buf != NULL)
|
||||
free (buf);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../core/usocket.h"
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
fprintf (stderr, "%s: file %s line %d %s\n", fun, __FILE__, __LINE__, msg);
|
||||
|
||||
#define UPATH "/tmp/ipc/usock-path.sock"
|
||||
|
||||
int main (int argc, char * argv[])
|
||||
{
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
int fd = 0;
|
||||
int pfd = 0;
|
||||
size_t msize = BUFSIZ;
|
||||
char *buf = NULL;
|
||||
|
||||
if ( (buf = malloc (BUFSIZ)) == NULL) {
|
||||
handle_err ("main", "malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
// socket + bind + listen
|
||||
if (usock_init (&fd, UPATH) < 0) {
|
||||
handle_err("main", "usock_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_accept (fd, &pfd) < 0) {
|
||||
handle_err("main", "usock_accept < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_recv (pfd, &buf, &msize) < 0) {
|
||||
handle_err("main", "usock_recv < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_send (pfd, buf, msize) < 0) {
|
||||
handle_err("main", "usock_send < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_close (fd) < 0) {
|
||||
handle_err("main", "usock_close fd < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_close (pfd) < 0) {
|
||||
handle_err("main", "usock_close pfd < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_remove (UPATH) < 0) {
|
||||
handle_err("main", "usock_remove < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (buf != NULL)
|
||||
free (buf);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../core/message.h"
|
||||
#include "../../core/error.h"
|
||||
#include "../../core/communication.h"
|
||||
|
||||
#define MSG "coucou"
|
||||
#define SERVICE_NAME "test"
|
||||
|
||||
int main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (application_connection (argc, argv, env, &srv, SERVICE_NAME, NULL, 0) < 0) {
|
||||
handle_err("main", "server_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("msg to send: %s\n", MSG);
|
||||
ipc_message_format_data (&m, MSG, strlen(MSG) +1);
|
||||
printf ("msg to send in the client: ");
|
||||
print_msg (&m);
|
||||
if (application_write (&srv, &m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ipc_message_free (&m);
|
||||
|
||||
if (application_read (&srv, &m) < 0) {
|
||||
handle_err("main", "application_read < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("msg recv: %s\n", m.payload);
|
||||
ipc_message_free (&m);
|
||||
|
||||
if (application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../core/error.h"
|
||||
#include "../../core/communication.h"
|
||||
|
||||
#define MSG "coucou"
|
||||
#define SERVICE_NAME "test"
|
||||
|
||||
int main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset(&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
struct ipc_client p;
|
||||
memset (&p, 0, sizeof (struct ipc_client));
|
||||
|
||||
// init service
|
||||
if (server_init (argc, argv, env, &srv, SERVICE_NAME) < 0) {
|
||||
handle_err("main", "server_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (server_accept (&srv, &p) < 0) {
|
||||
handle_err("main", "server_accept < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (server_read (&p, &m) < 0) {
|
||||
handle_err("main", "server_read < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("msg recv: %s\n", m.payload);
|
||||
|
||||
if (server_write (&p, &m) < 0) {
|
||||
handle_err("main", "server_write < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ipc_message_free (&m);
|
||||
|
||||
// client quits
|
||||
if (server_read (&p, &m) < 0) {
|
||||
handle_err("main", "server_read < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (m.type == MSG_TYPE_CLOSE) {
|
||||
printf ("the client quits\n");
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "err: should have received the client dis msg\n");
|
||||
}
|
||||
ipc_message_free (&m);
|
||||
|
||||
if (server_close_client (&p) < 0) {
|
||||
handle_err("main", "server_close_client < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (server_close (&srv) < 0) {
|
||||
handle_err("main", "server_close < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../core/usocket.h"
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
fprintf (stderr, "%s: file %s line %d %s\n", fun, __FILE__, __LINE__, msg);
|
||||
|
||||
#define UPATH "/tmp/ipc/usock-path.sock"
|
||||
#define MSG "coucou"
|
||||
|
||||
int main (int argc, char * argv[])
|
||||
{
|
||||
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
int fd = 0;
|
||||
size_t msize = BUFSIZ;
|
||||
char *buf = NULL;
|
||||
|
||||
if ( (buf = malloc (BUFSIZ)) == NULL) {
|
||||
handle_err ("main", "malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
if (usock_connect (&fd, UPATH) < 0) {
|
||||
handle_err("main", "usock_listen < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_send (fd, MSG, strlen(MSG)) < 0) {
|
||||
handle_err("main", "usock_send < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_recv (fd, &buf, &msize) < 0) {
|
||||
handle_err("main", "usock_recv < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("msg recv: %s\n", buf);
|
||||
|
||||
if (usock_close (fd) < 0) {
|
||||
handle_err("main", "usock_close < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (buf != NULL)
|
||||
free (buf);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../core/usocket.h"
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
fprintf (stderr, "%s: file %s line %d %s\n", fun, __FILE__, __LINE__, msg);
|
||||
|
||||
#define UPATH "/tmp/ipc/usock-path.sock"
|
||||
|
||||
int main (int argc, char * argv[])
|
||||
{
|
||||
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
int fd = 0;
|
||||
int pfd = 0;
|
||||
size_t msize = BUFSIZ;
|
||||
char *buf = NULL;
|
||||
|
||||
if ( (buf = malloc (BUFSIZ)) == NULL) {
|
||||
handle_err ("main", "malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
// socket + bind + listen
|
||||
if (usock_init (&fd, UPATH) < 0) {
|
||||
handle_err("main", "usock_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_accept (fd, &pfd) < 0) {
|
||||
handle_err("main", "usock_accept < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("new connection\n");
|
||||
|
||||
if (usock_recv (pfd, &buf, &msize) < 0) {
|
||||
handle_err("main", "usock_recv < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("msg recv: %s\n", buf);
|
||||
|
||||
if (usock_send (pfd, buf, msize) < 0) {
|
||||
handle_err("main", "usock_send < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_close (fd) < 0) {
|
||||
handle_err("main", "usock_close fd < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (usock_close (pfd) < 0) {
|
||||
handle_err("main", "usock_close pfd < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (usock_remove (UPATH) < 0) {
|
||||
handle_err("main", "usock_remove < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (buf != NULL)
|
||||
free (buf);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
.TH "COMMUNICATION-CLIENT" "1" "19/12/2016" "\ \&" "\ \&"
|
||||
.nh
|
||||
.ad l
|
||||
.SH "NAME"
|
||||
communication-client \- communication lib test (communication.c)
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
\fBcommunication-client\fR
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
\fBcommunication-client\fR is about regression tests of the communication library.
|
||||
It acts as a simple client connecting to a "\fBtest\fR" service, it sends a message and wait for a response then quits.
|
||||
.sp
|
||||
This program has currently no options.
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBcommunication-server\fR(1)
|
||||
.SH "BUGS"
|
||||
.sp
|
||||
Thanks to report bugs to karchnu+bugs@karchnu.fr
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
Philippe PITTOLI
|
||||
.SH "WWW"
|
||||
.sp
|
||||
\fBhttps://git.karchnu.fr/Karchnu/perfectos-junk
|
|
@ -1,26 +0,0 @@
|
|||
.TH "COMMUNICATION-SERVER" "1" "19/12/2016" "\ \&" "\ \&"
|
||||
.nh
|
||||
.ad l
|
||||
.SH "NAME"
|
||||
communication-server \- communication lib test (communication.c)
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
\fBcommunication-server\fR
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
\fBcommunication-server\fR is about regression tests of the communication library.
|
||||
It acts as a simple server for the "\fBtest\fR" service, it waits for a client, then waits for a message and sends it back before quitting.
|
||||
.sp
|
||||
This program has currently no options.
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBcommunication-client\fR(1)
|
||||
.SH "BUGS"
|
||||
.sp
|
||||
Thanks to report bugs to karchnu+bugs@karchnu.fr
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
Philippe PITTOLI
|
||||
.SH "WWW"
|
||||
.sp
|
||||
\fBhttps://git.karchnu.fr/Karchnu/perfectos-junk
|
|
@ -1,26 +0,0 @@
|
|||
.TH "USOCK-CLIENT" "1" "19/12/2016" "\ \&" "\ \&"
|
||||
.nh
|
||||
.ad l
|
||||
.SH "NAME"
|
||||
usock-client \- communication lib test (usock.c)
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
\fBusock-client\fR
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
\fBusock-client\fR is about regression tests of the communication library.
|
||||
It acts as a simple client connecting to a unix socket, it sends a message and wait for a response then quits.
|
||||
.sp
|
||||
This program has currently no options.
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBusock-server\fR(1)
|
||||
.SH "BUGS"
|
||||
.sp
|
||||
Thanks to report bugs to karchnu+bugs@karchnu.fr
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
Philippe PITTOLI
|
||||
.SH "WWW"
|
||||
.sp
|
||||
\fBhttps://git.karchnu.fr/Karchnu/perfectos-junk
|
|
@ -1,26 +0,0 @@
|
|||
.TH "USOCK-SERVER" "1" "19/12/2016" "\ \&" "\ \&"
|
||||
.nh
|
||||
.ad l
|
||||
.SH "NAME"
|
||||
usock-server \- communication lib test (usock.c)
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
\fBusock-server\fR
|
||||
.SH "DESCRIPTION"
|
||||
.sp
|
||||
\fBusock-server\fR is about regression tests of the communication library.
|
||||
It acts as a simple unix socket server waiting a connection from a client, it then waits for a message and sends it back before quitting.
|
||||
.sp
|
||||
This program has currently no options.
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBusock-client\fR(1)
|
||||
.SH "BUGS"
|
||||
.sp
|
||||
Thanks to report bugs to karchnu+bugs@karchnu.fr
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
Philippe PITTOLI
|
||||
.SH "WWW"
|
||||
.sp
|
||||
\fBhttps://git.karchnu.fr/Karchnu/perfectos-junk
|
291
core/Makefile
291
core/Makefile
|
@ -1,291 +0,0 @@
|
|||
PACKAGE = 'ipc'
|
||||
VERSION = '0.0.1'
|
||||
|
||||
PREFIX := /usr/local
|
||||
BINDIR := $(PREFIX)/bin
|
||||
LIBDIR := $(PREFIX)/lib
|
||||
SHAREDIR := $(PREFIX)/share
|
||||
INCLUDEDIR := $(PREFIX)/include
|
||||
MANDIR := $(SHAREDIR)/man
|
||||
|
||||
CC := cc
|
||||
AR := ar
|
||||
RANLIB := ranlib
|
||||
CFLAGS :=
|
||||
LDFLAGS :=
|
||||
|
||||
Q := @
|
||||
|
||||
all: libipc
|
||||
@:
|
||||
|
||||
libipc: libipc.so libipc.a
|
||||
@:
|
||||
libipc.install: libipc.so.install libipc.a.install
|
||||
|
||||
libipc.clean: libipc.so.clean libipc.a.clean
|
||||
|
||||
libipc.uninstall: libipc.so.uninstall libipc.a.uninstall
|
||||
|
||||
libipc.so: client.o communication.o logger.o message.o usocket.o utils.o
|
||||
@echo '[01;32m LD > [01;37mlibipc.so[00m'
|
||||
$(Q)$(CC) -o libipc.so -shared $(LDFLAGS) client.o communication.o logger.o message.o usocket.o utils.o
|
||||
|
||||
libipc.so.install: libipc.so
|
||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.so.0.0.1[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
|
||||
$(Q)install -m0755 libipc.so $(DESTDIR)$(LIBDIR)/libipc.so.0.0.1
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so.0.0[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.0.1' '$(DESTDIR)/$(LIBDIR)/libipc.so.0.0'
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so.0[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.0.1' '$(DESTDIR)/$(LIBDIR)/libipc.so.0'
|
||||
@echo '[01;33m LN > [01;37m$(LIBDIR)/libipc.so[00m'
|
||||
$(Q)ln -sf '$(LIBDIR)/libipc.so.0.0.1' '$(DESTDIR)/$(LIBDIR)/libipc.so'
|
||||
|
||||
libipc.so.clean:
|
||||
@echo '[01;37m RM > [01;37mlibipc.so[00m'
|
||||
$(Q)rm -f libipc.so
|
||||
|
||||
libipc.so.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0.0.1[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0.0.1'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0.0[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0.0'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so.0[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so.0'
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so'
|
||||
|
||||
libipc.a: client.o communication.o logger.o message.o usocket.o utils.o
|
||||
@echo '[01;32m LD > [01;37mlibipc.a[00m'
|
||||
$(Q)$(AR) rc 'libipc.a' client.o communication.o logger.o message.o usocket.o utils.o
|
||||
|
||||
libipc.a.install: libipc.a
|
||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.a[00m'
|
||||
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
|
||||
$(Q)install -m0755 libipc.a $(DESTDIR)$(LIBDIR)/libipc.a
|
||||
|
||||
libipc.a.clean:
|
||||
@echo '[01;37m RM > [01;37mlibipc.a[00m'
|
||||
$(Q)rm -f libipc.a
|
||||
|
||||
libipc.a.uninstall:
|
||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.a[00m'
|
||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.a'
|
||||
|
||||
client.o: client.c ./client.h
|
||||
@echo '[01;34m CC > [01;37mclient.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c client.c -fPIC -o client.o
|
||||
|
||||
client.o.install:
|
||||
|
||||
client.o.clean:
|
||||
@echo '[01;37m RM > [01;37mclient.o[00m'
|
||||
$(Q)rm -f client.o
|
||||
|
||||
client.o.uninstall:
|
||||
|
||||
communication.o: communication.c ./communication.h ./utils.h ./error.h ./event.h
|
||||
@echo '[01;34m CC > [01;37mcommunication.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c communication.c -fPIC -o communication.o
|
||||
|
||||
communication.o.install:
|
||||
|
||||
communication.o.clean:
|
||||
@echo '[01;37m RM > [01;37mcommunication.o[00m'
|
||||
$(Q)rm -f communication.o
|
||||
|
||||
communication.o.uninstall:
|
||||
|
||||
logger.o: logger.c ./logger.h
|
||||
@echo '[01;34m CC > [01;37mlogger.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c logger.c -fPIC -o logger.o
|
||||
|
||||
logger.o.install:
|
||||
|
||||
logger.o.clean:
|
||||
@echo '[01;37m RM > [01;37mlogger.o[00m'
|
||||
$(Q)rm -f logger.o
|
||||
|
||||
logger.o.uninstall:
|
||||
|
||||
message.o: message.c ./message.h ./error.h ./usocket.h
|
||||
@echo '[01;34m CC > [01;37mmessage.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c message.c -fPIC -o message.o
|
||||
|
||||
message.o.install:
|
||||
|
||||
message.o.clean:
|
||||
@echo '[01;37m RM > [01;37mmessage.o[00m'
|
||||
$(Q)rm -f message.o
|
||||
|
||||
message.o.uninstall:
|
||||
|
||||
usocket.o: usocket.c ./usocket.h ./utils.h ./error.h
|
||||
@echo '[01;34m CC > [01;37musocket.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c usocket.c -fPIC -o usocket.o
|
||||
|
||||
usocket.o.install:
|
||||
|
||||
usocket.o.clean:
|
||||
@echo '[01;37m RM > [01;37musocket.o[00m'
|
||||
$(Q)rm -f usocket.o
|
||||
|
||||
usocket.o.uninstall:
|
||||
|
||||
utils.o: utils.c ./utils.h
|
||||
@echo '[01;34m CC > [01;37mutils.o[00m'
|
||||
$(Q)$(CC) $(CFLAGS) -fPIC -c utils.c -fPIC -o utils.o
|
||||
|
||||
utils.o.install:
|
||||
|
||||
utils.o.clean:
|
||||
@echo '[01;37m RM > [01;37mutils.o[00m'
|
||||
$(Q)rm -f utils.o
|
||||
|
||||
utils.o.uninstall:
|
||||
|
||||
$(DESTDIR)$(PREFIX):
|
||||
@echo '[01;35m DIR > [01;37m$(PREFIX)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(PREFIX)
|
||||
$(DESTDIR)$(BINDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(BINDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(BINDIR)
|
||||
$(DESTDIR)$(LIBDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(LIBDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(LIBDIR)
|
||||
$(DESTDIR)$(SHAREDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(SHAREDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(SHAREDIR)
|
||||
$(DESTDIR)$(INCLUDEDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(INCLUDEDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(INCLUDEDIR)
|
||||
$(DESTDIR)$(MANDIR):
|
||||
@echo '[01;35m DIR > [01;37m$(MANDIR)[00m'
|
||||
$(Q)mkdir -p $(DESTDIR)$(MANDIR)
|
||||
install: subdirs.install libipc.install libipc.so.install libipc.a.install client.o.install communication.o.install logger.o.install message.o.install usocket.o.install utils.o.install client.o.install communication.o.install logger.o.install message.o.install usocket.o.install utils.o.install
|
||||
@:
|
||||
|
||||
subdirs.install:
|
||||
|
||||
uninstall: subdirs.uninstall libipc.uninstall libipc.so.uninstall libipc.a.uninstall client.o.uninstall communication.o.uninstall logger.o.uninstall message.o.uninstall usocket.o.uninstall utils.o.uninstall client.o.uninstall communication.o.uninstall logger.o.uninstall message.o.uninstall usocket.o.uninstall utils.o.uninstall
|
||||
@:
|
||||
|
||||
subdirs.uninstall:
|
||||
|
||||
test: all subdirs subdirs.test
|
||||
@:
|
||||
|
||||
subdirs.test:
|
||||
|
||||
clean: libipc.clean libipc.so.clean libipc.a.clean client.o.clean communication.o.clean logger.o.clean message.o.clean usocket.o.clean utils.o.clean client.o.clean communication.o.clean logger.o.clean message.o.clean usocket.o.clean utils.o.clean
|
||||
|
||||
distclean: clean
|
||||
|
||||
dist: dist-gz dist-xz dist-bz2
|
||||
$(Q)rm -- $(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir:
|
||||
$(Q)rm -rf -- $(PACKAGE)-$(VERSION)
|
||||
$(Q)ln -s -- . $(PACKAGE)-$(VERSION)
|
||||
|
||||
dist-gz: $(PACKAGE)-$(VERSION).tar.gz
|
||||
$(PACKAGE)-$(VERSION).tar.gz: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.gz[00m'
|
||||
$(Q)tar czf $(PACKAGE)-$(VERSION).tar.gz \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/error.h \
|
||||
$(PACKAGE)-$(VERSION)/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/event.h \
|
||||
$(PACKAGE)-$(VERSION)/client.c \
|
||||
$(PACKAGE)-$(VERSION)/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/message.c \
|
||||
$(PACKAGE)-$(VERSION)/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/client.h \
|
||||
$(PACKAGE)-$(VERSION)/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/message.h \
|
||||
$(PACKAGE)-$(VERSION)/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/utils.h
|
||||
|
||||
dist-xz: $(PACKAGE)-$(VERSION).tar.xz
|
||||
$(PACKAGE)-$(VERSION).tar.xz: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.xz[00m'
|
||||
$(Q)tar cJf $(PACKAGE)-$(VERSION).tar.xz \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/error.h \
|
||||
$(PACKAGE)-$(VERSION)/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/event.h \
|
||||
$(PACKAGE)-$(VERSION)/client.c \
|
||||
$(PACKAGE)-$(VERSION)/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/message.c \
|
||||
$(PACKAGE)-$(VERSION)/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/client.h \
|
||||
$(PACKAGE)-$(VERSION)/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/message.h \
|
||||
$(PACKAGE)-$(VERSION)/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/utils.h
|
||||
|
||||
dist-bz2: $(PACKAGE)-$(VERSION).tar.bz2
|
||||
$(PACKAGE)-$(VERSION).tar.bz2: distdir
|
||||
@echo '[01;33m TAR > [01;37m$(PACKAGE)-$(VERSION).tar.bz2[00m'
|
||||
$(Q)tar cjf $(PACKAGE)-$(VERSION).tar.bz2 \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||
$(PACKAGE)-$(VERSION)/error.h \
|
||||
$(PACKAGE)-$(VERSION)/ipc.h \
|
||||
$(PACKAGE)-$(VERSION)/event.h \
|
||||
$(PACKAGE)-$(VERSION)/client.c \
|
||||
$(PACKAGE)-$(VERSION)/communication.c \
|
||||
$(PACKAGE)-$(VERSION)/logger.c \
|
||||
$(PACKAGE)-$(VERSION)/message.c \
|
||||
$(PACKAGE)-$(VERSION)/usocket.c \
|
||||
$(PACKAGE)-$(VERSION)/utils.c \
|
||||
$(PACKAGE)-$(VERSION)/client.h \
|
||||
$(PACKAGE)-$(VERSION)/communication.h \
|
||||
$(PACKAGE)-$(VERSION)/logger.h \
|
||||
$(PACKAGE)-$(VERSION)/message.h \
|
||||
$(PACKAGE)-$(VERSION)/usocket.h \
|
||||
$(PACKAGE)-$(VERSION)/utils.h
|
||||
|
||||
help:
|
||||
@echo '[01;37m :: ipc-0.0.1[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mGeneric targets:[00m'
|
||||
@echo '[00m - [01;32mhelp [37m Prints this help message.[00m'
|
||||
@echo '[00m - [01;32mall [37m Builds all targets.[00m'
|
||||
@echo '[00m - [01;32mdist [37m Creates tarballs of the files of the project.[00m'
|
||||
@echo '[00m - [01;32minstall [37m Installs the project.[00m'
|
||||
@echo '[00m - [01;32mclean [37m Removes compiled files.[00m'
|
||||
@echo '[00m - [01;32muninstall [37m Deinstalls the project.[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mCLI-modifiable variables:[00m'
|
||||
@echo ' - [01;34mCC [37m ${CC}[00m'
|
||||
@echo ' - [01;34mCFLAGS [37m ${CFLAGS}[00m'
|
||||
@echo ' - [01;34mLDFLAGS [37m ${LDFLAGS}[00m'
|
||||
@echo ' - [01;34mDESTDIR [37m ${DESTDIR}[00m'
|
||||
@echo ' - [01;34mPREFIX [37m ${PREFIX}[00m'
|
||||
@echo ' - [01;34mBINDIR [37m ${BINDIR}[00m'
|
||||
@echo ' - [01;34mLIBDIR [37m ${LIBDIR}[00m'
|
||||
@echo ' - [01;34mSHAREDIR [37m ${SHAREDIR}[00m'
|
||||
@echo ' - [01;34mINCLUDEDIR [37m ${INCLUDEDIR}[00m'
|
||||
@echo ' - [01;34mMANDIR [37m ${MANDIR}[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mProject targets: [00m'
|
||||
@echo ' - [01;33mlibipc [37m library[00m'
|
||||
@echo ''
|
||||
@echo '[01;37mMakefile options:[00m'
|
||||
@echo ' - gnu: false'
|
||||
@echo ' - colors: true'
|
||||
@echo ''
|
||||
@echo '[01;37mRebuild the Makefile with:[00m'
|
||||
@echo ' zsh ./build.zsh -c'
|
||||
.PHONY: all subdirs clean distclean dist install uninstall help
|
||||
|
249
core/ipc.cr
249
core/ipc.cr
|
@ -1,249 +0,0 @@
|
|||
|
||||
@[Link("ipc")]
|
||||
lib LibIPC
|
||||
struct Service
|
||||
version : LibC::UInt
|
||||
index : LibC::UInt
|
||||
spath : LibC::Char[4096] # [PATH_MAX]
|
||||
fd : LibC::Int
|
||||
end
|
||||
|
||||
struct Client
|
||||
version : LibC::UInt
|
||||
index : LibC::UInt
|
||||
fd : LibC::Int
|
||||
end
|
||||
|
||||
enum MessageType
|
||||
ServerClose
|
||||
Error
|
||||
Data
|
||||
end
|
||||
|
||||
struct Message
|
||||
type : UInt8
|
||||
length : LibC::UInt
|
||||
payload : LibC::Char*
|
||||
end
|
||||
|
||||
struct Clients
|
||||
clients : Client**
|
||||
size : LibC::Int
|
||||
end
|
||||
|
||||
enum EventType
|
||||
NotSet
|
||||
Error
|
||||
Stdin
|
||||
Connection
|
||||
Disconnection
|
||||
Message
|
||||
end
|
||||
|
||||
struct Event
|
||||
type : EventType
|
||||
origin : Client*
|
||||
m : Message*
|
||||
end
|
||||
|
||||
# FIXME: IPC.initialize:
|
||||
# - throw exceptions on error.
|
||||
# - Make most arguments optional.
|
||||
fun ipc_server_init(env : LibC::Char**, service : Service*, sname : LibC::Char*) : LibC::Int
|
||||
# FIXME: IPC.(destroy?)
|
||||
fun ipc_server_close(Service*) : LibC::Int
|
||||
fun ipc_server_close_client(Client*) : LibC::Int
|
||||
|
||||
fun ipc_server_accept(Service*, Client*) : LibC::Int
|
||||
fun ipc_server_read(Client*, Message*) : LibC::Int
|
||||
fun ipc_server_write(Client*, Message*) : LibC::Int
|
||||
|
||||
fun ipc_server_select(Clients*, Service*, Clients*, LibC::Int*) : LibC::Int
|
||||
|
||||
fun ipc_service_poll_event(Clients*, Service*, Event*) : LibC::Int
|
||||
|
||||
fun ipc_application_connection(LibC::Char**, Service*, LibC::Char*) : LibC::Int
|
||||
fun ipc_application_close(Service*) : LibC::Int
|
||||
fun ipc_application_read(Service*, Message*) : LibC::Int
|
||||
fun ipc_application_write(Service*, Message*) : LibC::Int
|
||||
|
||||
fun ipc_client_add(Clients*, Client*) : LibC::Int
|
||||
fun ipc_client_del(Clients*, Client*) : LibC::Int
|
||||
|
||||
fun ipc_server_client_copy(Client*) : Client*
|
||||
fun ipc_server_client_eq(Client*, Client*) : LibC::Int
|
||||
|
||||
fun ipc_server_client_gen(Client*, LibC::UInt, LibC::UInt)
|
||||
|
||||
fun ipc_clients_free(Clients*)
|
||||
end
|
||||
|
||||
class IPC::Exception < ::Exception
|
||||
|
||||
end
|
||||
|
||||
class IPC::Service
|
||||
@closed = false
|
||||
@clients = LibIPC::Clients.new
|
||||
# FIXME: getter only as long as proper bindings are unfinished
|
||||
getter service = LibIPC::Service.new
|
||||
|
||||
def initialize(name : String)
|
||||
if LibIPC.ipc_server_init(LibC.environ, pointerof(@service), name) < 0
|
||||
raise Exception.new "ipc_server_init < 0" # FIXME: Add proper descriptions here.
|
||||
end
|
||||
|
||||
# Very important as there are filesystem side-effects.
|
||||
at_exit { close }
|
||||
end
|
||||
|
||||
def initialize(name : String, &block : Proc(IPC::Event::Connection | IPC::Event::Disconnection | IPC::Event::Message, Nil))
|
||||
initialize name
|
||||
loop &block
|
||||
close
|
||||
end
|
||||
|
||||
def close
|
||||
return if @closed
|
||||
|
||||
# FIXME: Probably check it’s not been closed already.
|
||||
if LibIPC.ipc_server_close(pointerof(@service)) < 0
|
||||
raise Exception.new "ipc_server_close < 0"
|
||||
end
|
||||
|
||||
@closed = true
|
||||
end
|
||||
def finalize
|
||||
close
|
||||
end
|
||||
|
||||
def accept
|
||||
::IPC::Server::Client.new pointerof(@service)
|
||||
end
|
||||
|
||||
def loop(&block)
|
||||
::loop do
|
||||
event = LibIPC::Event.new
|
||||
|
||||
r = LibIPC.ipc_service_poll_event pointerof(@clients), pointerof(@service), pointerof(event)
|
||||
|
||||
if r < 0
|
||||
raise Exception.new "ipc_service_poll_event < 0"
|
||||
end
|
||||
|
||||
client = IPC::RemoteClient.new event.origin.unsafe_as(Pointer(LibIPC::Client)).value
|
||||
|
||||
pp! event
|
||||
message = event.m.unsafe_as(Pointer(LibIPC::Message))
|
||||
unless message.null?
|
||||
pp! message.value
|
||||
end
|
||||
|
||||
case event.type
|
||||
when LibIPC::EventType::Connection
|
||||
yield IPC::Event::Connection.new client
|
||||
when LibIPC::EventType::Message
|
||||
message = event.m.unsafe_as(Pointer(LibIPC::Message)).value
|
||||
|
||||
yield IPC::Event::Message.new IPC::Message.new(message.type, message.length, message.payload), client
|
||||
when LibIPC::EventType::Disconnection
|
||||
yield IPC::Event::Disconnection.new client
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class IPC::Message
|
||||
enum Type
|
||||
CLOSE
|
||||
CONNECTION
|
||||
SYN
|
||||
ACK
|
||||
DATA
|
||||
end
|
||||
|
||||
getter type : UInt8
|
||||
getter payload : String
|
||||
|
||||
def initialize(type, length, payload)
|
||||
@type = type.to_u8
|
||||
@payload = String.new payload, length
|
||||
end
|
||||
end
|
||||
|
||||
class IPC::RemoteClient
|
||||
getter client : LibIPC::Client
|
||||
|
||||
def initialize(@client)
|
||||
end
|
||||
|
||||
def send(type : UInt8, payload : String)
|
||||
message = LibIPC::Message.new type: type, length: payload.bytesize, payload: payload.to_unsafe
|
||||
|
||||
if LibIPC.ipc_server_write(pointerof(@client), pointerof(message)) < 0
|
||||
raise Exception.new "ipc_server_write < 0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class IPC::Event
|
||||
class Connection
|
||||
getter client : IPC::RemoteClient
|
||||
def initialize(@client)
|
||||
end
|
||||
end
|
||||
|
||||
class Disconnection
|
||||
getter client : IPC::RemoteClient
|
||||
def initialize(@client)
|
||||
end
|
||||
end
|
||||
|
||||
class Message
|
||||
getter message : ::IPC::Message
|
||||
getter client : IPC::RemoteClient
|
||||
def initialize(@message, @client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class IPC::Client
|
||||
@service = LibIPC::Service.new
|
||||
|
||||
def initialize(@service_name : String)
|
||||
if LibIPC.ipc_application_connection(LibC.environ, pointerof(@service), @service_name) < 0
|
||||
raise Exception.new "ipc_application_connection < 0"
|
||||
end
|
||||
end
|
||||
def initialize(name, &block)
|
||||
initialize(name)
|
||||
|
||||
yield self
|
||||
|
||||
close
|
||||
end
|
||||
|
||||
def send(type, payload : String)
|
||||
message = LibIPC::Message.new type: type, length: payload.bytesize, payload: payload.to_unsafe
|
||||
|
||||
if LibIPC.ipc_application_write(pointerof(@service), pointerof(message)) < 0
|
||||
raise Exception.new "ipc_application_write < 0"
|
||||
end
|
||||
end
|
||||
|
||||
def read
|
||||
message = LibIPC::Message.new
|
||||
if LibIPC.ipc_application_read(pointerof(@service), pointerof(message)) < 0
|
||||
raise Exception.new "ipc_application_read < 0"
|
||||
end
|
||||
|
||||
IPC::Message.new message.type, message.length, message.payload
|
||||
end
|
||||
|
||||
def close
|
||||
if LibIPC.ipc_application_close(pointerof(@service)) < 0
|
||||
raise Exception.new "ipc_application_close < 0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
package=ipc
|
||||
version=0.0.1
|
||||
|
||||
targets=(libipc)
|
||||
type[libipc]=library
|
||||
sources[libipc]="$(ls *.c)"
|
||||
|
||||
dist=(Makefile project.zsh error.h ipc.h event.h)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
*.png
|
||||
*.pdf
|
|
@ -1,8 +0,0 @@
|
|||
# writing convention
|
||||
|
||||
Each diagram filename should be formatted as:
|
||||
|
||||
seq-service.diag: message sequence diagram
|
||||
pkt-service-info.pktdiag: message format
|
||||
|
||||
See the currently available files as examples.
|
|
@ -1,46 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ "$FONT" = "" ]
|
||||
then
|
||||
FONT=/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-R.ttf
|
||||
fi
|
||||
|
||||
echo "font : $FONT"
|
||||
|
||||
# $1 = program, $2 = filename extension
|
||||
function graphit()
|
||||
{
|
||||
PROG=$1
|
||||
FNEXT=$2
|
||||
ls *.$FNEXT 2>/dev/null 1>&2
|
||||
if [ $? -eq 0 ]; then
|
||||
for i in *\.$FNEXT
|
||||
do
|
||||
PDF=$(echo ${i} | sed "s/$FNEXT$/pdf/")
|
||||
if [ ! -f ${PDF} ] || [ $(stat -c "%X" ${PDF}) -lt $(stat -c "%X" ${i}) ]
|
||||
then
|
||||
|
||||
PROGOPT="-Tpdf"
|
||||
case $PROG in
|
||||
"seqdiag" | "packetdiag" | "nwdiag")
|
||||
PROGOPT="$PROGOPT -a -f $FONT"
|
||||
echo ${PROG} ${PROGOPT} ${i}
|
||||
${PROG} ${PROGOPT} ${i}
|
||||
;;
|
||||
"dot")
|
||||
echo "${PROG} ${PROGOPT} ${i} > ${PDF}"
|
||||
${PROG} ${PROGOPT} ${i} > ${PDF}
|
||||
;;
|
||||
esac
|
||||
|
||||
echo touch ${PDF}
|
||||
touch ${PDF}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
graphit "seqdiag" "diag"
|
||||
graphit "packetdiag" "pktdiag"
|
||||
graphit "nwdiag" "nwdiag"
|
||||
graphit "dot" "gviz-dot"
|
|
@ -1,13 +0,0 @@
|
|||
packetdiag {
|
||||
colwidth = 64
|
||||
node_height = 60
|
||||
node_width = 15
|
||||
default_fontsize = 16; // default value is 11
|
||||
|
||||
// basic header (type then length)
|
||||
0-7: type\n1 byte [color = "#CCEECC"]
|
||||
8-23: length\n2 bytes [color = "#CCEECC"]
|
||||
|
||||
// payload
|
||||
24-63: END\n3 bytes [color = "#CCCCEE"]
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
packetdiag {
|
||||
colwidth = 64
|
||||
node_height = 60
|
||||
node_width = 15
|
||||
default_fontsize = 16; // default value is 11
|
||||
|
||||
// basic header (type then length)
|
||||
0-7: type\n1 byte [color = "#CCEECC"]
|
||||
8-23: length\n2 bytes [color = "#CCEECC"]
|
||||
|
||||
// payload
|
||||
24-63: service name\nn bytes [color = "#CCCCEE"]
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
packetdiag {
|
||||
colwidth = 64
|
||||
node_height = 60
|
||||
node_width = 15
|
||||
default_fontsize = 16; // default value is 11
|
||||
|
||||
// basic header (type then length)
|
||||
0-7: type\n1 byte [color = "#CCEECC"]
|
||||
8-23: length\n2 bytes [color = "#CCEECC"]
|
||||
|
||||
// payload
|
||||
24-63: environment variable (one per packet)\nex: REMOTED_URI=tcp://user:pass@host.example.com:9000\nn bytes [color = "#CCCCEE"]
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
diagram {
|
||||
edge_length = 300;
|
||||
default_fontsize = 16; // default value is 11
|
||||
span_height = 8; // default value is 40
|
||||
node_height = 60; // default value is 40
|
||||
activation = none;
|
||||
|
||||
// Numbering edges automaticaly
|
||||
autonumber = True;
|
||||
|
||||
// Change note color
|
||||
default_note_color = lightblue;
|
||||
|
||||
|
||||
client [label = "client\nlocal"];
|
||||
remoted [label = "remoted\nlocal"];
|
||||
transportd [label = "transportd\n(ex: tcpd)\nlocal"];
|
||||
transportd2 [label = "transportd\n(ex: tcpd)\nremote"];
|
||||
remoted2 [label = "remoted\nremote"];
|
||||
service [label = "service\nremote"];
|
||||
|
||||
client -> remoted [label = "service-name (ex: pongd)"];
|
||||
client -> remoted [label = "REMOTED_VAR=URI
|
||||
ex: tcp://user:password@example.com:9000", fontsize=13];
|
||||
client -> remoted [label = "END (mark the end of the options)"
|
||||
, rightnote = "Remoted: authenticates, authorizes, determines the right transport daemon and
|
||||
applies forwarding rules", fontsize=13];
|
||||
remoted -> transportd [label = "connect URI + service name"];
|
||||
transportd -> transportd2 [label = "connection init
|
||||
service name + URI"];
|
||||
transportd2 -> remoted2 [label = "connection request
|
||||
service name + URI"];
|
||||
remoted2 -> transportd2 [label = "authorization (yes|no)"];
|
||||
transportd2 -> transportd [label = "connection established"];
|
||||
transportd -> remoted [label = "socket"];
|
||||
remoted -> client [label = "socket"];
|
||||
client -> service [label = "connection"];
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread
|
||||
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 -lcbor -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
rm *.bin
|
13
drop/ainput
13
drop/ainput
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
PARAMS="-ac 2 -ar 44000 -f s16le -acodec pcm_mulaw"
|
||||
|
||||
if [ $# != 1 ]
|
||||
then
|
||||
echo "usage: $0 music-file" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FILE="$1"
|
||||
|
||||
ffmpeg -loglevel 0 -i ${FILE} ${PARAMS} -
|
13
drop/aoutput
13
drop/aoutput
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
PARAMS="-ac 2 -ar 44000 -f s16le -acodec pcm_mulaw"
|
||||
|
||||
if [ $# != 1 ]
|
||||
then
|
||||
echo "usage: $0 music-file" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FILE="$1"
|
||||
|
||||
ffmpeg ${PARAMS} -i - ${FILE}
|
|
@ -1,19 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread -lcbor
|
||||
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 -lcbor -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
mrproper:
|
||||
rm *.bin
|
|
@ -1,36 +0,0 @@
|
|||
#include "cbor.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Reads data from a file. Example usage:
|
||||
* $ ./examples/readfile examples/data/nested_array.cbor
|
||||
*/
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf (stderr, "usage: %s file\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
FILE * f = fopen(argv[1], "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t length = (size_t)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char * buffer = malloc(length);
|
||||
fread(buffer, length, 1, f);
|
||||
|
||||
/* Assuming `buffer` contains `info.st_size` bytes of input data */
|
||||
struct cbor_load_result result;
|
||||
cbor_item_t * item = cbor_load(buffer, length, &result);
|
||||
/* Pretty-print the result */
|
||||
cbor_describe(item, stdout);
|
||||
fflush(stdout);
|
||||
/* Deallocate the result */
|
||||
cbor_decref(&item);
|
||||
|
||||
fclose(f);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#include "cbor.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
/* Preallocate the map structure */
|
||||
cbor_item_t * root = cbor_new_definite_map(2);
|
||||
/* Add the content */
|
||||
cbor_map_add(root, (struct cbor_pair) {
|
||||
.key = cbor_move(cbor_build_string("Is CBOR awesome?")),
|
||||
.value = cbor_move(cbor_build_bool(true))
|
||||
});
|
||||
cbor_map_add(root, (struct cbor_pair) {
|
||||
.key = cbor_move(cbor_build_uint8(42)),
|
||||
.value = cbor_move(cbor_build_string("Is the answer"))
|
||||
});
|
||||
/* Output: `length` bytes of data in the `buffer` */
|
||||
unsigned char * buffer;
|
||||
size_t buffer_size, length = cbor_serialize_alloc(root, &buffer, &buffer_size);
|
||||
|
||||
fwrite(buffer, 1, length, stdout);
|
||||
free(buffer);
|
||||
|
||||
fflush(stdout);
|
||||
cbor_decref(&root);
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#include "cbor.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* * Illustrates how one might skim through a map (which is assumed to have
|
||||
* * string keys and values only), looking for the value of a specific key
|
||||
* *
|
||||
* * Use the examples/data/map.cbor input to test this.
|
||||
* */
|
||||
|
||||
const char * key = "a secret key";
|
||||
bool key_found = false;
|
||||
|
||||
void find_string(void * _ctx, cbor_data buffer, size_t len)
|
||||
{
|
||||
(void) _ctx;
|
||||
if (key_found) {
|
||||
printf("Found the value: %*s\n", (int) len, buffer);
|
||||
key_found = false;
|
||||
} else if (len == strlen(key)) {
|
||||
key_found = (memcmp(key, buffer, len) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
FILE * f = fopen(argv[1], "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t length = (size_t)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char * buffer = malloc(length);
|
||||
fread(buffer, length, 1, f);
|
||||
|
||||
struct cbor_callbacks callbacks = cbor_empty_callbacks;
|
||||
struct cbor_decoder_result decode_result;
|
||||
size_t bytes_read = 0;
|
||||
callbacks.string = find_string;
|
||||
while (bytes_read < length) {
|
||||
decode_result = cbor_stream_decode(buffer + bytes_read,
|
||||
length - bytes_read,
|
||||
&callbacks, NULL);
|
||||
bytes_read += decode_result.read;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#include "../lib/communication.h"
|
||||
|
||||
#define SERVICE "windowing"
|
||||
|
||||
void
|
||||
ohshit(int32_t rvalue, const char* str) {
|
||||
fprintf(stderr, "%s\n", str);
|
||||
exit(rvalue);
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char * argv[], char *env[])
|
||||
{
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
ipc_server_init (argc, argv, env, &srv, SERVICE, NULL);
|
||||
printf ("Listening on %s.\n", srv.spath);
|
||||
|
||||
// creates the service named pipe, that listens to client applications
|
||||
if (server_create (&srv))
|
||||
ohshit(1, "service_create error");
|
||||
|
||||
/*
|
||||
* PROCESS
|
||||
*/
|
||||
|
||||
struct ipc_client p;
|
||||
memset (&p, 0, sizeof (struct ipc_client));
|
||||
|
||||
int32_t index = 0; // first time we communication with the service
|
||||
int32_t version = 1;
|
||||
|
||||
printf ("app creation\n");
|
||||
if (application_create (&p, index, version)) // called by the application
|
||||
ohshit (1, "application_create");
|
||||
|
||||
/*
|
||||
* some exchanges between App and S
|
||||
* specific code, talks between applications
|
||||
* then App wants to end the communication
|
||||
*/
|
||||
|
||||
printf ("destroying app\n");
|
||||
// the application will shut down, and remove the application named pipes
|
||||
if (application_destroy (&p))
|
||||
ohshit (1, "application_destroy");
|
||||
|
||||
/*
|
||||
* /PROCESS
|
||||
*/
|
||||
|
||||
// the application will shut down, and remove the service named pipe
|
||||
if (server_close (&srv))
|
||||
ohshit (1, "server_close error");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
56
drop/list.c
56
drop/list.c
|
@ -1,56 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../lib/queue.h"
|
||||
|
||||
// create the head of the list
|
||||
LIST_HEAD(mlist, node);
|
||||
|
||||
// elements structure of the list
|
||||
struct node {
|
||||
int32_t content;
|
||||
LIST_ENTRY(node) entries;
|
||||
};
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
// the list
|
||||
struct mlist *list;
|
||||
list = malloc (sizeof(struct mlist));
|
||||
LIST_INIT(list);
|
||||
|
||||
// create the elements
|
||||
struct node *n1 = malloc (sizeof(struct node));
|
||||
n1->content = 10;
|
||||
struct node *n2 = malloc (sizeof(struct node));
|
||||
n2->content = 20;
|
||||
|
||||
// insert element into the list
|
||||
LIST_INSERT_HEAD(list, n1, entries);
|
||||
LIST_INSERT_HEAD(list, n2, entries);
|
||||
|
||||
// loop over the list
|
||||
struct node *np = NULL;
|
||||
LIST_FOREACH(np, list, entries) {
|
||||
printf ("elem : %d\n", np->content);
|
||||
}
|
||||
|
||||
// remove elements from the list
|
||||
LIST_REMOVE(n1, entries);
|
||||
LIST_REMOVE(n2, entries);
|
||||
|
||||
// to be sure that nothing still is into the list
|
||||
np = NULL;
|
||||
LIST_FOREACH(np, list, entries) {
|
||||
printf ("\033[31mSHOULD NOT BE PRINTED : %d\033[00m\n", np->content);
|
||||
}
|
||||
|
||||
// free the elements then the list itself
|
||||
free (n1);
|
||||
free (n2);
|
||||
free (list);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
55
drop/msg.c
55
drop/msg.c
|
@ -1,55 +0,0 @@
|
|||
#include "../lib/pubsubd.h"
|
||||
#include <cbor.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PKT_CLOSE 0
|
||||
#define PKT_MSG 1
|
||||
#define PKT_ERROR 2
|
||||
|
||||
void
|
||||
ohshit(int32_t rvalue, const char* str) {
|
||||
fprintf (stderr, "\033[31merr: %s\033[00m\n", str);
|
||||
exit (rvalue);
|
||||
}
|
||||
|
||||
void usage (char **argv)
|
||||
{
|
||||
printf ( "NOT DONE YET\n");
|
||||
printf ( "usage: %s [type [param]]...\n", argv[0]);
|
||||
printf ( "ex: echo data | %s char_t 1\n", argv[0]);
|
||||
printf ( " This sends a CBOR msg [ 1, \"data\" ]\n");
|
||||
}
|
||||
|
||||
int32_t
|
||||
main(int32_t argc, char **argv)
|
||||
{
|
||||
if (argc == 2 && strcmp ("-h", argv[1]) == 0) {
|
||||
usage (argv);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
uint8_t buf[BUFSIZ];
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
ssize_t buflen = read (0, buf, BUFSIZ);
|
||||
|
||||
/* Preallocate the map structure */
|
||||
cbor_item_t * root = cbor_new_definite_map(1);
|
||||
/* Add the content */
|
||||
cbor_map_add(root, (struct cbor_pair) {
|
||||
.key = cbor_move(cbor_build_uint8(PKT_MSG)),
|
||||
.value = cbor_move(cbor_build_bytestring(buf, buflen))
|
||||
});
|
||||
/* Output: `length` bytes of data in the `buffer` */
|
||||
uint8_t * buffer;
|
||||
size_t buffer_size, length = cbor_serialize_alloc (root, &buffer, &buffer_size);
|
||||
|
||||
fwrite(buffer, 1, length, stdout);
|
||||
free(buffer);
|
||||
|
||||
fflush(stdout);
|
||||
cbor_decref(&root);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
char *fifopathin = "/tmp/123000-1-in";
|
||||
size_t msize = 100;
|
||||
|
||||
char buf[BUFSIZ];
|
||||
FILE *in = fopen (fifopathin, "rb");
|
||||
|
||||
printf ("opened\n");
|
||||
|
||||
if ((msize = fread (buf, msize, 1, in))) {
|
||||
printf ("error read %ld\n", msize);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf ("%s\n", buf);
|
||||
|
||||
sleep (10);
|
||||
printf ("read end\n");
|
||||
|
||||
fclose (in);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
char *fifopathin = "/tmp/123000-1-in";
|
||||
size_t msize;
|
||||
|
||||
FILE *out = fopen (fifopathin, "wb");
|
||||
|
||||
printf ("opened\n");
|
||||
|
||||
char *buf = "coucou";
|
||||
printf ("write %s\n", buf);
|
||||
|
||||
if ((msize = fread (buf, 6, 1, out))) {
|
||||
printf ("error read %ld\n", msize);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sleep (10);
|
||||
printf ("write end\n");
|
||||
|
||||
fclose (out);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define USOCK "./.socket"
|
||||
|
||||
#define handle_error(msg) \
|
||||
do { log_error (msg); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
do { log_error ("%s: file %s line %d %s", fun, __FILE__, __LINE__, msg); } while (0)
|
||||
|
||||
void log_format (const char* tag, const char* message, va_list args) {
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
|
||||
char * date =ctime(&now);
|
||||
date[strlen(date) - 1] = '\0';
|
||||
printf("%s:%s: ", date, tag);
|
||||
vprintf(message, args);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void log_error (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("error", message, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_info (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("info", message, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_debug (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("debug", message, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static
|
||||
int32_t recvsockfd (int32_t socket) // receive fd from socket
|
||||
{
|
||||
struct ipc_messagehdr msg = {0};
|
||||
|
||||
/* On Mac OS X, the struct iovec is needed, even if it points to minimal data */
|
||||
char m_buffer[1];
|
||||
struct iovec io = { .iov_base = m_buffer, .iov_len = sizeof(m_buffer) };
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
char c_buffer[256];
|
||||
msg.msg_control = c_buffer;
|
||||
msg.msg_controllen = sizeof(c_buffer);
|
||||
|
||||
if (recvmsg(socket, &msg, 0) < 0)
|
||||
handle_err ("recvsockfd", "Failed to receive message\n");
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
printf ("About to extract fd\n");
|
||||
int32_t fd;
|
||||
memmove(&fd, CMSG_DATA(cmsg), sizeof(fd));
|
||||
printf ("Extracted fd %d\n", fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int32_t usock_connect (int32_t *fd, const char *path)
|
||||
{
|
||||
assert (fd != NULL);
|
||||
assert (path != NULL);
|
||||
|
||||
if (fd == NULL) {
|
||||
handle_err ("usock_connect", "fd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
handle_err ("usock_connect", "path == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t sfd;
|
||||
struct sockaddr_un my_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd == -1) {
|
||||
handle_err ("usock_connect", "sfd == -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// clear structure
|
||||
memset(&my_addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
my_addr.sun_family = AF_UNIX;
|
||||
strncpy(my_addr.sun_path, path, strlen (path));
|
||||
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
if(connect(sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
|
||||
handle_err ("usock_connect", "connect == -1");
|
||||
perror("connect()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
*fd = sfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_init (int32_t *fd, const char *path)
|
||||
{
|
||||
assert (fd != NULL);
|
||||
assert (path != NULL);
|
||||
|
||||
if (fd == NULL) {
|
||||
handle_err ("usock_init", "fd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
handle_err ("usock_init", "path == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t sfd;
|
||||
struct sockaddr_un my_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd == -1) {
|
||||
handle_err ("usock_init", "sfd == -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// clear structure
|
||||
memset(&my_addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
my_addr.sun_family = AF_UNIX;
|
||||
strncpy(my_addr.sun_path, path, strlen (path));
|
||||
|
||||
// TODO FIXME
|
||||
// delete the unix socket if already created
|
||||
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
|
||||
if (bind (sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
|
||||
handle_err ("usock_init", "bind == -1");
|
||||
perror("bind()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen (sfd, 5) == -1) {
|
||||
handle_err ("usock_init", "listen == -1");
|
||||
perror("listen()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*fd = sfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_accept (int32_t fd, int32_t *pfd)
|
||||
{
|
||||
assert (pfd != NULL);
|
||||
|
||||
if (pfd == NULL) {
|
||||
handle_err ("usock_accept", "pfd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_un peer_addr;
|
||||
memset (&peer_addr, 0, sizeof (struct sockaddr_un));
|
||||
socklen_t peer_addr_size = 0;
|
||||
|
||||
*pfd = accept (fd, (struct sockaddr *) &peer_addr, &peer_addr_size);
|
||||
if (*pfd < 0) {
|
||||
handle_err ("usock_accept", "accept < 0");
|
||||
perror("listen()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_close (int32_t fd)
|
||||
{
|
||||
int32_t ret;
|
||||
ret = close (fd);
|
||||
if (ret < 0) {
|
||||
handle_err ("usock_close", "close ret < 0");
|
||||
perror ("closing");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t usock_remove (const char *path)
|
||||
{
|
||||
return unlink (path);
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
int32_t tcpsockfd;
|
||||
int32_t usockfd;
|
||||
// check the number of args on command line
|
||||
if(argc != 1)
|
||||
{
|
||||
fprintf (stderr, "USAGE: %s\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Connection to the unix socket\n");
|
||||
|
||||
// 1. unix socket connection
|
||||
int32_t ret = usock_connect (&usockfd, USOCK);
|
||||
if (ret != 0) {
|
||||
fprintf (stderr, "error: usock_connect\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Receiving the tcp socket\n");
|
||||
|
||||
// 2. receive the tcp socket
|
||||
tcpsockfd = recvsockfd (usockfd);
|
||||
|
||||
printf("Sending 'hello world' to the tcp socket\n");
|
||||
|
||||
// 3. send a message to check the connection is effective
|
||||
if (write(tcpsockfd, "hello world\n", strlen("hello world\n")) == -1) {
|
||||
perror("write");
|
||||
close(tcpsockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Disconnection of both sockets\n");
|
||||
|
||||
// 4. close sockets
|
||||
close(usockfd);
|
||||
close(tcpsockfd);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,322 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define USOCK "./.socket"
|
||||
|
||||
#define handle_error(msg) \
|
||||
do { log_error (msg); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#define handle_err(fun,msg)\
|
||||
do { log_error ("%s: file %s line %d %s", fun, __FILE__, __LINE__, msg); } while (0)
|
||||
|
||||
void log_format (const char* tag, const char* message, va_list args) {
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
|
||||
char * date =ctime(&now);
|
||||
date[strlen(date) - 1] = '\0';
|
||||
printf("%s:%s: ", date, tag);
|
||||
vprintf(message, args);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void log_error (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("error", message, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_info (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("info", message, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_debug (const char* message, ...) {
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
log_format("debug", message, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int32_t build_socket (char *servername, char * serverport)
|
||||
{
|
||||
int32_t sockfd;
|
||||
struct sockaddr_in6 server;
|
||||
socklen_t addrlen;
|
||||
|
||||
// socket factory
|
||||
if((sockfd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
perror("socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// init remote addr structure and other params
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_port = htons(atoi(serverport));
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
|
||||
// get addr from command line and convert it
|
||||
if(inet_pton(AF_INET6, servername, &server.sin6_addr) != 1)
|
||||
{
|
||||
perror("inet_pton");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Trying to connect to the remote host\n");
|
||||
if(connect(sockfd, (struct sockaddr *) &server, addrlen) == -1)
|
||||
{
|
||||
perror("connect");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
int32_t usock_connect (int32_t *fd, const char *path)
|
||||
{
|
||||
assert (fd != NULL);
|
||||
assert (path != NULL);
|
||||
|
||||
if (fd == NULL) {
|
||||
handle_err ("usock_connect", "fd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
handle_err ("usock_connect", "path == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t sfd;
|
||||
struct sockaddr_un my_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd == -1) {
|
||||
handle_err ("usock_connect", "sfd == -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// clear structure
|
||||
memset(&my_addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
my_addr.sun_family = AF_UNIX;
|
||||
strncpy(my_addr.sun_path, path, strlen (path));
|
||||
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
if(connect(sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
|
||||
handle_err ("usock_connect", "connect == -1");
|
||||
perror("connect()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
*fd = sfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_init (int32_t *fd, const char *path)
|
||||
{
|
||||
assert (fd != NULL);
|
||||
assert (path != NULL);
|
||||
|
||||
if (fd == NULL) {
|
||||
handle_err ("usock_init", "fd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
handle_err ("usock_init", "path == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t sfd;
|
||||
struct sockaddr_un my_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd == -1) {
|
||||
handle_err ("usock_init", "sfd == -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// clear structure
|
||||
memset(&my_addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
my_addr.sun_family = AF_UNIX;
|
||||
strncpy(my_addr.sun_path, path, strlen (path));
|
||||
|
||||
// TODO FIXME
|
||||
// delete the unix socket if already created
|
||||
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
|
||||
if (bind (sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
|
||||
handle_err ("usock_init", "bind == -1");
|
||||
perror("bind()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen (sfd, 5) == -1) {
|
||||
handle_err ("usock_init", "listen == -1");
|
||||
perror("listen()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*fd = sfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_accept (int32_t fd, int32_t *pfd)
|
||||
{
|
||||
assert (pfd != NULL);
|
||||
|
||||
if (pfd == NULL) {
|
||||
handle_err ("usock_accept", "pfd == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_un peer_addr;
|
||||
memset (&peer_addr, 0, sizeof (struct sockaddr_un));
|
||||
socklen_t peer_addr_size = 0;
|
||||
|
||||
*pfd = accept (fd, (struct sockaddr *) &peer_addr, &peer_addr_size);
|
||||
if (*pfd < 0) {
|
||||
handle_err ("usock_accept", "accept < 0");
|
||||
perror("listen()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t usock_close (int32_t fd)
|
||||
{
|
||||
int32_t ret;
|
||||
ret = close (fd);
|
||||
if (ret < 0) {
|
||||
handle_err ("usock_close", "close ret < 0");
|
||||
perror ("closing");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t usock_remove (const char *path)
|
||||
{
|
||||
return unlink (path);
|
||||
}
|
||||
|
||||
int32_t build_unix_socket (char * path)
|
||||
{
|
||||
int32_t remotefd, localfd;
|
||||
|
||||
usock_init (&localfd, path);
|
||||
usock_accept (localfd, &remotefd);
|
||||
|
||||
return remotefd;
|
||||
}
|
||||
|
||||
static
|
||||
void sendfd (int32_t socket, int32_t fd) // send fd by socket
|
||||
{
|
||||
struct ipc_messagehdr msg = { 0 };
|
||||
char buf[CMSG_SPACE(sizeof(fd))];
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
/* On Mac OS X, the struct iovec is needed, even if it points to minimal data */
|
||||
struct iovec io = { .iov_base = "", .iov_len = 1 };
|
||||
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = buf;
|
||||
msg.msg_controllen = sizeof(buf);
|
||||
|
||||
struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
|
||||
|
||||
memmove(CMSG_DATA(cmsg), &fd, sizeof(fd));
|
||||
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
|
||||
if (sendmsg(socket, &msg, 0) < 0)
|
||||
handle_err("sendfd", "Failed to send message\n");
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
// check the number of args on command line
|
||||
if(argc != 3)
|
||||
{
|
||||
fprintf (stderr, "USAGE: %s @server port_num\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
char *servername = argv[1];
|
||||
char *serverport = argv[2];
|
||||
|
||||
printf("Connection to the tcp socket\n");
|
||||
// 1. socket creation (tcp), connection to the server
|
||||
int32_t sockfd = build_socket (servername, serverport);
|
||||
|
||||
printf("Sending 'coucou' to the tcp socket\n");
|
||||
// send a message to check the connection is effective
|
||||
if (write(sockfd, "coucou\n", strlen("coucou\n")) == -1) {
|
||||
perror("write");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf ("Connection to the unix socket\n");
|
||||
// 2. socket creation (unix)
|
||||
int32_t usockfd = build_unix_socket (USOCK);
|
||||
|
||||
printf ("Passing the tcp socket to the unix socket\n");
|
||||
// 3. tcp socket passing to the client
|
||||
sendfd (usockfd, sockfd);
|
||||
|
||||
// send a message to check the connection is (still) effective
|
||||
if (write(sockfd, "bye\n", strlen("bye\n")) == -1) {
|
||||
perror("write");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Disconnection\n");
|
||||
|
||||
// 4. close sockets
|
||||
close(usockfd);
|
||||
close(sockfd);
|
||||
|
||||
usock_remove (USOCK);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
package=perfect-os-junk
|
||||
version=0.0.1
|
||||
|
||||
CFLAGS="-O2 -Wall -Wextra -Wshadow -ansi -pedantic -std=c99 -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=200809L"
|
||||
|
||||
targets=(libposj)
|
||||
type[libposj]=library
|
||||
sources[libposj]="$(echo lib/*.c)"
|
||||
|
||||
target="pingpong/pingpong"
|
||||
targets+=(${target})
|
||||
sources[${target}]="$(echo pingpong/*.c)"
|
||||
type[${target}]=binary
|
||||
depends[${target}]="libposj.a"
|
||||
ldflags[${target}]="libposj.a -lpthread"
|
||||
|
||||
target="pubsub/pubsub"
|
||||
targets+=(${target})
|
||||
sources[${target}]="$(ls pubsub/*.c | grep -v test-send)"
|
||||
type[${target}]=binary
|
||||
depends[${target}]="libposj.a"
|
||||
ldflags[${target}]="libposj.a -lpthread"
|
||||
|
||||
target="pubsub/pubsub-test-send"
|
||||
targets+=(${target})
|
||||
sources[${target}]="pubsub/pubsub-test-send.c"
|
||||
type[${target}]=binary
|
||||
depends[${target}]="libposj.a"
|
||||
ldflags[${target}]="libposj.a -lpthread"
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#include "../lib/pubsubd.h"
|
||||
#include <cbor.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PKT_CLOSE 0
|
||||
#define PKT_MSG 1
|
||||
#define PKT_ERROR 2
|
||||
|
||||
void usage (char **argv) {
|
||||
printf ("usage: echo something | msg | %s\n", argv[0]);
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char * argv[])
|
||||
{
|
||||
if (argc == 2 && strcmp ("-h", argv[1]) == 0) {
|
||||
usage (argv);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// read the message from the client
|
||||
size_t mlen = 0;
|
||||
uint8_t buf[BUFSIZ];
|
||||
mlen = read (0, buf, BUFSIZ);
|
||||
|
||||
/* Assuming `buffer` contains `info.st_size` bytes of input data */
|
||||
struct cbor_load_result result;
|
||||
cbor_item_t * item = cbor_load (buf, mlen, &result);
|
||||
|
||||
/* Pretty-print the result */
|
||||
cbor_describe(item, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct cbor_pair * pair = cbor_map_handle (item);
|
||||
cbor_mutable_data *data = cbor_bytestring_handle (pair->value);
|
||||
|
||||
size_t datalen = cbor_bytestring_length (pair->value);
|
||||
char *bstr = malloc (datalen +1);
|
||||
memset (bstr, 0, datalen +1);
|
||||
memcpy (bstr, data, datalen);
|
||||
|
||||
printf ("msg data (%ld bytes): %s\n", datalen, bstr);
|
||||
|
||||
/* Deallocate the result */
|
||||
cbor_decref (&item);
|
||||
|
||||
free (bstr);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
158
drop/tcpselect.c
158
drop/tcpselect.c
|
@ -1,158 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* port we're listening on */
|
||||
|
||||
#define PORT 2020
|
||||
|
||||
int32_t main(int32_t argc, char *argv[])
|
||||
{
|
||||
/* master file descriptor list */
|
||||
fd_set master;
|
||||
/* temp file descriptor list for select() */
|
||||
fd_set read_fds;
|
||||
/* server address */
|
||||
struct sockaddr_in serveraddr;
|
||||
/* client address */
|
||||
struct sockaddr_in clientaddr;
|
||||
|
||||
/* maximum file descriptor number */
|
||||
int32_t fdmax;
|
||||
/* listening socket descriptor */
|
||||
int32_t listener;
|
||||
/* newly accept()ed socket descriptor */
|
||||
int32_t newfd;
|
||||
/* buffer for client data */
|
||||
char buf[1024];
|
||||
int32_t nbytes;
|
||||
|
||||
/* for setsockopt() SO_REUSEADDR, below */
|
||||
int32_t yes = 1;
|
||||
int32_t addrlen;
|
||||
int32_t i, j;
|
||||
|
||||
/* clear the master and temp sets */
|
||||
FD_ZERO(&master);
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* get the listener */
|
||||
if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
perror("Server-socket() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Server-socket() is OK...\n");
|
||||
/*"address already in use" error message */
|
||||
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int32_t)) == -1)
|
||||
{
|
||||
perror("Server-setsockopt() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Server-setsockopt() is OK...\n");
|
||||
|
||||
/* bind */
|
||||
serveraddr.sin_family = AF_INET;
|
||||
serveraddr.sin_addr.s_addr = INADDR_ANY;
|
||||
serveraddr.sin_port = htons(PORT);
|
||||
memset(&(serveraddr.sin_zero), '\0', 8);
|
||||
|
||||
if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
|
||||
{
|
||||
|
||||
perror("Server-bind() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Server-bind() is OK...\n");
|
||||
|
||||
/* listen */
|
||||
if(listen(listener, 10) == -1)
|
||||
{
|
||||
perror("Server-listen() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Server-listen() is OK...\n");
|
||||
|
||||
/* add the listener to the master set */
|
||||
FD_SET(listener, &master);
|
||||
|
||||
/* keep track of the biggest file descriptor */
|
||||
fdmax = listener; /* so far, it's this one*/
|
||||
|
||||
/* loop */
|
||||
for(;;) {
|
||||
/* copy it */
|
||||
read_fds = master;
|
||||
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
perror("Server-select() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Server-select() is OK...\n");
|
||||
|
||||
/*run through the existing connections looking for data to be read*/
|
||||
for(i = 0; i <= fdmax; i++) {
|
||||
if(FD_ISSET(i, &read_fds)) {
|
||||
/* we got one... */
|
||||
if(i == listener) {
|
||||
/* handle new connections */
|
||||
addrlen = sizeof(clientaddr);
|
||||
if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1)
|
||||
{
|
||||
perror("Server-accept() error lol!");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Server-accept() is OK...\n");
|
||||
FD_SET(newfd, &master); /* add to master set */
|
||||
if(newfd > fdmax)
|
||||
{ /* keep track of the maximum */
|
||||
fdmax = newfd;
|
||||
}
|
||||
|
||||
printf("%s: New connection from %s on socket %d\n"
|
||||
, argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* handle data from a client */
|
||||
if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
|
||||
/* got error or connection closed by client */
|
||||
if(nbytes == 0)
|
||||
/* connection closed */
|
||||
printf("%s: socket %d hung up\n", argv[0], i);
|
||||
|
||||
else
|
||||
perror("recv() error lol!");
|
||||
|
||||
/* close it... */
|
||||
close(i);
|
||||
/* remove from master set */
|
||||
FD_CLR(i, &master);
|
||||
}
|
||||
else {
|
||||
/* we got some data from a client*/
|
||||
for(j = 0; j <= fdmax; j++) {
|
||||
/* send to everyone! */
|
||||
if(FD_ISSET(j, &master)) {
|
||||
/* except the listener and ourselves */
|
||||
if(j != listener && j != i) {
|
||||
if(send(j, buf, nbytes, 0) == -1)
|
||||
perror("send() error lol!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
title: libipc
|
||||
header: libipc Manual
|
||||
footer: libipc
|
||||
date: 2018-11-20
|
||||
section: 7
|
||||
...
|
||||
|
||||
# NAME
|
||||
|
||||
libipc - Simple, easy-to-use IPC library
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
**`#include <ipc.h>`**
|
||||
|
||||
**`...`**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**libipc** is a library that provides interprocess communication medium between applications.
|
||||
It provides both client and server code.
|
||||
|
||||
# USAGE
|
||||
|
||||
# NOTES
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
# BUGS & LIMITATIONS
|
||||
|
||||
- Documentation is currently limited.
|
||||
- Rerouting IPC connexions through other services (for example, through a network bridge service) is currently not possible.
|
||||
- Errors management is currently limited, and precise errors cannot be distinguished.
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# Service ping-pong
|
||||
|
||||
This service is a brain-dead application. It is only to a pedagogic end.
|
||||
|
||||
The purpose is only to communicate with an application once, the application
|
||||
sends a message and the service answer with the same message.
|
||||
|
||||
# How it works
|
||||
|
||||
* **S**: service
|
||||
* **A**: application
|
||||
|
||||
1. **S** creates the named pipe /tmp/pingpong, then listens
|
||||
2. **S** opens the named pipes in & out
|
||||
3. **A** talks with the test program *pingpong.sh*
|
||||
4. **S** closes the test program named pipes
|
||||
5. **S** removes the named pipe /tmp/pingpong after 10 served applications
|
||||
|
||||
# pingpong.sh
|
||||
|
||||
The script *pingpong.sh* lets you test the service.
|
||||
|
||||
Usage :
|
||||
|
||||
pingpong.sh [NB]
|
||||
# NB is the number of exchanged messages
|
||||
|
||||
or
|
||||
|
||||
pingpong.sh clean
|
||||
# it is to clean the /tmp/ipc/ directory
|
|
@ -1,29 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread -lreadline
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../lib/*.c ../../core/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
test:
|
||||
rm /tmp/ipc/pongd-0-0
|
||||
./pongd.bin
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(OBJECTS) $@.c -o $@.bin $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin $(PARAMS)
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
|
@ -1,211 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../core/communication.h"
|
||||
#include "../../core/error.h"
|
||||
|
||||
#define SERVICE_NAME "pongd"
|
||||
|
||||
#define MAX_MESSAGE_SIZE IPC_MAX_MESSAGE_SIZE
|
||||
#define MESSAGE "salut ça va ?"
|
||||
|
||||
void interactive (char * service_name, char *env[])
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (ipc_application_connection (env, &srv, service_name) < 0) {
|
||||
handle_err ("main", "ipc_application_connection < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct ipc_event event;
|
||||
memset (&event, 0, sizeof (struct ipc_event));
|
||||
|
||||
struct ipc_services services;
|
||||
memset (&services, 0, sizeof (struct ipc_services));
|
||||
ipc_services_add (&services, &srv);
|
||||
int ret = 0;
|
||||
|
||||
while (1) {
|
||||
printf ("msg to send: ");
|
||||
fflush (stdout);
|
||||
ret = ipc_application_peek_event (&services, &event);
|
||||
|
||||
if (ret != 0) {
|
||||
handle_error("ipc_application_peek_event != 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case IPC_EVENT_TYPE_STDIN:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
|
||||
|
||||
ipc_message_empty (m);
|
||||
free (m);
|
||||
|
||||
ipc_services_free (&services);
|
||||
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
char mtype_str[5];
|
||||
memset(mtype_str, 0, 5);
|
||||
printf ("message type: ");
|
||||
fflush(stdout);
|
||||
read(0, mtype_str, 5);
|
||||
m->type = atoi(mtype_str);
|
||||
memset(mtype_str, 0, 5);
|
||||
|
||||
if (ipc_application_write (&srv, m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IPC_EVENT_TYPE_MESSAGE:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
printf ("msg recv: %.*s", m->length, m->payload);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||
{
|
||||
printf ("server disconnected: quitting...\n");
|
||||
|
||||
// just remove srv from services, it's already closed
|
||||
ipc_services_free (&services);
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
};
|
||||
case IPC_EVENT_TYPE_NOT_SET:
|
||||
case IPC_EVENT_TYPE_CONNECTION:
|
||||
case IPC_EVENT_TYPE_ERROR:
|
||||
default :
|
||||
fprintf (stderr, "should not happen, event type %d\n", event.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void non_interactive (char msg_type, char *msg, char * service_name, char *env[])
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (ipc_application_connection (env, &srv, service_name) < 0) {
|
||||
handle_err ("main", "ipc_application_connection < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ipc_message_format (&m, msg_type, msg, strlen(msg) + 1);
|
||||
// print_msg (&m);
|
||||
|
||||
if (ipc_application_write (&srv, &m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
|
||||
if (ipc_application_read (&srv, &m) < 0) {
|
||||
handle_err("main", "application_read < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (m.length > 0) {
|
||||
printf ("msg recv: %.*s\n", m.length, m.payload);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
}
|
||||
|
||||
// usage: ipc-debug [service-name]
|
||||
int main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
if (argc == 1) {
|
||||
printf ("usage: %s [-n] [service_name [message-type [message]]]\n", argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
char service_name[100];
|
||||
memset (service_name, 0, 100);
|
||||
|
||||
int asked_non_interactive = 0;
|
||||
int current_param = 1;
|
||||
|
||||
if (argc >= 2) {
|
||||
if (memcmp (argv[current_param], "-n", 2) == 0) {
|
||||
// non interactive
|
||||
asked_non_interactive = 1;
|
||||
current_param++;
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
ssize_t t = strlen(argv[current_param]) > 100 ? 100 : strlen(argv[current_param]);
|
||||
memcpy(service_name, argv[current_param], t);
|
||||
current_param++;
|
||||
}
|
||||
else { memcpy(service_name, SERVICE_NAME, strlen(SERVICE_NAME)); }
|
||||
|
||||
char mtype = 2;
|
||||
if (argc > 2) {
|
||||
mtype = atoi(argv[current_param]);
|
||||
current_param++;
|
||||
}
|
||||
|
||||
char *msg = malloc (MAX_MESSAGE_SIZE);
|
||||
if (msg == NULL) {
|
||||
handle_err("main", "not enough memory");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
memset(msg, 0, MAX_MESSAGE_SIZE);
|
||||
|
||||
if (argc > 3) { memcpy(msg, argv[current_param], strlen(argv[current_param])); }
|
||||
else { memcpy(msg, MESSAGE, strlen(MESSAGE)); }
|
||||
|
||||
if (asked_non_interactive) {
|
||||
non_interactive (mtype, msg, service_name, env);
|
||||
free (msg);
|
||||
}
|
||||
else {
|
||||
|
||||
free (msg);
|
||||
interactive (service_name, env);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
138
pong/app/pong.c
138
pong/app/pong.c
|
@ -1,138 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../core/ipc.h"
|
||||
#include "../../core/error.h"
|
||||
|
||||
#define MSG "coucou"
|
||||
#define SERVICE_NAME "pongd"
|
||||
|
||||
void non_interactive (char *env[])
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (ipc_application_connection (env, &srv, SERVICE_NAME) < 0) {
|
||||
handle_err("main", "ipc_application_connection < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf ("msg to send: %.*s\n", (int) strlen(MSG), MSG);
|
||||
ipc_message_format_data (&m, MSG, strlen(MSG) +1);
|
||||
// printf ("msg to send in the client: ");
|
||||
// ipc_message_print (&m);
|
||||
if (ipc_application_write (&srv, &m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
|
||||
if (ipc_application_read (&srv, &m) < 0) {
|
||||
handle_err("main", "application_read < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf ("msg recv: %s\n", m.payload);
|
||||
ipc_message_empty (&m);
|
||||
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void interactive (char *env[])
|
||||
{
|
||||
int ret = 0;
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (ipc_application_connection (env, &srv, SERVICE_NAME) < 0) {
|
||||
handle_err ("main", "ipc_application_connection < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct ipc_event event;
|
||||
memset (&event, 0, sizeof (struct ipc_event));
|
||||
|
||||
struct ipc_services services;
|
||||
memset (&services, 0, sizeof (struct ipc_services));
|
||||
ipc_services_add (&services, &srv);
|
||||
|
||||
while (1) {
|
||||
printf ("msg to send: ");
|
||||
fflush (stdout);
|
||||
ret = ipc_application_peek_event (&services, &event);
|
||||
|
||||
if (ret != 0) {
|
||||
handle_error("ipc_application_peek_event != 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case IPC_EVENT_TYPE_STDIN:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
|
||||
|
||||
ipc_message_empty (m);
|
||||
free (m);
|
||||
|
||||
ipc_services_free (&services);
|
||||
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (ipc_application_write (&srv, m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IPC_EVENT_TYPE_MESSAGE:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
printf ("msg recv: %.*s", m->length, m->payload);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||
case IPC_EVENT_TYPE_NOT_SET:
|
||||
case IPC_EVENT_TYPE_CONNECTION:
|
||||
case IPC_EVENT_TYPE_ERROR:
|
||||
default :
|
||||
fprintf (stderr, "should not happen, event type %d\n", event.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
argc = argc; // warnings
|
||||
argv = argv; // warnings
|
||||
|
||||
if (argc == 1)
|
||||
non_interactive (env);
|
||||
else
|
||||
interactive (env);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
164
pong/app/pongd.c
164
pong/app/pongd.c
|
@ -1,164 +0,0 @@
|
|||
#include "../../core/ipc.h"
|
||||
#include "../../core/error.h"
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PONGD_SERVICE_NAME "pongd"
|
||||
#define PONGD_PRINT_MESSAGES
|
||||
|
||||
int cpt = 0;
|
||||
|
||||
struct ipc_service *srv = 0;
|
||||
struct ipc_clients *clients;
|
||||
|
||||
|
||||
void main_loop ()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
clients = malloc (sizeof (struct ipc_clients));
|
||||
memset(clients, 0, sizeof(struct ipc_clients));
|
||||
|
||||
struct ipc_event event;
|
||||
memset(&event, 0, sizeof (struct ipc_event));
|
||||
event.type = IPC_EVENT_TYPE_NOT_SET;
|
||||
|
||||
while(1) {
|
||||
// ipc_service_poll_event provides one event at a time
|
||||
// warning: event->m is free'ed if not NULL
|
||||
ret = ipc_service_poll_event (clients, srv, &event);
|
||||
if (ret != 0) {
|
||||
handle_error("ipc_service_poll_event != 0");
|
||||
// the application will shut down, and close the service
|
||||
if (ipc_server_close (srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case IPC_EVENT_TYPE_CONNECTION:
|
||||
{
|
||||
cpt++;
|
||||
#ifdef PONGD_PRINT_MESSAGES
|
||||
printf ("connection: client fd %d, %d clients connected\n"
|
||||
, ((struct ipc_client*) event.origin)->proc_fd, cpt);
|
||||
#endif
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||
{
|
||||
cpt--;
|
||||
#ifdef PONGD_PRINT_MESSAGES
|
||||
printf ("disconnection: %d clients remaining\n", cpt);
|
||||
#endif
|
||||
|
||||
// free the ipc_client structure
|
||||
free (event.origin);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_MESSAGE:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
#ifdef PONGD_PRINT_MESSAGES
|
||||
if (m->length > 0) {
|
||||
printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
|
||||
}
|
||||
#endif
|
||||
if (ipc_server_write (event.origin, m) < 0) {
|
||||
handle_err( "handle_new_msg", "server_write < 0");
|
||||
}
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_ERROR:
|
||||
{
|
||||
fprintf (stderr, "a problem happened with client %d\n"
|
||||
, ((struct ipc_client*) event.origin)->proc_fd);
|
||||
};
|
||||
break;
|
||||
default :
|
||||
{
|
||||
fprintf (stderr, "there must be a problem, event not set\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// should never go there
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
void exit_program(int signal)
|
||||
{
|
||||
printf("Quitting, signal: %d\n", signal);
|
||||
|
||||
// free remaining clients
|
||||
for (int i = 0; i < clients->size ; i++) {
|
||||
struct ipc_client *cli = clients->clients[i];
|
||||
// TODO: replace with specific ipc_client_empty function
|
||||
if (cli != NULL) {
|
||||
// ipc_client_empty (cli);
|
||||
free (cli);
|
||||
}
|
||||
clients->clients[i] = NULL;
|
||||
}
|
||||
|
||||
ipc_clients_free (clients);
|
||||
free (clients);
|
||||
|
||||
|
||||
// the application will shut down, and close the service
|
||||
if (ipc_server_close (srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
free (srv);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* service ping-pong: send back everything sent by the clients
|
||||
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
||||
*/
|
||||
|
||||
int main(int argc, char * argv[], char **env)
|
||||
{
|
||||
argc = argc; // warnings
|
||||
argv = argv; // warnings
|
||||
|
||||
printf ("pid = %d\n", getpid ());
|
||||
|
||||
srv = malloc (sizeof (struct ipc_service));
|
||||
if (srv == NULL) {
|
||||
exit (1);
|
||||
}
|
||||
memset (srv, 0, sizeof (struct ipc_service));
|
||||
srv->index = 0;
|
||||
srv->version = 0;
|
||||
|
||||
// unlink("/tmp/ipc/pongd-0-0");
|
||||
|
||||
if (ipc_server_init (env, srv, PONGD_SERVICE_NAME) < 0) {
|
||||
handle_error("ipc_server_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf ("Listening on %s.\n", srv->spath);
|
||||
|
||||
printf("MAIN: server created\n" );
|
||||
|
||||
signal (SIGHUP, exit_program);
|
||||
signal (SIGALRM, exit_program);
|
||||
signal (SIGUSR1, exit_program);
|
||||
signal (SIGUSR2, exit_program);
|
||||
signal (SIGTERM, exit_program);
|
||||
signal (SIGINT, exit_program);
|
||||
|
||||
// the service will loop until the end of time, or a signal
|
||||
main_loop ();
|
||||
|
||||
// main_loop should not return
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../core/communication.h"
|
||||
#include "../../core/error.h"
|
||||
|
||||
#define SERVICE_NAME "pongd"
|
||||
|
||||
#define NUMBER_OF_MESSAGES 1000
|
||||
#define MAX_MESSAGE_SIZE IPC_MAX_MESSAGE_SIZE
|
||||
#define MESSAGE "salut ça va ?"
|
||||
|
||||
void non_interactive (char msg_type, char *msg, char * service_name, char *env[])
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
// index and version should be filled
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
// init service
|
||||
if (ipc_application_connection (env, &srv, service_name) < 0) {
|
||||
handle_err ("main", "ipc_application_connection < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < NUMBER_OF_MESSAGES ; i++) {
|
||||
ipc_message_format (&m, msg_type, msg, strlen(msg) + 1);
|
||||
// print_msg (&m);
|
||||
|
||||
if (ipc_application_write (&srv, &m) < 0) {
|
||||
handle_err("main", "application_write < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
|
||||
if (ipc_application_read (&srv, &m) < 0) {
|
||||
handle_err("main", "application_read < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef WITH_PRINT_MESSAGES
|
||||
if (m.length > 0) {
|
||||
printf ("msg recv: %.*s\n", m.length, m.payload);
|
||||
}
|
||||
#endif
|
||||
ipc_message_empty (&m);
|
||||
}
|
||||
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
}
|
||||
|
||||
// usage: ipc-debug [service-name]
|
||||
int main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
if (argc == 1) {
|
||||
printf ("usage: %s service_name [message-type [message]]\n", argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
char service_name[100];
|
||||
memset (service_name, 0, 100);
|
||||
|
||||
int current_param = 1;
|
||||
|
||||
if (argc != 1) {
|
||||
ssize_t t = strlen(argv[current_param]) > 100 ? 100 : strlen(argv[current_param]);
|
||||
memcpy(service_name, argv[current_param], t);
|
||||
current_param++;
|
||||
}
|
||||
else { memcpy(service_name, SERVICE_NAME, strlen(SERVICE_NAME)); }
|
||||
|
||||
char mtype = 2;
|
||||
if (argc > 2) {
|
||||
mtype = atoi(argv[current_param]);
|
||||
current_param++;
|
||||
}
|
||||
|
||||
char *msg = malloc (MAX_MESSAGE_SIZE);
|
||||
if (msg == NULL) {
|
||||
handle_err("main", "not enough memory");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
memset(msg, 0, MAX_MESSAGE_SIZE);
|
||||
|
||||
if (argc > 3) { memcpy(msg, argv[current_param], strlen(argv[current_param])); }
|
||||
else { memcpy(msg, MESSAGE, strlen(MESSAGE)); }
|
||||
|
||||
non_interactive (mtype, msg, service_name, env);
|
||||
free (msg);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
package=ipc
|
||||
version=0.1.0
|
||||
|
||||
targets=(libipc src/ipc.h man/libipc.7)
|
||||
|
||||
type[libipc]=library
|
||||
sources[libipc]="$(ls src/*.c)"
|
||||
|
||||
type[src/ipc.h]=header
|
||||
|
||||
type[man/libipc.7]=man
|
||||
|
||||
dist=(Makefile project.zsh src/error.h src/ipc.h src/event.h man/*.md)
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../lib/*.c ../../core/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
|
@ -1,171 +0,0 @@
|
|||
#include "../../core/ipc.h"
|
||||
|
||||
#include "../lib/message.h"
|
||||
#include "../lib/channels.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PUBSUBD_SERVICE_NAME "pubsubd"
|
||||
|
||||
void usage (char **argv) {
|
||||
printf ( "usage: %s [chan [pub]]\n", argv[0]);
|
||||
}
|
||||
|
||||
void print_cmd (void) {
|
||||
printf ("\033[32m>\033[00m ");
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
void chan_sub (struct ipc_service *srv, char *chan)
|
||||
{
|
||||
struct pubsub_msg msg;
|
||||
memset (&msg, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
// meta data on the message
|
||||
msg.type = PUBSUB_MSG_TYPE_SUB;
|
||||
pubsub_message_set_chan (&msg, chan, strlen(chan));
|
||||
|
||||
pubsub_message_send (srv, &msg);
|
||||
printf ("subscribed to %s\n", chan);
|
||||
|
||||
pubsub_message_empty (&msg);
|
||||
}
|
||||
|
||||
void main_loop (char **env, int index, int version
|
||||
, char *cmd, char *chan)
|
||||
{
|
||||
printf ("connection to pubsubd: index %d version %d "
|
||||
"cmd %s chan %s\n"
|
||||
, index, version, cmd, chan );
|
||||
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
int ret = ipc_application_connection (env, &srv, PUBSUBD_SERVICE_NAME);
|
||||
if (ret != 0) {
|
||||
handle_err ("pubsub_connection", "application_connection != 0");
|
||||
}
|
||||
printf ("connected\n");
|
||||
|
||||
if (strncmp (cmd, "sub", 3) == 0) {
|
||||
chan_sub (&srv, chan);
|
||||
}
|
||||
|
||||
printf ("main_loop\n");
|
||||
|
||||
struct pubsub_msg msg;
|
||||
memset (&msg, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
// meta data on the message
|
||||
msg.type = PUBSUB_MSG_TYPE_PUB;
|
||||
pubsub_message_set_chan (&msg, chan, strlen(chan));
|
||||
|
||||
struct ipc_event event;
|
||||
memset (&event, 0, sizeof (struct ipc_event));
|
||||
|
||||
struct ipc_services services;
|
||||
memset (&services, 0, sizeof (struct ipc_services));
|
||||
ipc_service_add (&services, &srv);
|
||||
|
||||
int should_continue = 1;
|
||||
|
||||
while (should_continue) {
|
||||
print_cmd ();
|
||||
ret = ipc_application_peek_event (&services, &event);
|
||||
|
||||
if (ret != 0) {
|
||||
handle_error("ipc_application_peek_event != 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case IPC_EVENT_TYPE_STDIN:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
|
||||
ipc_message_empty (m);
|
||||
free (m);
|
||||
|
||||
should_continue = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// get the curent payload, change it to be compatible with the application
|
||||
// then send it
|
||||
char *pointer_to_return = strchr (m->payload, '\n');
|
||||
*pointer_to_return = '\0';
|
||||
m->length--;
|
||||
pubsub_message_set_chan (&msg, chan, strlen(chan));
|
||||
pubsub_message_set_data (&msg, m->payload, m->length);
|
||||
|
||||
pubsub_message_send (&srv, &msg);
|
||||
|
||||
pubsub_message_empty (&msg);
|
||||
}
|
||||
break;
|
||||
case IPC_EVENT_TYPE_MESSAGE:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
// print_hexa ("received msg hexa", (unsigned char *) m->payload, m->length);
|
||||
|
||||
pubsub_message_from_message (&msg, m);
|
||||
printf ("\r\033[31m>\033[00m %.*s\n", (int) msg.datalen, msg.data);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||
{
|
||||
printf ("server disconnected: quitting...\n");
|
||||
|
||||
// just remove srv from services, it's already closed
|
||||
ipc_services_free (&services);
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_NOT_SET:
|
||||
case IPC_EVENT_TYPE_CONNECTION:
|
||||
case IPC_EVENT_TYPE_ERROR:
|
||||
default :
|
||||
fprintf (stderr, "should not happen, event type %d\n", event.type);
|
||||
}
|
||||
}
|
||||
|
||||
// free everything
|
||||
pubsub_message_empty (&msg);
|
||||
|
||||
printf ("disconnection...\n");
|
||||
ipc_services_free (&services);
|
||||
if (ipc_application_close (&srv) < 0) {
|
||||
handle_err("main", "application_close < 0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
char *cmd = "sub";
|
||||
char *chan = "chan1";
|
||||
|
||||
if (argc == 2 && strncmp("-h", argv[1], 2) == 0) {
|
||||
usage (argv);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if (argc >= 2) {
|
||||
chan = argv[1];
|
||||
}
|
||||
|
||||
if (argc >= 3) {
|
||||
cmd = argv[2];
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
// don't care about the version
|
||||
int version = 0;
|
||||
|
||||
main_loop (env, index, version, cmd, chan);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
#include "../../core/ipc.h"
|
||||
#include "../lib/message.h"
|
||||
#include "../lib/channels.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define PUBSUBD_SERVICE_NAME "pubsubd"
|
||||
|
||||
// to quit them properly if a signal occurs
|
||||
struct ipc_service srv;
|
||||
struct channels chans;
|
||||
|
||||
void pubsubd_send (const struct ipc_clients *clients, const struct pubsub_msg * pubsub_msg)
|
||||
{
|
||||
if (clients == NULL) {
|
||||
fprintf (stderr, "pubsubd_send: clients == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pubsub_msg == NULL) {
|
||||
fprintf (stderr, "pubsubd_send: pubsub_msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
pubsub_message_to_message (pubsub_msg, &m);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < clients->size ; i++) {
|
||||
ipc_server_write (clients->clients[i], &m);
|
||||
}
|
||||
ipc_message_empty (&m);
|
||||
}
|
||||
|
||||
void pubsubd_main_loop (struct ipc_service *srv, struct channels *chans)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
struct ipc_clients clients;
|
||||
memset(&clients, 0, sizeof(struct ipc_clients));
|
||||
|
||||
struct ipc_clients proc_to_read;
|
||||
memset(&proc_to_read, 0, sizeof(struct ipc_clients));
|
||||
|
||||
struct ipc_event event;
|
||||
memset(&event, 0, sizeof (struct ipc_event));
|
||||
event.type = IPC_EVENT_TYPE_NOT_SET;
|
||||
|
||||
int cpt = 0;
|
||||
|
||||
while(1) {
|
||||
ret = ipc_service_poll_event (&clients, srv, &event);
|
||||
if (ret != 0) {
|
||||
handle_error("ipc_service_poll_event != 0");
|
||||
// the application will shut down, and close the service
|
||||
if (ipc_server_close (srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case IPC_EVENT_TYPE_CONNECTION:
|
||||
{
|
||||
cpt++;
|
||||
struct ipc_client *cli = event.origin;
|
||||
printf ("connection of client %d: %d clients connected\n", cli->proc_fd, cpt);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||
{
|
||||
cpt--;
|
||||
struct ipc_client *cli = event.origin;
|
||||
printf ("disconnection of client %d: %d clients remaining\n", cli->proc_fd, cpt);
|
||||
|
||||
pubsubd_channels_unsubscribe_everywhere (chans, cli);
|
||||
|
||||
// free the ipc_client structure
|
||||
free (event.origin);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_MESSAGE:
|
||||
{
|
||||
struct ipc_message *m = event.m;
|
||||
// print_hexa ("received msg hexa", (unsigned char *) m->payload, m->length);
|
||||
struct ipc_client *cli = event.origin;
|
||||
|
||||
struct pubsub_msg pm;
|
||||
memset (&pm, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
pubsub_message_from_message (&pm, m);
|
||||
|
||||
if (pm.type == PUBSUB_MSG_TYPE_SUB) {
|
||||
printf ("client %d subscribing to %s\n"
|
||||
, cli->proc_fd
|
||||
, pm.chan);
|
||||
pubsubd_channels_subscribe (chans
|
||||
, pm.chan, cli);
|
||||
}
|
||||
|
||||
if (pm.type == PUBSUB_MSG_TYPE_UNSUB) {
|
||||
printf ("client %d unsubscribing to %s\n", cli->proc_fd, pm.chan);
|
||||
pubsubd_channels_unsubscribe (chans, pm.chan, cli);
|
||||
}
|
||||
|
||||
if (pm.type == PUBSUB_MSG_TYPE_PUB) {
|
||||
// printf ("client %d: publishing to %s: %s\n", cli->proc_fd, pm.chan, pm.data);
|
||||
printf ("client %d: ", cli->proc_fd);
|
||||
pubsub_message_print (&pm);
|
||||
|
||||
struct channel *chan = pubsubd_channel_search (chans, pm.chan);
|
||||
if (chan == NULL) {
|
||||
handle_err ("handle_new_msg", "publish on nonexistent channel");
|
||||
ipc_message_empty (m);
|
||||
continue;
|
||||
}
|
||||
pubsubd_send (chan->subs, &pm);
|
||||
}
|
||||
|
||||
pubsub_message_empty (&pm);
|
||||
};
|
||||
break;
|
||||
case IPC_EVENT_TYPE_ERROR:
|
||||
{
|
||||
fprintf (stderr, "a problem happened with client %d\n"
|
||||
, ((struct ipc_client*) event.origin)->proc_fd);
|
||||
};
|
||||
break;
|
||||
default :
|
||||
{
|
||||
fprintf (stderr, "there must be a problem, event not set\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < clients.size; i++) {
|
||||
if (ipc_server_close_client (clients.clients[i]) < 0) {
|
||||
handle_error( "server_close_client < 0");
|
||||
}
|
||||
}
|
||||
|
||||
pubsubd_channels_del_all (chans);
|
||||
}
|
||||
|
||||
void handle_signal (int signalnumber)
|
||||
{
|
||||
// the application will shut down, and remove the service named pipe
|
||||
if (ipc_server_close (&srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
|
||||
pubsubd_channels_del_all (&chans);
|
||||
|
||||
fprintf (stderr, "received a signal %d\n", signalnumber);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv, char **env)
|
||||
{
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
// set the service
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
signal(SIGHUP, handle_signal);
|
||||
signal(SIGINT, handle_signal);
|
||||
signal(SIGQUIT, handle_signal);
|
||||
|
||||
// set the channels
|
||||
memset (&chans, 0, sizeof (struct channels));
|
||||
pubsubd_channels_init (&chans);
|
||||
|
||||
if (ipc_server_init (env, &srv, PUBSUBD_SERVICE_NAME) < 0) {
|
||||
handle_error("ipc_server_init < 0");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf ("Listening on %s.\n", srv.spath);
|
||||
|
||||
printf("MAIN: server created\n" );
|
||||
|
||||
// the service will loop until the end of time, a specific message, a signal
|
||||
pubsubd_main_loop (&srv, &chans);
|
||||
|
||||
// the application will shut down, and remove the service named pipe
|
||||
if (ipc_server_close (&srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../core/error.h"
|
||||
#include "../../core/client.h"
|
||||
|
||||
#include "channels.h"
|
||||
|
||||
void pubsubd_channel_print (const struct channel *chan)
|
||||
{
|
||||
if (chan->chan == NULL) {
|
||||
handle_err ("pubsubd_channel_print", "chan->chan == NULL");
|
||||
}
|
||||
|
||||
printf ( "\033[32mchan %s\033[00m\n", chan->chan);
|
||||
|
||||
if (chan->subs == NULL) {
|
||||
handle_err ("pubsubd_channel_print", "chan->subs == NULL");
|
||||
}
|
||||
else {
|
||||
ipc_clients_print (chan->subs);
|
||||
}
|
||||
}
|
||||
|
||||
void pubsubd_channels_print (const struct channels *chans)
|
||||
{
|
||||
printf ("\033[36mmchannels\033[00m\n");
|
||||
|
||||
if (chans == NULL) {
|
||||
handle_err ("pubsubd_channels_print", "chans == NULL");
|
||||
return ;
|
||||
}
|
||||
|
||||
struct channel *chan = NULL;
|
||||
LIST_FOREACH(chan, chans, entries) {
|
||||
pubsubd_channel_print (chan);
|
||||
}
|
||||
}
|
||||
|
||||
void pubsubd_channels_init (struct channels *chans) { LIST_INIT(chans); }
|
||||
|
||||
struct channel * pubsubd_channels_add (struct channels *chans, const char *chan)
|
||||
{
|
||||
if(chans == NULL || chan == NULL) {
|
||||
handle_err ("pubsubd_channels_add", "chans == NULL or chan == NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct channel *n = malloc (sizeof (struct channel));
|
||||
memset (n, 0, sizeof (struct channel));
|
||||
pubsubd_channel_new (n, chan);
|
||||
|
||||
LIST_INSERT_HEAD(chans, n, entries);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void pubsubd_channels_del (struct channels *chans, struct channel *c)
|
||||
{
|
||||
struct channel *todel = pubsubd_channel_get (chans, c);
|
||||
if(todel != NULL) {
|
||||
pubsubd_channel_free (todel);
|
||||
LIST_REMOVE(todel, entries);
|
||||
free (todel);
|
||||
todel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void pubsubd_channels_del_all (struct channels *chans)
|
||||
{
|
||||
if (!chans)
|
||||
return;
|
||||
|
||||
struct channel *c = NULL;
|
||||
|
||||
while (!LIST_EMPTY(chans)) {
|
||||
c = LIST_FIRST(chans);
|
||||
LIST_REMOVE(c, entries);
|
||||
pubsubd_channel_free (c);
|
||||
free (c);
|
||||
c = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int pubsubd_channel_new (struct channel *c, const char * name)
|
||||
{
|
||||
if (c == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t nlen = (strlen (name) > BUFSIZ) ? BUFSIZ : strlen (name);
|
||||
|
||||
if (c->chan == NULL)
|
||||
c->chan = malloc (nlen +1);
|
||||
|
||||
memset (c->chan, 0, nlen +1);
|
||||
memcpy (c->chan, name, nlen);
|
||||
c->chanlen = nlen;
|
||||
|
||||
c->subs = malloc (sizeof (struct ipc_clients));
|
||||
memset (c->subs, 0, sizeof (struct ipc_clients));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pubsubd_channel_free (struct channel * c)
|
||||
{
|
||||
if (c == NULL)
|
||||
return;
|
||||
|
||||
if (c->chan != NULL) {
|
||||
free (c->chan);
|
||||
c->chan = NULL;
|
||||
}
|
||||
|
||||
if (c->subs != NULL) {
|
||||
ipc_clients_free (c->subs);
|
||||
free (c->subs);
|
||||
}
|
||||
}
|
||||
|
||||
struct channel * pubsubd_channel_search (struct channels *chans, char *chan)
|
||||
{
|
||||
struct channel * np = NULL;
|
||||
LIST_FOREACH(np, chans, entries) {
|
||||
// TODO debug
|
||||
// printf ("pubsubd_channel_search: %s (%ld) vs %s (%ld)\n"
|
||||
// , np->chan, np->chanlen, chan, strlen(chan));
|
||||
if (np->chanlen == strlen (chan)
|
||||
&& strncmp (np->chan, chan, np->chanlen) == 0) {
|
||||
// printf ("pubsubd_channel_search: FOUND\n");
|
||||
return np;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct channel * pubsubd_channel_get (struct channels *chans, struct channel *c)
|
||||
{
|
||||
struct channel * np = NULL;
|
||||
LIST_FOREACH(np, chans, entries) {
|
||||
if (pubsubd_channel_eq (np, c))
|
||||
return np;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pubsubd_channel_eq (const struct channel *c1, const struct channel *c2)
|
||||
{
|
||||
return c1->chanlen == c2->chanlen &&
|
||||
strncmp (c1->chan, c2->chan, c1->chanlen) == 0;
|
||||
}
|
||||
|
||||
void pubsubd_channel_subscribe (const struct channel *c, struct ipc_client *p)
|
||||
{
|
||||
ipc_client_add (c->subs, p);
|
||||
}
|
||||
|
||||
void pubsubd_channel_unsubscribe (const struct channel *c, struct ipc_client *p)
|
||||
{
|
||||
ipc_client_del (c->subs, p);
|
||||
}
|
||||
|
||||
void pubsubd_channels_subscribe (struct channels *chans
|
||||
, char *chname, struct ipc_client *p)
|
||||
{
|
||||
struct channel *chan = pubsubd_channel_search (chans, chname);
|
||||
if (chan == NULL) {
|
||||
printf ("chan %s non existent : creation\n", chname);
|
||||
chan = pubsubd_channels_add (chans, chname);
|
||||
}
|
||||
|
||||
pubsubd_channel_subscribe (chan, p);
|
||||
}
|
||||
|
||||
void pubsubd_channels_unsubscribe (struct channels *chans
|
||||
, char *chname, struct ipc_client *p)
|
||||
{
|
||||
struct channel *chan = pubsubd_channel_search (chans, chname);
|
||||
if (chan == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pubsubd_channel_unsubscribe (chan, p);
|
||||
}
|
||||
|
||||
void pubsubd_channels_unsubscribe_everywhere (struct channels *chans
|
||||
, struct ipc_client *p)
|
||||
{
|
||||
struct channel * chan = NULL;
|
||||
LIST_FOREACH(chan, chans, entries) {
|
||||
pubsubd_channel_unsubscribe (chan, p);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#ifndef __CHANNELS_H__
|
||||
#define __CHANNELS_H__
|
||||
|
||||
#include "../../core/ipc.h"
|
||||
|
||||
// head of the list
|
||||
LIST_HEAD(channels, channel);
|
||||
|
||||
// element of the list
|
||||
// channel : chan name + chan name length + a list of applications
|
||||
struct channel {
|
||||
char *chan;
|
||||
size_t chanlen;
|
||||
struct ipc_clients *subs;
|
||||
LIST_ENTRY(channel) entries;
|
||||
};
|
||||
|
||||
// simple channel
|
||||
int pubsubd_channel_new (struct channel *c, const char *name);
|
||||
struct channel * pubsubd_channel_get (struct channels *chans, struct channel *c);
|
||||
void pubsubd_channel_free (struct channel *c);
|
||||
int pubsubd_channel_eq (const struct channel *c1, const struct channel *c2);
|
||||
void pubsubd_channel_print (const struct channel *c);
|
||||
|
||||
// list of channels
|
||||
void pubsubd_channels_init (struct channels *chans);
|
||||
void pubsubd_channels_print (const struct channels *chans);
|
||||
struct channel * pubsubd_channels_add (struct channels *chans, const char *chan);
|
||||
void pubsubd_channels_del (struct channels *chans, struct channel *c);
|
||||
void pubsubd_channels_del_all (struct channels *chans);
|
||||
struct channel * pubsubd_channel_search (struct channels *chans, char *chan);
|
||||
|
||||
// add and remove subscribers
|
||||
void pubsubd_channel_subscribe (const struct channel *c, struct ipc_client *p);
|
||||
void pubsubd_channel_unsubscribe (const struct channel *c, struct ipc_client *p);
|
||||
|
||||
void pubsubd_channels_subscribe (struct channels *chans
|
||||
, char *chname, struct ipc_client *p);
|
||||
void pubsubd_channels_unsubscribe (struct channels *chans
|
||||
, char *chname, struct ipc_client *p);
|
||||
|
||||
void pubsubd_channels_unsubscribe_everywhere (struct channels *chans
|
||||
, struct ipc_client *p);
|
||||
|
||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // strndup, strncpy
|
||||
|
||||
#include "message.h"
|
||||
|
||||
void pubsub_message_set_data (struct pubsub_msg *pm, char *data, size_t len)
|
||||
{
|
||||
pm->datalen = len;
|
||||
if (pm->data != NULL) {
|
||||
free (pm->data);
|
||||
}
|
||||
pm->data = malloc (len + 1);
|
||||
memset (pm->data, 0, len);
|
||||
strncpy (pm->data, data, len);
|
||||
pm->data[len] = '\0';
|
||||
}
|
||||
|
||||
void pubsub_message_set_chan (struct pubsub_msg *pm, char *chan, size_t len)
|
||||
{
|
||||
pm->chanlen = len;
|
||||
if (pm->chan != NULL) {
|
||||
free (pm->chan);
|
||||
}
|
||||
pm->chan = malloc (len + 1);
|
||||
memset (pm->chan, 0, len);
|
||||
strncpy (pm->chan, chan, len);
|
||||
pm->chan[len] = '\0';
|
||||
}
|
||||
|
||||
void pubsub_message_from_message (struct pubsub_msg *pm, struct ipc_message *m)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
pubsub_message_empty (pm); // just in case
|
||||
|
||||
pm->type = m->type;
|
||||
|
||||
// chan
|
||||
memcpy (&pm->chanlen, m->payload + offset, sizeof (size_t));
|
||||
if (pm->chanlen > BUFSIZ) {
|
||||
handle_err ("pubsub_message_from_message", "chanlen > BUFSIZ");
|
||||
return;
|
||||
}
|
||||
offset += sizeof (size_t);
|
||||
if (pm->chanlen > 0) {
|
||||
pubsub_message_set_chan (pm, m->payload + offset, pm->chanlen);
|
||||
offset += pm->chanlen;
|
||||
}
|
||||
|
||||
// data
|
||||
memcpy (&pm->datalen, m->payload + offset, sizeof (size_t));
|
||||
if (pm->datalen > BUFSIZ) {
|
||||
handle_err ("pubsub_message_from_message", "chanlen > BUFSIZ");
|
||||
return;
|
||||
}
|
||||
offset += sizeof (size_t);
|
||||
if (pm->datalen > 0) {
|
||||
pubsub_message_set_data (pm, m->payload + offset, pm->datalen);
|
||||
offset += pm->datalen;
|
||||
}
|
||||
}
|
||||
|
||||
void pubsub_message_to_message (const struct pubsub_msg *msg, struct ipc_message *m)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("pubsub_message_to_message", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m == NULL) {
|
||||
handle_err ("pubsub_message_to_message", "data == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
ipc_message_empty (m); // just in case
|
||||
|
||||
size_t buflen = 2 * sizeof (size_t) + msg->chanlen + msg->datalen;
|
||||
|
||||
if (buflen > BUFSIZ) {
|
||||
handle_err ("pubsub_message_serialize", "chanlen + datalen too high");
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf = malloc (buflen);
|
||||
memset (buf, 0, buflen);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
m->type = msg->type;
|
||||
|
||||
// chan
|
||||
memcpy (buf + offset, &msg->chanlen, sizeof (size_t));
|
||||
offset += sizeof (size_t);
|
||||
memcpy (buf + offset, msg->chan, msg->chanlen);
|
||||
offset += msg->chanlen;
|
||||
|
||||
// data
|
||||
memcpy (buf + offset, &msg->datalen, sizeof (size_t));
|
||||
offset += sizeof (size_t);
|
||||
memcpy (buf + offset, msg->data, msg->datalen);
|
||||
offset += msg->datalen;
|
||||
|
||||
m->payload = buf;
|
||||
m->length = buflen;
|
||||
}
|
||||
|
||||
void pubsub_message_empty (struct pubsub_msg *msg)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("pubsub_message_empty", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->chan != NULL) {
|
||||
free (msg->chan);
|
||||
msg->chan = NULL;
|
||||
}
|
||||
|
||||
if (msg->data != NULL) {
|
||||
free (msg->data);
|
||||
msg->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void pubsub_message_print (const struct pubsub_msg *pm)
|
||||
{
|
||||
if (pm == NULL) {
|
||||
handle_err ("pubsub_message_print", "pm == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pm->chanlen > 0 && pm->datalen > 0) {
|
||||
printf ("msg: type: %u, chan: %s (%lu bytes), data: %s (%lu bytes)\n"
|
||||
, pm->type, pm->chan, pm->chanlen, pm->data, pm->datalen);
|
||||
} else if (pm->chanlen > 0) {
|
||||
printf ("msg: type: %u, chan: %s (%lu bytes), and no data\n"
|
||||
, pm->type, pm->chan, pm->chanlen);
|
||||
} else if (pm->datalen > 0) {
|
||||
printf ("msg: type: %u, no chan, data: %s (%lu bytes)\n"
|
||||
, pm->type, pm->data, pm->datalen);
|
||||
}
|
||||
}
|
||||
|
||||
int pubsub_message_send (struct ipc_service *srv, const struct pubsub_msg * pm)
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
pubsub_message_to_message (pm, &m);
|
||||
ipc_application_write (srv, &m);
|
||||
ipc_message_empty (&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * pubsub_action_to_str (enum subscriber_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case PUBSUB_PUB : return strdup (PUBSUB_SUBSCRIBER_ACTION_STR_PUB);
|
||||
case PUBSUB_SUB : return strdup (PUBSUB_SUBSCRIBER_ACTION_STR_SUB);
|
||||
default : return strdup ("undocumented action");
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef __PUBSUB_MSG_H__
|
||||
#define __PUBSUB_MSG_H__
|
||||
|
||||
#include "../../core/ipc.h"
|
||||
|
||||
#define PUBSUB_SUBSCRIBER_ACTION_STR_PUB "pub"
|
||||
#define PUBSUB_SUBSCRIBER_ACTION_STR_SUB "sub"
|
||||
|
||||
enum subscriber_action {PUBSUB_PUB, PUBSUB_SUB};
|
||||
|
||||
#define PUBSUB_TYPE_MESSAGE 1
|
||||
#define PUBSUB_TYPE_ERROR 2
|
||||
#define PUBSUB_TYPE_DEBUG 4
|
||||
#define PUBSUB_TYPE_INFO 5
|
||||
|
||||
enum pubsub_message_types {
|
||||
PUBSUB_MSG_TYPE_SUB
|
||||
, PUBSUB_MSG_TYPE_UNSUB
|
||||
, PUBSUB_MSG_TYPE_PUB
|
||||
};
|
||||
|
||||
struct pubsub_msg {
|
||||
enum pubsub_message_types type; // message type : alert, notification, …
|
||||
char *chan;
|
||||
size_t chanlen;
|
||||
char *data;
|
||||
size_t datalen;
|
||||
};
|
||||
|
||||
void pubsub_message_from_message (struct pubsub_msg *msg, struct ipc_message *m);
|
||||
void pubsub_message_to_message (const struct pubsub_msg *msg, struct ipc_message *m);
|
||||
|
||||
void pubsub_message_set_chan (struct pubsub_msg *pm, char *chan, size_t len);
|
||||
void pubsub_message_set_data (struct pubsub_msg *pm, char *data, size_t len);
|
||||
|
||||
void pubsub_message_empty (struct pubsub_msg *msg);
|
||||
void pubsub_message_print (const struct pubsub_msg *msg);
|
||||
|
||||
int pubsub_message_send (struct ipc_service *srv, const struct pubsub_msg * m);
|
||||
|
||||
#endif
|
|
@ -1,168 +0,0 @@
|
|||
#if 0
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../core/error.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
// WORKERS: one thread per client
|
||||
|
||||
void pubsubd_workers_init (struct workers *wrkrs) { LIST_INIT(wrkrs); }
|
||||
|
||||
struct worker * pubsubd_workers_add (struct workers *wrkrs, const struct worker *w)
|
||||
{
|
||||
if (wrkrs == NULL || w == NULL) {
|
||||
printf ("pubsubd_workers_add: wrkrs == NULL or w == NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct worker *n = malloc (sizeof (struct worker));
|
||||
memset (n, 0, sizeof (struct worker));
|
||||
memcpy (n, w, sizeof (struct worker));
|
||||
if (w->ale != NULL)
|
||||
n->ale = pubsubd_subscriber_copy (w->ale);
|
||||
|
||||
LIST_INSERT_HEAD(wrkrs, n, entries);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void pubsubd_worker_del (struct workers *wrkrs, struct worker *w)
|
||||
{
|
||||
struct worker *todel = pubsubd_worker_get (wrkrs, w);
|
||||
if(todel != NULL) {
|
||||
LIST_REMOVE(todel, entries);
|
||||
pubsubd_worker_free (todel);
|
||||
free (todel);
|
||||
todel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// kill the threads
|
||||
void pubsubd_workers_stop (struct workers *wrkrs)
|
||||
{
|
||||
if (!wrkrs)
|
||||
return;
|
||||
|
||||
struct worker *w = NULL;
|
||||
struct worker *wtmp = NULL;
|
||||
|
||||
LIST_FOREACH_SAFE(w, wrkrs, entries, wtmp) {
|
||||
if (w->thr == NULL)
|
||||
continue;
|
||||
|
||||
pthread_cancel (*w->thr);
|
||||
void *ret = NULL;
|
||||
pthread_join (*w->thr, &ret);
|
||||
if (ret != NULL) {
|
||||
free (ret);
|
||||
}
|
||||
free (w->thr);
|
||||
w->thr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void pubsubd_workers_del_all (struct workers *wrkrs)
|
||||
{
|
||||
if (!wrkrs)
|
||||
return;
|
||||
|
||||
struct worker *w = NULL;
|
||||
|
||||
while (!LIST_EMPTY(wrkrs)) {
|
||||
printf ("KILL THE WORKERS : %p\n", w);
|
||||
w = LIST_FIRST(wrkrs);
|
||||
LIST_REMOVE(w, entries);
|
||||
pubsubd_worker_free (w);
|
||||
free (w);
|
||||
w = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void pubsubd_worker_free (struct worker * w)
|
||||
{
|
||||
if (w == NULL)
|
||||
return;
|
||||
pubsubd_subscriber_free (w->ale);
|
||||
free (w->ale);
|
||||
w->ale = NULL;
|
||||
}
|
||||
|
||||
struct worker * pubsubd_worker_get (struct workers *wrkrs, struct worker *w)
|
||||
{
|
||||
struct worker * np = NULL;
|
||||
LIST_FOREACH(np, wrkrs, entries) {
|
||||
if (pubsubd_worker_eq (np, w))
|
||||
return np;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pubsubd_worker_eq (const struct worker *w1, const struct worker *w2)
|
||||
{
|
||||
return w1 == w2; // if it's the same pointer
|
||||
}
|
||||
|
||||
// a thread for each connected client
|
||||
void * pubsubd_worker_thread (void *params)
|
||||
{
|
||||
int s = 0;
|
||||
|
||||
s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
if (s != 0)
|
||||
printf ("pthread_setcancelstate: %d\n", s);
|
||||
|
||||
struct worker *w = (struct worker *) params;
|
||||
if (w == NULL) {
|
||||
fprintf (stderr, "error pubsubd_worker_thread : params NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct channels *chans = w->chans;
|
||||
struct channel *chan = w->chan;
|
||||
struct subscriber *ale = w->ale;
|
||||
|
||||
// main loop
|
||||
while (1) {
|
||||
struct pubsub_msg m;
|
||||
memset (&m, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
pubsub_message_recv (ale->p, &m);
|
||||
|
||||
if (m.type == PUBSUB_TYPE_DISCONNECT) {
|
||||
// printf ("client %d disconnecting...\n", ale->p->pid);
|
||||
if ( 0 != pubsubd_subscriber_del (chan->alh, ale)) {
|
||||
fprintf (stderr, "err : subscriber not registered\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
struct channel *ch = pubsubd_channel_search (chans, chan->chan);
|
||||
if (ch == NULL) {
|
||||
printf ("CHAN NOT FOUND\n");
|
||||
}
|
||||
else {
|
||||
printf ("what should be sent: ");
|
||||
pubsub_message_print (&m);
|
||||
printf ("send the message to:\t");
|
||||
pubsubd_channel_print (ch);
|
||||
pubsub_message_send (ch->alh, &m);
|
||||
}
|
||||
}
|
||||
pubsub_message_free (&m);
|
||||
}
|
||||
|
||||
pubsubd_subscriber_free (ale);
|
||||
free (w->ale);
|
||||
w->ale = NULL;
|
||||
|
||||
free (w->thr);
|
||||
w->thr = NULL;
|
||||
|
||||
pubsubd_worker_del (w->my_workers, w);
|
||||
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
#if 0
|
||||
#ifndef __WORKERS_H__
|
||||
#define __WORKERS_H__
|
||||
|
||||
// WORKERS: one thread per client
|
||||
|
||||
// head of the list
|
||||
LIST_HEAD(workers, worker);
|
||||
|
||||
// element of the list
|
||||
// worker : client to handle (threaded)
|
||||
struct worker {
|
||||
pthread_t *thr;
|
||||
struct workers *my_workers;
|
||||
struct channels *chans;
|
||||
struct channel *chan;
|
||||
struct subscriber *ale;
|
||||
LIST_ENTRY(worker) entries;
|
||||
};
|
||||
|
||||
void pubsubd_worker_free (struct worker * w);
|
||||
struct worker * pubsubd_worker_get (struct workers *wrkrs, struct worker *w);
|
||||
int pubsubd_worker_eq (const struct worker *w1, const struct worker *w2);
|
||||
void pubsubd_workers_init (struct workers *wrkrs);
|
||||
void * pubsubd_worker_thread (void *params);
|
||||
struct worker * pubsubd_workers_add (struct workers *wrkrs, const struct worker *w);
|
||||
void pubsubd_workers_del_all (struct workers *wrkrs);
|
||||
void pubsubd_workers_stop (struct workers *wrkrs);
|
||||
void pubsubd_worker_del (struct workers *wrkrs, struct worker *w);
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../lib/*.c ../../core/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
|
@ -1,152 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lib/channels.h"
|
||||
#include "../../core/error.h"
|
||||
|
||||
void fake_client (struct ipc_client *p
|
||||
, unsigned int index, unsigned int version, int fake_fd)
|
||||
{
|
||||
p->version = version;
|
||||
p->index = index;
|
||||
p->proc_fd = fake_fd;
|
||||
}
|
||||
|
||||
void phase1 ()
|
||||
{
|
||||
struct channel chan1;
|
||||
memset (&chan1, 0, sizeof (struct channel));
|
||||
pubsubd_channel_new (&chan1, "chan1");
|
||||
|
||||
struct channel chan2;
|
||||
memset (&chan2, 0, sizeof (struct channel));
|
||||
pubsubd_channel_new (&chan2, "chan2");
|
||||
|
||||
printf ("chan1:");
|
||||
pubsubd_channel_print (&chan1);
|
||||
|
||||
printf ("chan2:");
|
||||
pubsubd_channel_print (&chan2);
|
||||
|
||||
pubsubd_channel_free (&chan1);
|
||||
pubsubd_channel_free (&chan2);
|
||||
}
|
||||
|
||||
void phase2 ()
|
||||
{
|
||||
struct channel chan1;
|
||||
memset (&chan1, 0, sizeof (struct channel));
|
||||
pubsubd_channel_new (&chan1, "chan1");
|
||||
|
||||
struct channel chan2;
|
||||
memset (&chan2, 0, sizeof (struct channel));
|
||||
pubsubd_channel_new (&chan2, "chan1");
|
||||
|
||||
printf ("chan1:");
|
||||
pubsubd_channel_print (&chan1);
|
||||
|
||||
printf ("chan2:");
|
||||
pubsubd_channel_print (&chan2);
|
||||
|
||||
if (pubsubd_channel_eq (&chan1, &chan2)) {
|
||||
printf ("chan1 == chan2\n");
|
||||
}
|
||||
else {
|
||||
handle_err ("phase2", "pubsubd_channel_eq (&chan1, &chan2) == 0");
|
||||
}
|
||||
|
||||
pubsubd_channel_free (&chan1);
|
||||
pubsubd_channel_free (&chan2);
|
||||
}
|
||||
|
||||
void phase3 ()
|
||||
{
|
||||
struct channels chans;
|
||||
memset (&chans, 0, sizeof (struct channels));
|
||||
|
||||
pubsubd_channels_init (&chans);
|
||||
struct channel * chan1 = pubsubd_channels_add (&chans, "chan1");
|
||||
struct channel * chan2 = pubsubd_channels_add (&chans, "chan2");
|
||||
pubsubd_channels_print (&chans);
|
||||
pubsubd_channels_del (&chans, chan1);
|
||||
pubsubd_channels_print (&chans);
|
||||
pubsubd_channels_del (&chans, chan2);
|
||||
pubsubd_channels_print (&chans);
|
||||
}
|
||||
|
||||
void phase4 ()
|
||||
{
|
||||
struct channels chans;
|
||||
memset (&chans, 0, sizeof (struct channels));
|
||||
|
||||
pubsubd_channels_init (&chans);
|
||||
struct channel * chan1 = pubsubd_channels_add (&chans, "chan1");
|
||||
struct channel * chan2 = pubsubd_channels_add (&chans, "chan2");
|
||||
|
||||
struct ipc_client proc1;
|
||||
fake_client (&proc1, 0, 0, 1);
|
||||
|
||||
struct ipc_client proc2;
|
||||
fake_client (&proc2, 0, 0, 2);
|
||||
|
||||
printf ("chan1: proc1, chan2: proc2\n");
|
||||
pubsubd_channel_subscribe (chan1, &proc1);
|
||||
pubsubd_channel_subscribe (chan2, &proc2);
|
||||
|
||||
pubsubd_channels_print (&chans);
|
||||
pubsubd_channels_del_all (&chans);
|
||||
|
||||
printf ("channels removed\n");
|
||||
pubsubd_channels_print (&chans);
|
||||
}
|
||||
|
||||
void phase5 ()
|
||||
{
|
||||
struct channels chans;
|
||||
memset (&chans, 0, sizeof (struct channels));
|
||||
|
||||
pubsubd_channels_init (&chans);
|
||||
pubsubd_channels_add (&chans, "chan1");
|
||||
pubsubd_channels_add (&chans, "chan2");
|
||||
|
||||
struct ipc_client proc1;
|
||||
fake_client (&proc1, 0, 0, 1);
|
||||
|
||||
struct ipc_client proc2;
|
||||
fake_client (&proc2, 0, 0, 2);
|
||||
|
||||
printf ("chan1 & 2 => proc1 and 2 added\n");
|
||||
pubsubd_channels_subscribe (&chans, "chan1", &proc1);
|
||||
pubsubd_channels_subscribe (&chans, "chan1", &proc2);
|
||||
|
||||
pubsubd_channels_subscribe (&chans, "chan2", &proc1);
|
||||
pubsubd_channels_subscribe (&chans, "chan2", &proc2);
|
||||
|
||||
pubsubd_channels_print (&chans);
|
||||
|
||||
printf ("chan1 => proc1 removed\n");
|
||||
pubsubd_channels_unsubscribe (&chans, "chan1", &proc1);
|
||||
|
||||
pubsubd_channels_print (&chans);
|
||||
pubsubd_channels_del_all (&chans);
|
||||
|
||||
printf ("channels removed\n");
|
||||
pubsubd_channels_print (&chans);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
// phase1(); // new + print + free
|
||||
// phase2(); // new + print + eq + free
|
||||
|
||||
// channels
|
||||
// phase3(); // channels init + add + print + del
|
||||
// phase4(); // channels del_all + channel subscribe
|
||||
phase5(); // channels del_all + channels subscribe + unsubscribe
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lib/message.h"
|
||||
#include "../../core/error.h"
|
||||
#include "../../core/utils.h"
|
||||
|
||||
#define CHAN "chan1"
|
||||
#define DATA "hello chan1"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
argc = argc;
|
||||
argv = argv;
|
||||
|
||||
struct pubsub_msg msg;
|
||||
memset (&msg, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
msg.type = 8;
|
||||
|
||||
msg.chanlen = strlen (CHAN) + 1;
|
||||
msg.chan = malloc (msg.chanlen);
|
||||
memset (msg.chan, 0, msg.chanlen);
|
||||
memcpy (msg.chan, CHAN, msg.chanlen);
|
||||
|
||||
msg.datalen = strlen (DATA) + 1;
|
||||
msg.data = malloc (msg.datalen);
|
||||
memset (msg.data, 0, msg.datalen);
|
||||
memcpy (msg.data, DATA, msg.datalen);
|
||||
|
||||
printf ("msg 1: ");
|
||||
pubsub_message_print (&msg);
|
||||
|
||||
char *buffer = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
pubsub_message_serialize (&msg, &buffer, &len);
|
||||
mprint_hexa ("buffer msg 1", (unsigned char *) buffer, len);
|
||||
|
||||
struct pubsub_msg msg2;
|
||||
memset (&msg2, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
pubsub_message_unserialize (&msg2, buffer, len);
|
||||
|
||||
printf ("msg 2: ");
|
||||
pubsub_message_print (&msg2);
|
||||
|
||||
pubsub_message_free (&msg);
|
||||
pubsub_message_free (&msg2);
|
||||
|
||||
if (buffer != NULL)
|
||||
free (buffer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
int main() { return 0; }
|
||||
|
||||
#if 0
|
||||
#include "../lib/pubsubd.h"
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MYMESSAGE "coucou"
|
||||
|
||||
void
|
||||
ohshit(int rvalue, const char* str) {
|
||||
fprintf (stderr, "\033[31merr: %s\033[00m\n", str);
|
||||
exit (rvalue);
|
||||
}
|
||||
|
||||
void usage (char **argv)
|
||||
{
|
||||
printf ( "usage : %s pid index (pub|sub|both|quit) [chan]\n", argv[0]);
|
||||
}
|
||||
|
||||
void sim_connection (int argc, char **argv, char **env, pid_t pid, int index, int version, char *cmd, char *chan)
|
||||
{
|
||||
printf ("Simulate connection : pid %d index %d version %d "
|
||||
"cmd %s chan %s\n"
|
||||
, pid, index, version, cmd, chan );
|
||||
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
ipc_server_init (argc, argv, env, &srv, PUBSUB_SERVICE_NAME, NULL);
|
||||
printf ("Writing on %s.\n", srv.spath);
|
||||
|
||||
struct ipc_client p;
|
||||
memset (&p, 0, sizeof (struct ipc_client));
|
||||
|
||||
printf ("app creation\n");
|
||||
if (application_create (&p, pid, index, version)) // called by the application
|
||||
ohshit (1, "application_create");
|
||||
|
||||
printf ("connection\n");
|
||||
// send a message to warn the service we want to do something
|
||||
// line : pid index version action chan
|
||||
pubsub_connection (&srv, &p, PUBSUB_PUB, chan);
|
||||
|
||||
struct pubsub_msg m;
|
||||
memset (&m, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
if (strcmp (cmd, "pub") == 0) {
|
||||
// first message, "coucou"
|
||||
m.type = PUBSUB_TYPE_MESSAGE;
|
||||
m.chan = malloc (strlen (chan) + 1);
|
||||
memset (m.chan, 0, strlen (chan) + 1);
|
||||
m.chan[strlen (chan)] = '\0';
|
||||
m.chanlen = strlen (chan);
|
||||
|
||||
m.data = malloc (strlen (MYMESSAGE) + 1);
|
||||
memset (m.data, 0, strlen (MYMESSAGE) + 1);
|
||||
strncpy ((char *) m.data, MYMESSAGE, strlen (MYMESSAGE) + 1);
|
||||
m.datalen = strlen (MYMESSAGE);
|
||||
|
||||
printf ("send message\n");
|
||||
pubsub_message_send (&p, &m);
|
||||
}
|
||||
else {
|
||||
pubsub_message_recv (&p, &m);
|
||||
pubsubd_message_print (&m);
|
||||
}
|
||||
|
||||
// free everything
|
||||
pubsubd_message_free (&m);
|
||||
|
||||
printf ("disconnection\n");
|
||||
// disconnect from the server
|
||||
pubsub_disconnect (&p);
|
||||
|
||||
printf ("destroying app\n");
|
||||
// the application will shut down, and remove the application named pipes
|
||||
if (application_destroy (&p))
|
||||
ohshit (1, "application_destroy");
|
||||
}
|
||||
|
||||
void sim_disconnection (int argc, char **argv, char **env, pid_t pid, int index, int version)
|
||||
{
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
ipc_server_init (argc, argv, env, &srv, PUBSUB_SERVICE_NAME, NULL);
|
||||
printf ("Disconnecting from %s.\n", srv.spath);
|
||||
|
||||
struct ipc_client p;
|
||||
memset (&p, 0, sizeof (struct ipc_client));
|
||||
|
||||
// create the fake client
|
||||
ipc_server_client_gen (&p, pid, index, version);
|
||||
|
||||
// send a message to disconnect
|
||||
// line : pid index version action chan
|
||||
pubsub_disconnect (&p);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv, char **env)
|
||||
{
|
||||
|
||||
if (argc < 3) {
|
||||
usage (argv);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pid_t pid = 0;
|
||||
pid = atol(argv[1]);
|
||||
|
||||
int index = 0;
|
||||
index = atoi (argv[2]);
|
||||
|
||||
// don't care about the version
|
||||
int version = COMMUNICATION_VERSION;
|
||||
|
||||
char * cmd = NULL;
|
||||
cmd = argv[3];
|
||||
|
||||
if (strcmp(cmd, "quit") != 0) {
|
||||
char *chan = NULL;
|
||||
chan = argv[4];
|
||||
sim_connection (argc, argv, env, pid, index, version, cmd, chan);
|
||||
}
|
||||
else {
|
||||
sim_disconnection (argc, argv, env, pid, index, version);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
int main() { return 0; }
|
||||
|
||||
#if 0
|
||||
#include "../lib/pubsubd.h"
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MYMESSAGE "coucou"
|
||||
#define MYCHAN "chan1"
|
||||
|
||||
void
|
||||
ohshit(int rvalue, const char* str) {
|
||||
fprintf (stderr, "\033[31merr: %s\033[00m\n", str);
|
||||
exit (rvalue);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv, char **env)
|
||||
{
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
ipc_server_init (argc, argv, env, &srv, PUBSUB_SERVICE_NAME, NULL);
|
||||
printf ("Writing on %s.\n", srv.spath);
|
||||
|
||||
struct ipc_client p;
|
||||
memset (&p, 0, sizeof (struct ipc_client));
|
||||
int index = 1;
|
||||
|
||||
pid_t pid = getpid();
|
||||
|
||||
if (application_create (&p, pid, index, COMMUNICATION_VERSION))
|
||||
ohshit (1, "application_create");
|
||||
|
||||
// send a message to warn the service we want to do something
|
||||
// line : pid index version action chan
|
||||
pubsub_connection (&srv, &p, PUBSUB_PUB, MYCHAN);
|
||||
|
||||
struct pubsub_msg m;
|
||||
memset (&m, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
// first message, "coucou"
|
||||
m.type = PUBSUB_TYPE_INFO;
|
||||
m.chan = malloc (strlen (MYCHAN));
|
||||
m.chanlen = strlen (MYCHAN);
|
||||
m.data = malloc (strlen (MYMESSAGE));
|
||||
m.datalen = strlen (MYMESSAGE);
|
||||
pubsub_message_send (&p, &m);
|
||||
|
||||
// second message, to disconnect from the server
|
||||
m.type = PUBSUB_TYPE_DISCONNECT;
|
||||
pubsub_message_send (&p, &m);
|
||||
|
||||
// free everything
|
||||
|
||||
pubsubd_message_free (&m);
|
||||
|
||||
// the application will shut down, and remove the application named pipes
|
||||
if (application_destroy (&p))
|
||||
ohshit (1, "application_destroy");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Wextra
|
||||
LDFLAGS= -pthread
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../lib/*.c ../../core/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
|
@ -1,25 +0,0 @@
|
|||
# remoted
|
||||
|
||||
This service creates a path on the relevent remote location, going through anything network-related: TCP, UDP, HTTP, ...
|
||||
|
||||
# TODO
|
||||
|
||||
* authorizations
|
||||
* code the -d option
|
||||
|
||||
### authorizations
|
||||
|
||||
The idea is to have a simple configuration file for authentication of remote connections, such as:
|
||||
|
||||
table dynusers # dynamic user table
|
||||
|
||||
clients = { "client123", alice.example.com, john@doe.com }
|
||||
localclients = { pamuser1, <dynusers> }
|
||||
|
||||
level1services = { pongd, weather }
|
||||
|
||||
ifext = enp0s25
|
||||
pass in on $ifext from any for all to local services $level1services
|
||||
pass out on $ifext from local for $localclients to any services $level1services
|
||||
|
||||
block all
|
|
@ -1,121 +0,0 @@
|
|||
#include "../../core/communication.h"
|
||||
#include "../../core/error.h"
|
||||
#include "../lib/remoted.h"
|
||||
#include "../lib/remotec.h"
|
||||
#include "../lib/message.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* remoted test application
|
||||
*
|
||||
* this application can:
|
||||
* listen, given an URI (including a transport layer and eventually a port)
|
||||
* connect to a remote service through a tunnel
|
||||
* the remote service used for testing is pongd
|
||||
*
|
||||
* TODO: this test application is a work in progress
|
||||
* currently, this application will:
|
||||
* connect itself to the remoted service
|
||||
* hang up the connection with the remoted service
|
||||
*/
|
||||
|
||||
void usage (char **argv) {
|
||||
printf ( "usage: %s uri service\n", argv[0]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void * listener (void *params)
|
||||
{
|
||||
int s = 0;
|
||||
s = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
|
||||
if (s != 0) {
|
||||
handle_err ("listener", "pthread_setcancelstate != 0");
|
||||
}
|
||||
|
||||
struct ipc_service *srv = NULL;
|
||||
srv = (struct ipc_service *) params;
|
||||
if (srv == NULL) {
|
||||
handle_err ("listener", "no service passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// main loop
|
||||
while (1) {
|
||||
struct remoted_msg m;
|
||||
memset (&m, 0, sizeof (struct remoted_msg));
|
||||
|
||||
remote_message_recv (srv, &m);
|
||||
printf ("\r\033[31m>\033[00m %s\n", m.data);
|
||||
print_cmd ();
|
||||
|
||||
remote_message_free (&m);
|
||||
}
|
||||
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main_loop (int argc, char **argv, char **env
|
||||
, int index, int version, char *uri, char *service)
|
||||
{
|
||||
printf ("connection to remoted: index %d version %d uri %s service %s\n"
|
||||
, index, version, uri, service);
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
(void) env;
|
||||
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
|
||||
remotec_connection (argc, argv, env, &srv);
|
||||
log_debug ("remotec connected, entering main loop");
|
||||
|
||||
struct remoted_msg msg;
|
||||
memset (&msg, 0, sizeof (struct remoted_msg));
|
||||
|
||||
#if 0
|
||||
// msg loop
|
||||
for (;;) {
|
||||
char buf[BUFSIZ];
|
||||
memset (buf, 0, BUFSIZ);
|
||||
|
||||
/* TODO */
|
||||
msg.datalen = 5; // FIXME: take parameters into account
|
||||
msg.data = malloc (msg.datalen);
|
||||
memset (msg.data, 0, msg.datalen);
|
||||
strncpy ((char *) msg.data, "salut", msg.datalen);
|
||||
|
||||
/* TODO */
|
||||
remotec_message_send (&srv, &msg);
|
||||
free (msg.data);
|
||||
msg.data = NULL;
|
||||
msg.datalen = 0;
|
||||
}
|
||||
|
||||
// free everything
|
||||
remote_message_free (&msg);
|
||||
#endif
|
||||
|
||||
log_debug ("remotec disconnection...");
|
||||
// disconnect from the server
|
||||
remotec_disconnection (&srv);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
if (argc != 3) {
|
||||
usage (argv);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
int version = 0;
|
||||
|
||||
main_loop (argc, argv, env, index, version, argv[1], argv[2]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
#include "../../core/communication.h"
|
||||
#include "../../core/client.h"
|
||||
#include "../../core/error.h"
|
||||
#include "../lib/remoted.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../core/logger.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// to quit them properly if a signal occurs
|
||||
struct ipc_service srv;
|
||||
|
||||
void handle_signal (int signalnumber)
|
||||
{
|
||||
// the application will shut down, and remove the service unix socket
|
||||
if (ipc_server_close (&srv) < 0) {
|
||||
handle_error("ipc_server_close < 0");
|
||||
}
|
||||
|
||||
log_info ("remoted received a signal %d\n", signalnumber);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void usage ()
|
||||
{
|
||||
fprintf (stderr, "remoted [-d <unix-socket-dir>] [-h]\n");
|
||||
}
|
||||
|
||||
/* TODO: handle command line arguments */
|
||||
|
||||
// cmdline: remoted -d <unix-socket-dir>
|
||||
void remoted_cmd_args (int argc, char **argv, char **env
|
||||
, struct remoted_ctx *ctx)
|
||||
{
|
||||
(void) env;
|
||||
(void) ctx;
|
||||
|
||||
int c;
|
||||
while ( (c = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
ctx->unix_socket_dir = malloc (strlen (optarg) +1);
|
||||
strncpy (ctx->unix_socket_dir, optarg, strlen (optarg));
|
||||
log_debug ("remoted unix socket dir: %s", ctx->unix_socket_dir);
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
default:
|
||||
log_debug ("remoted getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
log_debug ("remoted non-option ARGV-elements:");
|
||||
while (optind < argc)
|
||||
log_debug ("\t%s", argv[optind++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: handle authorizations */
|
||||
int remoted_auth_conf (struct remoted_ctx *ctx)
|
||||
{
|
||||
(void) ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
struct remoted_ctx ctx;
|
||||
memset (&ctx, 0, sizeof (struct remoted_ctx));
|
||||
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
srv.index = 0;
|
||||
srv.version = 0;
|
||||
|
||||
signal(SIGHUP, handle_signal);
|
||||
signal(SIGINT, handle_signal);
|
||||
signal(SIGQUIT, handle_signal);
|
||||
|
||||
remoted_cmd_args (argc, argv, env, &ctx);
|
||||
|
||||
log_info ("remoted started");
|
||||
// load configuration
|
||||
if (remoted_auth_conf (&ctx)) {
|
||||
log_error ("remoted cannot load configuration");
|
||||
}
|
||||
else
|
||||
log_info ("remoted configuration loaded");
|
||||
|
||||
if (ipc_server_init (argc, argv, env, &srv, REMOTED_SERVICE_NAME) < 0) {
|
||||
handle_error("server_init < 0");
|
||||
}
|
||||
log_info ("remoted listening on %s", srv.spath);
|
||||
|
||||
// TODO: here comes pledge (openbsd)
|
||||
|
||||
// the service will loop until the end of time, a specific message, a signal
|
||||
remoted_main_loop (&srv, &ctx);
|
||||
|
||||
// the application will shut down, and remove the service unix socket
|
||||
if (ipc_server_close (&srv) < 0) {
|
||||
handle_error("server_close < 0");
|
||||
}
|
||||
log_info ("remoted ended");
|
||||
|
||||
remoted_free_ctx (&ctx);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "message.h"
|
||||
#include "../../core/error.h"
|
||||
|
||||
void remote_message_serialize (const struct remoted_msg *msg, char **data, size_t *len)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("remote remote_message_serialize", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == NULL) {
|
||||
handle_err ("remote remote_message_serialize", "data == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (*data != NULL) {
|
||||
handle_err ("remote remote_message_serialize", "*data != NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == NULL) {
|
||||
handle_err ("remote remote_message_serialize", "len == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
// buflen = remote msg type (1) + size_t (16) + data
|
||||
size_t buflen = 1 + sizeof (size_t) + msg->datalen;
|
||||
|
||||
if (buflen > BUFSIZ) {
|
||||
handle_err ("remote remote_message_serialize", "datalen too high");
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf = malloc (buflen);
|
||||
memset (buf, 0, buflen);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
// msg type
|
||||
buf[offset++] = msg->type;
|
||||
|
||||
// data
|
||||
memcpy (buf + offset, &msg->datalen, sizeof (size_t));
|
||||
offset += sizeof (size_t);
|
||||
memcpy (buf + offset, msg->data, msg->datalen);
|
||||
offset += msg->datalen;
|
||||
|
||||
*data = buf;
|
||||
*len = buflen;
|
||||
}
|
||||
|
||||
void remote_message_unserialize (struct remoted_msg *msg, const char *buf, size_t mlen)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("remote remote_message_unserialize", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
remote_message_free (msg);
|
||||
|
||||
if (mlen > BUFSIZ) {
|
||||
handle_err ("remote remote_message_unserialize", "mlen > BUFSIZ");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
// msg type
|
||||
msg->type = buf[offset++];
|
||||
|
||||
// data
|
||||
memcpy (&msg->datalen, buf + offset, sizeof (size_t));
|
||||
if (msg->datalen > BUFSIZ) {
|
||||
handle_err ("remote remote_message_unserialize", "datalen > BUFSIZ");
|
||||
return;
|
||||
}
|
||||
msg->data = malloc (msg->datalen);
|
||||
memset (msg->data, 0, msg->datalen);
|
||||
offset += sizeof (size_t);
|
||||
memcpy (msg->data, buf + offset, msg->datalen);
|
||||
offset += msg->datalen;
|
||||
}
|
||||
|
||||
void remote_message_free (struct remoted_msg *msg)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("remote remote_message_free", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->data) {
|
||||
free (msg->data);
|
||||
msg->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void remote_message_print (const struct remoted_msg *msg)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
handle_err ("remote remote_message_print", "msg == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("msg: type=%d data=%s\n", msg->type, msg->data);
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef __REMOTE_MSG_H__
|
||||
#define __REMOTE_MSG_H__
|
||||
|
||||
#define REMOTE_MSG_TYPE_CONNECT 1
|
||||
#define REMOTE_MSG_TYPE_LISTEN 2
|
||||
#define REMOTE_MSG_TYPE_PUB 3
|
||||
|
||||
struct remoted_msg {
|
||||
unsigned char type; // message types = commands (connect, listen, ...)
|
||||
char *data;
|
||||
size_t datalen;
|
||||
};
|
||||
|
||||
void remote_message_serialize (const struct remoted_msg *msg, char **data, size_t *len);
|
||||
void remote_message_unserialize (struct remoted_msg *msg, const char *data, size_t len);
|
||||
|
||||
void remote_message_free (struct remoted_msg *msg);
|
||||
void remote_message_print (const struct remoted_msg *msg);
|
||||
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
#include "../../core/communication.h"
|
||||
#include "../../core/error.h"
|
||||
#include "message.h"
|
||||
#include "remotec.h"
|
||||
#include "remoted.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int remotec_connection (int argc, char **argv, char **env, struct ipc_service *srv)
|
||||
{
|
||||
int ret = ipc_application_connection (argc, argv, env
|
||||
, srv, REMOTED_SERVICE_NAME, NULL, 0);
|
||||
|
||||
if (ret != 0) {
|
||||
handle_err ("remote remotec_connection", "application_connection != 0");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int remotec_disconnection (struct ipc_service *srv)
|
||||
{
|
||||
return ipc_application_close (srv);
|
||||
}
|
||||
|
||||
int remotec_message_send (struct ipc_service *srv, const struct remoted_msg * m)
|
||||
{
|
||||
size_t msize = 0;
|
||||
char * buf = NULL;
|
||||
remote_message_serialize (m, &buf, &msize);
|
||||
|
||||
struct ipc_message m_data;
|
||||
memset (&m_data, 0, sizeof (struct ipc_message));
|
||||
|
||||
// format the connection msg
|
||||
if (ipc_message_format_data (&m_data, buf, msize) < 0) {
|
||||
handle_err ("remotec_message_send", "ipc_message_format_data");
|
||||
if (buf != NULL)
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipc_application_write (srv, &m_data);
|
||||
ipc_message_free (&m_data);
|
||||
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remotec_message_recv (struct ipc_service *srv, struct remoted_msg *m)
|
||||
{
|
||||
if (srv == NULL) {
|
||||
handle_err ("remotec_message_recv", "srv == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m == NULL) {
|
||||
handle_err ("remotec_message_recv", "m == NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ipc_message m_recv;
|
||||
memset (&m_recv, 0, sizeof (struct ipc_message));
|
||||
|
||||
ipc_application_read (srv, &m_recv);
|
||||
remote_message_unserialize (m, m_recv.payload, m_recv.length);
|
||||
|
||||
ipc_message_free (&m_recv);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef __REMOTEC_H__
|
||||
#define __REMOTEC_H__
|
||||
|
||||
#include "../../core/client.h"
|
||||
#include "../../core/message.h"
|
||||
#include "remoted.h"
|
||||
|
||||
/* TODO */
|
||||
|
||||
int remotec_connection (int argc, char **argv, char **env, struct ipc_service *srv);
|
||||
int remotec_disconnection (struct ipc_service *srv);
|
||||
|
||||
int remotec_message_send (struct ipc_service *srv, const struct remoted_msg *msg);
|
||||
int remotec_message_recv (struct ipc_service *srv, struct remoted_msg *msg);
|
||||
|
||||
#endif
|
|
@ -1,149 +0,0 @@
|
|||
#include "../../core/communication.h"
|
||||
#include "../../core/message.h"
|
||||
#include "../../core/client.h"
|
||||
#include "../../core/utils.h"
|
||||
#include "../../core/error.h"
|
||||
#include "../../core/logger.h"
|
||||
|
||||
#include "remoted.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* new connection, once accepted the client is added to the array_proc
|
||||
* structure to be checked periodically for new messages
|
||||
*/
|
||||
void handle_new_connection (struct ipc_service *srv, struct ipc_clients *ap)
|
||||
{
|
||||
struct ipc_client *p = malloc(sizeof(struct ipc_client));
|
||||
memset(p, 0, sizeof(struct ipc_client));
|
||||
|
||||
if (ipc_server_accept (srv, p) < 0) {
|
||||
handle_error("ipc_server_accept < 0");
|
||||
} else {
|
||||
log_debug ("remoted, new connection", p->proc_fd);
|
||||
}
|
||||
|
||||
if (ipc_client_add (ap, p) < 0) {
|
||||
handle_error("ipc_client_add < 0");
|
||||
}
|
||||
}
|
||||
|
||||
void handle_new_msg (struct ipc_clients *ap, struct ipc_clients *proc_to_read)
|
||||
{
|
||||
struct ipc_message m;
|
||||
memset (&m, 0, sizeof (struct ipc_message));
|
||||
int i;
|
||||
for (i = 0; i < proc_to_read->size; i++) {
|
||||
if (ipc_server_read (proc_to_read->clients[i], &m) < 0) {
|
||||
handle_error("ipc_server_read < 0");
|
||||
}
|
||||
|
||||
mprint_hexa ("msg received: ", (unsigned char *) m.payload, m.length);
|
||||
|
||||
// close the client then delete it from the client array
|
||||
if (m.type == MSG_TYPE_CLOSE) {
|
||||
struct ipc_client *p = proc_to_read->clients[i];
|
||||
|
||||
log_debug ("remoted, client %d disconnecting", p->proc_fd);
|
||||
|
||||
// close the connection to the client
|
||||
if (ipc_server_close_client (p) < 0)
|
||||
handle_error( "ipc_server_close_client < 0");
|
||||
|
||||
// remove the client from the clientes list
|
||||
if (ipc_client_del (ap, p) < 0)
|
||||
handle_error( "ipc_client_del < 0");
|
||||
if (ipc_client_del (proc_to_read, p) < 0)
|
||||
handle_err( "handle_new_msg", "ipc_client_del < 0");
|
||||
|
||||
ipc_message_free (&m);
|
||||
|
||||
// free client
|
||||
free (p);
|
||||
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct pubsub_msg m_data;
|
||||
memset (&m_data, 0, sizeof (struct pubsub_msg));
|
||||
|
||||
pubsub_message_unserialize (&m_data, m.payload, m.length);
|
||||
|
||||
if (m_data.type == PUBSUB_MSG_TYPE_SUB) {
|
||||
printf ("client %d subscribing to %s\n"
|
||||
, proc_to_read->clients[i]->proc_fd
|
||||
, m_data.chan);
|
||||
pubsubd_channels_subscribe (chans
|
||||
, m_data.chan, proc_to_read->clients[i]);
|
||||
}
|
||||
|
||||
if (m_data.type == PUBSUB_MSG_TYPE_UNSUB) {
|
||||
printf ("client %d unsubscribing to %s\n"
|
||||
, proc_to_read->clients[i]->proc_fd
|
||||
, m_data.chan);
|
||||
pubsubd_channels_unsubscribe (chans
|
||||
, m_data.chan, proc_to_read->clients[i]);
|
||||
}
|
||||
|
||||
if (m_data.type == PUBSUB_MSG_TYPE_PUB) {
|
||||
printf ("client %d publishing to %s\n"
|
||||
, proc_to_read->clients[i]->proc_fd
|
||||
, m_data.chan);
|
||||
struct channel *chan = pubsubd_channel_search (chans, m_data.chan);
|
||||
if (chan == NULL) {
|
||||
handle_err ("handle_new_msg", "publish on nonexistent channel");
|
||||
ipc_message_free (&m);
|
||||
return ;
|
||||
}
|
||||
pubsubd_send (chan->subs, &m_data);
|
||||
}
|
||||
|
||||
pubsub_message_free (&m_data);
|
||||
#endif
|
||||
ipc_message_free (&m);
|
||||
}
|
||||
}
|
||||
|
||||
void remoted_main_loop (struct ipc_service *srv, struct remoted_ctx *ctx)
|
||||
{
|
||||
log_debug ("remoted entering main loop");
|
||||
int i, ret = 0;
|
||||
|
||||
struct ipc_clients ap;
|
||||
memset(&ap, 0, sizeof(struct ipc_clients));
|
||||
|
||||
struct ipc_clients proc_to_read;
|
||||
memset(&proc_to_read, 0, sizeof(struct ipc_clients));
|
||||
|
||||
while(1) {
|
||||
/* TODO: authorizations */
|
||||
ret = ipc_server_select (&ap, srv, &proc_to_read);
|
||||
|
||||
if (ret == CONNECTION) {
|
||||
handle_new_connection (srv, &ap);
|
||||
} else if (ret == APPLICATION) {
|
||||
handle_new_msg (&ap, &proc_to_read);
|
||||
} else { // both new connection and new msg from at least one client
|
||||
handle_new_connection (srv, &ap);
|
||||
handle_new_msg (&ap, &proc_to_read);
|
||||
}
|
||||
ipc_clients_free (&proc_to_read);
|
||||
}
|
||||
|
||||
for (i = 0; i < ap.size; i++) {
|
||||
if (ipc_server_close_client (ap.clients[i]) < 0) {
|
||||
handle_error( "ipc_server_close_client < 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remoted_free_ctx (struct remoted_ctx *ctx)
|
||||
{
|
||||
if (ctx->unix_socket_dir != NULL)
|
||||
free (ctx->unix_socket_dir), ctx->unix_socket_dir = NULL;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __REMOTED_H__
|
||||
#define __REMOTED_H__
|
||||
|
||||
#include "../../core/client.h"
|
||||
#include "../../core/message.h"
|
||||
#include "message.h"
|
||||
|
||||
#define REMOTED_SERVICE_NAME "remoted"
|
||||
|
||||
struct remoted_ctx {
|
||||
char * unix_socket_dir;
|
||||
/* TODO: authorizations */
|
||||
};
|
||||
|
||||
void remoted_main_loop (struct ipc_service *srv, struct remoted_ctx *ctx);
|
||||
void remoted_free_ctx (struct remoted_ctx *ctx);
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g
|
||||
LDFLAGS= -pthread
|
||||
CFILES=$(wildcard *.c) # CFILES => recompiles everything on a C file change
|
||||
EXEC=$(basename $(wildcard *.c))
|
||||
SOURCES=$(wildcard ../../lib/communication.c ../../lib/process.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
TESTS=$(addsuffix .test, $(EXEC))
|
||||
LCBOR=-lbor
|
||||
|
||||
all: $(SOURCES) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJECTS) $(CFILES)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -o $@.bin
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(TESTS):
|
||||
valgrind --show-leak-kinds=all --leak-check=full -v --track-origins=yes ./$(basename $@).bin
|
||||
|
||||
clean:
|
||||
@-rm $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@-rm *.bin
|
||||
|
||||
cleantmp:
|
||||
rm /tmp/ipc/*
|
799
tcp/app/tcpd.c
799
tcp/app/tcpd.c
|
@ -1,799 +0,0 @@
|
|||
#include "tcpd.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h> // mkfifo
|
||||
#include <linux/limits.h>
|
||||
|
||||
#define PORT 6000
|
||||
#define NBCLIENT 10
|
||||
#define SERVICE_TCP "tcpd"
|
||||
#define LISTEN_BACKLOG 50
|
||||
#define handle_error(msg) \
|
||||
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
|
||||
int init_connection(const info_request *req)
|
||||
{
|
||||
int yes = 1;
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//struct sockaddr_in sin = { 0 };
|
||||
|
||||
if(sock == -1)
|
||||
{
|
||||
perror("socket()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/*"address already in use" error message */
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
|
||||
{
|
||||
perror("Server-setsockopt() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Server-setsockopt() is OK...\n");
|
||||
|
||||
if(bind(sock,(struct sockaddr *) &req->addr, sizeof(req->addr)) == -1)
|
||||
{
|
||||
perror("bind()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if(listen(sock, 10) == -1)
|
||||
{
|
||||
perror("listen()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void write_message(int sock, const char *buffer, size_t size_buf)
|
||||
{
|
||||
if(send(sock, buffer, size_buf, 0) < 0)
|
||||
{
|
||||
perror("send()");
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
||||
int read_message(int sock, char *buffer)
|
||||
{
|
||||
return read(sock, buffer, BUFSIZ);
|
||||
}
|
||||
|
||||
void endConnection(int sock) {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void printAddr(struct sockaddr_in *csin) {
|
||||
printf("IP Addr : %s\n", inet_ntoa(csin->sin_addr));
|
||||
printf("Port : %u\n", ntohs(csin->sin_port));
|
||||
}
|
||||
|
||||
/*
|
||||
* Chaque client correspond à un thread service
|
||||
* Le 1er message du client indiquera le service voulu et sa version
|
||||
* Etablir la connection avec le service
|
||||
* Ecouter ensuite sur la socket client et socket unix pour traiter les messages
|
||||
*/
|
||||
void * service_thread(void * c_data) {
|
||||
client_data *cda = (client_data*) c_data;
|
||||
char *service;
|
||||
int version;
|
||||
int clientSock = cda->sfd;
|
||||
int nbMessages = 0;
|
||||
|
||||
//buffer for message
|
||||
size_t nbytes = 0;
|
||||
char *buffer = malloc (BUFSIZ);
|
||||
if (buffer == NULL) {
|
||||
perror("malloc()");
|
||||
return NULL;
|
||||
}
|
||||
memset(buffer, 0, BUFSIZ);
|
||||
|
||||
if (read_message(clientSock, buffer) == -1) {
|
||||
perror("read_message()");
|
||||
return NULL;
|
||||
}else {
|
||||
parseServiceVersion(buffer, &service, &version);
|
||||
}
|
||||
|
||||
/* TODO : service correspond au service que le client veut utiliser
|
||||
** il faut comparer service à un tableau qui contient les services
|
||||
** disponibles
|
||||
*/
|
||||
|
||||
//pid index version
|
||||
char * piv = malloc(PATH_MAX);
|
||||
memset(piv , 0, PATH_MAX);
|
||||
if (piv == NULL) {
|
||||
perror("malloc()");
|
||||
}
|
||||
makePivMessage(&piv, getpid(), cda->index, version);
|
||||
|
||||
struct ipc_service srv;
|
||||
memset (&srv, 0, sizeof (struct ipc_service));
|
||||
srv->index = 0;
|
||||
srv->version = 0;
|
||||
ipc_server_init (0, NULL, NULL, &srv, service, NULL);
|
||||
if (application_server_connection(&srv, piv, strlen(piv)) == -1) {
|
||||
handle_error("application_server_connection\n");
|
||||
}
|
||||
free(piv);
|
||||
|
||||
/*struct ipc_client p;
|
||||
ipc_application_create(&p, getpid(), cda->index, version);
|
||||
ipc_server_client_print(&p);*/
|
||||
//sleep(1);
|
||||
//printf("%s\n",p.path_proc );
|
||||
/*if (proc_connection(&p) == -1){
|
||||
handle_error("proc_connection");
|
||||
}*/
|
||||
//utilisation du select() pour surveiller la socket du client et fichier in
|
||||
fd_set rdfs;
|
||||
|
||||
int max = clientSock > srv.service_fd ? clientSock : srv.service_fd;
|
||||
|
||||
printf("Waitting for new messages...\n" );
|
||||
while(1) {
|
||||
FD_ZERO(&rdfs);
|
||||
|
||||
//add client's socket
|
||||
FD_SET(clientSock, &rdfs);
|
||||
|
||||
//add in file
|
||||
FD_SET(srv.service_fd, &rdfs);
|
||||
|
||||
if(select(max + 1, &rdfs, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
perror("select()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if (FD_ISSET(srv.service_fd, &rdfs)){
|
||||
nbytes = file_read(srv.service_fd, &buffer);
|
||||
if(nbytes < 0) {
|
||||
perror("application_read()");
|
||||
}
|
||||
printf("message from file : %s\n", buffer );
|
||||
write_message(clientSock, buffer, nbytes);
|
||||
nbMessages--;
|
||||
|
||||
} else if (FD_ISSET(clientSock, &rdfs)) {
|
||||
nbytes = read_message(clientSock, buffer);
|
||||
if(nbytes > 0 && strncmp(buffer, "exit", 4) != 0) {
|
||||
printf("Server : message (%ld bytes) : %s\n", nbytes, buffer);
|
||||
if(file_write(srv.service_fd, buffer, nbytes) < 0) {
|
||||
perror("file_write");
|
||||
}
|
||||
|
||||
nbMessages++;
|
||||
}
|
||||
if (strncmp(buffer, "exit", 4) == 0 && nbMessages == 0){
|
||||
//message end to server
|
||||
if(file_write(srv.service_fd, "exit", 4) < 0) {
|
||||
perror("file_write");
|
||||
}
|
||||
|
||||
printf("------thread %d shutdown----------\n\n", cda->index );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//close the files descriptors
|
||||
close(srv.service_fd);
|
||||
close(clientSock);
|
||||
free(buffer);
|
||||
|
||||
//release the resources
|
||||
pthread_detach(pthread_self());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void parseServiceVersion(char * buf, char ** service, int *version) {
|
||||
char *token = NULL, *saveptr = NULL;
|
||||
char *str = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (str = buf, i = 1; ; str = NULL, i++) {
|
||||
token = strtok_r(str, " ", &saveptr);
|
||||
if (token == NULL)
|
||||
break;
|
||||
|
||||
if (i == 1) {
|
||||
*service = token;
|
||||
}
|
||||
else if (i == 2) {
|
||||
*version = strtoul(token, NULL, 10);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int fifo_create (char * path)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = mkfifo (path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
|
||||
switch (errno) {
|
||||
case EACCES :
|
||||
printf ("file %s : EACCES\n", path);
|
||||
return 1;
|
||||
case EEXIST :
|
||||
printf ("file %s : EEXIST\n", path);
|
||||
break;
|
||||
case ENAMETOOLONG :
|
||||
printf ("file %s : ENAMETOOLONG\n", path);
|
||||
return 2;
|
||||
case ENOENT :
|
||||
printf ("file %s : ENOENT\n", path);
|
||||
return 3;
|
||||
case ENOSPC :
|
||||
printf ("file %s : ENOSPC\n", path);
|
||||
return 4;
|
||||
case ENOTDIR :
|
||||
printf ("file %s : ENOTDIR\n", path);
|
||||
return 5;
|
||||
case EROFS :
|
||||
printf ("file %s : EROFS\n", path);
|
||||
return 6;
|
||||
default :
|
||||
printf ("err file %s unknown\n", path);
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void inOutPathCreate(char ** pathname, int index, int version) {
|
||||
snprintf(pathname[0] , PATH_MAX, "%s%d-%d-%d-in" , TMPDIR, getpid(), index, version);
|
||||
snprintf(pathname[1] , PATH_MAX, "%s%d-%d-%d-out", TMPDIR, getpid(), index, version);
|
||||
}
|
||||
|
||||
void makePivMessage (char ** piv, int pid, int index, int version) {
|
||||
|
||||
snprintf(*piv , PATH_MAX, "%d %d %d" , getpid(), index, version);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* lancer le serveur, ecouter sur une l'adresse et port
|
||||
* A chaque nouveau client lance un thread service
|
||||
*/
|
||||
void * ipc_server_thread(void * reqq) {
|
||||
info_request *req = (info_request*) reqq;
|
||||
|
||||
//client
|
||||
client_data tab_client[NBCLIENT];
|
||||
pthread_t tab_service_threads[NBCLIENT];
|
||||
int actual = 0;
|
||||
int i;
|
||||
|
||||
int sock = init_connection(req);
|
||||
fd_set rdfs;
|
||||
|
||||
printf("Waitting for new clients :\n" );
|
||||
while(1) {
|
||||
FD_ZERO(&rdfs);
|
||||
|
||||
/* add STDIN_FILENO */
|
||||
FD_SET(STDIN_FILENO, &rdfs);
|
||||
|
||||
//add listener's socket
|
||||
FD_SET(sock, &rdfs);
|
||||
|
||||
if(select(sock + 1, &rdfs, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
perror("select()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* something from standard input : i.e keyboard */
|
||||
if(FD_ISSET(STDIN_FILENO, &rdfs))
|
||||
{
|
||||
/* stop client when type on keyboard */
|
||||
for (i = 0; i < actual; i++) {
|
||||
if (pthread_cancel(tab_service_threads[i]) != 0) {
|
||||
printf("Aucun thread correspond \n");
|
||||
}
|
||||
}
|
||||
printf("server shutdown\n");
|
||||
break;
|
||||
}
|
||||
else if (FD_ISSET(sock, &rdfs)){
|
||||
//New client
|
||||
socklen_t sinsize = sizeof (struct sockaddr_in);
|
||||
tab_client[actual].sfd = accept(sock, (struct sockaddr *)&tab_client[actual].c_addr, &sinsize);
|
||||
if(tab_client[actual].sfd == -1)
|
||||
{
|
||||
perror("accept()");
|
||||
close(sock);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
printf("New client :\n");
|
||||
printAddr(&tab_client[actual].c_addr);
|
||||
|
||||
tab_client[actual].index = actual;
|
||||
|
||||
int ret = pthread_create( &tab_service_threads[actual], NULL, &service_thread, (void *) &tab_client[actual]);
|
||||
if (ret) {
|
||||
perror("pthread_create()");
|
||||
endConnection(sock);
|
||||
exit(errno);
|
||||
} else {
|
||||
printf("\n----------Creation of listen thread %d ------------\n", actual);
|
||||
}
|
||||
|
||||
actual++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < actual; i++) {
|
||||
pthread_join(tab_service_threads[i], NULL);
|
||||
}
|
||||
|
||||
printf("--------------server thread shutdown--------------- \n");
|
||||
endConnection(sock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* user can send 2 types of request to server : listen or connect
|
||||
* listen = server for a service such as pongd
|
||||
* connect = connect to a server
|
||||
*/
|
||||
int ipc_server_get_new_request(char *buf, info_request *req) {
|
||||
|
||||
char *token = NULL, *saveptr = NULL;
|
||||
char *str = NULL;
|
||||
int i = 0;
|
||||
|
||||
//for a "connect" request
|
||||
pid_t pid = 0;
|
||||
int index = 0;
|
||||
int version = 0;
|
||||
|
||||
for (str = buf, i = 1; ; str = NULL, i++) {
|
||||
token = strtok_r(str, " ", &saveptr);
|
||||
if (token == NULL)
|
||||
break;
|
||||
|
||||
if (i == 1) {
|
||||
if(strncmp("exit", token, 4) == 0 ) {
|
||||
strncpy(req->request, token, 4);
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
req->request = token;
|
||||
}
|
||||
else if (i == 2){
|
||||
req->addr.sin_addr.s_addr = inet_addr(token);
|
||||
}
|
||||
else if (i == 3) {
|
||||
req->addr.sin_port = htons(strtoul(token, NULL, 10));
|
||||
}
|
||||
else if (i == 4 && (strcmp("connect", req->request)) == 0){
|
||||
pid = strtoul(token, NULL, 10);
|
||||
}
|
||||
else if (i == 5 && (strcmp("connect", req->request)) == 0) {
|
||||
index = strtoul(token, NULL, 10);
|
||||
}
|
||||
else if (i == 6 && (strcmp("connect", req->request)) == 0) {
|
||||
version = strtoul(token, NULL, 10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
req->addr.sin_family = AF_INET;
|
||||
|
||||
if (strcmp("connect", req->request) == 0) {
|
||||
ipc_server_client_gen (req->p, pid, index, version);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* client thread est lancé suite à une requete "connect"
|
||||
* connecter à une adresse, port le 1er message indiquera le service et le version voulus
|
||||
* Se mettre ensuite sur l'écoute de la socket serveur et le fichier client pour traiter les messages
|
||||
*/
|
||||
void * client_thread(void *reqq) {
|
||||
info_request *req = (info_request*) reqq;
|
||||
/* buffer for client data */
|
||||
int nbytes;
|
||||
char *buffer= malloc(BUFSIZ);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
handle_error("malloc");
|
||||
}
|
||||
memset(buffer, 0, BUFSIZ);;
|
||||
int nbMessages = 0;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sock == -1)
|
||||
{
|
||||
perror("socket()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if(connect(sock,(struct sockaddr *) &req->addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
perror("connect()");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
printf("Connected to server at :\n");
|
||||
printAddr(&req->addr);
|
||||
|
||||
write_message(sock, "pongd 5", strlen("pongd 5"));
|
||||
|
||||
/*//init socket unix for server
|
||||
int sfd;
|
||||
struct sockaddr_un peer_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = set_listen_socket(req->p->path_proc);
|
||||
if (sfd == -1){
|
||||
handle_error("set_listen_socket");
|
||||
}*/
|
||||
|
||||
/* master file descriptor list */
|
||||
fd_set master;
|
||||
/* temp file descriptor list for select() */
|
||||
fd_set read_fds;
|
||||
|
||||
/* maximum file descriptor number */
|
||||
int fdmax;
|
||||
/* listening socket descriptor */
|
||||
int listener = req->p->proc_fd;
|
||||
/* newly accept()ed socket descriptor */
|
||||
//int newfd;
|
||||
|
||||
/* clear the master and temp sets */
|
||||
FD_ZERO(&master);
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* add the listener to the master set */
|
||||
FD_SET(listener, &master);
|
||||
FD_SET(sock, &master);
|
||||
|
||||
/* keep track of the biggest file descriptor */
|
||||
fdmax = sock > listener ? sock : listener;
|
||||
|
||||
while(1) {
|
||||
/* copy it */
|
||||
read_fds = master;
|
||||
|
||||
if(select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
perror("select()");
|
||||
exit(errno);
|
||||
}
|
||||
printf("select...OK\n");
|
||||
|
||||
|
||||
// if(FD_ISSET(listener, &read_fds)) {
|
||||
// /* handle new connections */
|
||||
// peer_addr_size = sizeof(struct sockaddr_un);
|
||||
// newfd = accept(sfd, (struct sockaddr *) &peer_addr, &peer_addr_size);
|
||||
// if (newfd == -1) {
|
||||
// handle_error("accept");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printf("Server-accept() is OK...\n");
|
||||
// FD_SET(newfd, &master); /* add to master set */
|
||||
// if(newfd > fdmax)
|
||||
// { /* keep track of the maximum */
|
||||
// fdmax = newfd;
|
||||
// }
|
||||
// req->p->proc_fd = newfd;
|
||||
// }
|
||||
// }
|
||||
/*
|
||||
* TODO:
|
||||
* Que se passe-t-il si on reçoit un message du serveur avant l'app client?
|
||||
* Ou ecrit-on le message ??
|
||||
*/
|
||||
/*else*/ if (FD_ISSET(sock, &read_fds)) {
|
||||
int n = read_message(sock, buffer);
|
||||
if(n > 0) {
|
||||
printf("Client : message from server(%d bytes) : %s\n", n, buffer);
|
||||
if(application_write(req->p, buffer, strlen(buffer)) < 0) {
|
||||
perror("file_write");
|
||||
}
|
||||
nbMessages--;
|
||||
|
||||
} else if (n == 0){
|
||||
//message end from server
|
||||
printf("server down\n");
|
||||
printf("------thread client shutdown----------\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}else {
|
||||
nbytes = ipc_application_read (req->p, &buffer);
|
||||
printf("Client : message from app %d : %s\n",nbytes, buffer );
|
||||
if ( nbytes == -1) {
|
||||
handle_error("file_read");
|
||||
} else if( nbytes == 0) {
|
||||
/* close it... */
|
||||
close(req->p->proc_fd);
|
||||
/* remove from master set */
|
||||
FD_CLR(req->p->proc_fd, &master);
|
||||
break;
|
||||
}else {
|
||||
//printf("Client : size message %d \n",nbytes );
|
||||
write_message(sock, buffer, nbytes);
|
||||
if (strncmp(buffer, "exit", 4) != 0) {
|
||||
nbMessages++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("------thread client shutdown----------\n");
|
||||
close(listener);
|
||||
close(sock);
|
||||
free(buffer);
|
||||
|
||||
//release the resources
|
||||
pthread_detach(pthread_self());
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void request_print (const info_request *req) {
|
||||
printf("%s \n",req->request);
|
||||
}
|
||||
|
||||
/*
|
||||
*Surveiller le fichier tmp/ipc/service
|
||||
*Accepter 2 types de requetes :
|
||||
* listen : lancer un serveur, ecouter sur un port ie "listen 127.0.0.1 6000"
|
||||
* connect : connecter à une adresse, port ie "connect 127.0.0.1 6000 ${pid} 1 1"
|
||||
*/
|
||||
void main_loop (struct ipc_service *srv) {
|
||||
//request
|
||||
info_request tab_req[NBCLIENT];
|
||||
int ret;
|
||||
int i;
|
||||
//pid server
|
||||
pthread_t pid_s;
|
||||
//pid client
|
||||
pthread_t tab_client[NBCLIENT];
|
||||
int nbclient = 0;
|
||||
|
||||
//init socket unix for server
|
||||
int sfd;
|
||||
struct sockaddr_un peer_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = set_listen_socket(srv->spath);
|
||||
if (sfd == -1){
|
||||
handle_error("set_listen_socket");
|
||||
}
|
||||
|
||||
/* master file descriptor list */
|
||||
fd_set master;
|
||||
/* temp file descriptor list for select() */
|
||||
fd_set read_fds;
|
||||
|
||||
/* maximum file descriptor number */
|
||||
int fdmax;
|
||||
/* listening socket descriptor */
|
||||
int listener = sfd;
|
||||
/* newly accept()ed socket descriptor */
|
||||
int newfd;
|
||||
/* buffer for client data */
|
||||
char *buf = malloc(BUFSIZ);
|
||||
if (buf == NULL)
|
||||
{
|
||||
handle_error("malloc");
|
||||
}
|
||||
memset(buf, 0, BUFSIZ);
|
||||
int nbytes;
|
||||
|
||||
/* clear the master and temp sets */
|
||||
FD_ZERO(&master);
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* add the listener to the master set */
|
||||
FD_SET(listener, &master);
|
||||
//FD_SET(sfd, &master);
|
||||
|
||||
/* keep track of the biggest file descriptor */
|
||||
fdmax = listener; /* so far, it's this one*/
|
||||
|
||||
for(;;) {
|
||||
/* copy it */
|
||||
read_fds = master;
|
||||
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
perror("Server-select() error lol!");
|
||||
exit(1);
|
||||
}
|
||||
//printf("Server-select...OK\n");
|
||||
|
||||
for (i = 0; i <= fdmax; i++) {
|
||||
if(FD_ISSET(i, &read_fds)) {
|
||||
if(i == listener) {
|
||||
/* handle new connections */
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
newfd = accept(sfd, (struct sockaddr *) &peer_addr, &peer_addr_size);
|
||||
if (newfd == -1) {
|
||||
handle_error("accept");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Server-accept() is OK...\n");
|
||||
//FD_SET(newfd, &master); /* add to master set */
|
||||
//if(newfd > fdmax)
|
||||
//{ /* keep track of the maximum */
|
||||
//fdmax = newfd;
|
||||
//}
|
||||
|
||||
nbytes = file_read (newfd, &buf);
|
||||
if ( nbytes == -1) {
|
||||
handle_error("file_read");
|
||||
} else if( nbytes == 0) {
|
||||
/* close it... */
|
||||
close(i);
|
||||
/* remove from master set */
|
||||
FD_CLR(i, &master);
|
||||
}else {
|
||||
buf[BUFSIZ - 1] = '\0';
|
||||
printf ("msg received (%d) : %s\n", nbytes, buf);
|
||||
if (strncmp ("exit", buf, 4) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tab_req[nbclient].p = malloc(sizeof(struct ipc_client));
|
||||
// -1 : error, 0 = no new client, 1 = new client
|
||||
ret = ipc_server_get_new_request (buf, &tab_req[nbclient]);
|
||||
tab_req[nbclient].p->proc_fd = newfd;
|
||||
if (ret == -1) {
|
||||
perror("server_get_new_request()");
|
||||
exit(1);
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
request_print(&tab_req[nbclient]);
|
||||
|
||||
if (strcmp("listen", tab_req[nbclient].request) == 0) {
|
||||
int ret = pthread_create( &pid_s, NULL, &server_thread, (void *) &tab_req[nbclient]);
|
||||
if (ret) {
|
||||
perror("pthread_create()");
|
||||
exit(errno);
|
||||
} else {
|
||||
printf("\n----------Creation of server thread ------------\n");
|
||||
}
|
||||
nbclient++;
|
||||
}else {
|
||||
int ret = pthread_create( &tab_client[nbclient], NULL, &client_thread, (void *) &tab_req[nbclient]);
|
||||
if (ret) {
|
||||
perror("pthread_create()");
|
||||
exit(errno);
|
||||
} else {
|
||||
printf("\n----------Creation of client thread ------------\n");
|
||||
}
|
||||
nbclient++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*else {
|
||||
nbytes = file_read (i, &buf);
|
||||
if ( nbytes == -1) {
|
||||
handle_error("file_read");
|
||||
} else if( nbytes == 0) {*/
|
||||
/* close it... */
|
||||
//close(i);
|
||||
/* remove from master set */
|
||||
/*FD_CLR(i, &master);
|
||||
}else {
|
||||
buf[BUFSIZ - 1] = '\0';
|
||||
printf ("msg received (%d) : %s\n", nbytes, buf);
|
||||
if (strncmp ("exit_server", buf, 4) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tab_req[nbclient].p = malloc(sizeof(struct ipc_client));
|
||||
// -1 : error, 0 = no new client, 1 = new client
|
||||
ret = ipc_server_get_new_request (buf, &tab_req[nbclient]);
|
||||
tab_req[nbclient].p->proc_fd = i;
|
||||
if (ret == -1) {
|
||||
perror("server_get_new_request()");
|
||||
exit(1);
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
request_print(&tab_req[nbclient]);
|
||||
|
||||
if (strcmp("listen", tab_req[nbclient].request) == 0) {
|
||||
int ret = pthread_create( &pid_s, NULL, &server_thread, (void *) &tab_req[nbclient]);
|
||||
if (ret) {
|
||||
perror("pthread_create()");
|
||||
exit(errno);
|
||||
} else {
|
||||
printf("\n----------Creation of server thread ------------\n");
|
||||
}
|
||||
nbclient++;
|
||||
}else {
|
||||
int ret = pthread_create( &tab_client[nbclient], NULL, &client_thread, (void *) &tab_req[nbclient]);
|
||||
if (ret) {
|
||||
perror("pthread_create()");
|
||||
exit(errno);
|
||||
} else {
|
||||
printf("\n----------Creation of client thread ------------\n");
|
||||
}
|
||||
nbclient++;
|
||||
|
||||
}
|
||||
}
|
||||
}*/ //i == listener
|
||||
} //if FDISSET
|
||||
}//boucle for
|
||||
if (strncmp ("exit", buf, 4) == 0) {
|
||||
break;
|
||||
}
|
||||
}//boucle while
|
||||
|
||||
if (pthread_cancel(pid_s) != 0) {
|
||||
printf("Aucun thread correspond \n");
|
||||
}
|
||||
|
||||
pthread_join(pid_s, NULL);
|
||||
|
||||
/*for (i = 0; i < nbclient; i++) {
|
||||
pthread_join(tab_client[i], NULL);
|
||||
}*/
|
||||
|
||||
for (i = 0; i < nbclient; i++) {
|
||||
free(tab_req[i].p);
|
||||
}
|
||||
free(buf);
|
||||
close(sfd);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[], char **env) {
|
||||
struct ipc_service srv;
|
||||
ipc_server_init (argc, argv, env, &srv, SERVICE_TCP, NULL);
|
||||
printf ("Listening on %s.\n", srv.spath);
|
||||
|
||||
// creates the service named pipe, that listens to client applications
|
||||
int ret;
|
||||
if ((ret = ipc_server_create (&srv))) {
|
||||
fprintf(stdout, "error service_create %d\n", ret);
|
||||
exit (1);
|
||||
}
|
||||
printf("MAIN: server created\n" );
|
||||
|
||||
// the service will loop until the end of time, a specific message, a signal
|
||||
main_loop (&srv);
|
||||
|
||||
// the application will shut down, and remove the service named pipe
|
||||
if ((ret = ipc_server_close (&srv))) {
|
||||
fprintf(stdout, "error service_close %d\n", ret);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
#ifndef __TCPDSERVER_H__
|
||||
#define __TCPDSERVER_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "../../lib/communication.h"
|
||||
|
||||
typedef struct {
|
||||
struct sockaddr_in c_addr;
|
||||
int sfd;
|
||||
int index;
|
||||
} client_data;
|
||||
|
||||
//informations for server to listen at a address
|
||||
typedef struct {
|
||||
struct sockaddr_in addr;
|
||||
char * request;
|
||||
struct ipc_client *p;
|
||||
} info_request;
|
||||
|
||||
int initConnection (const info_request *req);
|
||||
void endConnection (int sock);
|
||||
|
||||
void printAddr (struct sockaddr_in *csin);
|
||||
|
||||
void write_message(int sock, const char *buffer, size_t size);
|
||||
int read_message(int sock, char *buffer);
|
||||
|
||||
//2 threads for listen and send data
|
||||
void * service_thread(void * pdata);
|
||||
|
||||
//parse the first message from client in service and version
|
||||
void parseServiceVersion(char * buf, char ** service, int *version);
|
||||
|
||||
//create 2 pathnames such as : pid-index-version-in/out
|
||||
void inOutPathCreate(char ** pathname, int index, int version);
|
||||
|
||||
//create a fifo file
|
||||
int fifo_create (char * path);
|
||||
|
||||
//create first message for a service : pid index version
|
||||
void makePivMessage(char ** piv, int pid, int index, int version);
|
||||
|
||||
void * ipc_server_thread(void *reqq);
|
||||
|
||||
void * client_thread(void *reqq);
|
||||
|
||||
int ipc_server_get_new_request(char *buf, info_request *req);
|
||||
|
||||
void request_print (const info_request *req);
|
||||
|
||||
void main_loop(struct ipc_service *srv);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/dash
|
||||
|
||||
REP=/tmp/ipc/
|
||||
SERVICE="tcpd"
|
||||
|
||||
# pid index version
|
||||
echo "connect 127.0.0.1 6000 111111 1 1" | nc -U ${REP}${SERVICE}
|
||||
sleep 1
|
||||
echo "hello frero" | nc -U ${REP}111111-1-1
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/dash
|
||||
|
||||
REP=/tmp/ipc/
|
||||
SERVICE="tcpd"
|
||||
|
||||
# pid index version
|
||||
echo "exit" | nc -U ${REP}${SERVICE}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/dash
|
||||
|
||||
REP=/tmp/ipc/
|
||||
SERVICE="tcpd"
|
||||
|
||||
echo "listen 127.0.0.1 6000" | nc -U ${REP}${SERVICE}
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/dash
|
||||
|
||||
REP=/tmp/ipc/
|
||||
SERVICE="tcpd"
|
||||
NB=10
|
||||
|
||||
if [ $# -ne 0 ]
|
||||
then
|
||||
NB=$1
|
||||
fi
|
||||
|
||||
for pid in `seq 1 ${NB}`
|
||||
do
|
||||
./tcpdtest.bin
|
||||
|
||||
done
|
|
@ -1,66 +0,0 @@
|
|||
#include "../../lib/communication.h"
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define PONGD_SERVICE_NAME "pongd"
|
||||
#define LISTEN_BACKLOG 50
|
||||
#define handle_error(msg) \
|
||||
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
char *server_message = malloc(BUFSIZ);
|
||||
char *pidfile = malloc(BUFSIZ);
|
||||
char *buffer = malloc(BUFSIZ);
|
||||
|
||||
snprintf(server_message, BUFSIZ, "%s %d 1 1", "connect 127.0.0.1 6000", getpid());
|
||||
snprintf(pidfile, BUFSIZ, "%s%d-1-1", "/tmp/ipc/", getpid());
|
||||
|
||||
char *proc_message = "hello frero";
|
||||
|
||||
int sfd;
|
||||
struct sockaddr_un my_addr;
|
||||
socklen_t peer_addr_size;
|
||||
|
||||
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd == -1)
|
||||
return -1;
|
||||
|
||||
memset(&my_addr, 0, sizeof(struct sockaddr_un));
|
||||
// Clear structure
|
||||
my_addr.sun_family = AF_UNIX;
|
||||
strncpy(my_addr.sun_path, "/tmp/ipc/tcpd", sizeof(my_addr.sun_path) - 1);
|
||||
|
||||
peer_addr_size = sizeof(struct sockaddr_un);
|
||||
if(connect(sfd,(struct sockaddr *) &my_addr, peer_addr_size) == -1)
|
||||
{
|
||||
perror("connect()");
|
||||
exit(errno);
|
||||
}
|
||||
//printf("connected...\n");
|
||||
file_write(sfd, ipc_server_message, strlen(server_message));
|
||||
//printf("%s\n", proc_message);
|
||||
//sleep(1);
|
||||
file_write(sfd, proc_message, strlen(proc_message));
|
||||
file_read(sfd, &buffer);
|
||||
printf("%s\n", buffer);
|
||||
//sleep(1);
|
||||
file_write(sfd, "exit", 4);
|
||||
|
||||
close(sfd);
|
||||
|
||||
// //sleep(1);
|
||||
// cfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
// if (sfd == -1)
|
||||
// return -1;
|
||||
// strncpy(my_addr.sun_path, pidfile, sizeof(my_addr.sun_path) - 1);
|
||||
// if(connect(cfd,(struct sockaddr *) &my_addr, peer_addr_size) == -1)
|
||||
// {
|
||||
// perror("connect()");
|
||||
// exit(errno);
|
||||
// }
|
||||
|
||||
// close(cfd);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue