# Freddie: Elixir Socket Framework
See the getting started guide and the [online documentation](https://hexdocs.pm/freddie/).
## Overview
Freddie is the Socket Framework for the Elixir. It is written to work with optimized non-bloking socket IO, enabling clients to communicate very quickly. Use Google's protobuf as a unit of packets. Thus, it is easy to create an implementation on most platforms and languages. One protocol file per protocol is matched (Nested structures are also allowed). All messages are optionally encrypted based on AES256. For example, you can use encryption for security-critical messages, and in most cases, you can use it without encryption. All code in freddie is written to follow OTP and works fault-tolerance in the event of a failure. Currently, it can only be used with TCP restrictions, but it will support the RUDP protocol.
### Freddie
Freddie's internal structure can be separated in several ways. Each element works only for its own role.
- Router
- Categorize the packets sent by the client and then dispatch them to each handler.
- Unpacking and decrypting packets are provided internally.
- Handlers for special cases such as connection and disconnection are also available.
- Session
- This is the endpoint where the connection to each client is abstracted.
- Freddie offers several protocols, but for one client, it works through Session.
- Context
- The information in the Session and the user-available map are internal structures.
- Corresponds with one context per session. Therefore, Session can be identified through Context.
- Context is synchronized through Session, so synchronization is guaranteed for writing. However, when you read it in another process, you can temporarily see the context of the past.
- Scheme
- Module defining packets used by the application.
- Protocols
- Match the structure of each protocol and packet.
- This is where the protocol number is defined number.
## Installation
```console
$ mix local.hex
$ mix archive.install hex freddie_scaffold [version]
```
## Create Freddie Application
Create a project with the following commands:
```console
$ mix freddie.scaffold echo_server
```
## Configurate Application
Configure a confg/config.exs file
```elixir
# configure freddie
config :freddie,
# Type app name
app_mod: :echo_server,
# Type listen port
port: 5050,
# Type size of acceptor pool
acceptor_pool_size: 100,
# Type redis host address
redis_host: "localhost",
# Type redis port
redis_port: 6379,
# Type size of redis pool
redis_pool_size: 10,
# Type packet scheme root mod
scheme_root_mod: EchoServer.Scheme,
# Type protocol type root mod
packet_type_mod: EchoServer.Protocols.Types,
# Type packet handler mod (derive from Freddie.Router)
packet_handler_mod: EchoServer.Handler
```
## Add Protocol Schemes
You can add a schema for the protocol under the path 'lib/echo_server/scheme'
### lib/echo_sever/scheme/cs_echo.proto
```proto
syntax = "proto3";
message CS_Echo {
string msg = 1;
}
```
### lib/echo_server/scheme/sc_echo.proto
```proto
syntax = "proto3";
message SC_Echo {
string msg = 1;
}
```
## Define Protocol
And then you define spec of protocols like this
### lib/echo_server/protocols.ex
```elixir
defmodule EchoServer.Protocols do
use EnumType
# define protocol type and protocol number (please type full name of schemes)
defenum Types do
# echo
value(EchoServer.Scheme.CS_Echo, 1)
value(EchoServer.Scheme.SC_Echo, 2)
end
end
```
## Add Protocol Handler
Finally, you define protocol-specific processes in handler.
### lib/echo_server/handler.ex
```elixir
defmodule EchoServer.Handler do
use Freddie.Router
require Logger
alias EchoServer.Handler
# define (Client-Server) type protocol handler
defhandler EchoServer.Scheme.CS_Echo do
{meta, msg, context}
|> Handler.Echo.handle()
end
# define connnection event handler
connect do
Logger.info("Client #{inspect(context)} is connected!")
end
# define disconnection event handler
disconnect do
Logger.info("Client #{inspect(context)} is disconnected!")
end
end
```
### lib/echo_server/handler/echo.ex
```elixir
defmodule EchoServer.Handler.Echo do
alias EchoServer.Scheme
def handle({_meta, msg, context}) do
# make response message
response_packet =
[{:msg, msg.msg}]
|> Keyword.new()
|> Scheme.SC_Echo.new()
# send a meesage to session using context
Freddie.Session.send(context, response_packet)
end
end
```
## Start Application
Start the server with the following command
start server with iex:
```console
$ iex --erl "+spp true +K true +Q 65536 +IOp 2 +scl false" -S mix freddie.server start
```
or
start server without iex:
```console
$ elixir --erl "+spp true +K true +Q 65536 +IOp 2 +scl false" -S mix freddie.server start
```
## Todo
1. Provides Reliable UDP communication(Guarantee the latest order or Guaranteed both sequence and retransmission)
2. Optimize network code
3. Divide transmission into reliable and unreliable
4. Add scaffold mix tool
5. Add route mix tool & web page for dev
## Examples
[example projects](https://github.com/kernelgarden/freddie_example)