Browse Source

I believe I had improved the error handling now.. we now trigger the

waiting clients when an error occures to be passed back up...  we
also clear the fetchingurls flag so that if an error occures, then
next query will try again...

[git-p4: depot-paths = "//depot/": change = 861]
v0.3
John-Mark Gurney 18 years ago
parent
commit
04122f05dd
1 changed files with 28 additions and 8 deletions
  1. +28
    -8
      shoutcast.py

+ 28
- 8
shoutcast.py View File

@@ -5,6 +5,12 @@
__version__ = '$Change$' __version__ = '$Change$'
# $Id$ # $Id$


# The handling of defers and state in this module is not very good. It
# needs some work to ensure that error cases are properly handled. What
# do we do if we get no URLs for a PLS? Do we delete ourselves just to be
# readded (when we get PLS refeshing working)? Do we set a content-length
# to zero till we get one?

import ConfigParser import ConfigParser
import StringIO import StringIO
import os.path import os.path
@@ -188,7 +194,12 @@ class ShoutProxy(resource.Resource):
protocol.ClientCreator(reactor, ShoutTransfer, request, protocol.ClientCreator(reactor, ShoutTransfer, request,
self.startNextConnection).connectTCP(host, port) self.startNextConnection).connectTCP(host, port)


def triggerdefered(self, fun):
map(fun, self.afterurls)
self.afterurls = None

def gotPLS(self, page): def gotPLS(self, page):
self.fetchingurls = False
try: try:
pls = ConfigParser.SafeConfigParser() pls = ConfigParser.SafeConfigParser()
pls.readfp(StringIO.StringIO(page)) pls.readfp(StringIO.StringIO(page))
@@ -203,19 +214,23 @@ class ShoutProxy(resource.Resource):
self.urlpos = random.randrange(len(self.urls)) self.urlpos = random.randrange(len(self.urls))
except: except:
self.dump_exc() self.dump_exc()
self.urls = None
self.triggerdefered(lambda x: x.errback(1))
return return


self.afterurls.callback(1)
self.afterurls = None
self.triggerdefered(lambda x: x.callback(1))


def errPLS(self, failure): def errPLS(self, failure):
self.request.write(failure.render(self.request))
self.request.finish()
self.request = None
self.fetchingurls = False
self.triggerdefered(lambda x: x.errback(1))


def processRequest(self, ign, request): def processRequest(self, ign, request):
self.startNextConnection(request) self.startNextConnection(request)


def errRequest(self, ign, request):
request.write(failure.render(self.request))
request.finish()

def render(self, request): def render(self, request):
request.setHeader('content-type', self.mt) request.setHeader('content-type', self.mt)


@@ -236,15 +251,20 @@ class ShoutProxy(resource.Resource):
# shouldn't getPage do proper escaping for me? # shouldn't getPage do proper escaping for me?
getPage(self.shoutpls.encode('ascii')) \ getPage(self.shoutpls.encode('ascii')) \
.addCallbacks(self.gotPLS, self.errPLS) .addCallbacks(self.gotPLS, self.errPLS)
self.afterurls = defer.Deferred()
self.afterurls = [ defer.Deferred() ]
else:
self.afterurls.append(defer.Deferred())
# Always add the callback if we don't have urls # Always add the callback if we don't have urls
self.afterurls.addCallback(self.processRequest, request)
self.afterurls[-1].addCallbacks(self.processRequest,
errback=self.errRequest, callbackArgs=(request, ),
errbackArgs=(request, ))
else: else:
self.startNextConnection(request) self.startNextConnection(request)
# and make sure the connection doesn't get closed # and make sure the connection doesn't get closed
return server.NOT_DONE_YET return server.NOT_DONE_YET


synchronized = [ 'render', 'gotPLS', 'startNextConnection' ]
synchronized = [ 'gotPLS', 'render', 'startNextConnection',
'triggerdefered', ]
threadable.synchronize(ShoutProxy) threadable.synchronize(ShoutProxy)


class ShoutStation(AudioItem): class ShoutStation(AudioItem):


Loading…
Cancel
Save