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

RelpServer

Defined Under Namespace

Classes: ConnectionClosed, FrameReadException, 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



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
91
92
93
# File 'lib/logstash/util/relp.rb', line 63

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 Errno::ECONNRESET
    raise ConnectionClosed
  rescue EOFError,IOError
    raise FrameReadException
  end
  if ! self.valid_command?(frame['command'])#TODO: is this enough to catch framing errors?
    if self.server?
      self.serverclose(socket)
    else
      self.close
    end
    raise InvalidCommand,frame['command']
  end
  return frame
end

#frame_write(socket, frame) ⇒ Object



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
61
# File 'lib/logstash/util/relp.rb', line 35

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)


95
96
97
# File 'lib/logstash/util/relp.rb', line 95

def server?
  @server
end

#valid_command?(command) ⇒ Boolean

Returns:

  • (Boolean)


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

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