p3 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/p3.rb +178 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7eb67b801a8b88a152d7a5a0d5b0266c4a3ee38
|
4
|
+
data.tar.gz: 4dfcd78e495231a0ba38a2d74d6da1c5d2b70beb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f26b62209d05fa4264c3f98234f4457bad5164f2412a777e6c19dd8ae52a30adb5960fd39f5d6be5c4aa9fca41d01d751c067631b3dcd50abbfb9ad4c1a6f95
|
7
|
+
data.tar.gz: 9923ae7b08f012316bd25882739de4b3efe010a3d0e459827ef6712c0327d4e8e610ed2738041b54bf5824e3334b73eafbe1fb73582848f97ca26e2c0f26e463
|
data/lib/p3.rb
CHANGED
@@ -1 +1,179 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
1
3
|
|
4
|
+
require "pp"
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
class P3
|
8
|
+
|
9
|
+
P3_START='~'.ord
|
10
|
+
P3_END='~'.ord
|
11
|
+
P3_ESC='#'.ord
|
12
|
+
|
13
|
+
def initialize(hash={},&block)
|
14
|
+
@p3mode=false
|
15
|
+
@p3start=0
|
16
|
+
@p3buf=[]
|
17
|
+
@p3esc=false
|
18
|
+
@clients={}
|
19
|
+
@block=block
|
20
|
+
end
|
21
|
+
|
22
|
+
def unpack buf #buils object from packet byte array
|
23
|
+
blen=buf.size
|
24
|
+
#puts "GOT: buf<#{buf}> buflen=#{buf.size}"
|
25
|
+
return if blen<4
|
26
|
+
check2=0
|
27
|
+
buf[0...blen-1].each do |b|
|
28
|
+
check2^=b
|
29
|
+
end
|
30
|
+
i=0
|
31
|
+
proto=buf[i].chr
|
32
|
+
i+=1
|
33
|
+
mac=sprintf "%02X:%02X",buf[i],buf[i+1]
|
34
|
+
i+=4
|
35
|
+
ip=sprintf "%d.%d.%d.%d",buf[i+3],buf[i+2],buf[i+1],buf[i]
|
36
|
+
i+=4
|
37
|
+
port=buf[i]*0x100+buf[i+1]
|
38
|
+
i+=2
|
39
|
+
len=buf[i]
|
40
|
+
i+=1
|
41
|
+
check=buf[i+len]
|
42
|
+
data=buf[i...i+len]
|
43
|
+
pac={
|
44
|
+
proto:proto,
|
45
|
+
mac: mac,
|
46
|
+
ip: ip,
|
47
|
+
port:port,
|
48
|
+
data:data,
|
49
|
+
}
|
50
|
+
#puts "proto=#{proto},mac=#{mac},ip=#{ip},socket=#{socket},len=#{len},check=#{check}==#{check2},data='#{data.pack("C*")}'"
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
def pack pac #builds p3 packet from pac object
|
56
|
+
#pp pac
|
57
|
+
begin
|
58
|
+
buf=[]
|
59
|
+
buf<<pac[:proto].ord
|
60
|
+
macs=pac[:mac].split(":")
|
61
|
+
buf<<macs[0].to_i(16)
|
62
|
+
buf<<macs[1].to_i(16)
|
63
|
+
buf<<0
|
64
|
+
buf<<0
|
65
|
+
ips=pac[:ip].split(".")
|
66
|
+
buf<<ips[3].to_i
|
67
|
+
buf<<ips[2].to_i
|
68
|
+
buf<<ips[1].to_i
|
69
|
+
buf<<ips[0].to_i
|
70
|
+
buf<<pac[:port]/0x100
|
71
|
+
buf<<(pac[:port]&0xff)
|
72
|
+
buf<<pac[:data].size
|
73
|
+
buf+=pac[:data].unpack("C*")
|
74
|
+
check=0
|
75
|
+
buf.each do |b|
|
76
|
+
check^=b
|
77
|
+
end
|
78
|
+
buf<<check
|
79
|
+
#pp buf
|
80
|
+
#pp "~#{buf.pack("C*")}~"
|
81
|
+
return "~#{buf.pack("C*")}~"
|
82
|
+
rescue => e
|
83
|
+
p e
|
84
|
+
p e.backtrace
|
85
|
+
end
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def p3_packet_in buf
|
90
|
+
#puts "packet in #{buf}"
|
91
|
+
pac= unpack buf
|
92
|
+
return if not pac
|
93
|
+
pp pac
|
94
|
+
pp @clients
|
95
|
+
if pac[:proto]=="U"
|
96
|
+
if not @clients[pac[:mac]]
|
97
|
+
puts "new client #{pac[:mac]}"
|
98
|
+
@clients[pac[:mac]]={socket: UDPSocket.new,created:Time.now,count_r:0, count_s:0}
|
99
|
+
@clients[pac[:mac]][:thread]=Thread.new(pac[:mac]) do |my_mac|
|
100
|
+
loop do
|
101
|
+
begin
|
102
|
+
r,stuff=@clients[my_mac][:socket].recvfrom(2000) #get_packet --high level func!
|
103
|
+
ip=stuff[2]
|
104
|
+
port=stuff[1]
|
105
|
+
#puts "got reply '#{r}' from server #{ip}:#{port} to our mac #{my_mac}"
|
106
|
+
pac={
|
107
|
+
proto:'U',
|
108
|
+
mac: my_mac,
|
109
|
+
ip: ip,
|
110
|
+
port:port,
|
111
|
+
data:r,
|
112
|
+
}
|
113
|
+
#pp pac
|
114
|
+
# received return packet from server!
|
115
|
+
if @block
|
116
|
+
@block.call pac
|
117
|
+
end
|
118
|
+
#$sp.write pack pac
|
119
|
+
@clients[my_mac][:last_r]=Time.now
|
120
|
+
@clients[my_mac][:count_r]+=1
|
121
|
+
rescue => e
|
122
|
+
puts "thread dies..."
|
123
|
+
p e
|
124
|
+
p e.backtrace
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
pp @clients
|
129
|
+
end
|
130
|
+
@clients[pac[:mac]][:socket].send(pac[:data].pack("C*"), 0, pac[:ip], pac[:port])
|
131
|
+
_,port,_,_ = @clients[pac[:mac]][:socket].addr
|
132
|
+
@clients[pac[:mac]][:gw_port]=port
|
133
|
+
@clients[pac[:mac]][:last_s]=Time.now
|
134
|
+
@clients[pac[:mac]][:count_s]+=1
|
135
|
+
pp @clients
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def shutdown
|
140
|
+
@clients.each do |k,c|
|
141
|
+
if c[:socket]
|
142
|
+
c[:socket].close
|
143
|
+
puts "closed #{k}: #{c[:socket]}"
|
144
|
+
end
|
145
|
+
if c[:thread]
|
146
|
+
c[:thread].kill
|
147
|
+
puts "killed #{k}: #{c[:thread]}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
@clients={}
|
151
|
+
end
|
152
|
+
|
153
|
+
def inchar ch
|
154
|
+
#puts "got:#{ch}"
|
155
|
+
if ch==P3_START and not @p3esc and not @p3mode
|
156
|
+
@p3mode=true
|
157
|
+
@p3start=Time.now
|
158
|
+
@p3buf=[]
|
159
|
+
elsif ch==P3_END and not @p3esc and @p3mode
|
160
|
+
@p3mode=false
|
161
|
+
p3_packet_in @p3buf
|
162
|
+
@p3buf=[]
|
163
|
+
else
|
164
|
+
if not @p3mode
|
165
|
+
return false #not done, please process .. show to user
|
166
|
+
else
|
167
|
+
if @p3esc
|
168
|
+
@p3esc=false
|
169
|
+
elsif ch==P3_ESC
|
170
|
+
@p3esc=true
|
171
|
+
return
|
172
|
+
end
|
173
|
+
@p3buf<<ch
|
174
|
+
end
|
175
|
+
end
|
176
|
+
return true #char was done -- do not process
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|