October 07, 2008

うまく動かない

 インターフェースのColeFire基板をSilentCでいじってるんだけど、どうもうまくいかない。

 てか、SilentCが謎。
 正直、あまり信用していない。
 うまく動いてくれないときに、自分のプログラムのせいなのかSilentCの仕様なのか判別つきにくいというのは、開発性を大いに下げていると思う。

 FlashからSocketでつないだときのセキュリティポリシーファイルのやりとりまでは完成してから記事にしようと思ったんだけど、ちょっとやる気なくなってきたので、ここまで。

既知の私がSilentCの仕様でバグと思っている箇所
・Listenソケットがクローズできない
・GetReceiveBuffer関数の戻り値が直後の呼び出し時に適用されていない場合がある。
 (直後にSystemSleep()を入れることで対処)

 ところで、Ctrl+Cでプログラムの実行を中断する機能って、本当に存在します??私の環境(TeraTerm)では使えないみたい。

 あと、これは要望なんだけど、インタプリタ言語でよく目にするeval関数が欲しい。
 てか、これ、内部的にはあるだろ。telnet接続時にコマンドラインから関数呼び出しできるけど、あの機能。
 メモリ内をガンガン漁れば見つかるんだろうけど・・そこまでの元気はない。

 デバッグ途中のプログラムは→

 08/10/19 動いたー!!
 完全に自分のスクリプトのバグだった。恥ずい・・

・本チャン用だけど動いてないコード
 ポリシーファイル送った後にソケットクローズして、再Acceptするんだけど、そこで止まってるみたい。
 その後にSocketでつなぎにいくとちゃんと接続できるので、システムは落ちてない。おそらくサーバー側(SilentC)とクライアント側(Flash)のソケット切断→再接続の微妙なタイミングの問題だと思う。
main(){
  char *c,*buf,listen,soc,;int i,length,totalLength;#stop 0
  totalLength=0;
  buf=MemoryAlloc(128);
  SystemSleep();
  listen=CreateSocket(1);
  Bind(listen,5000,1);
  soc=Accept(listen,-1);
  PrStr("connected\r\n");
  buf[0]=0;
  for(;;){
    length=Read(soc,0);
    if(length==-3){
      CloseSocket(soc);
      SystemSleep();
      soc=Accept(listen,-1);
    }
    if(length>0){
      c=GetReceiveBuffer(soc,1);
      Write(soc,c,length);
      StrCat(buf,c);
      totalLength+=length;
      SystemSleep();
      if(StrChr(c,'>')||StrChr(c,'\n')){
        if(StrStr(buf,"<policy-file-request/>")){
           Write(soc,"<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>",90);
           WaitWriteComplete(soc);
           CloseSocket(soc);
           SystemSleep();
           soc=Accept(listen,-1); // ここで止まる
           MemClear(buf,128);
           PrStr("reconnected\r\n");
        }
        if(StrStr(buf,"end")break;
        PrStr(buf);
        buf[0]=0;
      }
      MemoryFree(c);
    }
    SystemSleep();
  }
  CloseSocket(soc);
  SystemSleep();
  MemoryFree(c);
  MemoryFree(buf);
  PrStr("end\r\n");
}


・テスト用に書いた動いてるコード  こちらだと、Flashに一回しか応答できないし、Socket切れたらシステムも落ちるので不十分。
main(){
  char *c,*buf,listen,soc,;int i,length,totalLength;#stop 0
  totalLength=0;
  buf=MemoryAlloc(128);
  SystemSleep();
  listen=CreateSocket(1);
  Bind(listen,5000,1);
  soc=Accept(listen,-1);
  PrStr("connected\r\n");
  length=GetNetLine(soc,buf,128,10);
  PrStr(buf);
  if(StrStr(buf,"policy")){
    Write(soc,"<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>",90);
    MemClear(buf,128);
    SystemSleep();
    CloseSocket(soc);
    SystemSleep();
    soc=Accept(listen,-1);
    PrStr("reconnected\r\n");
  }
  for(;;){
    length=Read(soc,0);
    if(length==-3)break;
    if(length>0){
      c=GetReceiveBuffer(soc,1);
      SystemSleep();
      Write(soc,c,length);
      StrCat(buf,c);
      totalLength+=length;
      SystemSleep();
      if(StrChr(c,'\n')>0){
        if(StrStr(buf,"end")break;
          PrStr(buf);
          buf[0]=0;
        }
        MemoryFree(c);
      }
      SystemSleep();
    }
  CloseSocket(soc);
  SystemSleep();
  MemoryFree(c);
  MemoryFree(buf);
  PrStr("end\r\n");
}


 SilentCの実装を想像しながら書かなきゃいけないから、「初心者にオススメ!」とは言いにくいねー。

 安価お手軽な無線化の方法はこちら。
 Fon自身も3.3[V]で動作してるので、電源もそっちから持ってこれる。ACアダプタ要らず♪



 Socket使ったプログラムを動かして、終了して、その後マイコンにリセットをかけずに同じプログラムを動かそうとするとうまくいかないのは、やっぱSilentCの内部的にListenソケットが残ってるとかじゃーなかろーか?と邪推。

 あと、マイコンにACアダプタからの電源を直接ブチ込むようになってるのは、インターフェース基板の仕様書レベルのバグだと思う。
 ACアダプタから出てくる電圧っていいかげん(なことが多いと個人的には思ってる)なので、それを直接マイコンに入れるってのは怖い。自分なら、そんな設計はしない。
 だから、基板にはDCジャックじゃなくてレギュレータか、もしくはそのパターンを作って欲しかった。


トラックバックURL

この記事へのトラックバック

1. eval関数を実現する (1)  [ 新適当マイコン電子工作研究所 ]   October 18, 2008 20:54
「eval関数が欲しい」 何だか、危険な香りがするぞ。

この記事へのコメント

1. Posted by のりたん   October 16, 2008 15:17
私のわかる所をいくつか、

> Ctrl+Cでプログラムの実行を中断する機能
プログラム中に記述されている、"#stop 0"は、Ctrl+Cによる実行中断機能を止めるステートメントです。従って、このプログラムでは、Ctrl+Cは効きません。

> Listenソケットがクローズできない
SilentCは、プログラムを停止させても、再実行させても、原則として確保したリソースを勝手に開放したりしません。そのため、クローズしない限り、ソケットは有効です。明示的に"CloseSocket(listen)"を入れてください。

> StrCat(buf,c);
TCP通信で送られてきた通信文 c の最後に '\0' があれば良いのですが、もしそうでなければ、StrCat関数はヒープ領域を破壊してしまうと思います。
BufCopy(buf,c,length);buf[length]=0;
などとすれば、bufに必要なサイズのデータがコピーされ、最後に '\0' が入ります。
GetNetLine関数は、この処理を代行してくれますが、内部に状態変数を持っているので、使用する前に初期化が必要です。
また、通信文がbufの長さを超えていないことも要注意です。

2. Posted by yoneken   October 17, 2008 01:36
あ、のりたんさん。
MCF52233付録基板の解析お疲れさまです。
関数表とか、すっごくお世話になってます!

> "#stop 0"
あぁ!ブレークチェック禁止って、そういう意味でしたか!ありがとうございます。解決しました。

> Listenソケット
"CloseSocket(listen);"って入れたら、SilentCが沈黙しませんか?CreateSocketで作ったソケットと、Acceptで取得したソケットではSilentCの中での扱いが違う気がします。

> StrCat(buf,c);
おわ、本当だ。危険ですね。
この使い方をする場合は、バッファ領域を最初にMemClear(buf,128);(128はbufのサイズ)と初期化してやる必要があると思います。MemClear関数が「指定したポインタから指定したバイト数まで"\0"を書き込む」という動作をしているという予想の上ですが。
通信文の長さに気をつけなければならないのは、その通りです。totalLengthが確保したバイト数以下であることを確認するif文を入れないといけないですね。

--

ところで、eval関数って見つからないですか?
のりたんさんなら見つけられるかも、と淡い期待を抱いているのですが(笑)
これがあれば、任意ポートにTCPからつないだクライアントでSilentCのライブラリ関数を呼び出せて楽しい。23番(telnet)では、やってることなので、他のポートでもできるようになってると思うんですよ。
3. Posted by のりたん   October 17, 2008 08:26
Listenソケットは、クローズできるはずです。と、ここまで書いて例を探しましたが、これでは Listen ソケットをクローズするところまで、プログラムが実行されません。

http://noritan-micon.blog.so-net.ne.jp/2008-10-04
付録基板同士のクライアント・サーバ・システム

週末の課題にしよう。


SilentCが持っている関数は、BLOGの三連記事で書いたものがすべてです。見てきた(どこを?)ので間違いありません。eval関数はありませんでした。

UserDriver で作るという可能性はありますが、関数もスクリプトも同じスレッドで動作するため競合ので、今は可能性だけ。

アップデート版で使用可能になったスクリプト付きCreateTimerを使えば似たようなことが出来るかも知れません。あっ、CreateTimerがやっている事をマネすればいいのか。

これも週末の課題かな?

他には、CGIを埋め込んだHTMLをtftpで転送しておいて、ブラウザで呼び出すとか。究極のクロス・サイト・スクリプティングですね。
4. Posted by yoneken   October 18, 2008 02:15
>週末の課題
うわー!期待しちゃっていいですか?(笑)

eval関数ができたら、Flashからプログラムを転送して保存・実行することができるようになるので、できることが一気に広がるんですよ♪
SilentCで書いたプログラムをFlashで配布すれば、ユーザはネットで公開されているサンプルアプリを実行するとき、「ローカルディスクに保存→tftpで転送」という手間のかかる手順を踏むことなく、「Flashが設置されたwebページにアクセスして、Flash内で転送先のIPを指定する」だけでよくなるんですね。

>XSS
XSSは、あるwebページから、javascript等で別URIに存在するwebページの内容や動作に手を加えるもので、この場合はXSSとは言いませんねぇ。
・・すいません。この辺はちょっとうるさいもんで <(;^-^)

この週末は私も付録基板をいじって、のりたんさんに教えて頂いたことを確認しようと思います。
ありがとうございましたー
5. Posted by のりたん   October 18, 2008 09:24
まずは、LISTENソケットの方ですが、当方でも沈黙してしまいました。私が見たところ、LISTEN状態からCLOSED状態への状態遷移が定義されていないのではないかと思います。

eval関数は、SilentCの隠された機能である DoCgi ReplaceCgi で簡単に出来ないかと試したのですが、これも沈黙してしまいました。理由は不明です。

他の手を試します。
6. Posted by のりたん   October 18, 2008 09:30
ところで、
Flash 経由でプログラムを配布したいとの事ですが、このばあい、付録基板ではプログラムを受け取るためのサーバが動作しているという状態を想定されているのでしょうか。
もし、単にプログラムを送り込むだけであれば、 Flash に tftp クライアント役をやらせればよいだけのように思います。

セキュリティ的にすごく危ないような気がしてきた。
7. Posted by yoneken   October 18, 2008 14:01
のりたんさん早い早い(笑)

"#stop 0"解除しましたー。Ctrl+Cできるって何て楽なんだろう。。

>Listenソケットがクローズできない
了解です。検証ありがとうございます。
今のところ、ユーザ側では対処できない問題のようですね。

>eval関数
こっち超期待です。

>Flashにtftpクライアント
それがー、Flashに限らないんですが、web上で動くアプリケーションはセキュリティの制約があって、直接ローカルのリソースにアクセスできないんですよ。。↓
http://blog.livedoor.jp/k_yon/archives/51699796.html
そこで、SilentC上でポリシーファイルに応答するサーバーを先に立てておく必要があるんです。

>セキュリティ
とりあえず今は考えないことに (^-^)b
対抗策は幾らでもありますから。
http://www.atmarkit.co.jp/fsecurity/special/34xss/xss01.html
8. Posted by のりたん   October 31, 2008 21:57
まいど!
サイレント・システムさんにListenソケットがクローズできるようにしてもらいました。ここから、最新版がダウンロードできます。

http://silentsystem.jp/

取り急ぎ、お知らせまで。
9. Posted by yoneken   November 01, 2008 23:10
>のりたんさん
速報ありがとうございます。
最新版のファイル確認しました。今回ものりたんさんへの謝辞がありますね♪さすがです。

ですが、これを入れちゃうとメモリ配置が変わるので、おそらく今までのEval関数って使えなくなりますよね?
う〜〜む。公式で対応してくれないものか。。

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
現状報告
 KiCad解説本の重版が決定しました!ありがとうございます♪.(2016/12/10)

自己紹介
yoneken
logo
 ロボットの研究・開発をしています。

続きを読む

連絡先は
ad

Syndicate this site
 2012年からKiCad日本語版バイナリのメンテナもしています.
来てくれた人たち
  • 今日:
  • 昨日:
  • 累計:

ショップリンク
嬉しいコメント
記事について
 このブログ記事の著作権は全てyonekenに属します。
 転載や個別記事へのリンクはご自由にどうぞ。連絡は必要ありません。
 記事の内容は無保証です。古い記事の内容は当時と状況が変わっている場合があります。
 内容に関する質問はコメント欄でもらえると、他の人にも役立ちます。
記事検索
月別
リア友リンク