Ripster
I am writing an application that reads incoming packets and I’d like to decode them and route them to the appropriate handler.
The header of each packet is what defines its type.
So for example a user login packet may look like this:
<<
header::integer-little-8,
ulen::unsigned-little-integer-32,
user::binary-size(ulen),
plen::unsigned-little-integer-32,
pass::binary-size(plen)
>>
I’d like to be able to do something like this in my receive function:
<<
header::integer-little-8,
data::bytes
>> = received
{:ok, packet} = Packet.parse(header, data)
:ok = packet.run()
Where Packet.parse/2 is defined at compile time.
defmodule Packet do
defmacro __using__(header) do
# track __CALLER__ and header?
@behaviour Packet
end
@callback parse(BitString) :: {:ok, Map}
@callback def run() :: :ok | {:error, reason}
# Generate these at compile time
def parse(1, data), do: Packets.Login.parse(data)
def parse(2, data), do: Packets.Chat.parse(data)
end
defmodule Packets.Login do
use Packet, header: 1
defstruct :username, :password
def parse(packet_data), do: # decode packet
def run, do: # run code to handle packet
end
Is there a way to do this using macros or a better way that wouldn’t require macros?
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 14 to 5- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
OvermindDL1
We try, don’t hesitate to ask!
Ripster
I’ll likely either hard code or use ProtocolEx as you’ve suggested. ProtocolEx does look really nice, the only reason I’ve been shying away from it is this is a learning experience for me.
Prior to this project I didn’t even know the difference between
use,import, andrequire. As I’m reading and learning I’m trying to use everything I’m learning in some way even if it’s not the most appropriate for the situation. I need to get it to sink in somehow!I appreciate everyone’s patience and I’ve been really surprised by how helpful and knowledgeable the Elixir community is. Thank you for the examples, links, and information you’ve provided. It’s been a huge help.
OvermindDL1
That says they are either on the wrong file or not put in early in the compilation process.
Honestly I’m thinking this is just a bit odd of a design overall regardless, I would probably just hardcode those all in as it’s not like they are going to be changing often anyway and adding new ones is easy. ^.^;
If you really want to go the more complex route (which be sure that you do), I’d really say take a look at my afore-mentioned protocol_ex, your solution might look similar to (typed in-post so likely has syntax errors):
Then just write the implementations like:
Then maybe another one somewhere else:
Etc…
And of course you can add a run function and all sorts as well too. Whatever. (If you need new features in protocol_ex, just ask). It has a lot of other abilities and optimizations and such you can do as well, but as-is it already does what you posted that you want.
Don’t forget to add the compile for protocol_ex to the
mix.exsfile as per the documentation too (or you can always handle it manually too if you want).(EDIT: Updated examples to be actual code rather than just placeholder code)
Ripster
I’ve been messing around with
requirequite a bit and still can’t seem to get it to work. What seems to be happening isMix.Tasks.Xref.calls()comes up empty on first compile. If I edit what seems to be just about any file related to the router and then recompile, it comes up with a list of callers like I expect.Doing a
requireon the router module, packet module, or even requiring the actual packet definition in the router does not seem to get it working.I’ve started looking through the code on github for
mix xref callersbecause it seems to always list out the dependency’s ofPacketcorrectly (or at least the files that use it). I’m hoping that will shed some light on a possible solution.I have to admit I’m still fairly new to elixir. If you think creating a compiler plugin is a good way to go I would love to know where I can find related documentation so I can learn more. If you don’t mind can you help point me in the right direction here?
OvermindDL1
That just means the compile cannot figure out the dependency chain properly, adding some
require’s would help that but that would miss ‘new’ ones, or making the module as always dirty would fix it but would have to recompile it every time, or a compiler plugin (as ProtocolEx does) would always work instead too.Basically the issue is that the Elixir compiler doesn’t know when it needs to recompile a module, which
require’s fixes for known things, but for unknown things it doesn’t know when to add the dependency chain.Ripster
For some reason the functions are not getting generated unless I compile the app, modify the router
I have defined 2 modules
packet.ex
router.ex
Now if I use this by defining
server/packet/login.ex
server/packet/router.ex
The router does not end up with any parse functions in it.
If I compile the app and then modify server/packet/router.ex (add or remove a blank line) then recompile the parse function does get generated.
Have I done something wrong here or did I miss something important?
OvermindDL1
I really should release my library of mine that does that at compile-time… >.>
Hmm, actually you could use my ProtocolEx (it’s like the Protocol Library built into elixir, except it is based on matchers and guards instead of types, and has the ability to be faster too by inlining and more) library if you don’t mind putting your
parsefunctions in implementation modules (you can of course put multiples of the parse functions in a single implementation if you want, so you can group like-functionality.kip
Using the code above you could then generate the functions you’re after with something like:
kip
Here’s some code that will introspect the known modules and identify if they implement a behaviour. I’ve shown two ways to get the known modules, one is Elixir release dependent, the other uses the Mix api. Both are really only available in a build environment but I guess thats OK for your use. The second issue is that they introspect artefacts that are already compiled which may introduce some dependency issues.
Ripster
You’re right that I want to pattern match on the header. I want the header to be defined in the module that handles the actual packet though. Otherwise you end up with a module that is nothing but a large list mapping the header numbers to modules. I don’t want to separate that information.
If I was able to get every module that has
use Packet, header: 1or implements aPacketbehaviour, or every module with a@packet_headerattribute, then I could build the list without having to list them all out manually.