OpenSettlersII #6

As always, a commit!

Slowly crawling towards functioning lib.

This commit is not really that different from other, yet I started using Elixir convetion for return values: the tuple {:ok, response}/{:error, message}. I am quite not happy withΒ  the as_server function and I guess I will rename/rewrite it later. It’s quite obvious what it does – checks the rightmost bit and responds and sets “as server” to according boolean value.

Also, encoding and decoding version – I have no way of validating it, but I’m not sure if I should. This is one of two things I need to check before proceeding – another one being the Signature – I’m not sure if it’s version specific or not, so that’s something to get to know before coding it.

And that’s it for now πŸ™‚

OpenSettlers#5

As always – a commit!

Here’s a thing I struggled while doing previous commit – decoding command to something more structurized – according to docs it’s composed of command name and body – all coming in one binary. I had to get the name and body (if any)

It seems like you have to use ::binary-size for the first one, and just ::binary for the rest – I may be wrong thou and I will have to research that more in the future.

It’s slowly starting to be a mess – that’s why I refactored enconding a bit to make a use of pattern matching. Not it’s more “elixir style”. Still I feel the lack of the bigger picture – I guess rushing into it wasn’t as good idea as first though πŸ˜‰ I will have to do some more research and maybe a post on a protocol – it will surely help me. For example – turns out that command will never have “more” frames incoming – as you can see in changes in code – now all command have “more” set as false (with is quite redundant).

OpenSettlers#4

As always – commit!

I really need to spend more time. Today I struggled a lot with bitstrings. And still didn’t find an answer for what I was looking for, but I created a map for command without redundant info. So no more flags, only command name, data and size.

After push thou I saw a better solution – I could do pattern match on functions, so I could eliminate switch. I get a lot of mess with all those maps. I think that rethinking/refactoring it should happen sooner than I initially thought.

Also “size” field seems a bit off. Additionally I don’t feel as comfortable enough with specification as I was expecting, so I guess I’ll spend some more time with it – this should also get me up to speed.

OpenSettlersII #3

As always, commit to look at!

Today even smaller changes as I had little to no time, but at least moving slowly forward.

I added encoding of long frames. I did the same thing as in decoding, pattern match on flags and then construct proper binary data.

In tests file I added 2 tests for long frames and changed body: property in input to be binary as well. I think it’s starting to be a good time to introduce some struct for my frames, but I will worry about this later. I’m also not happy with return values – they should be more “elixiry”, so next step will be worrying about this (with some explanation what does it mean).

As I dislike post trailers – I’m going to Erlang Factory Lite tomorrow. I will try to write down as much as possible and make a interesting review next week, so stay tuned!

OpenSettlersII #2

Here’s a commit for you to look at!

I didn’t do much this week but progess is progress πŸ™‚

I added the support for long frames. According documentation, long frame is defined by flag (Bit 1, “second one from right” must be 1). If the flag is set, size will be 8 octets, and body will be size octets. (So if size is 256, body will be 256 octets).

First lets look at tests. First change you can see is that I removed “reserved” from flags as it is not needed at all and obscured the data.
Next I renamed “command” key to “type” – as it reflects better what it is – it indicated the type of frame – if it is a command or message.
Next change (in decode) is that body is still in binary (inside << >>). I guess I will work on that later, but was needed in some changes.
I added 2 tests to correctly decode long frames, for both command and message. What’s important is :: size(64). It indicates the size of binary element. If not specified it will be default (8). What’s also important (and quite logical) size have to be divisible by 8.

Now onward to code itself. There’s only one public decode function, but it calls one of the private ones depending of the flag. There’s a pattern matching on long key, and binary data. As you can see here I used ::size accordingly.
What’s worth noting is if you want to match against unknown sized binary data you can use ::binary. Here I used it for body and for “rest” in main function – as before getting flags I don’t care about size and body.

And that’s it! Not a lot, but I learnt a bit when it comes to working with binary data in Elixir and made code a bit “better”.

RabbitMQ vs ZeroMQ

As for OpenSettlersII I want to present an interface to be able to implement for any possible GUI. And as I don’t want to tie anyone with Elixir/Erlang I decided to go with messages. I looked throu the net and my own experience, and there are two picks that I though I could use

RabbitMQ

RabbitMQ is a Your Typical Message Queue. There’s a message broker that handles messaging and whatnot. It’s written in Erlang, which is huge advantage, as I could use it directly from Elixir (you can call any Erlang function from Elixir with no obstacles). Not only that -there’s an official support for Elixir itself. I also used it in my previous work, as a client. It was trivial, as should be using it in OSII.

Or is it? My aim is to be able, after getting interface for GUI, to get started as quick as possible. With RabbitMQ, when you get to the server part, not only you have to install additional software, it can get ugly quickly. As for commercial products it’s not a problem, as there’s company with support behind it, for open source, pet project it is a problem.

ZeroMQ

I really need a citation here, but apparently creator of protocol for RabbitMQ decided that it’s not really that good and did ZMTP (ZeroMQ Message Transport Protocol). It is brokerless message queue and some may argue that it’s just simple socket. The biggest problem is message persistency – if you don’t have anything to hold/save messages while other party is offline – you’ll lost them. This doesn’t really sound like a problem to me, as I think that there are some mechanisms in OTP that can help me here.

ZeroMQ is really easy to configure, I worked a bit more with it and have fond memories with it. Basic communication worked out of the box, no need for any additional installations or configurations.

 

I decided to go with ZeroMQ for reasons stated above, but there’s one more reason. I may not google that much, but I haven’t seend any ZMTP 3.0/3.1 implementations made in Elixir. There are some bindings, sure. But nothing made out of scratch. I won’t lie – if I can learn even more doing this project and possibly make first 3.0/3.1 ZMTP for Elixir – I’m in!