README.md

# gen_fw
Generic firewall process for Erlang/Elixir. It's an Erlang process between client processes and server process/port and prevents receiving some unwanted Erlang messages from server process/port.

## When to use **gen_fw**?
When writing new server process, It's better to receive all messages and handle unwanted messages in that process instead of using `gen_fw`. But when you are using some generic behaviour or someone else's library and you don't want your client processes send everything (even wrongly) to server process/port, `gen_fw` is your firned. In below example i will show you how to prevent client process call `supervisor:terminate/2` successfully for your supervisor.  

## How to use?
To starting main process you have to give its `MFA` to `gen_fw` and `gen_fw` will start itself and main process in order. Note that if you want to register main process, you have to **give** its register name to `gen_fw` and `gen_fw` will register itself.  
API functions for starting linked `gen_fw` process:  
```erlang
gen_fw:start_link({Mod, Func, Args}=_MFA, Rules).
gen_fw:start_link({local, Name}, {Mod, Func, Args}=_MFA, Rules).
```
API functions for starting stand-alone `gen_fw` process:  
```erlang
gen_fw:start({Mod, Func, Args}=_MFA, Rules).
gen_fw:start({local, Name}, {Mod, Func, Args}=_MFA, Rules).
```

#### Rules
```erlang
-type rules() :: [] | [rule()].
-type  rule() :: {'cast', action()}
               | {'call', action()}
               | {'message', action()}
               | {'system', action()}
               | {'all', action()}.
-type   action() :: 'allow' | 'deny' | 'dynamic'.
```
For example:  
```erlang
gen_fw:start_link({gen_server, start_link, [module, [], []]}
                 ,[{cast, deny}, {message, allow}, {system, allow}, {call, dynamic}]).
```
means start my process using `gen_server:start_link(module, [], [])` and:  
* Prevent receiving `cast` messages (Means that `module:handle_cast/2` never runs)  
* Allow receiving messages (Means that `module:handle_info/2` may run)  
* Allow receiving system message (Means you can use `sys:get_state/1`, `sys:get_status/1`, ...)    
* Use callback function `module:fw_handle_message/2` and this function will tell you that i want to receive calls or not (Means that `gen_server` may receive some calls and `module:handle_call/3` may run)  


If function `module:fw_handle_message/2` is not exported or if it did not yield `allow` or `deny` or if it crashed, `gen_fw` denies message silently.  

Note that instead of writing:
```erlang
gen_fw:start_link({gen_server, start_link, [module, [], []]}, [{cast, deny}, {message, deny}, {system, deny}, {call, allow}]).
```
you can just write:
```erlang
gen_fw:start_link({gen_server, start_link, [module, [], []]}, [{all, deny}, {call, allow}]).
```

## Example
I wrote a supervisor called [my_sup](https://github.com/pouriya-jahanbakhsh/gen_fw/blob/master/examples/my_sup.erl). Let's start supervisor directly first:  
```erlang