Module: Plug::Blit

Includes:
Base
Defined in:
lib/rbkb/plug/blit.rb

Constant Summary collapse

DEFAULT_IPADDR =
'127.0.0.1'
DEFAULT_PORT =
25_195
DEFAULT_PROTOCOL =
:TCP
OPCODES =
{
  0 => :squelch,
  1 => :unsquelch,
  2 => :delete,
  5 => :sendmsg,
  6 => :list_peers,
  7 => :starttls,

  0xfe => :clear,
  0xff => :kill
}
SIG =

Blit protocol stuff

'BLT'
BLIT_HANDLERS =

Convenience methods for blit clients

{
  TCP: lambda { |msg|
    s = TCPSocket.new(@blit_addr, @blit_port)
    wl = s.write(msg)
    s.close
    wl
  },
  UDP: lambda { |msg|
    s = UDPSocket.new
    wl = s.send(msg, 0, @blit_addr, @blit_port)
    s.close
    wl
  }
}

Instance Attribute Summary collapse

Attributes included from Base

#no_stop_on_unbind, #peers, #tls, #tls_opts, #transport

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Base

#connection_completed, #name, #plug_peer, #plug_receive, #say

Instance Attribute Details

#kind ⇒ Object

Returns the value of attribute kind.



24
25
26
# File 'lib/rbkb/plug/blit.rb', line 24

def kind
  @kind
end

Class Method Details

.blit_header(op) ⇒ Object



62
63
64
65
66
# File 'lib/rbkb/plug/blit.rb', line 62

def self.blit_header(op)
  return nil unless opno = OPCODES.invert[op]

  SIG + opno.chr
end

.blit_init(opts = {}) ⇒ Object



201
202
203
204
205
206
207
# File 'lib/rbkb/plug/blit.rb', line 201

def self.blit_init(opts = {})
  @blit_addr = opts[:addr] || DEFAULT_IPADDR
  @blit_port = opts[:port] || DEFAULT_PORT
  proto = opts[:protocol] || DEFAULT_PROTOCOL
  @blit_handler = BLIT_HANDLERS[proto]
  raise 'invalid blit transport protocol' unless @blit_handler
end

.blit_raw(buf) ⇒ Object



223
224
225
226
227
# File 'lib/rbkb/plug/blit.rb', line 223

def self.blit_raw(buf)
  raise 'use blit_init first!' unless initialized?

  @blit_handler.call buf
end

.blit_send(data, idx = 0) ⇒ Object



213
214
215
216
# File 'lib/rbkb/plug/blit.rb', line 213

def self.blit_send(data, idx = 0)
  msg = make_sendmsg(idx, data)
  blit_raw(msg)
end

.blit_starttls(idx = 0) ⇒ Object



218
219
220
221
# File 'lib/rbkb/plug/blit.rb', line 218

def self.blit_starttls(idx = 0)
  msg = make_starttls(idx)
  blit_raw(msg)
end

.initialized? ⇒ Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/rbkb/plug/blit.rb', line 209

def self.initialized?
  @blit_addr and @blit_port and @blit_handler
end

.make_clear ⇒ Object



158
159
160
# File 'lib/rbkb/plug/blit.rb', line 158

def self.make_clear
  blit_header(:clear)
end

.make_delete(idx = 0) ⇒ Object



166
167
168
169
# File 'lib/rbkb/plug/blit.rb', line 166

def self.make_delete(idx = 0)
  blit_header(:delete) +
    idx.to_bytes(:big, 2)
end

.make_kill(_idx = nil) ⇒ Object



149
150
151
# File 'lib/rbkb/plug/blit.rb', line 149

def self.make_kill(_idx = nil)
  blit_header(:kill)
end

.make_list_peers ⇒ Object



178
179
180
# File 'lib/rbkb/plug/blit.rb', line 178

def self.make_list_peers
  blit_header(:list_peers)
end

.make_mute(peerno) ⇒ Object



92
93
94
95
# File 'lib/rbkb/plug/blit.rb', line 92

def self.make_mute(peerno)
  blit_header(:squelch) +
    peerno.to_bytes(:big, 2)
end

.make_sendmsg(idx, dat) ⇒ Object

Blit packed message format is (SUBJECT TO CHANGE):

"BLT"
char   opcode
uint16be idx   = index of slave peer to send to
uint32le size  = length of data
str      data


137
138
139
140
141
142
# File 'lib/rbkb/plug/blit.rb', line 137

def self.make_sendmsg(idx, dat)
  blit_header(:sendmsg) +
    idx.to_bytes(:big, 2) +
    dat.size.to_bytes(:big, 4) +
    dat
end

.make_squelch(peerno) ⇒ Object



105
106
107
108
# File 'lib/rbkb/plug/blit.rb', line 105

def self.make_squelch(peerno)
  blit_header(:squelch) +
    peerno.to_bytes(:big, 2)
end

.make_starttls(peerno) ⇒ Object



79
80
81
# File 'lib/rbkb/plug/blit.rb', line 79

def self.make_starttls(peerno)
  blit_header(:starttls) + peerno.to_bytes(:big, 2)
end

Instance Method Details

#clear ⇒ Object



153
154
155
156
# File 'lib/rbkb/plug/blit.rb', line 153

def clear
  @peers.each { |p| p.close }
  @peers.replace []
end

#delete(peerno) ⇒ Object



162
163
164
# File 'lib/rbkb/plug/blit.rb', line 162

def delete(peerno)
  @peers.delete(peerno)
end

#initbuf ⇒ Object

(re)initializes the blit buffer



47
48
49
# File 'lib/rbkb/plug/blit.rb', line 47

def initbuf
  @buf = StringIO.new
end

#initialize(transport, slave) ⇒ Object



26
27
28
29
30
31
32
33
# File 'lib/rbkb/plug/blit.rb', line 26

def initialize(transport, slave)
  super(transport)

  @kind = :blitsrv
  @slave = slave
  @peers = slave.peers
  initbuf
end

#kill ⇒ Object



144
145
146
147
# File 'lib/rbkb/plug/blit.rb', line 144

def kill
  UI.log('** BLIT-KILL - Received shutdown command')
  EM.stop
end

#list_peers ⇒ Object



171
172
173
174
175
176
# File 'lib/rbkb/plug/blit.rb', line 171

def list_peers
  UI.log('** BLIT-LISTPEERS - Received list peers command')

  @peers.each_index { |i| UI.log "**   #{i} - #{@peers[i].name}" }
  UI.log('** BLIT-LISTPEERS-END - End of peer list')
end

#mute ⇒ Object



83
84
85
86
87
88
89
90
# File 'lib/rbkb/plug/blit.rb', line 83

def mute
  unless peerno = @buf.read(2) and peerno.size == 2 and
         @peers[peerno.dat_to_num(:big)]

    UI.log '** BLIT-ERROR(Malformed or missing peer for mute)'
    true
  end
end

#post_init ⇒ Object



35
36
37
# File 'lib/rbkb/plug/blit.rb', line 35

def post_init
  # override so we don't get unneccessary "Start" message from Base
end

#receive_data(dat) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/rbkb/plug/blit.rb', line 51

def receive_data(dat)
  return unless (@buf.write(dat) > SIG.size) or (@buf.pos > (SIG.size + 1))

  @buf.rewind

  return unless @buf.read(SIG.size) == SIG and
                op = OPCODES[@buf.read(1)[0]]

  initbuf if send(op)
end

#sendmsg ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rbkb/plug/blit.rb', line 110

def sendmsg
  unless peerno = @buf.read(2) and peerno.size == 2 and
         bufsiz = @buf.read(4) and bufsiz.size == 4
    UI.log '** BLIT-ERROR(Malformed sendmsg)'
    return true
  end

  peerno = peerno.dat_to_num(:big)
  bufsiz = bufsiz.dat_to_num(:big)

  if (rdat = @buf.read(bufsiz)).size == bufsiz
    if peer = @peers[peerno]
      peer.say(rdat, self)
      true
    else
      UI.log "** BLIT-ERROR(Invalid peer index #{peerno})"
      true
    end
  end
end

#starttls ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/rbkb/plug/blit.rb', line 68

def starttls
  unless peerno = @buf.read(2) and peerno.size == 2 and
         peer = @peers[peerno.dat_to_num(:big)]

    UI.log '** BLIT-ERROR(Malformed or missing peer for starttls)'
    return true
  end

  peer.start_tls(self)
end

#unbind ⇒ Object



39
40
41
# File 'lib/rbkb/plug/blit.rb', line 39

def unbind
  # override so we don't get unneccessary "closed" message from Base
end

#unmute ⇒ Object



97
98
99
100
101
102
103
# File 'lib/rbkb/plug/blit.rb', line 97

def unmute
  unless peerno = @buf.read(2) and peerno.size == 2 and
         @peers[peerno.dat_to_num(:big)]
    UI.log '** BLIT-ERROR(Malformed or missing peer for unmute)'
    true
  end
end