yboaron
yboaron

Reputation: 21

socat: Is it possible to pass the received message at server side (unix domain socket) for a function?

I want to implement a simple client/server (UNIX DOMAIN socket) using socat, I need to call a function (e.g: func_handle) whenever a msg is received at the server side, passing the received message as parameter.

I tried the following

(server side):

#!/bin/bash 
set -ex
declare -r haproxy_sock="/var/run/haproxy/haproxy-master.sock"                                           
if [ -S "$haproxy_sock" ]; then                                                                          
    rm "$haproxy_sock"                                                                                   
fi                                                                                                       
function handle_func() {   
   echo $1
   # do something 
}
socat UNIX-LISTEN:${haproxy_sock},fork - | handle_func 

Client side:

echo "reload" | socat /var/run/haproxy/haproxy-master.sock - 

I'm getting the following error whenever I send a message from the client side.

+ declare -r haproxy_sock=/var/run/haproxy/haproxy-master.sock
+ '[' -S /var/run/haproxy/haproxy-master.sock ']'
+ socat UNIX-LISTEN:/var/run/haproxy/haproxy-master.sock,fork -
+ handle_func 
+ echo 

2019/06/16 11:15:54 socat[71366] E write(1, 0x5615507b8bd0, 7): Broken pipe

Any help will be highly appreciated

Upvotes: 1

Views: 1035

Answers (1)

KamilCuk
KamilCuk

Reputation: 140880

The function handle_func doesn't read from stdin, so it executes echo $1 and exits. You may want to read from the input:

handle_func() {   
   while read -r line; do
       echo "Read: $line"
   done
}

Because you don't read from stdin, the stdin "pipe" is closed, so from the socat point of view it's "broken".

But note that when doing socat .... - | func the output will go to your server side stdout. So you won't be able to send anything to the client.

Just go with:

export -f handle_func
socat ... system:'bash -c handle_func'

that way the echo "READ: $line" from handle_func will be visible on client.

Note: the syntax function name() should never be used. Just go with name() without function keyword.

Example:

Server script:

#!/bin/bash
# server.sh
set -x

handle_func() {
  while read -r line; do
          echo "The client sended: $line" >&2
          if [ "$line" = hello ]; then
                  echo "Answering with 'world!'" >&2
                  echo 'world!'
         fi
 done
}

export -f handle_func
socat UNIX-LISTEN:${haproxy_sock},fork system:"bash -c handle_func"

Server side output:

+ export -f handle_func
+ socat UNIX-LISTEN:/tmp/haproxy-master.sock,fork 'system:bash -c handle_func'
The client sended: hello
Answering with 'world!'
^C

Client side output:

$ echo "hello" | socat /tmp/haproxy-master.sock -
world!

Upvotes: 2

Related Questions