Package flumotion :: Package common :: Module server
[hide private]

Source Code for Module flumotion.common.server

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """helper classes for creating a twisted server 
 23  """ 
 24   
 25  import os 
 26   
 27  from twisted.internet import reactor 
 28  from zope.interface import Interface 
 29   
 30  from flumotion.common import log 
 31   
 32  __version__ = "$Rev: 7162 $" 
 33   
 34   
35 -class _ServerContextFactory(log.Loggable):
36 37 logCategory = "SSLServer" 38
39 - def __init__(self, pemFile):
40 self._pemFile = pemFile
41
42 - def getContext(self):
43 """ 44 Create an SSL context. 45 """ 46 from OpenSSL import SSL 47 ctx = SSL.Context(SSL.SSLv23_METHOD) 48 try: 49 ctx.use_certificate_file(self._pemFile) 50 ctx.use_privatekey_file(self._pemFile) 51 except SSL.Error, e: 52 self.warning('SSL error: %r' % e.args) 53 self.error('Could not open certificate %s' % self._pemFile) 54 return ctx
55 56
57 -class IServable(Interface):
58 """ 59 I am an interface for objects that want to be servable through a 60 L{Server}. 61 """ 62
63 - def getFactory():
64 """ 65 @rtype: L{twisted.spread.pb.PBServerFactory} 66 """
67
68 - def setConnectionInfo(host, port, useSSL):
69 """ 70 @param host: the host to listen as 71 @type host: str 72 @param port: the port to listen on 73 @type port: int 74 @param useSSL: whether this connection uses SSL 75 @type useSSL: bool 76 """
77 78
79 -class Server(log.Loggable):
80 logCategory = "server" 81
82 - def __init__(self, servable):
83 """ 84 I expose a servable to the network using TCP or SSL. 85 86 @type servable: an implemtor of L{IServable} 87 """ 88 self._servable = servable
89
90 - def startSSL(self, host, port, pemFile, configDir):
91 """ 92 Listen as the given host and on the given port using SSL. 93 Use the given .pem file, or look for it in the config directory. 94 95 @param pemFile: File containing the SSL certificate. 96 If it's a full path, respects the full path. 97 If not, looks in configDir for this file. 98 @param configDir: directory where .pem file is stored 99 @returns: {twisted.internet.interfaces.IListeningPort} on which 100 we are listening; call .stopListening() to stop. 101 """ 102 from flumotion.common import common 103 common.assertSSLAvailable() 104 105 # if no path in pemFile, then look for it in the config directory 106 if not os.path.split(pemFile)[0]: 107 pemFile = os.path.join(configDir, pemFile) 108 if not os.path.exists(pemFile): 109 self.error(".pem file %s does not exist.\n" \ 110 "For more information, see \n" \ 111 "http://www.flumotion.net/doc/flumotion/manual/html/" \ 112 "chapter-security.html" % pemFile) 113 log.debug('manager', 'Using PEM certificate file %s' % pemFile) 114 ctxFactory = _ServerContextFactory(pemFile) 115 116 self.info('Starting on port %d using SSL' % port) 117 if not host == "": 118 self.info('Listening as host %s' % host) 119 self._servable.setConnectionInfo(host, port, True) 120 return reactor.listenSSL(port, self._servable.getFactory(), 121 ctxFactory, interface=host)
122
123 - def startTCP(self, host, port):
124 """ 125 Listen as the given host and on the given port using normal TCP. 126 127 @returns: {twisted.internet.interfaces.IListeningPort} on which 128 we are listening; call .stopListening() to stop. 129 """ 130 self.info('Starting on port %d using TCP' % port) 131 if not host == "": 132 self.info('Listening as host %s' % host) 133 self._servable.setConnectionInfo(host, port, False) 134 return reactor.listenTCP(port, self._servable.getFactory(), 135 interface=host)
136