Dart で プログラマブルなメールサービスを作ろう (1) Network Byte Order

メールを受信したり、送信したりを Pure Dart で実装していこうという趣旨の記事です。全30回くらいの内容になります。

また、メールの送受信は Gmail などの メールプロバイダーを経由しないで、自信のDart が動作するLinuxサーバーを経由して行う方式を取ります。 

特定のメールに対して自動返信できる用になりますので、メール配信方のゲームを作成したり。自動で会員登録処理をしたり。簡単な質問に答えるAIを間に入れたりなど、Dart で組む事が出来るようになります。

また、 Pure Dart で 組んでいくので、ネットワークの知識がつきます。DNS や SMTP などの知識が得る効能があります。


### - SMTP

サーバー間でおメールを受信するには、SMTPプロトコルが利用されます。
https://datatracker.ietf.org/doc/html/rfc5321


### - DNS 
メールの送信先のIPアドレスを調べたり。送信相手が、なりすましをしていないかの判定にしようします。

https://datatracker.ietf.org/doc/html/rfc1034
https://datatracker.ietf.org/doc/html/rfc1035
https://datatracker.ietf.org/doc/html/rfc3901


## INDEX
(1) [Dart で プログラマブルなメールサービスを作ろう (1) Network Byte Order](https://qiita.com/kyorohiro/items/545372fc919f18d4ce0d)
(2) [Dart で プログラマブルなメールサービスを作ろう (2) DNS 用のQuery を組んでみる](https://qiita.com/kyorohiro/items/c6e52d57c106f82c86a0)
(3) [Dart で プログラマブルなメールサービスを作ろう (3) DNS の Compression](https://qiita.com/kyorohiro/items/e07cac1b3b0c230c2763)

# Network Byte Order

第一回は、ネットワークバイトオーダーについて解説します。

1バイトのデーターをメモリーに格納していく場合、特別問題はありません。

例えば、0 から 16 までのデーターをメモリーに格納する場合のコードを書いてみます。

```dart:main.dart
import 'dart:typed_data' show Uint8List;

String toHex(Uint8List buffer) {
  const List<String> vv = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
    var b = StringBuffer();
    for (var i = 0; i < buffer.length; i++) {
      var v = buffer[i];
      var v1 = (v >> 4) & 0xF;
      var v2 = v & 0xF;
      b.write('${vv[v1]}${vv[v2]}');
    }
    return b.toString();
}

main() async {
  var input = <int>[0x00, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f];  
  var buffer = Uint8List(16);
  for(var i=0;i<input.length;i++){
    buffer[i] = input[i] & 0xFF;
  }
  print(toHex(buffer));
}
```

これを実行すると、`000102030405060708090a0b0c0d0e0f` といったデータが出力されます。


ただし、問題になるのは、2byte の short型のデータ、4byteの int型のデータ
などはどのようにメモリーに記録すると良いでしょうか..

いくつか記録方法があるのですが、2つの記録方法が主流です。
- ビッグエンディアン
`0x1234` をメモリーに記録した場合、`[0x12,0x34]` と記録される
- リトルエンディアン
`0x1234` をメモリーに記録した場合、`[0x34,0x12]` と記録される


## リトルエンディアン で格納してみる

```dart:main.dart
main() async {
  var input = 0x1234;
  var buffer = Uint8List(2);
  
  //print(((input>>8) & 0xFF).toRadixString(16)); --> 12
  //print((input & 0xFF).toRadixString(16)); --> 34
  buffer[0] = input & 0xFF;
  buffer[1] = (input>>8) & 0xFF;
  print(toHex(buffer));
}
```

もしも、リトルエンディアンなら、`0x34` `0x12` と順に表示されるはずです。
もしも、ビッグエンディアンなら、`0x12` `0x32` と順に表示されるはずです。

これを実行すると、`3412` と返すので、無事、リトルエンディアンで格納できました。

## ビックエンディアン で格納してみる

```dart:main.dart
main() async {
  var input = 0x1234;
  var buffer = Uint8List(2);
  
  //print(((input>>8) & 0xFF).toRadixString(16)); --> 12
  // print((input & 0xFF).toRadixString(16)); --> 34
  buffer[0] = (input>>8) & 0xFF;
  buffer[1] = input & 0xFF;
  print(toHex(buffer));
}
```

これを実行すると、`1234` と返すので、無事、ビックエンディアンで格納できました。

※ Dart だと Dart2か Dart1の後半でAPIが追加されたはずです..が見つからない..


## 通信プロトコルはビックエンディアン

今回は、DNS と SMTP のプロトコルを実装していくのですが、これらはRFCに仕様が記載されています。 このこれらのプロトコルでは、特に記載がなければ、ビックエンディアンでデータがやりとりされます。



# 次回

DNS から データーを MXレコードと TXTレコードと、Aレコードを、取得する機能を Pure Dart で 書いていく予定です。




# REF

https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3