Compare commits

..

10 commits

14 changed files with 236 additions and 10 deletions

19
README.md Normal file
View file

@ -0,0 +1,19 @@
[LibIPC][libipc] examples in many languages:
- C
- Zig
- Crystal
and soon even more!
# Build
Just type `make` in the right directory.
# Some makefile utilities
All examples' makefiles include `mk/makefile.utils`.
Go have a look.
You'll be able to ask for a static build, run an application with valgrind with many options, and so on.
For example: `make STATIC=1 build` will compile your example as a static executable (in all languages).
[libipc]: https://git.baguette.netlib.re/Baguette/libipc

2
c/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
pong
pongd

View file

@ -1,6 +1,25 @@
Some C examples, nothing fancy. [LibIPC][libipc] C examples: `pong` and `pongd` (simple service and its client, just echoing received messages).
Implementation is straightforward. Implementations are straightforward.
# Build ## Build
`make` `make`
Some options are available, such as static builds.
```sh
make STATIC=1 # Build static executables.
```
## Usage
```sh
./zig-out/bin/pongd # run the service
./zig-out/bin/pong # run the client
```
## LICENSE
ISC
[libipc]: https://git.baguette.netlib.re/Baguette/libipc

View file

@ -1,12 +1,10 @@
# LibIPC examples
Crystal LibIPC examples, using [libipc bindings shard][bindings]. Crystal LibIPC examples, using [libipc bindings shard][bindings].
## Installation ## Build
```sh ```sh
# Compiles all examples. # Compiles all examples.
shards build make
``` ```
Currently there are 2 examples: Currently there are 2 examples:
@ -21,7 +19,7 @@ Currently there are 2 examples:
./bin/pong # run the client ./bin/pong # run the client
``` ```
# LICENCE ## LICENSE
ISC ISC

37
crystal/makefile Normal file
View file

@ -0,0 +1,37 @@
# The following shows how to use a library that is not installed.
# Usage example: make LIBPATH=/tmp/libipc/zig-out/lib/ build run
LIBPATH ?=
LD_LIBRARY_PATH=LD_LIBRARY_PATH=$(LIBPATH)
CRYSTAL_LIBRARY_PATH=CRYSTAL_LIBRARY_PATH=$(LIBPATH)
CRYSTAL_BUILD_OPTIONS ?=
CRYSTAL_BUILD_OPTIONS += $(CRYSTAL_STATIC_BUILD)
LIBIPC_RUNDIR ?= /tmp/libipc-run
all: run
build: build-pongd build-pong build-input2ipc build-fromipc
run: run-pongd
include ../mk/makefile.utils
build-pongd:
$(CRYSTAL_LIBRARY_PATH) shards build pongd $(CRYSTAL_BUILD_OPTIONS)
run-pongd:
rm $(LIBIPC_RUNDIR)/pong 2>/dev/null || true
$(LD_LIBRARY_PATH) ./bin/pongd
build-pong:
$(CRYSTAL_LIBRARY_PATH) shards build pong $(CRYSTAL_BUILD_OPTIONS)
run-pong:
$(LD_LIBRARY_PATH) ./bin/pong
-include makefile.user
build-input2ipc:
$(CRYSTAL_LIBRARY_PATH) shards build input2ipc $(CRYSTAL_BUILD_OPTIONS)
build-fromipc:
$(CRYSTAL_LIBRARY_PATH) shards build fromipc $(CRYSTAL_BUILD_OPTIONS)

30
crystal/makefile.user Normal file
View file

@ -0,0 +1,30 @@
WS_PORT ?= 8080
WS_SERVICE ?= 127.0.0.1:$(WS_PORT)
WS_TARGET_SERVICE ?= pong
WS_TARGET ?= unix:/tmp/.libipc-run/$(WS_TARGET_SERVICE)
init-websocket-tcpd:
@# '-b' binary, '-E' quit on end-of-file, 'ws-l' websocket URI to listen
@# each connection is redirected to last parameter
websocat -b -E ws-l:$(WS_SERVICE) $(WS_TARGET)
init-websocket-client:
@# websocat -b -E tcp-l:127.0.0.1:9000 ws://127.0.0.1:9999
websocat -b -E ws://$(WS_SERVICE)
#
# The following rules help for debugging stuff.
# Changes can happen from time to time depending on what I'm working on.
#
TCP_SERVICE ?= 127.0.0.1:9000
init-websocket-ipc-unix:
@#websocat -b -E ws-l:$(WS_SERVICE) tcp:$(TCP_SERVICE)
@#websocat -b -E ws-l:$(WS_SERVICE) | ./bin/input2ipc | nc -U /tmp/.libipc-run/pong
websocat -b -E -s 8080 | ./bin/input2ipc | nc -U /tmp/.libipc-run/pong
# 1. read TCP messages (nc),
# 2. convert them into IPC messages (input2ipc),
# 3. send them through websocket (websocat).
init-tcpd-ipc-websocket:
nc -k -l 9000 | ./bin/input2ipc | make init-websocket-client

View file

@ -13,11 +13,20 @@ targets:
pongd: pongd:
main: src/pongd.cr main: src/pongd.cr
# Those two examples show what it is required to serialize and deserialize
# an IPC message, which only is to add (and remove) the message length in
# the first 4 bytes of the message.
# They can be used to handle messages from a simple shell script.
fromipc:
main: src/fromipc.cr
input2ipc:
main: src/input2ipc.cr
dependencies: dependencies:
ipc: ipc:
git: https://git.baguette.netlib.re/Baguette/ipc.cr git: https://git.baguette.netlib.re/Baguette/ipc.cr
branch: master branch: master
crystal: 1.7.1 crystal: 1.8.2
license: ISC license: ISC

7
crystal/src/fromipc.cr Normal file
View file

@ -0,0 +1,7 @@
# Read an IPC network packet and remove the first 4 bytes.
buffer = Bytes.new 1_000_000
while true
len = STDIN.read buffer
break if len == 0
STDOUT.write buffer[4.. len -1]
end

8
crystal/src/input2ipc.cr Normal file
View file

@ -0,0 +1,8 @@
# Input to IPC network packets.
buffer = Bytes.new 1_000_000
while true
len = STDIN.read buffer
break if len == 0
STDOUT.write_bytes len, IO::ByteFormat::BigEndian
STDOUT.write buffer[0.. len -1]
end

View file

@ -0,0 +1,51 @@
# WARNING: This code is for DEBUG only.
# Listen to a UNIX socket, connect to another one.
require "ipc"
ipc = IPC.new
ipc.timer 5000 # timer event every 5 seconds
fd = ipc.connect "pong" # 'pong' service
ipc.loop do |event|
case event.type
when LibIPC::EventType::MessageRx
m = event.message
if m.nil?
puts "No message"
else
received = String.new(m.to_unsafe, m.size)
pp! received
ipc.schedule event.fd, m, m.size
end
when LibIPC::EventType::MessageTx
puts "A message has been sent"
when LibIPC::EventType::Connection
puts "A client just connected #JOY"
when LibIPC::EventType::Disconnection
puts "A client just disconnected #SAD"
when LibIPC::EventType::Timer
STDOUT.write "\rTimer!".to_slice
when LibIPC::EventType::External
else
puts "Unexpected: #{event.type}"
exit 1
end
end
# Read an IPC network packet and remove the first 4 bytes.
buffer = Bytes.new 1_000_000
while true
len = STDIN.read buffer
break if len == 0
STDOUT.write buffer[4.. len -1]
end
# Input to IPC network packets.
buffer = Bytes.new 1_000_000
while true
len = STDIN.read buffer
break if len == 0
STDOUT.write_bytes len, IO::ByteFormat::BigEndian
STDOUT.write buffer[0.. len -1]
end

View file

@ -1,5 +1,7 @@
ifdef STATIC ifdef STATIC
STATIC_BUILD ?= -static STATIC_BUILD ?= -static
CRYSTAL_STATIC_BUILD ?= --static
ZIG_STATIC_BUILD ?= -Dstatic=true
endif endif
# For interactive completion in the shell. # For interactive completion in the shell.

34
zig/README.md Normal file
View file

@ -0,0 +1,34 @@
Zig [LibIPC][libipc] examples:
`pong` and `pongd` (as you find in all other examples).
`tcpd` and `ipcd`, to make any LibIPC application network-ready.
Documentation will come soon for these.
## Build
```sh
# Compiles all examples.
make
```
Several options are available.
```sh
# Compiles all examples.
make STATIC=1 # Build static executables.
make ZIG_OPTIM=ReleaseSmall # Build small executables.
```
Read the makefile.
## Usage
```sh
./zig-out/bin/pongd # run the service
./zig-out/bin/pong # run the client
```
## LICENSE
ISC
[libipc]: https://git.baguette.netlib.re/Baguette/libipc

View file

@ -58,4 +58,12 @@ pub fn build(b: *std.Build) void {
.optimize = optimize, .optimize = optimize,
}); });
link_and_install(pongd_exe); link_and_install(pongd_exe);
const is_static = b.option(bool, "static", "Compile static binaries.") orelse false;
if (is_static) {
ipcd_exe.linkage = .static;
tcpd_exe.linkage = .static;
pong_exe.linkage = .static;
pongd_exe.linkage = .static;
}
} }

View file

@ -1,9 +1,11 @@
all: build all: build
include ../mk/makefile.utils
update-libipc: update-libipc:
git submodule update git submodule update
ZIG_OPTS ?= ZIG_OPTS ?=
ZIG_OPTIM ?= ReleaseSafe ZIG_OPTIM ?= ReleaseSafe
build: build:
zig build -Doptimize=$(ZIG_OPTIM) $(ZIG_OPTS) zig build -Doptimize=$(ZIG_OPTIM) $(ZIG_OPTS) $(ZIG_STATIC_BUILD)