]>
Commit | Line | Data |
---|---|---|
e0edde6f | 1 | # Copyright (c) 2011, 2012 Nicira, Inc. |
0be6140a AA |
2 | # |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at: | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | ||
15 | """ | |
16 | tcp module contains listener and sender classes for TCP protocol | |
17 | """ | |
18 | ||
19 | from twisted.internet.protocol import Factory, ClientFactory, Protocol | |
20 | from twisted.internet import interfaces | |
21 | from zope.interface import implements | |
22 | import time | |
23 | ||
24 | ||
25 | class TcpListenerConnection(Protocol): | |
26 | """ | |
27 | This per-connection class is instantiated each time sender connects | |
28 | """ | |
29 | def __init__(self): | |
30 | self.stats = 0 | |
31 | ||
0be6140a AA |
32 | def dataReceived(self, data): |
33 | self.stats += len(data) | |
34 | ||
35 | def connectionLost(self, reason): | |
0be6140a AA |
36 | self.factory.stats += self.stats |
37 | ||
38 | ||
39 | class TcpListenerFactory(Factory): | |
40 | """ | |
41 | This per-listening socket class is used to | |
42 | instantiate TcpListenerConnections | |
43 | """ | |
44 | protocol = TcpListenerConnection | |
45 | ||
46 | def __init__(self): | |
47 | self.stats = 0 | |
48 | ||
0be6140a AA |
49 | def getResults(self): |
50 | """ returns the number of bytes received as string""" | |
8d25d9a2 AA |
51 | # XML RPC does not support 64bit int (http://bugs.python.org/issue2985) |
52 | # so we have to convert the amount of bytes into a string | |
0be6140a AA |
53 | return str(self.stats) |
54 | ||
55 | ||
56 | class Producer(object): | |
57 | implements(interfaces.IPushProducer) | |
58 | """ | |
59 | This producer class generates infinite byte stream for a specified time | |
60 | duration | |
61 | """ | |
62 | def __init__(self, proto, duration): | |
63 | self.proto = proto | |
64 | self.start = time.time() | |
65 | self.produced = 0 | |
66 | self.paused = False | |
67 | self.data = "X" * 65535 | |
68 | self.duration = duration | |
69 | ||
70 | def pauseProducing(self): | |
71 | """This function is called whenever write() to socket would block""" | |
72 | self.paused = True | |
73 | ||
74 | def resumeProducing(self): | |
75 | """This function is called whenever socket becomes writable""" | |
76 | self.paused = False | |
77 | current = time.time() | |
78 | while (not self.paused) and (current < self.start + self.duration): | |
79 | self.proto.transport.write(self.data) | |
80 | self.produced += len(self.data) | |
81 | current = time.time() | |
82 | if current >= self.start + self.duration: | |
83 | self.proto.factory.stats += self.produced | |
84 | self.proto.transport.unregisterProducer() | |
85 | self.proto.transport.loseConnection() | |
86 | ||
87 | def stopProducing(self): | |
88 | pass | |
89 | ||
90 | ||
91 | class TcpSenderConnection(Protocol): | |
92 | """ | |
93 | TCP connection instance class that sends all traffic at full speed. | |
94 | """ | |
95 | ||
96 | def connectionMade(self): | |
0be6140a AA |
97 | producer = Producer(self, self.factory.duration) |
98 | self.transport.registerProducer(producer, True) | |
99 | producer.resumeProducing() | |
100 | ||
101 | def dataReceived(self, data): | |
0be6140a AA |
102 | self.transport.loseConnection() |
103 | ||
0be6140a AA |
104 | |
105 | class TcpSenderFactory(ClientFactory): | |
106 | """ | |
107 | This factory is responsible to instantiate TcpSenderConnection classes | |
108 | each time sender initiates connection | |
109 | """ | |
110 | protocol = TcpSenderConnection | |
111 | ||
112 | def __init__(self, duration): | |
113 | self.duration = duration | |
114 | self.stats = 0 | |
115 | ||
0be6140a AA |
116 | def getResults(self): |
117 | """Returns amount of bytes sent to the Listener (as a string)""" | |
118 | return str(self.stats) |