OSDN Git Service

Multithreads are abandoned. Alternatly, The asyncore substitutes.(#16776)
[fukui-no-namari/fukui-no-namari.git] / src / FukuiNoNamari / network_manager.py
1 # Copyright (C) 2009 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 import gobject
19 import asyncore
20 from asyncore import dispatcher
21 import socket
22 #import time
23 import rfc822
24 from StringIO import StringIO
25 from urlparse import urlparse
26 import os
27
28
29 class BusyException: pass
30
31
32 class Response:
33
34     def __init__(self):
35         self.status = ""
36         self.headers = {}
37         self.message = ""
38
39
40 class HttpClientGet(dispatcher):
41
42     def __init__(self, uri, headers, on_received):
43         dispatcher.__init__(self)
44
45         self.fd = StringIO()
46         self.closed = False
47         self.on_received = on_received
48         self.response = Response()
49
50         port = 80
51         ret = urlparse(uri)
52         if ret.scheme != "http":
53             print "%s is not http" % uri
54             return
55         if ret.port:
56             port = ret.port
57
58         headers["Host".capitalize()] = ret.hostname
59         request = 'GET %s HTTP/1.0' % ret.geturl()
60
61         # build request
62         fd = StringIO()
63         fd.write(request)
64         fd.write('\r\n')
65         for key, value in headers.iteritems():
66             fd.write("%s: %s" % (key, value))
67             fd.write("\r\n")
68         fd.write('\r\n')
69         fd.seek(0)
70         self.buffer = fd.read()
71
72         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
73         try:
74             self.connect((ret.hostname, port))
75         except socket.gaierror, e:
76             self.del_channel()
77             raise e
78
79     def close(self):
80         dispatcher.close(self)
81         self.closed = True
82
83     def handle_connect(self):
84         print "####request####"
85         print self.buffer.strip()
86         #print time.time(), "connected"
87
88     def handle_close(self):
89         self.close()
90         #print time.time(), "closed"
91
92         # consuming the retrived data.
93         self.fd.seek(0)
94         self.response.message = self.fd.read()
95         self.on_received(self.response)
96
97     def _process_status_headers(self, entity):
98         fd = StringIO(entity)
99         fd.seek(0)
100         self.response.status = fd.readline().strip()
101         print "====response===="
102         print self.response.status
103         msg = rfc822.Message(fd)
104         for key, value in msg.dict.iteritems():
105             key = key.capitalize()
106             self.response.headers[key] = value
107             print "%s: %s" % (key, value)
108         self.fd.write(fd.read())
109
110     def _process_recv_data(self, entity):
111         if not self.response.status:
112             self._process_status_headers(entity)
113         else:
114             self.fd.write(entity)
115
116     def handle_read(self):
117         if not self.closed:
118             entity = self.recv(8192)
119             if entity:
120                 self._process_recv_data(entity)
121
122     def handle_error(self):
123         import traceback
124         traceback.print_exc()
125
126     def writable(self):
127         return (len(self.buffer) > 0)
128
129     def handle_write(self):
130         #print time.time(), "send"
131         sent = self.send(self.buffer)
132         self.buffer = self.buffer[sent:]
133
134
135 def _get_get_dispatcher():
136     for value in asyncore.socket_map.itervalues():
137         if isinstance(value, HttpClientGet):
138             return value
139
140 def _loop_chain():
141     if len(asyncore.socket_map) != 0:
142         asyncore.loop(timeout=5, count=1)
143         gobject.idle_add(_loop_chain)
144
145 # facade of 'network manager'
146 #   request(uri, on_recived)
147 #   on_received function,
148 #   "def on_received(response):"
149 def request_get(uri, headers, on_received):
150     get_dispatcher = _get_get_dispatcher()
151
152     if get_dispatcher:
153         raise BusyException()
154
155     need_exec_loop = len(asyncore.socket_map) == 0
156
157     get_dispatcher = HttpClientGet(uri, headers, on_received)
158     if need_exec_loop:
159         gobject.idle_add(_loop_chain)
160
161 # facade of 'network manager'
162 #   cancel_get
163 def cancel_get():
164     get_dispatcher = _get_get_dispatcher()
165     if get_dispatcher:
166         get_dispatcher.close()