~radix/corotwine/trunk

1 by Christopher Armstrong
Initial import of Corotwine.
1
"""
2
Some sample protocols. This is meant to be an example; please read the source
3
code, not the API docs.
4
"""
5
import string, random
6
6 by Christopher Armstrong
switch back to raising the original twisted reason exception for connection
7
from twisted.internet.error import ConnectionClosed
1 by Christopher Armstrong
Initial import of Corotwine.
8
from twisted.protocols.amp import AMP, Command, String
9
from twisted.web.client import getPage
10
11
from corotwine.protocol import gListenTCP, gConnectTCP, LineBuffer
12
from corotwine.defer import blockOn, deferredGreenlet
14.1.1 by Jean-Paul Calderone
Centralize the choice about which greenlet library to use. Then add a fallback to that decision to the plain "greenlet" module if "py.magic.greenlet" is unavailable.
13
from corotwine import greenlet
1 by Christopher Armstrong
Initial import of Corotwine.
14
15
16
def echo(transport):
17
    while 1:
18
        try:
19
            transport.write(transport.read())
20
        except ConnectionClosed:
21
            return
22
23
24
def discard(transport):
25
    while 1:
26
        try:
27
            transport.read()
28
        except ConnectionClosed:
29
            return
30
31
32
def qotd(transport):
33
    transport.write("An apple a day keeps the doctor away.\r\n")
34
35
36
def chargen(transport):
37
    # Sample of efficient streaming.  transport.write switches back to the
38
    # reactor greenlet when buffers are full.
39
    while 1:
40
        try:
41
            transport.write(''.join(random.choice(string.letters)
42
                                    for i in range(1024)))
43
        except ConnectionClosed:
44
            return
45
46
47
class Chat(object):
48
    def __init__(self):
49
        self.clients = []
50
51
    def handleConnection(self, transport):
52
        transport = LineBuffer(transport)
53
        self.clients.append(transport)
54
        try:
55
            try:
56
                for line in transport:
57
                    for client in self.clients:
58
                        if client is not transport:
59
                            client.writeLine(line)
60
            finally:
61
                self.clients.remove(transport)
9 by Christopher Armstrong
d'oh, ConnectionClosed not ConnectionLost
62
        except ConnectionClosed:
1 by Christopher Armstrong
Initial import of Corotwine.
63
            return
64
65
66
def fetchGoogle(transport):
67
    result = blockOn(getPage("http://google.com/"))
68
    transport.write(result)
69
70
12 by Christopher Armstrong
describe the return/raise semantics of connection-handling functions.
71
1 by Christopher Armstrong
Initial import of Corotwine.
72
## And an amp example, to show off deferredGreenlet
73
74
class FetchGoogle(Command):
75
    arguments = []
76
    response = [("google", String())]
77
78
class GoogleGetter(AMP):
79
    @FetchGoogle.responder
80
    @deferredGreenlet
81
    def fetchGoogle(self):
82
        return {"google": blockOn(getPage("http://google.com/"))}
83
84
85
86
## Clients!
87
88
def echoclient():
89
    transport = gConnectTCP("localhost", 1027)
90
    transport.write("Heyo!")
91
    if transport.read() == "Heyo!":
92
        print "Echo server test succeeded!"
93
    else:
94
        print "Echo server test failed :-("
95
96
97
def googleAMPClient():
98
    from twisted.internet.protocol import ClientCreator
99
    cc = ClientCreator(reactor, AMP)
100
    ampConnection = blockOn(cc.connectTCP("localhost", 1030))
101
    result = blockOn(ampConnection.callRemote(FetchGoogle))
102
    if "I'm Feeling Lucky" in result["google"]:
103
        print "Google AMP Client test succeeded"
104
    else:
105
        print "Google AMP client test failed :-("
106
    ampConnection.transport.loseConnection()
107
108
109
# Deployment code
110
111
def startServers():
112
    gListenTCP(1025, discard)
113
    gListenTCP(1026, qotd)
114
    gListenTCP(1027, echo)
115
    gListenTCP(1028, chargen)
116
    gListenTCP(1029, fetchGoogle)
117
118
    from twisted.internet.protocol import Factory
119
    ampf = Factory()
120
    ampf.protocol = GoogleGetter
121
    reactor.listenTCP(1030, ampf)
122
123
    chat = Chat()
124
    gListenTCP(1031, chat.handleConnection)
125
126
127
if __name__ == '__main__':
128
    from twisted.internet import reactor
129
    from twisted.python.log import startLogging
130
    import sys
131
    startLogging(sys.stdout)
132
133
    startServers()
134
    greenlet(echoclient).switch()
135
136
    # Uncomment to test google thingy.
137
    #greenlet(googleAMPClient).switch()
138
139
    reactor.run()