Skip to content
This repository was archived by the owner on Jun 27, 2018. It is now read-only.

Commit 7927048

Browse files
committed
Added RegexpQuery
With RegexpQuery, it's possible to register callbacks on string matches.
1 parent 5bc1fbc commit 7927048

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

pyretic/examples/regexp.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
################################################################################
2+
# The Pyretic Project #
3+
# frenetic-lang.org/pyretic #
4+
# author: Joshua Reich ([email protected]) #
5+
################################################################################
6+
# Licensed to the Pyretic Project by one or more contributors. See the #
7+
# NOTICES file distributed with this work for additional information #
8+
# regarding copyright and ownership. The Pyretic Project licenses this #
9+
# file to you under the following license. #
10+
# #
11+
# Redistribution and use in source and binary forms, with or without #
12+
# modification, are permitted provided the following conditions are met: #
13+
# - Redistributions of source code must retain the above copyright #
14+
# notice, this list of conditions and the following disclaimer. #
15+
# - Redistributions in binary form must reproduce the above copyright #
16+
# notice, this list of conditions and the following disclaimer in #
17+
# the documentation or other materials provided with the distribution. #
18+
# - The names of the copyright holds and contributors may not be used to #
19+
# endorse or promote products derived from this work without specific #
20+
# prior written permission. #
21+
# #
22+
# Unless required by applicable law or agreed to in writing, software #
23+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT #
24+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the #
25+
# LICENSE file distributed with this work for specific language governing #
26+
# permissions and limitations under the License. #
27+
################################################################################
28+
29+
################################################################################
30+
# SETUP #
31+
# ------------------------------------------------------------------- #
32+
# mininet: mininet.sh --topo=single,3,3 (or other single subnet network) #
33+
# test: h1 python2 -m SimpleHTTPServer 3000 #
34+
# h2 curl 10.0.0.1:3000 #
35+
# #
36+
# It should output: #
37+
# #
38+
################################################################################
39+
40+
from pyretic.lib.corelib import *
41+
from pyretic.lib.std import *
42+
from pyretic.lib.query import *
43+
from pyretic.modules.mac_learner import mac_learner
44+
45+
def print_urls(pkt, match):
46+
print 'verb: %-5s | path: %-25s | version: %-3s' % match.groups()
47+
48+
### Main ###
49+
def main():
50+
re = RegexpQuery("(?P<verb>GET|POST|DELETE|PUT|HEAD)\s*(?P<path>.*?)\s*HTTP/(?P<http>.*?)\n")
51+
re.register_callback(print_urls)
52+
53+
return mac_learner() + re

pyretic/lib/query.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
# permissions and limitations under the License. #
2727
################################################################################
2828

29-
from pyretic.core.language import identity, match, union, DerivedPolicy, DynamicFilter, FwdBucket
29+
from pyretic.core.language import identity, match, union, DerivedPolicy, DynamicFilter, FwdBucket, Query
3030
import time
31+
import re
3132
from threading import Thread
3233

3334
class LimitFilter(DynamicFilter):
@@ -145,3 +146,53 @@ class count_bytes(AggregateFwdBucket):
145146
"""AggregateFwdBucket that calls back with aggregate bytesize of packets."""
146147
def aggregator(self,aggregate,pkt):
147148
return aggregate + pkt['header_len'] + pkt['payload_len']
149+
150+
class RegexpQuery(Query):
151+
"""
152+
Class for registering callbacks on matching string in packet data?
153+
"""
154+
def __init__(self, pattern=""):
155+
super(RegexpQuery, self).__init__()
156+
self.re = pattern
157+
158+
def compile(self):
159+
"""Produce a Classifier for this policy
160+
161+
:rtype: Classifier
162+
"""
163+
r = Rule(identity,[Controller])
164+
return Classifier([r])
165+
166+
@property
167+
def re(self):
168+
return self._re
169+
170+
@re.setter
171+
def re(self, pattern):
172+
if not isinstance(pattern, re._pattern_type):
173+
pattern = re.compile(pattern, re.S)
174+
175+
self._re = pattern
176+
177+
def apply(self):
178+
with self.bucket_lock:
179+
for pkt in self.bucket:
180+
#XXX Should we go with raw data or payload?
181+
#XXX Logic for iteration here? first match or all of them?
182+
for m in self.re.finditer(pkt['raw']):
183+
for callback in self.callbacks:
184+
callback(pkt, m)
185+
186+
self.bucket.clear()
187+
188+
def __repr__(self):
189+
return "RegexpQuery"
190+
191+
def __eq__(self, other):
192+
# TODO: if buckets eventually have names, equality should
193+
# be on names.
194+
return isinstance(other, RegexpQuery) and (other.re == self.re)
195+
196+
197+
198+

0 commit comments

Comments
 (0)