Class: Relp

Inherits:
Object
  • Object
show all
Defined in:
lib/logstash/util/relp.rb

Overview

This isn’t much use on its own, but gives RelpServer and RelpClient things

Direct Known Subclasses

RelpClient, RelpServer

Defined Under Namespace

Classes: ConnectionClosed, InappropriateCommand, InsufficientCommands, InvalidCommand, RelpError

Constant Summary collapse

RelpVersion =

TODO: spec says this is experimental, but rsyslog still seems to exclusively use it

'0'
RelpSoftware =
'logstash,1.1.1,http://logstash.net'

Instance Method Summary collapse

Instance Method Details

#frame_read(socket) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/logstash/util/relp.rb', line 62

def frame_read(socket)
  begin
    frame = Hash.new
    frame['txnr'] = socket.readline(' ').strip.to_i
    frame['command'] = socket.readline(' ').strip

    #Things get a little tricky here because if the length is 0 it is not followed by a space.
    leading_digit=socket.read(1)
    if leading_digit=='0' then
      frame['datalen'] = 0
      frame['message'] = ''
    else
      frame['datalen'] = (leading_digit + socket.readline(' ')).strip.to_i
      frame['message'] = socket.read(frame['datalen'])
    end
    @logger.debug? and @logger.debug("Read frame", :frame => frame)
  rescue EOFError,Errno::ECONNRESET,IOError
    raise ConnectionClosed
  end
  if ! self.valid_command?(frame['command'])#TODO: is this enough to catch framing errors?
    if self.server?
      self.serverclose
    else
      self.close
    end
    raise InvalidCommand,frame['command']
  end
  return frame
end

#frame_write(socket, frame) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/logstash/util/relp.rb', line 34

def frame_write(socket, frame)
  unless self.server? #I think we have to trust a server to be using the correct txnr
    #Only allow txnr to be 0 or be determined automatically
    frame['txnr'] = self.nexttxnr() unless frame['txnr']==0
  end
  frame['txnr'] = frame['txnr'].to_s
  frame['message'] = '' if frame['message'].nil?
  frame['datalen'] = frame['message'].length.to_s
  wiredata=[
    frame['txnr'],
    frame['command'],
    frame['datalen'],
    frame['message']
  ].join(' ').strip
  begin
    @logger.debug? and @logger.debug("Writing to socket", :data => wiredata)
    socket.write(wiredata)
    #Ending each frame with a newline is required in the specifications
    #Doing it a separately is useful (but a bit of a bodge) because
    #for some reason it seems to take 2 writes after the server closes the
    #connection before we get an exception
    socket.write("\n")
  rescue Errno::EPIPE,IOError,Errno::ECONNRESET#TODO: is this sufficient to catch all broken connections?
    raise ConnectionClosed
  end
  return frame['txnr'].to_i
end

#server?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/logstash/util/relp.rb', line 92

def server?
  @server
end

#valid_command?(command) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/logstash/util/relp.rb', line 15

def valid_command?(command)
  valid_commands = Array.new
  
  #Allow anything in the basic protocol for both directions
  valid_commands << 'open'
  valid_commands << 'close'

  #These are things that are part of the basic protocol, but only valid in one direction (rsp, close etc.) TODO: would they be invalid or just innapropriate?
  valid_commands += @basic_relp_commands

  #These are extra commands that we require, otherwise refuse the connection TODO: some of these are only valid on one direction
  valid_commands += @required_relp_commands

  #TODO: optional_relp_commands

  #TODO: vague mentions of abort and starttls commands in spec need looking into
  return valid_commands.include?(command)
end