Class: KineticRuby::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/kinetic_server.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port = DEFAULT_KINETIC_PORT, log_level = Logger::LOG_LEVEL_INFO) ⇒ Server

Returns a new instance of Server.



147
148
149
150
151
152
153
154
155
# File 'lib/kinetic_server.rb', line 147

def initialize(port = DEFAULT_KINETIC_PORT, log_level=Logger::LOG_LEVEL_INFO)
  @host = 'localhost'
  @port ||= DEFAULT_KINETIC_PORT
  raise "Invalid server port specified: #{port}" if !@port || @port < 0
  @logger = Logger.new(log_level)
  @logger.prefix = 'KineticSim: '
  @worker = nil
  @logger.log 'Kinetic device test server started!'
end

Instance Attribute Details

#connectedObject (readonly)

Returns the value of attribute connected.



145
146
147
# File 'lib/kinetic_server.rb', line 145

def connected
  @connected
end

#hostObject (readonly)

Returns the value of attribute host.



145
146
147
# File 'lib/kinetic_server.rb', line 145

def host
  @host
end

#portObject (readonly)

Returns the value of attribute port.



145
146
147
# File 'lib/kinetic_server.rb', line 145

def port
  @port
end

Instance Method Details

#report_buffer(buf) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/kinetic_server.rb', line 157

def report_buffer(buf)
  bytes = buf.bytes
  row_len = 16
  @logger.log "Raw Data (length=#{buf.count}):"
  while !bytes.empty?
    row_len = bytes.count >= row_len ? row_len : bytes.count
    @logger.log "  row_len: #{row_len}"
    row = bytes.slice!(row_len)
    @logger.log "  row: #{row.inspect}"
    msg = "  "
    row.each do |b|
      msg += sprintf("0x%02X", b)
    end
    @logger.log msg
  end
  report
end

#shutdownObject



266
267
268
269
270
271
272
273
274
275
# File 'lib/kinetic_server.rb', line 266

def shutdown
  return if @worker.nil?
  @logger.log 'shutting down...'
  if @worker
    @worker.exit
    @worker.join 2.0
    @worker = nil
  end
  @logger.log 'shutdown complete'
end

#startObject



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/kinetic_server.rb', line 175

def start
  return unless @worker.nil?

  # Setup handler for signaled shutdown (via ctrl+c)
  trap("INT") do
    @logger.log "INT triggered shutdown"
    shutdown
  end

  # Create background thread for processing client requests
  @worker = Thread.new do
    
    # Service client connections (sequentially)
    ClientProvider.each_client(@host, @port, @logger) do |client|

      request = ''
      pdu = nil
      connected = true
      raw_proto = nil

      # Process requests while client available
      while connected && (data = client.receive)
        if data.nil? || data.empty?
          connected = false
          break
        end

        # Append received data to request for processing
        request += data

        # Incrementally parse PDU until complete
        if PDU.valid_header? request
          @logger.log 'Receiving a PDU...'
          raw_pdu = request.bytes.map{|b| sprintf("%02X", b)}.join('')
          @logger.log "  request[#{request.length}]: #{raw_pdu}"
          pdu ||= PDU.new(@logger)
          if pdu.parse(request)
            @logger.log "Received PDU successfully!"
          else
            @logger.log "Waiting on remainder of PDU..."
          end
        end

        # Handle raw protobuf.. for tests
        if raw_proto || request.match(/^\n/)
            @logger.log "Appears to be a standalone protobuf incoming..."
            pdu = nil
            raw_proto ||= []
            raw_proto += request.bytes
            @logger.log "  protobuf: (#{raw_proto.length} bytes)"

        # Otherwise, handle custom test requests
        elsif pdu.nil?
          @logger.logv "Checking for custom request: '#{request}'"
          request_match = request.match(/^read\((\d+)\)/)
          if request_match
            len = request_match[1].to_i
            response = 'G'*len
            @logger.log "Responding to 'read(#{len})' w/ '#{response}'"
            client.send response
            request = ''
            pdu = nil
          elsif request =~ /^readProto()/
            response = Proto.new(@logger).test_encode
            @logger.log "Responding to 'read(#{len})' w/ dummy protobuf (#{response.length} bytes)"
            client.send response
            request = ''
            pdu = nil
          elsif request.match(/^read/) && data.length < 7
            @logger.log "no command match for request: '#{request}' (...yet)";
          else
            @logger.log "Unknown request! Aborting..."
            request = ''
            pdu = nil
            connected = false
          end
        end

      end #request service loop pass

      @logger.log "Disconnecting from client..."

    end #client connection

    @logger.log "Client listener shutting down..."
  end #worker thread

  @logger.log "Listener shutdown successfully!"

end