10
0
Fork 0
softsim/lib/client.rb

96 lines
2.7 KiB
Ruby

# this is the client part of the SAP
# it implements the state machine for the client
require 'common'
# this is an abstract class
# TODO : verify state before sending, respect max size
class Client < SAP
# make the class abstract
private :initialize
def initialize(io)
super(io)
# state of the state machine
@state = nil
# initiate the state machine (connect_req)
set_state :not_connected
@max_msg_size = 0xffff
end
def start
# start the client in another thread
thread = Thread.new do
super
end
thread.abort_on_exception = true
end
def state_machine(message)
# check direction
raise "got client to server message" unless message[:server_to_client]
case message[:name]
when "CONNECT_RESP"
connection_status = message[:payload][0][:value][0]
max_msg_size = (message[:payload][1][:value][0]<<8)+message[:payload][1][:value][1]
# print response
if message[:payload].size == 1 then
log("client","connection : #{SAP::CONNECTION_STATUS[connection_status]}",3)
else
log("client","connection : #{SAP::CONNECTION_STATUS[connection_status]} (max message size = #{@max_msg_size})",3)
end
# verify response
if connection_status==0x00 and message[:payload].size==2 then
# OK, Server can fulfill requirements
log("client","connection to server succeded",3)
set_state :idle
elsif connection_status==0x02 and message[:payload].size==2 then
# Error, Server does not support maximum message size
log("client","server can not handle size. adapting",3)
@max_msg_size = max_msg_size
set_state :not_connected
else
set_state :not_connected
raise "connection error"
end
else
raise "not implemented or unknown message type : #{message[:name]}"
end
end
# send CONNECT_REQ
def connect
log("client","connecting",3)
until @state==:idle do
if @state == :not_connected then
payload = []
# ["MaxMsgSize",[size]]
payload << [0x00,[(@max_msg_size>>8)&0xff,@max_msg_size&0xff]]
connect = create_message("CONNECT_REQ",payload)
send(connect)
set_state :connection_under_negociation
elsif @state!=:connection_under_negociation
raise "can not connect. required state : not_connected, current state : #{@state}"
return false
end
sleep 0.1
end
return true
end
# send TRANSFER_ATR_REQ
def get_atr
if @state == :idle then
connect = create_message("TRANSFER_ATR_REQ",[])
send(connect)
@state = :processing_atr_request
else
@sap.close
raise "can request ATR. required state : idle, current state : #{@sate}"
end
end
end