#!/usr/local/bin/tt

# 簡易 TCP Echo サーバーです。指定された｛IPアドレスorホスト名｝＆｛ポート番号orサービス名｝にて、
# TCP クライアントからの接続を待ち受け、接続要求を処理し（リンクを確立し）、その後、
# TCP クライアントからのメッセージを待ち受け受信し、クライアントへ送信（返答）します。

/*--1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---G---H---I---J---K---L---M---N---*/

# 引数の確認
	global option = opshift()
    if( argr!=2 )
        dying("使い方:  %s  [-v]  (Server)IPアドレスorホスト名  (Server)ポート番号orサービス名\n",CMD)

# サーバー情報の取得
    ip   = shift()                      # IPアドレス、又は、ホスト名  （文字列）
    port = shift()                      # ポート番号、又は、サービス名（文字列）

# サーバー用 TCP ソケットの作成
    sock = tcp_socket(ip,port);
    if( sock==NULL )
        dying("TCP %s<Server>%s Error: cannot make TCP socket!!\n",C_BLU,C_DEF)
	disp_sockbase(sock)					# 作成直後のソケット情報

# メインループ（ソケット sock で接続の待ち受けをし、ソケット work で送受信をする）
    while( work = listen(sock) ){

    # Listen & Accept の表示
        print("TCP %s<Server>%s %sListen Socket = %d / Return Socket = %d%s\n",C_BLU,C_DEF,C_YEL,sock,work,C_DEF);
		disp_sockbase(sock)				# 接続直後のソケット情報
		disp_sockwork(work)				# 接続直後のソケット情報

    # 受信（デフォルトソケット TCP_SOCKET{=work} を利用）
        (msg,len) = rx_tcp()
        print("TCP %s<Server>%s %sRecv From:%s Message=\"%s\"(Length=%d)\n",C_BLU,C_DEF,C_GRE,C_DEF,msg,len)
		disp_sockbase(sock)				# 受信直後のソケット情報
		disp_sockwork(work)				# 受信直後のソケット情報

    # 送信（デフォルトソケット TCP_SOCKET{=work} を利用）
        ret = tx_tcp(msg,len)
        print("TCP %s<Server>%s %sSend To  :%s Message=\"%s\"(Length=%d)\n",C_BLU,C_DEF,C_GRE,C_DEF,msg,len)
		disp_sockbase(sock)				# 送信直後のソケット情報
		disp_sockwork(work)				# 送信直後のソケット情報

}

# ソケット情報を、初回時及び変化時のみ表示する。（オプション "-v" 指定時は常に表示）
def disp_sockbase(sock){

static flag_init=TRUE
static lo_ip,lo_port,lo_type,ro_ip,ro_port,ro_type

	# ソケット情報の読み込み
	(lx_ip,*,lx_port,*,lx_type,rx_ip,*,rx_port,*,rx_type) = sockinfo(sock)

	# 変化の検出
	if( flag_init || lo_ip!=lx_ip || lo_port!=lx_port || lo_type!=lx_type \
				  || ro_ip!=rx_ip || ro_port!=rx_port || ro_type!=rx_type )
		flag_diff=TRUE
	else
		flag_diff=FALS

	# 表示＆FIFO
	if( option=="-v" || flag_diff ){
		flag_init=FALS
		lo_ip=lx_ip; lo_port=lx_port ; lo_type=lx_type
		ro_ip=rx_ip; ro_port=rx_port ; ro_type=rx_type
		print("TCP ${C_BLU}<Server>${C_YEL} Sock=%d ",sock)
    	print("[Loc]IP=%s/Port=%5s/Type=%s "         ,lo_ip==NULL?"(null)":ip2str(lo_ip),str(lo_port),lo_type)
    	print("[Rem]IP=%s/Port=%5s/Type=%s${C_DEF}\n",ro_ip==NULL?"(null)":ip2str(ro_ip),str(ro_port),ro_type);
	}

}

def disp_sockwork(sock){

static flag_init=TRUE
static lo_ip,lo_port,lo_type,ro_ip,ro_port,ro_type

	# ソケット情報の読み込み
	(lx_ip,*,lx_port,*,lx_type,rx_ip,*,rx_port,*,rx_type) = sockinfo(sock)

	# 変化の検出
	if( flag_init || lo_ip!=lx_ip || lo_port!=lx_port || lo_type!=lx_type \
				  || ro_ip!=rx_ip || ro_port!=rx_port || ro_type!=rx_type )
		flag_diff=TRUE
	else
		flag_diff=FALS

	# 表示＆FIFO
	if( option=="-v" || flag_diff ){
		flag_init=FALS
		lo_ip=lx_ip; lo_port=lx_port ; lo_type=lx_type
		ro_ip=rx_ip; ro_port=rx_port ; ro_type=rx_type
		print("TCP ${C_BLU}<Server>${C_YEL} Sock=%d ",sock)
    	print("[Loc]IP=%s/Port=%5s/Type=%s "         ,lo_ip==NULL?"(null)":ip2str(lo_ip),str(lo_port),lo_type)
    	print("[Rem]IP=%s/Port=%5s/Type=%s${C_DEF}\n",ro_ip==NULL?"(null)":ip2str(ro_ip),str(ro_port),ro_type);
	}

}
