Initial Commit

This commit is contained in:
2022-09-13 20:05:26 -07:00
commit 5fb20af2fd
51 changed files with 4051 additions and 0 deletions

15
content/_index.md Normal file
View File

@@ -0,0 +1,15 @@
+++
title = "Home"
description = "Homepage for Arsen's Site"
slug = "home"
+++
{{<button href="/about">}}
About Me
{{</button>}}
<span style="margin-left: 5px;">
{{<button href="/projects">}}
Projects
{{</button>}}
</span>

34
content/about.md Normal file
View File

@@ -0,0 +1,34 @@
+++
title = "About"
description = "About Me"
showDate = false
slug = "about"
+++
I am Arsen Musayelyan, also sometimes known as Arsen6331 or Heisenbug online. I am <span id="age">Loading...</span> years old, and I am a Software Engineer.
I am very passionate about software development, automation, microcontrollers, and open-source projects in general. I also love learning new things in those fields and trying them out to see if I can make anything I find interesting.
In my free time, I work on anything from DIY microcontroller gadgets to smartwatch companion apps to contributions to open-source projects.
I've contributed to several projects, such as the [TinyGo compiler](https://github.com/tinygo-org/tinygo), [TinyGo's Drivers](https://github.com/tinygo-org/drivers), and [InfiniTime](https://github.com/infiniTimeOrg/InfiniTime).
I also have many of my own open-source projects, some of which are listed on the [projects page](/projects) of this site, and the rest can be found on my [Gitea](https://gitea.arsenm.dev/Arsen6331) or mirrored to my [GitHub](https://github.com/Arsen6331).
Online Profiles:
- [Gitea](https://gitea.arsenm.dev/Arsen6331)
- [GitHub](https://github.com/Arsen6331)
- [LinkedIn](https://www.linkedin.com/in/arsen-musayelyan-9a850a1ab/)
<script>
birthday = new Date("April 24, 2005");
now = new Date();
age = now.getFullYear() - birthday.getFullYear();
if (now.getMonth() < birthday.getMonth()) {
age--;
} else if (now.getMonth() == birthday.getMonth() && now.getDate() < birthday.getDate()) {
age--;
}
document.getElementById("age").innerHTML = age;
</script>

View File

@@ -0,0 +1,4 @@
+++
title = "Projects"
showPosts = false
+++

20
content/projects/itd.md Normal file
View File

@@ -0,0 +1,20 @@
+++
title = "ITD"
date = "2022-09-13"
summary = "Linux companion daemon for the PineTime smartwatch"
weight = 30
+++
[ITD](https://gitea.arsenm.dev/Arsen6331/itd) (short for [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime) Daemon) is my biggest and most-used project so far. It is a companion daemon that runs on Linux for the PineTime smartwatch. This means it the same thing as the Watch app on iOS, but on Linux instead of iOS and for the PineTime instead of the Apple Watch.
It runs in the background, managing Bluetooth communication with the watch. When it starts, it exposes a UNIX socket where it accepts API requests from the frontends I've built. I have a CLI frontend called `itctl` and a GUI frontend called `itgui`.
ITD implements all features exposed by the InfiniTime firmware, and even some that are not out yet or have no frontend on the watch. The only feature not implemented is navigation, which I skipped because there is no standard for it on Linux.
I've worked with developers of the InfiniTime firmware to design and add new features to the firmware, and to ITD. Developers of the firmware have also used ITD to test new features they were implementing.
My companion is mentioned in many places, including the InfiniTime README, Pine64's wiki pages for PineTime, and several blog posts from Pine64 (the manufacturer of the PineTime).
Recently, thanks to the amazing [GoReleaser](https://github.com/goreleaser/goreleaser), I have begun releasing Linux packages such as `.deb`, `.rpm`, and `.apk` (Alpine Linux, not Android) automatically whenever a new release is created.
This project combines a lot of my knowledge into a single project. It uses SQLite to store metrics such as step count, heart rate, etc., it uses Bluetooth Low-Energy to communicate with the watch, DBus to communicate with the Bluetooth daemon, UNIX sockets for Inter-Process Communication between the frontends and the daemon, it even uses a custom RPC library I built specifically for it.

111
content/projects/lrpc.md Normal file
View File

@@ -0,0 +1,111 @@
+++
title = "LRPC"
date = "2022-09-13"
showSummary = true
summary = "Lightweight, simple RPC framework for Go"
weight = 20
+++
## About
LRPC stands for Lightweight RPC. It is a very lightweight RPC framework that is designed to be as idiomatic and easy to use as possible in Go.
To add a new function, simply create a type and define a method on it, like so:
```go
package main
import (
"fmt"
"time"
"strconv"
"go.arsenm.dev/lrpc/server"
"go.arsenm.dev/lrpc/codec"
)
type RPC struct{}
// No arguments, no return values, no error, no channel
func (RPC) Hello(_ *server.Context) {
fmt.Println("Hello, World")
}
// 1 argument, no return values, no error, no channel
func (RPC) Hello(_ *server.Context, name string) {
fmt.Println("Hello,", name)
}
// 1 argument, 1 return value, no error, no channel
func (RPC) Hello(_ *server.Context, name string) string {
return "Hello, " + name
}
// 1 argument, 1 return value, with error, no channel
func (RPC) Atoi(_ *server.Context, num string) (int, error) {
return strconv.Atoi(num)
}
// 1 argument, 0 return values, with error, with channel
// (client-terminated)
func (RPC) Nums(ctx *server.Context, num int) error {
ch, err := ctx.MakeChannel()
go func() {
for {
select {
case <-time.After(time.Second):
ch <- num
num++
case <-ctx.Done(): // Signal received when client cancels their context
return
}
}
}()
return nil
}
// 1 argument, 0 return values, with error, with channel
// (server-terminated)
func (RPC) Nums(ctx *server.Context, amount int) error {
ch, err := ctx.MakeChannel()
for i := 0; i < amount; i++ {
ch <- i
time.Sleep(time.Second)
}
// Sends a signal to the client, closing the channel
// on the client-side as well.
close(ch)
return nil
}
```
Then, it can be simply run like so:
```go
func main() {
ctx := context.Background()
srv := server.New()
err := srv.Register(RPC{})
if err != nil {
panic(err)
}
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
srv.Serve(ctx, ln, codec.Default) // Default is Msgpack
}
```
## Why
The reason I made LRPC is that I used to simply read JSON messages from a socket for ITD, but that was quickly becoming unmaintainable as more and more features were added. Therefore, I decided to switch to an RPC framework.
Seeing as Go's `net/rpc` was [frozen](https://github.com/golang/go/issues/16844), I decided to look for a different one, and found [RPCX](https://github.com/smallnest/rpcx). Upon importing it, I noticed that it added a ridiculous 7MB to my binary. Two days later, LRPC was born. It's extremely lightweight, because it omits most of the features RPCX has, since I didn't need them anyway. Also, I needed a feature like the channels I implemented, and while RPCX was capable of doing something similar, it was very ugly and didn't work very well.

31
content/projects/pcre.md Normal file
View File

@@ -0,0 +1,31 @@
+++
title = "PCRE"
date = "2022-09-13"
showSummary = true
summary = "CGo-free port of PCRE2 to the Go programming language"
weight = 10
+++
## About
[PCRE](https://gitea.arsenm.dev/Arsen6331/pcre) is a CGo-free port of the PCRE2 regular expression engine to Go. Being CGo-free means that rather than just being bindings to the PCRE2 library, this is a pure Go implementation of PCRE2.
## How it works
There is an amazing program called [ccgo](https://pkg.go.dev/modernc.org/ccgo/v3). This is a transpiler that converts C code to Go. It was used to compile the source code of PCRE2 to Go.
Unfortunately, `ccgo` does create OS and CPU architecture-specific code but I only have `linux/amd64` and `linux/arm64` systems, so I used various C cross-compiler toolchains to compile to the desired target, then used `qemu-user-static` to emulate the CPU arcitectures in order to test the cross-compiled code.
For macOS, the process was a little more complicated. Since there isn't a straightforward cross-compile toolchain for macOS from Linux as far as I know, I ran a macOS VM, which I created using this project: https://github.com/kholia/OSX-KVM. With that VM, I transpiled PCRE2 to both `darwin/amd64` and `darwin/arm64`.
## Why
The reason I created this is that Go's standard library [`regexp`](https://pkg.go.dev/regexp) is missing features such as lookaheads and lookbehinds. There is a good reason for this. Due to the omission of those features, Go's `regexp` library can guarantee that regular expressions cannot be exploited for a DoS attack, known as a ReDoS attack.
This seems like a big deal, and it is in many cases, but not in all cases. For example, if the expression is compiled into the program or provided in a config file, the source is trusted and therefore can be used without worrying about DoS attacks. Some applications also require the features in order to function properly, and they might have a different way to ensure no DoS attack occurs. In these cases, PCRE2 provides extra features without sacrificing anything. This is why I made this project, to allow these use cases to exist.
It also mimics the standard library as closely as possible, meaning it can be used in conjunction with interfaces to provide different regular expression engines based on input, which may be useful in some cases.
## When not to use
Due to the extra features such as lookaheads and lookbehinds, PCRE2 is vulnerable to an attack known as ReDoS. This is where an expression is provided that recurses infinitely, consuming resources forever until there are none left for anything else. This means, if you don't need the features and can't trust the source of the expression, do not use this. Use Go's standard library `regexp` instead.