# encoding: UTF-8
require 'socket'
require 'rexml/document'
require 'rexml/element'
require_relative 'protocol'
require_relative 'board'
require_relative 'client_interface'
require_relative 'util/constants'
# This class handles the socket connection to the server
class Network
include Logging
include Constants
# @!attribute [r] connected
# @return [Boolean] true, if the client is connected to a server
attr_reader :connected
def initialize(host, port, board, client, reservation = nil)
@host = host
@port = port
@board = board
@client = client
@connected = false
@protocol = Protocol.new(self, @client)
@reservation_id = reservation || ''
@receive_buffer = ''
end
# connects the client with a given server
#
# @return [Boolean] true, if successfully connected to the server
def connect
@socket = TCPSocket.open(@host, @port)
logger.info 'Connection to server established.'
@connected = true
sendString('')
document = REXML::Document.new
if @reservation_id != ''
element = REXML::Element.new('joinPrepared')
element.add_attribute('reservationCode', @reservation_id)
else
element = REXML::Element.new('join')
element.add_attribute('gameType', GAME_IDENTIFIER)
end
document.add(element)
sendXML(document)
@connected
end
# disconnects the client from a server
def disconnect
if @connected
sendString('')
@connected = false
@socket.close
end
logger.info 'Connection to server closed.'
end
# reads from the socket until "" is read
def readString
return false unless @connected
sock_msg = ''
line = ''
logger.debug 'reading'
@socket.each_char do |char|
line += char
sock_msg += char
line = '' if ['\n', ' '].include? char
break if ['', ''].include? line
end
logger.debug 'ended reading'
if sock_msg != ''
@receive_buffer.concat(sock_msg)
# Remove tag
@receive_buffer = @receive_buffer.gsub('', '')
@receive_buffer = @receive_buffer.gsub('', '')
logger.debug "Received XML from server: #{@receive_buffer}"
# Process text
@protocol.process_string(@receive_buffer)
emptyReceiveBuffer
end
true
end
# sends a xml Document to the buffer
#
# @param xml [REXML::Document] the Document, that will be sent
def sendXML(xml)
text = ''
xml.write(text)
sendString(text)
end
# processes an incomming message
#
# @return [Boolean] true, if the processing of a incomming message was successfull
def processMessages
return false unless @connected
readString
end
# sends a string to the socket
#
# @param s [String] the message, to be sent
def sendString(s)
return unless @connected
logger.debug "Sending: #{s}"
@socket.print(s)
end
private
# empties the receive buffer
def emptyReceiveBuffer
@receive_buffer = ''
end
end