うさちゃんと一緒(31) Z80の魔改造?Rabbit4000で ECHO 再び

Joseph Halfmoon

前回「素の」telnetでラズパイ4からうさちゃんRabbit4000へ通信してみました。裏でtelnetが通信条件など双方向でネゴっていることを学びました。でも実際のデータ転送は一方通行でした。うさちゃんからのお返事はなし。今回はうさちゃん側からのお返事あり、としてみとうございます。

※「うさちゃんと一緒」投稿順 Index はこちら

※Rabbitシリーズのマニュアルは、販売元のDigi社のページからダウンロードできます。

※実験にはRabbit4000搭載のRCM4010モジュールを使用しています。ソフトウエアはDynamic C 10.72でコンパイルしています。

※うさちゃんの対向機には、Raspberry Pi 4 model B(Raspberry Pi OS 64bit bullseye)を使用しています。telnet、wiresharkなどはこのラズパイ4で動かしてます。

過去に「ほぼほぼ」telnetで双方向通信していた

大分以前の回になりますが「telnetで双方向通信した」と主張するところの回がございます。以下です。

うさちゃんと一緒(7) TCPパケットをオウム返しでtelnet、Rabbit4000

たしかに上記では、対向機側は telnet コマンドを通信して、データを送受しているので telnet 使っていることに間違いはありません。しかし、前回のお勉強を経て、上記回の問題点は理解しましたぞ。

立派なtelnetサーバであれば端末の通信条件など双方向のネゴシエーションに対応しているけれども、上記では何もせず、ただ踏みつぶしている。

ということであります。telnetは寛大なのでネゴの件、踏みつぶされても通信はしてくれる、と。

今回からは上記の第7回で使用した ECHO.C なるサンプルソースを元に、手を加えていきたいと思います。

今回の追加点

今回より、telnetから送られてきたユーザからの「問いかけ」にうさちゃんが答えるようなソフトに仕立てていくつもりであります。その最初として、上記のECHO.Cでは、TCPパケットで送られてきたものをそのままオウム返ししていたものを「ほんのり加工」してから送り返すことにいたしたいと思います。

まずは 対向機からうさちゃんに送られてくるパケットを待ち受ける do ループの中に、反応のための関数 userResponse()と、その加工結果の送信を加えてみました。変更部分はこんな感じ。

do {
    bytes_read=sock_fastread(&socket,buffer,sizeof(buffer)-1);
    if(bytes_read>0) {
        buffer[bytes_read]=0;
        printf("%s",buffer);
        if (bytes_res = userResponse(buffer, bytes_read)) {
            sock_write(&socket,responseBuf,bytes_res);
            resBufLen = 0;
        }
    }
} while(tcp_tick(&socket));

そして、「ささやかな」userResponse()本体が以下です。CRかLFが送られてくるまでバッファに送られてきた文字をため続け、CRかLFが送られてきたらば、末尾にCR+LFつけて送り返します。その際「ためこんだ文字」の先頭には$記号がついておる、と。これだけ。

#define	MAX_BUF	(102)
char	responseBuf[MAX_BUF];
int resBufLen = 0;

int userResponse(char* buf, size_t blen)
{
    int goflag;
    int cnt;
    if (resBufLen == 0) {
        responseBuf[0] = '$';
        resBufLen++;
    }
    goflag = 0;
    if ((MAX_BUF - resBufLen) > blen) {
        for (cnt = 0; cnt < blen; cnt++) {
            if ((*buf == '\n') || (*buf == '\r')) {
                goflag = 1;
                break;
            }
            responseBuf[resBufLen++] = *buf++;
        }
    } else {
        goflag = 1;
    }
    if (goflag) {
        responseBuf[resBufLen++] = '\r';
        responseBuf[resBufLen++] = '\n';
        return resBufLen;
    }
    return 0;
}
実機上の動作確認

うさちゃんRabbit4000と、ラズパイ4上のtelnetを接続してみました。うさちゃん側のStdioへの出力は以下のとおり。ECHO2RabbitStdio

Connection received… 後、やたらと黒四角が出力されてますが、これはラズパイ4側のtelnetから通信条件のネゴを持ち掛けられてるもの。前回のソフトであれば、telnetのコマンド文字を解析して「それらしい」レスポンスを送り返しているので平穏にネゴは終わってます。しかし、今回はそういうことをしていないです。でも、相手側で通信条件はよきに計らってくれて、通信は成立しているみたい。前回はちゃんとレスポンスしたおかげで、telnetからの送信は「行モード」に設定されてましたが、今回はテキトーにレスポンス返したためか、デフォルトの「一文字毎」になってました。

今回着目いたしますのは、上記で黄色のマーカをひいた aaa という部分です。telnet側では、aaaリターン とキーを押してます。

その部分を例によって wireshark で解析したものがこちら。

wiresharkECHO2flow

上記の黄色、黄緑、青の3回のやりとりは、すべて一文字「a」を送っているだけのパケットとそのレスポンスです。aを送っているところが以下に。fromTelnet

ラズパイ4側(192.168.2.126)から3回 a が送られたあと、ピンクのところでラズパイ4から CR+LF を送り出してます。ここだけ2文字なのは、telnetの設定で、行末になったら CR+LF を送るように設定してあるためです。こんな感じ。

fromTelnetCRLF

ここにいたって、先ほど作成した userRespose()関数の効力が発動、送られてきた文字列の頭に$をつけ、末尾にCR+LFをつけて送り返してくるはず。うさちゃんから返送されるパケット8をみるとこんな感じ。fromTelnetRes

無事に「ほんわか」加工した内容が送り返されております。よかった。

うさちゃんと一緒(30) Z80の魔改造? Rabbit4000でtelnetその2 へ戻る