##// END OF EJS Templates
debugging websocket connections...
Min RK -
Show More
@@ -13,9 +13,7 b' except ImportError:'
13 from urlparse import urlparse # Py 2
13 from urlparse import urlparse # Py 2
14
14
15 import tornado
15 import tornado
16 from tornado import ioloop
16 from tornado import gen, ioloop, web, websocket
17 from tornado import web
18 from tornado import websocket
19
17
20 from IPython.kernel.zmq.session import Session
18 from IPython.kernel.zmq.session import Session
21 from IPython.utils.jsonutil import date_default, extract_dates
19 from IPython.utils.jsonutil import date_default, extract_dates
@@ -197,7 +195,12 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):'
197 """
195 """
198 pass
196 pass
199
197
200 def get(self, *args, **kwargs):
198 def pre_get(self):
199 """Run before finishing the GET request
200
201 Extend this method to add logic that should fire before
202 the websocket finishes completing.
203 """
201 # Check to see that origin matches host directly, including ports
204 # Check to see that origin matches host directly, including ports
202 # Tornado 4 already does CORS checking
205 # Tornado 4 already does CORS checking
203 if tornado.version_info[0] < 4:
206 if tornado.version_info[0] < 4:
@@ -213,15 +216,22 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):'
213 self.session.session = cast_unicode(self.get_argument('session_id'))
216 self.session.session = cast_unicode(self.get_argument('session_id'))
214 else:
217 else:
215 self.log.warn("No session ID specified")
218 self.log.warn("No session ID specified")
219
220 @gen.coroutine
221 def get(self, *args, **kwargs):
222 # pre_get can be a coroutine in subclasses
223 yield gen.maybe_future(self.pre_get())
216 # FIXME: only do super get on tornado β‰₯ 4
224 # FIXME: only do super get on tornado β‰₯ 4
217 # tornado 3 has no get, will raise 405
225 # tornado 3 has no get, will raise 405
218 if tornado.version_info >= (4,):
226 if tornado.version_info >= (4,):
219 return super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
227 super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
220
228
221 def initialize(self):
229 def initialize(self):
230 self.log.debug("Initializing websocket connection %s", self.request.path)
222 self.session = Session(config=self.config)
231 self.session = Session(config=self.config)
223
232
224 def open(self, *args, **kwargs):
233 def open(self, *args, **kwargs):
234 self.log.debug("Opening websocket %s", self.request.path)
225 if tornado.version_info < (4,):
235 if tornado.version_info < (4,):
226 try:
236 try:
227 self.get(*self.open_args, **self.open_kwargs)
237 self.get(*self.open_args, **self.open_kwargs)
@@ -7,6 +7,7 b' import json'
7 import logging
7 import logging
8 from tornado import gen, web
8 from tornado import gen, web
9 from tornado.concurrent import Future
9 from tornado.concurrent import Future
10 from tornado.ioloop import IOLoop
10
11
11 from IPython.utils.jsonutil import date_default
12 from IPython.utils.jsonutil import date_default
12 from IPython.utils.py3compat import cast_unicode
13 from IPython.utils.py3compat import cast_unicode
@@ -85,6 +86,10 b' class KernelActionHandler(IPythonHandler):'
85
86
86 class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
87 class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
87
88
89 @property
90 def kernel_info_timeout(self):
91 return self.settings.get('kernel_info_timeout', 10)
92
88 def __repr__(self):
93 def __repr__(self):
89 return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized'))
94 return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized'))
90
95
@@ -150,7 +155,8 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):'
150 if protocol_version != kernel_protocol_version:
155 if protocol_version != kernel_protocol_version:
151 self.session.adapt_version = int(protocol_version.split('.')[0])
156 self.session.adapt_version = int(protocol_version.split('.')[0])
152 self.log.info("Kernel %s speaks protocol %s", self.kernel_id, protocol_version)
157 self.log.info("Kernel %s speaks protocol %s", self.kernel_id, protocol_version)
153 self._kernel_info_future.set_result(info)
158 if not self._kernel_info_future.done():
159 self._kernel_info_future.set_result(info)
154
160
155 def initialize(self):
161 def initialize(self):
156 super(ZMQChannelHandler, self).initialize()
162 super(ZMQChannelHandler, self).initialize()
@@ -160,10 +166,29 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):'
160 self._kernel_info_future = Future()
166 self._kernel_info_future = Future()
161
167
162 @gen.coroutine
168 @gen.coroutine
169 def pre_get(self):
170 # authenticate first
171 super(ZMQChannelHandler, self).pre_get()
172 # then request kernel info, waiting up to a certain time before giving up.
173 # We don't want to wait forever, because browsers don't take it well when
174 # servers never respond to websocket connection requests.
175 future = self.request_kernel_info()
176
177 def give_up():
178 """Don't wait forever for the kernel to reply"""
179 if future.done():
180 return
181 self.log.warn("Timeout waiting for kernel_info reply from %s", self.kernel_id)
182 future.set_result(None)
183 loop = IOLoop.current()
184 loop.add_timeout(loop.time() + self.kernel_info_timeout, give_up)
185 # actually wait for it
186 yield future
187
188 @gen.coroutine
163 def get(self, kernel_id):
189 def get(self, kernel_id):
164 self.kernel_id = cast_unicode(kernel_id, 'ascii')
190 self.kernel_id = cast_unicode(kernel_id, 'ascii')
165 yield self.request_kernel_info()
191 yield super(ZMQChannelHandler, self).get(kernel_id=kernel_id)
166 super(ZMQChannelHandler, self).get(kernel_id)
167
192
168 def open(self, kernel_id):
193 def open(self, kernel_id):
169 super(ZMQChannelHandler, self).open()
194 super(ZMQChannelHandler, self).open()
General Comments 0
You need to be logged in to leave comments. Login now